strmbase: do not lock in BaseOutputPinImpl_GetDeliveryBuffer the MemInputPin will...
[wine] / dlls / gdi32 / dibdrv / primitives.c
1 /*
2  * DIB driver primitives.
3  *
4  * Copyright 2011 Huw Davies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22
23 #include "gdi_private.h"
24 #include "dibdrv.h"
25
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(dib);
29
30 /* Bayer matrices for dithering */
31
32 static const BYTE bayer_4x4[4][4] =
33 {
34     {  0,  8,  2, 10 },
35     { 12,  4, 14,  6 },
36     {  3, 11,  1,  9 },
37     { 15,  7, 13,  5 }
38 };
39
40 static const BYTE bayer_16x16[16][16] =
41 {
42     {   0, 128,  32, 160,   8, 136,  40, 168,   2, 130,  34, 162,  10, 138,  42, 170 },
43     { 192,  64, 224,  96, 200,  72, 232, 104, 194,  66, 226,  98, 202,  74, 234, 106 },
44     {  48, 176,  16, 144,  56, 184,  24, 152,  50, 178,  18, 146,  58, 186,  26, 154 },
45     { 240, 112, 208,  80, 248, 120, 216,  88, 242, 114, 210,  82, 250, 122, 218,  90 },
46     {  12, 140,  44, 172,   4, 132,  36, 164,  14, 142,  46, 174,   6, 134,  38, 166 },
47     { 204,  76, 236, 108, 196,  68, 228, 100, 206,  78, 238, 110, 198,  70, 230, 102 },
48     {  60, 188,  28, 156,  52, 180,  20, 148,  62, 190,  30, 158,  54, 182,  22, 150 },
49     { 252, 124, 220,  92, 244, 116, 212,  84, 254, 126, 222,  94, 246, 118, 214,  86 },
50     {   3, 131,  35, 163,  11, 139,  43, 171,   1, 129,  33, 161,   9, 137,  41, 169 },
51     { 195,  67, 227,  99, 203,  75, 235, 107, 193,  65, 225,  97, 201,  73, 233, 105 },
52     {  51, 179,  19, 147,  59, 187,  27, 155,  49, 177,  17, 145,  57, 185,  25, 153 },
53     { 243, 115, 211,  83, 251, 123, 219,  91, 241, 113, 209,  81, 249, 121, 217,  89 },
54     {  15, 143,  47, 175,   7, 135,  39, 167,  13, 141,  45, 173,   5, 133,  37, 165 },
55     { 207,  79, 239, 111, 199,  71, 231, 103, 205,  77, 237, 109, 197,  69, 229, 101 },
56     {  63, 191,  31, 159,  55, 183,  23, 151,  61, 189,  29, 157,  53, 181,  21, 149 },
57     { 255, 127, 223,  95, 247, 119, 215,  87, 253, 125, 221,  93, 245, 117, 213,  85 },
58 };
59
60 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
61 {
62     return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 4);
63 }
64
65 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
66 {
67     return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride) + (dib->rect.left + x) * 3 / 4;
68 }
69
70 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
71 {
72     return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 3;
73 }
74
75 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
76 {
77     return (WORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 2);
78 }
79
80 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
81 {
82     return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + dib->rect.left + x;
83 }
84
85 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
86 {
87     return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 2;
88 }
89
90 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
91 {
92     return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 8;
93 }
94
95 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
96 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
97
98 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
99 {
100     *ptr = (*ptr & and) ^ xor;
101 }
102
103 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
104 {
105     *ptr = (*ptr & and) ^ xor;
106 }
107
108 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
109 {
110     *ptr = (*ptr & and) ^ xor;
111 }
112
113 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
114 {
115     *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
116 }
117
118 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
119 {
120     do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
121 }
122
123 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
124 {
125     do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
126 }
127
128 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
129 {
130     do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
131 }
132
133 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
134 {
135     do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
136 }
137
138 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
139 {
140     for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
141 }
142
143 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
144 {
145     for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
146         do_rop_codes_32( dst, *src, codes );
147 }
148
149 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
150 {
151     for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
152 }
153
154 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
155 {
156     for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
157         do_rop_codes_16( dst, *src, codes );
158 }
159
160 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
161 {
162     for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
163 }
164
165 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
166 {
167     for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
168         do_rop_codes_8( dst, *src, codes );
169 }
170
171 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
172                                       struct rop_codes *codes, int len)
173 {
174     BYTE src_val;
175
176     for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
177     {
178         if (dst_x & 1)
179         {
180             if (src_x & 1) src_val = *src++;
181             else           src_val = *src >> 4;
182             do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
183         }
184         else
185         {
186             if (src_x & 1) src_val = *src++ << 4;
187             else           src_val = *src;
188             do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
189         }
190     }
191 }
192
193 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
194                                           struct rop_codes *codes, int len)
195 {
196     BYTE src_val;
197
198     src_x += len - 1;
199     dst_x += len - 1;
200     for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
201     {
202         if (dst_x & 1)
203         {
204             if (src_x & 1) src_val = *src;
205             else           src_val = *src-- >> 4;
206             do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
207         }
208         else
209         {
210             if (src_x & 1) src_val = *src << 4;
211             else           src_val = *src--;
212             do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
213         }
214     }
215 }
216
217 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
218                                       struct rop_codes *codes, int len)
219 {
220     BYTE src_val;
221
222     for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
223     {
224         src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
225         do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
226         if ((src_x & 7) == 7) src++;
227         if ((dst_x & 7) == 7) dst++;
228     }
229 }
230
231 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
232                                           struct rop_codes *codes, int len)
233 {
234     BYTE src_val;
235
236     src_x += len - 1;
237     dst_x += len - 1;
238     for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
239     {
240         src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
241         do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
242         if ((src_x & 7) == 0) src--;
243         if ((dst_x & 7) == 0) dst--;
244     }
245 }
246
247 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
248 {
249     DWORD *ptr, *start;
250     int x, y, i;
251
252     for(i = 0; i < num; i++, rc++)
253     {
254         start = get_pixel_ptr_32(dib, rc->left, rc->top);
255         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
256             for(x = rc->left, ptr = start; x < rc->right; x++)
257                 do_rop_32(ptr++, and, xor);
258     }
259 }
260
261 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
262 {
263     DWORD *ptr, *start;
264     BYTE *byte_ptr, *byte_start;
265     int x, y, i;
266     DWORD and_masks[3], xor_masks[3];
267
268     and_masks[0] = ( and        & 0x00ffffff) | ((and << 24) & 0xff000000);
269     and_masks[1] = ((and >>  8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
270     and_masks[2] = ((and >> 16) & 0x000000ff) | ((and <<  8) & 0xffffff00);
271     xor_masks[0] = ( xor        & 0x00ffffff) | ((xor << 24) & 0xff000000);
272     xor_masks[1] = ((xor >>  8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
273     xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor <<  8) & 0xffffff00);
274
275     for(i = 0; i < num; i++, rc++)
276     {
277         int left = dib->rect.left + rc->left;
278         int right = dib->rect.left + rc->right;
279
280         if (left >= right) continue;
281
282         if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
283         {
284             byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
285             for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
286             {
287                 for(x = left, byte_ptr = byte_start; x < right; x++)
288                 {
289                     do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
290                     do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
291                     do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
292                 }
293             }
294         }
295         else
296         {
297             start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
298             for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
299             {
300                 ptr = start;
301
302                 switch(left & 3)
303                 {
304                 case 1:
305                     do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
306                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
307                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
308                     break;
309                 case 2:
310                     do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
311                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
312                     break;
313                 case 3:
314                     do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
315                     break;
316                 }
317
318                 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
319                 {
320                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
321                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
322                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
323                 }
324
325                 switch(right & 3)
326                 {
327                 case 1:
328                     do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
329                     break;
330                 case 2:
331                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
332                     do_rop_32(ptr,   and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
333                     break;
334                 case 3:
335                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
336                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
337                     do_rop_32(ptr,   and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
338                     break;
339                 }
340             }
341         }
342     }
343 }
344
345 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
346 {
347     WORD *ptr, *start;
348     int x, y, i;
349
350     for(i = 0; i < num; i++, rc++)
351     {
352         start = get_pixel_ptr_16(dib, rc->left, rc->top);
353         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
354             for(x = rc->left, ptr = start; x < rc->right; x++)
355                 do_rop_16(ptr++, and, xor);
356     }
357 }
358
359 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
360 {
361     BYTE *ptr, *start;
362     int x, y, i;
363
364     for(i = 0; i < num; i++, rc++)
365     {
366         start = get_pixel_ptr_8(dib, rc->left, rc->top);
367         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
368             for(x = rc->left, ptr = start; x < rc->right; x++)
369                 do_rop_8(ptr++, and, xor);
370     }
371 }
372
373 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
374 {
375     BYTE *ptr, *start;
376     int x, y, i;
377     BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
378     BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
379
380     for(i = 0; i < num; i++, rc++)
381     {
382         int left = dib->rect.left + rc->left;
383         int right = dib->rect.left + rc->right;
384
385         if (left >= right) continue;
386         start = get_pixel_ptr_4(dib, rc->left, rc->top);
387         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
388         {
389             ptr = start;
390             if(left & 1) /* upper nibble untouched */
391                 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
392
393             for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
394                 do_rop_8(ptr++, byte_and, byte_xor);
395
396             if(right & 1) /* lower nibble untouched */
397                 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
398         }
399     }
400 }
401
402 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
403 {
404     BYTE *ptr, *start;
405     int x, y, i;
406     BYTE byte_and = (and & 1) ? 0xff : 0;
407     BYTE byte_xor = (xor & 1) ? 0xff : 0;
408     BYTE start_and, start_xor, end_and, end_xor, mask;
409     static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
410
411     for(i = 0; i < num; i++, rc++)
412     {
413         int left = dib->rect.left + rc->left;
414         int right = dib->rect.left + rc->right;
415
416         if (left >= right) continue;
417
418         start = get_pixel_ptr_1(dib, rc->left, rc->top);
419
420         if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
421         {
422             mask = masks[left & 7] & ~masks[right & 7];
423
424             start_and = byte_and | ~mask;
425             start_xor = byte_xor & mask;
426             for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
427             {
428                 do_rop_8(start, start_and, start_xor);
429             }
430         }
431         else
432         {
433             mask = masks[left & 7];
434             start_and = byte_and | ~mask;
435             start_xor = byte_xor & mask;
436
437             mask = masks[right & 7];
438             /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
439             end_and = byte_and | mask;
440             end_xor = byte_xor & ~mask;
441
442             for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
443             {
444                 ptr = start;
445
446                 if(left & 7)
447                     do_rop_8(ptr++, start_and, start_xor);
448
449                 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
450                     do_rop_8(ptr++, byte_and, byte_xor);
451
452                 if(right & 7)
453                     do_rop_8(ptr, end_and, end_xor);
454             }
455         }
456     }
457 }
458
459 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
460 {
461     return;
462 }
463
464 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
465                           DWORD and, DWORD xor)
466 {
467     DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
468     int len = params->length, err = params->err_start;
469     int major_inc, minor_inc;
470
471     if (params->x_major)
472     {
473         major_inc = params->x_inc;
474         minor_inc = (dib->stride * params->y_inc) / 4;
475     }
476     else
477     {
478         major_inc = (dib->stride * params->y_inc) / 4;
479         minor_inc = params->x_inc;
480     }
481
482     while (len--)
483     {
484         do_rop_32( ptr, and, xor );
485         if (err + params->bias > 0)
486         {
487             ptr += minor_inc;
488             err += params->err_add_1;
489         }
490         else err += params->err_add_2;
491         ptr += major_inc;
492     }
493 }
494
495 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
496                          DWORD and, DWORD xor)
497 {
498     BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
499     int len = params->length, err = params->err_start;
500     int major_inc, minor_inc;
501
502     if (params->x_major)
503     {
504         major_inc = params->x_inc * 3;
505         minor_inc = dib->stride * params->y_inc;
506     }
507     else
508     {
509         major_inc = dib->stride * params->y_inc;
510         minor_inc = params->x_inc * 3;
511     }
512
513     while (len--)
514     {
515         do_rop_8( ptr,     and,       xor );
516         do_rop_8( ptr + 1, and >> 8,  xor >> 8 );
517         do_rop_8( ptr + 2, and >> 16, xor >> 16 );
518         if (err + params->bias > 0)
519         {
520             ptr += minor_inc;
521             err += params->err_add_1;
522         }
523         else err += params->err_add_2;
524         ptr += major_inc;
525     }
526 }
527
528 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
529                           DWORD and, DWORD xor)
530 {
531     WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
532     int len = params->length, err = params->err_start;
533     int major_inc, minor_inc;
534
535     if (params->x_major)
536     {
537         major_inc = params->x_inc;
538         minor_inc = (dib->stride * params->y_inc) / 2;
539     }
540     else
541     {
542         major_inc = (dib->stride * params->y_inc) / 2;
543         minor_inc = params->x_inc;
544     }
545
546     while (len--)
547     {
548         do_rop_16( ptr, and, xor );
549         if (err + params->bias > 0)
550         {
551             ptr += minor_inc;
552             err += params->err_add_1;
553         }
554         else err += params->err_add_2;
555         ptr += major_inc;
556     }
557 }
558
559 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
560                          DWORD and, DWORD xor)
561 {
562     BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
563     int len = params->length, err = params->err_start;
564     int major_inc, minor_inc;
565
566     if (params->x_major)
567     {
568         major_inc = params->x_inc;
569         minor_inc = dib->stride * params->y_inc;
570     }
571     else
572     {
573         major_inc = dib->stride * params->y_inc;
574         minor_inc = params->x_inc;
575     }
576
577     while (len--)
578     {
579         do_rop_8( ptr, and, xor );
580         if (err + params->bias > 0)
581         {
582             ptr += minor_inc;
583             err += params->err_add_1;
584         }
585         else err += params->err_add_2;
586         ptr += major_inc;
587     }
588 }
589
590 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
591                          DWORD and, DWORD xor)
592 {
593     BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
594     int len = params->length, err = params->err_start;
595     int x = dib->rect.left + start->x;
596
597     and = (and & 0x0f) | ((and << 4) & 0xf0);
598     xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
599
600     if (params->x_major)
601     {
602         while (len--)
603         {
604             do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
605             if (err + params->bias > 0)
606             {
607                 ptr += dib->stride * params->y_inc;
608                 err += params->err_add_1;
609             }
610             else err += params->err_add_2;
611             if ((x / 2) != ((x + params->x_inc) / 2))
612                 ptr += params->x_inc;
613             x += params->x_inc;
614         }
615     }
616     else
617     {
618         while (len--)
619         {
620             do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
621             if (err + params->bias > 0)
622             {
623                 if ((x / 2) != ((x + params->x_inc) / 2))
624                     ptr += params->x_inc;
625                 x += params->x_inc;
626                 err += params->err_add_1;
627             }
628             else err += params->err_add_2;
629             ptr += dib->stride * params->y_inc;
630         }
631     }
632 }
633
634 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
635                          DWORD and, DWORD xor)
636 {
637     BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
638     int len = params->length, err = params->err_start;
639     int x = dib->rect.left + start->x;
640
641     and = (and & 0x1) ? 0xff : 0;
642     xor = (xor & 0x1) ? 0xff : 0;
643
644     if (params->x_major)
645     {
646         while (len--)
647         {
648             do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
649             if (err + params->bias > 0)
650             {
651                 ptr += dib->stride * params->y_inc;
652                 err += params->err_add_1;
653             }
654             else err += params->err_add_2;
655             if ((x / 8) != ((x + params->x_inc) / 8))
656                 ptr += params->x_inc;
657             x += params->x_inc;
658         }
659     }
660     else
661     {
662         while (len--)
663         {
664             do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
665             if (err + params->bias > 0)
666             {
667                 if ((x / 8) != ((x + params->x_inc) / 8))
668                     ptr += params->x_inc;
669                 x += params->x_inc;
670                 err += params->err_add_1;
671             }
672             else err += params->err_add_2;
673             ptr += dib->stride * params->y_inc;
674         }
675     }
676 }
677
678 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
679                             DWORD and, DWORD xor)
680 {
681     return;
682 }
683
684 static inline INT calc_offset(INT edge, INT size, INT origin)
685 {
686     INT offset;
687
688     if(edge - origin >= 0)
689         offset = (edge - origin) % size;
690     else
691     {
692         offset = (origin - edge) % size;
693         if(offset) offset = size - offset;
694     }
695     return offset;
696 }
697
698 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
699 {
700     POINT offset;
701
702     offset.x = calc_offset(rc->left, brush->width,  origin->x);
703     offset.y = calc_offset(rc->top,  brush->height, origin->y);
704
705     return offset;
706 }
707
708 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
709                              const dib_info *brush, void *and_bits, void *xor_bits)
710 {
711     DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
712     int x, y, i;
713     POINT offset;
714
715     for(i = 0; i < num; i++, rc++)
716     {
717         offset = calc_brush_offset(rc, brush, origin);
718
719         start = get_pixel_ptr_32(dib, rc->left, rc->top);
720         start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
721         start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
722
723         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
724         {
725             and_ptr = start_and + offset.x;
726             xor_ptr = start_xor + offset.x;
727
728             for(x = rc->left, ptr = start; x < rc->right; x++)
729             {
730                 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
731                 if(and_ptr == start_and + brush->width)
732                 {
733                     and_ptr = start_and;
734                     xor_ptr = start_xor;
735                 }
736             }
737
738             offset.y++;
739             if(offset.y == brush->height)
740             {
741                 start_and = and_bits;
742                 start_xor = xor_bits;
743                 offset.y = 0;
744             }
745             else
746             {
747                 start_and += brush->stride / 4;
748                 start_xor += brush->stride / 4;
749             }
750         }
751     }
752 }
753
754 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
755                              const dib_info *brush, void *and_bits, void *xor_bits)
756 {
757     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
758     int x, y, i;
759     POINT offset;
760
761     for(i = 0; i < num; i++, rc++)
762     {
763         offset = calc_brush_offset(rc, brush, origin);
764
765         start = get_pixel_ptr_24(dib, rc->left, rc->top);
766         start_and = (BYTE*)and_bits + offset.y * brush->stride;
767         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
768
769         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
770         {
771             and_ptr = start_and + offset.x * 3;
772             xor_ptr = start_xor + offset.x * 3;
773
774             for(x = rc->left, ptr = start; x < rc->right; x++)
775             {
776                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
777                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
778                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
779                 if(and_ptr == start_and + brush->width * 3)
780                 {
781                     and_ptr = start_and;
782                     xor_ptr = start_xor;
783                 }
784             }
785
786             offset.y++;
787             if(offset.y == brush->height)
788             {
789                 start_and = and_bits;
790                 start_xor = xor_bits;
791                 offset.y = 0;
792             }
793             else
794             {
795                 start_and += brush->stride;
796                 start_xor += brush->stride;
797             }
798         }
799     }
800 }
801
802 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
803                              const dib_info *brush, void *and_bits, void *xor_bits)
804 {
805     WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
806     int x, y, i;
807     POINT offset;
808
809     for(i = 0; i < num; i++, rc++)
810     {
811         offset = calc_brush_offset(rc, brush, origin);
812
813         start = get_pixel_ptr_16(dib, rc->left, rc->top);
814         start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
815         start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
816
817         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
818         {
819             and_ptr = start_and + offset.x;
820             xor_ptr = start_xor + offset.x;
821
822             for(x = rc->left, ptr = start; x < rc->right; x++)
823             {
824                 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
825                 if(and_ptr == start_and + brush->width)
826                 {
827                     and_ptr = start_and;
828                     xor_ptr = start_xor;
829                 }
830             }
831
832             offset.y++;
833             if(offset.y == brush->height)
834             {
835                 start_and = and_bits;
836                 start_xor = xor_bits;
837                 offset.y = 0;
838             }
839             else
840             {
841                 start_and += brush->stride / 2;
842                 start_xor += brush->stride / 2;
843             }
844         }
845     }
846 }
847
848 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
849                             const dib_info *brush, void *and_bits, void *xor_bits)
850 {
851     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
852     int x, y, i;
853     POINT offset;
854
855     for(i = 0; i < num; i++, rc++)
856     {
857         offset = calc_brush_offset(rc, brush, origin);
858
859         start = get_pixel_ptr_8(dib, rc->left, rc->top);
860         start_and = (BYTE*)and_bits + offset.y * brush->stride;
861         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
862
863         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
864         {
865             and_ptr = start_and + offset.x;
866             xor_ptr = start_xor + offset.x;
867
868             for(x = rc->left, ptr = start; x < rc->right; x++)
869             {
870                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
871                 if(and_ptr == start_and + brush->width)
872                 {
873                     and_ptr = start_and;
874                     xor_ptr = start_xor;
875                 }
876             }
877
878             offset.y++;
879             if(offset.y == brush->height)
880             {
881                 start_and = and_bits;
882                 start_xor = xor_bits;
883                 offset.y = 0;
884             }
885             else
886             {
887                 start_and += brush->stride;
888                 start_xor += brush->stride;
889             }
890         }
891     }
892 }
893
894 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
895                             const dib_info *brush, void *and_bits, void *xor_bits)
896 {
897     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
898     int x, y, i, left, right;
899     POINT offset;
900
901     for(i = 0; i < num; i++, rc++)
902     {
903         offset = calc_brush_offset(rc, brush, origin);
904         left = dib->rect.left + rc->left;
905         right = dib->rect.left + rc->right;
906
907         start = get_pixel_ptr_4(dib, rc->left, rc->top);
908         start_and = (BYTE*)and_bits + offset.y * brush->stride;
909         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
910
911         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
912         {
913             INT brush_x = offset.x;
914             BYTE byte_and, byte_xor;
915
916             and_ptr = start_and + brush_x / 2;
917             xor_ptr = start_xor + brush_x / 2;
918
919             for(x = left, ptr = start; x < right; x++)
920             {
921                 /* FIXME: Two pixels at a time */
922                 if(x & 1) /* lower dst nibble */
923                 {
924                     if(brush_x & 1) /* lower pat nibble */
925                     {
926                         byte_and = *and_ptr++ | 0xf0;
927                         byte_xor = *xor_ptr++ & 0x0f;
928                     }
929                     else /* upper pat nibble */
930                     {
931                         byte_and = (*and_ptr >> 4) | 0xf0;
932                         byte_xor = (*xor_ptr >> 4) & 0x0f;
933                     }
934                 }
935                 else /* upper dst nibble */
936                 {
937                     if(brush_x & 1) /* lower pat nibble */
938                     {
939                         byte_and = (*and_ptr++ << 4) | 0x0f;
940                         byte_xor = (*xor_ptr++ << 4) & 0xf0;
941                     }
942                     else /* upper pat nibble */
943                     {
944                         byte_and = *and_ptr | 0x0f;
945                         byte_xor = *xor_ptr & 0xf0;
946                     }
947                 }
948                 do_rop_8(ptr, byte_and, byte_xor);
949
950                 if(x & 1) ptr++;
951
952                 if(++brush_x == brush->width)
953                 {
954                     brush_x = 0;
955                     and_ptr = start_and;
956                     xor_ptr = start_xor;
957                 }
958             }
959
960             offset.y++;
961             if(offset.y == brush->height)
962             {
963                 start_and = and_bits;
964                 start_xor = xor_bits;
965                 offset.y = 0;
966             }
967             else
968             {
969                 start_and += brush->stride;
970                 start_xor += brush->stride;
971             }
972         }
973     }
974 }
975
976 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
977                             const dib_info *brush, void *and_bits, void *xor_bits)
978 {
979     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
980     int x, y, i, left, right;
981     POINT offset;
982
983     for(i = 0; i < num; i++, rc++)
984     {
985         offset = calc_brush_offset(rc, brush, origin);
986         left = dib->rect.left + rc->left;
987         right = dib->rect.left + rc->right;
988
989         start = get_pixel_ptr_1(dib, rc->left, rc->top);
990         start_and = (BYTE*)and_bits + offset.y * brush->stride;
991         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
992
993         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
994         {
995             INT brush_x = offset.x;
996             BYTE byte_and, byte_xor;
997
998             and_ptr = start_and + brush_x / 8;
999             xor_ptr = start_xor + brush_x / 8;
1000
1001             for(x = left, ptr = start; x < right; x++)
1002             {
1003                 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1004                 byte_and |= ~pixel_masks_1[x % 8];
1005                 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1006                 byte_xor &= pixel_masks_1[x % 8];
1007
1008                 do_rop_8(ptr, byte_and, byte_xor);
1009
1010                 if((x & 7) == 7) ptr++;
1011
1012                 if((brush_x & 7) == 7)
1013                 {
1014                     and_ptr++;
1015                     xor_ptr++;
1016                 }
1017
1018                 if(++brush_x == brush->width)
1019                 {
1020                     brush_x = 0;
1021                     and_ptr = start_and;
1022                     xor_ptr = start_xor;
1023                 }
1024             }
1025
1026             offset.y++;
1027             if(offset.y == brush->height)
1028             {
1029                 start_and = and_bits;
1030                 start_xor = xor_bits;
1031                 offset.y = 0;
1032             }
1033             else
1034             {
1035                 start_and += brush->stride;
1036                 start_xor += brush->stride;
1037             }
1038         }
1039     }
1040 }
1041
1042 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1043                                const dib_info *brush, void *and_bits, void *xor_bits)
1044 {
1045     return;
1046 }
1047
1048 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1049                          const dib_info *src, const POINT *origin, int rop2, int overlap)
1050 {
1051     DWORD *dst_start, *src_start;
1052     struct rop_codes codes;
1053     int y, dst_stride, src_stride;
1054
1055     if (overlap & OVERLAP_BELOW)
1056     {
1057         dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1058         src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1059         dst_stride = -dst->stride / 4;
1060         src_stride = -src->stride / 4;
1061     }
1062     else
1063     {
1064         dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1065         src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1066         dst_stride = dst->stride / 4;
1067         src_stride = src->stride / 4;
1068     }
1069
1070     if (rop2 == R2_COPYPEN)
1071     {
1072         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1073             memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1074         return;
1075     }
1076
1077     get_rop_codes( rop2, &codes );
1078     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1079     {
1080         if (overlap & OVERLAP_RIGHT)
1081             do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1082         else
1083             do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1084     }
1085 }
1086
1087 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1088                          const dib_info *src, const POINT *origin, int rop2, int overlap)
1089 {
1090     BYTE *dst_start, *src_start;
1091     int y, dst_stride, src_stride;
1092     struct rop_codes codes;
1093
1094     if (overlap & OVERLAP_BELOW)
1095     {
1096         dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1097         src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1098         dst_stride = -dst->stride;
1099         src_stride = -src->stride;
1100     }
1101     else
1102     {
1103         dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1104         src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1105         dst_stride = dst->stride;
1106         src_stride = src->stride;
1107     }
1108
1109     if (rop2 == R2_COPYPEN)
1110     {
1111         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1112             memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1113         return;
1114     }
1115
1116     get_rop_codes( rop2, &codes );
1117     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1118     {
1119         if (overlap & OVERLAP_RIGHT)
1120             do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1121         else
1122             do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1123     }
1124 }
1125
1126 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1127                          const dib_info *src, const POINT *origin, int rop2, int overlap)
1128 {
1129     WORD *dst_start, *src_start;
1130     int y, dst_stride, src_stride;
1131     struct rop_codes codes;
1132
1133     if (overlap & OVERLAP_BELOW)
1134     {
1135         dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1136         src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1137         dst_stride = -dst->stride / 2;
1138         src_stride = -src->stride / 2;
1139     }
1140     else
1141     {
1142         dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1143         src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1144         dst_stride = dst->stride / 2;
1145         src_stride = src->stride / 2;
1146     }
1147
1148     if (rop2 == R2_COPYPEN)
1149     {
1150         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1151             memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1152         return;
1153     }
1154
1155     get_rop_codes( rop2, &codes );
1156     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1157     {
1158         if (overlap & OVERLAP_RIGHT)
1159             do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1160         else
1161             do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1162     }
1163 }
1164
1165 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1166                         const dib_info *src, const POINT *origin, int rop2, int overlap)
1167 {
1168     BYTE *dst_start, *src_start;
1169     int y, dst_stride, src_stride;
1170     struct rop_codes codes;
1171
1172     if (overlap & OVERLAP_BELOW)
1173     {
1174         dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1175         src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1176         dst_stride = -dst->stride;
1177         src_stride = -src->stride;
1178     }
1179     else
1180     {
1181         dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1182         src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1183         dst_stride = dst->stride;
1184         src_stride = src->stride;
1185     }
1186
1187     if (rop2 == R2_COPYPEN)
1188     {
1189         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1190             memmove( dst_start, src_start, (rc->right - rc->left) );
1191         return;
1192     }
1193
1194     get_rop_codes( rop2, &codes );
1195     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1196     {
1197         if (overlap & OVERLAP_RIGHT)
1198             do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1199         else
1200             do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1201     }
1202 }
1203
1204 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1205                         const dib_info *src, const POINT *origin, int rop2, int overlap)
1206 {
1207     BYTE *dst_start, *src_start;
1208     int y, dst_stride, src_stride;
1209     struct rop_codes codes;
1210     int left = dst->rect.left + rc->left;
1211     int right = dst->rect.left + rc->right;
1212     int org_x = src->rect.left + origin->x;
1213
1214     if (overlap & OVERLAP_BELOW)
1215     {
1216         dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1217         src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1218         dst_stride = -dst->stride;
1219         src_stride = -src->stride;
1220     }
1221     else
1222     {
1223         dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1224         src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1225         dst_stride = dst->stride;
1226         src_stride = src->stride;
1227     }
1228
1229     if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1230     {
1231         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1232             memmove( dst_start, src_start, (right - left) / 2 );
1233         return;
1234     }
1235
1236     get_rop_codes( rop2, &codes );
1237     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1238     {
1239         if (overlap & OVERLAP_RIGHT)
1240             do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1241         else
1242             do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1243     }
1244 }
1245
1246 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1247                         const dib_info *src, const POINT *origin, int rop2, int overlap)
1248 {
1249     BYTE *dst_start, *src_start;
1250     int y, dst_stride, src_stride;
1251     struct rop_codes codes;
1252     int left = dst->rect.left + rc->left;
1253     int right = dst->rect.left + rc->right;
1254     int org_x = src->rect.left + origin->x;
1255
1256     if (overlap & OVERLAP_BELOW)
1257     {
1258         dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1259         src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1260         dst_stride = -dst->stride;
1261         src_stride = -src->stride;
1262     }
1263     else
1264     {
1265         dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1266         src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1267         dst_stride = dst->stride;
1268         src_stride = src->stride;
1269     }
1270
1271     if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1272     {
1273         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1274             memmove( dst_start, src_start, (right - left) / 8 );
1275         return;
1276     }
1277
1278     get_rop_codes( rop2, &codes );
1279     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1280     {
1281         if (overlap & OVERLAP_RIGHT)
1282             do_rop_codes_line_rev_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1283         else
1284             do_rop_codes_line_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1285     }
1286 }
1287
1288 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1289                            const dib_info *src, const POINT *origin, int rop2, int overlap)
1290 {
1291     return;
1292 }
1293
1294 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
1295 {
1296     DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1297     return *ptr;
1298 }
1299
1300 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1301 {
1302     BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1303     return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1304 }
1305
1306 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1307 {
1308     WORD *ptr = get_pixel_ptr_16( dib, x, y );
1309     return *ptr;
1310 }
1311
1312 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1313 {
1314     BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1315     return *ptr;
1316 }
1317
1318 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1319 {
1320     BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1321
1322     if ((dib->rect.left + x) & 1)
1323         return *ptr & 0x0f;
1324     else
1325         return (*ptr >> 4) & 0x0f;
1326 }
1327
1328 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1329 {
1330     BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1331     return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
1332 }
1333
1334 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
1335 {
1336     return 0;
1337 }
1338
1339 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1340 {
1341     return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1342 }
1343
1344 static const DWORD field_masks[33] =
1345 {
1346     0x00,  /* should never happen */
1347     0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1348     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1349     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1350     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1351 };
1352
1353 static inline DWORD get_field(DWORD field, int shift, int len)
1354 {
1355     shift = shift - (8 - len);
1356     if (shift < 0)
1357         field <<= -shift;
1358     else
1359         field >>= shift;
1360     field &= field_masks[len];
1361     field |= field >> len;
1362     return field;
1363 }
1364
1365 static inline DWORD put_field(DWORD field, int shift, int len)
1366 {
1367     shift = shift - (8 - len);
1368     field &= field_masks[len];
1369     if (shift < 0)
1370         field >>= -shift;
1371     else
1372         field <<= shift;
1373     return field;
1374 }
1375
1376 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1377 {
1378     DWORD r,g,b;
1379
1380     r = GetRValue(colour);
1381     g = GetGValue(colour);
1382     b = GetBValue(colour);
1383
1384     return put_field(r, dib->red_shift,   dib->red_len) |
1385            put_field(g, dib->green_shift, dib->green_len) |
1386            put_field(b, dib->blue_shift,  dib->blue_len);
1387 }
1388
1389 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1390 {
1391     return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1392 }
1393
1394 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1395 {
1396     int i, best_index = 0;
1397     DWORD diff, best_diff = 0xffffffff;
1398
1399     /* special case for conversion to 1-bpp without a color table:
1400      * we get a 1-entry table containing the background color
1401      */
1402     if (dib->bit_count == 1 && dib->color_table_size == 1)
1403         return (r == dib->color_table[0].rgbRed &&
1404                 g == dib->color_table[0].rgbGreen &&
1405                 b == dib->color_table[0].rgbBlue);
1406
1407     for(i = 0; i < dib->color_table_size; i++)
1408     {
1409         const RGBQUAD *cur = dib->color_table + i;
1410         diff = (r - cur->rgbRed)   * (r - cur->rgbRed)
1411             +  (g - cur->rgbGreen) * (g - cur->rgbGreen)
1412             +  (b - cur->rgbBlue)  * (b - cur->rgbBlue);
1413
1414         if(diff == 0)
1415         {
1416             best_index = i;
1417             break;
1418         }
1419
1420         if(diff < best_diff)
1421         {
1422             best_diff = diff;
1423             best_index = i;
1424         }
1425     }
1426     return best_index;
1427 }
1428
1429 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1430 {
1431     return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1432 }
1433
1434 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1435 {
1436     return 0;
1437 }
1438
1439 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1440 {
1441     return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1442 }
1443
1444 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1445 {
1446     return RGB( get_field( pixel, dib->red_shift,   dib->red_len ),
1447                 get_field( pixel, dib->green_shift, dib->green_len ),
1448                 get_field( pixel, dib->blue_shift,  dib->blue_len ) );
1449 }
1450
1451 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1452 {
1453     return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1454                 ((pixel >> 2) & 0xf8) | ((pixel >>  7) & 0x07),
1455                 ((pixel << 3) & 0xf8) | ((pixel >>  2) & 0x07) );
1456 }
1457
1458 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1459 {
1460     if (pixel < dib->color_table_size)
1461     {
1462         RGBQUAD quad = dib->color_table[pixel];
1463         return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1464     }
1465     return 0;
1466 }
1467
1468 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1469 {
1470     return 0;
1471 }
1472
1473 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1474 {
1475     assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1476
1477     return d1->red_mask   == d2->red_mask &&
1478            d1->green_mask == d2->green_mask &&
1479            d1->blue_mask  == d2->blue_mask;
1480 }
1481
1482 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1483 {
1484     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1485     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1486
1487     switch(src->bit_count)
1488     {
1489     case 32:
1490     {
1491         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1492         if(src->funcs == &funcs_8888)
1493         {
1494             if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1495                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1496             else
1497             {
1498                 for(y = src_rect->top; y < src_rect->bottom; y++)
1499                 {
1500                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1501                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1502                     dst_start += dst->stride / 4;
1503                     src_start += src->stride / 4;
1504                 }
1505             }
1506         }
1507         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1508         {
1509             for(y = src_rect->top; y < src_rect->bottom; y++)
1510             {
1511                 dst_pixel = dst_start;
1512                 src_pixel = src_start;
1513                 for(x = src_rect->left; x < src_rect->right; x++)
1514                 {
1515                     src_val = *src_pixel++;
1516                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << 16) |
1517                                    (((src_val >> src->green_shift) & 0xff) <<  8) |
1518                                     ((src_val >> src->blue_shift)  & 0xff);
1519                 }
1520                 if(pad_size) memset(dst_pixel, 0, pad_size);
1521                 dst_start += dst->stride / 4;
1522                 src_start += src->stride / 4;
1523             }
1524         }
1525         else
1526         {
1527             for(y = src_rect->top; y < src_rect->bottom; y++)
1528             {
1529                 dst_pixel = dst_start;
1530                 src_pixel = src_start;
1531                 for(x = src_rect->left; x < src_rect->right; x++)
1532                 {
1533                     src_val = *src_pixel++;
1534                     *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1535                                     get_field( src_val, src->green_shift, src->green_len ) << 8 |
1536                                     get_field( src_val, src->blue_shift, src->blue_len ));
1537                 }
1538                 if(pad_size) memset(dst_pixel, 0, pad_size);
1539                 dst_start += dst->stride / 4;
1540                 src_start += src->stride / 4;
1541             }
1542         }
1543         break;
1544     }
1545
1546     case 24:
1547     {
1548         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1549
1550         for(y = src_rect->top; y < src_rect->bottom; y++)
1551         {
1552             dst_pixel = dst_start;
1553             src_pixel = src_start;
1554             for(x = src_rect->left; x < src_rect->right; x++)
1555             {
1556                 RGBQUAD rgb;
1557                 rgb.rgbBlue  = *src_pixel++;
1558                 rgb.rgbGreen = *src_pixel++;
1559                 rgb.rgbRed   = *src_pixel++;
1560
1561                 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1562             }
1563             if(pad_size) memset(dst_pixel, 0, pad_size);
1564             dst_start += dst->stride / 4;
1565             src_start += src->stride;
1566         }
1567         break;
1568     }
1569
1570     case 16:
1571     {
1572         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1573         if(src->funcs == &funcs_555)
1574         {
1575             for(y = src_rect->top; y < src_rect->bottom; y++)
1576             {
1577                 dst_pixel = dst_start;
1578                 src_pixel = src_start;
1579                 for(x = src_rect->left; x < src_rect->right; x++)
1580                 {
1581                     src_val = *src_pixel++;
1582                     *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1583                                    ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1584                                    ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1585                 }
1586                 if(pad_size) memset(dst_pixel, 0, pad_size);
1587                 dst_start += dst->stride / 4;
1588                 src_start += src->stride / 2;
1589             }
1590         }
1591         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1592         {
1593             for(y = src_rect->top; y < src_rect->bottom; y++)
1594             {
1595                 dst_pixel = dst_start;
1596                 src_pixel = src_start;
1597                 for(x = src_rect->left; x < src_rect->right; x++)
1598                 {
1599                     src_val = *src_pixel++;
1600                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1601                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1602                                    (((src_val >> src->green_shift) << 11) & 0x00f800) |
1603                                    (((src_val >> src->green_shift) <<  6) & 0x000700) |
1604                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1605                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1606                 }
1607                 if(pad_size) memset(dst_pixel, 0, pad_size);
1608                 dst_start += dst->stride / 4;
1609                 src_start += src->stride / 2;
1610             }
1611         }
1612         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1613         {
1614             for(y = src_rect->top; y < src_rect->bottom; y++)
1615             {
1616                 dst_pixel = dst_start;
1617                 src_pixel = src_start;
1618                 for(x = src_rect->left; x < src_rect->right; x++)
1619                 {
1620                     src_val = *src_pixel++;
1621                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1622                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1623                                    (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1624                                    (((src_val >> src->green_shift) <<  4) & 0x000300) |
1625                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1626                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1627                 }
1628                 if(pad_size) memset(dst_pixel, 0, pad_size);
1629                 dst_start += dst->stride / 4;
1630                 src_start += src->stride / 2;
1631             }
1632         }
1633         else
1634         {
1635             for(y = src_rect->top; y < src_rect->bottom; y++)
1636             {
1637                 dst_pixel = dst_start;
1638                 src_pixel = src_start;
1639                 for(x = src_rect->left; x < src_rect->right; x++)
1640                 {
1641                     src_val = *src_pixel++;
1642                     *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1643                                     get_field( src_val, src->green_shift, src->green_len ) << 8 |
1644                                     get_field( src_val, src->blue_shift, src->blue_len ));
1645                 }
1646                 if(pad_size) memset(dst_pixel, 0, pad_size);
1647                 dst_start += dst->stride / 4;
1648                 src_start += src->stride / 2;
1649             }
1650         }
1651         break;
1652     }
1653
1654     case 8:
1655     {
1656         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1657         for(y = src_rect->top; y < src_rect->bottom; y++)
1658         {
1659             dst_pixel = dst_start;
1660             src_pixel = src_start;
1661             for(x = src_rect->left; x < src_rect->right; x++)
1662             {
1663                 RGBQUAD rgb = src->color_table[*src_pixel++];
1664                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1665             }
1666             if(pad_size) memset(dst_pixel, 0, pad_size);
1667             dst_start += dst->stride / 4;
1668             src_start += src->stride;
1669         }
1670         break;
1671     }
1672
1673     case 4:
1674     {
1675         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1676         for(y = src_rect->top; y < src_rect->bottom; y++)
1677         {
1678             int pos = (src->rect.left + src_rect->left) & 1;
1679             src_pixel = src_start;
1680             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1681             {
1682                 RGBQUAD rgb;
1683                 if (pos & 1)
1684                     rgb = src->color_table[*src_pixel++ & 0xf];
1685                 else
1686                     rgb = src->color_table[*src_pixel >> 4];
1687                 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1688             }
1689             if(pad_size) memset(dst_start + x, 0, pad_size);
1690             dst_start += dst->stride / 4;
1691             src_start += src->stride;
1692         }
1693         break;
1694     }
1695
1696     case 1:
1697     {
1698         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1699         for(y = src_rect->top; y < src_rect->bottom; y++)
1700         {
1701             int pos = (src->rect.left + src_rect->left) & 7;
1702             for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1703             {
1704                 RGBQUAD rgb;
1705                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1706                 rgb = src->color_table[src_val];
1707                 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1708             }
1709             if(pad_size) memset(dst_start + x, 0, pad_size);
1710             dst_start += dst->stride / 4;
1711             src_start += src->stride;
1712         }
1713         break;
1714     }
1715     }
1716 }
1717
1718 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1719 {
1720     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1721     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1722
1723     switch(src->bit_count)
1724     {
1725     case 32:
1726     {
1727         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1728
1729         if(src->funcs == &funcs_8888)
1730         {
1731             for(y = src_rect->top; y < src_rect->bottom; y++)
1732             {
1733                 dst_pixel = dst_start;
1734                 src_pixel = src_start;
1735                 for(x = src_rect->left; x < src_rect->right; x++)
1736                 {
1737                     src_val = *src_pixel++;
1738                     *dst_pixel++ = put_field(src_val >> 16, dst->red_shift,   dst->red_len)   |
1739                                    put_field(src_val >>  8, dst->green_shift, dst->green_len) |
1740                                    put_field(src_val,       dst->blue_shift,  dst->blue_len);
1741                 }
1742                 if(pad_size) memset(dst_pixel, 0, pad_size);
1743                 dst_start += dst->stride / 4;
1744                 src_start += src->stride / 4;
1745             }
1746         }
1747         else if(bit_fields_match(src, dst))
1748         {
1749             if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1750                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1751             else
1752             {
1753                 for(y = src_rect->top; y < src_rect->bottom; y++)
1754                 {
1755                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1756                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1757                     dst_start += dst->stride / 4;
1758                     src_start += src->stride / 4;
1759                 }
1760             }
1761         }
1762         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1763                 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1764         {
1765             for(y = src_rect->top; y < src_rect->bottom; y++)
1766             {
1767                 dst_pixel = dst_start;
1768                 src_pixel = src_start;
1769                 for(x = src_rect->left; x < src_rect->right; x++)
1770                 {
1771                     src_val = *src_pixel++;
1772                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << dst->red_shift)   |
1773                                    (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1774                                    (((src_val >> src->blue_shift)  & 0xff) << dst->blue_shift);
1775                 }
1776                 if(pad_size) memset(dst_pixel, 0, pad_size);
1777                 dst_start += dst->stride / 4;
1778                 src_start += src->stride / 4;
1779             }
1780         }
1781         else
1782         {
1783             for(y = src_rect->top; y < src_rect->bottom; y++)
1784             {
1785                 dst_pixel = dst_start;
1786                 src_pixel = src_start;
1787                 for(x = src_rect->left; x < src_rect->right; x++)
1788                 {
1789                     src_val = *src_pixel++;
1790                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
1791                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1792                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
1793                 }
1794                 if(pad_size) memset(dst_pixel, 0, pad_size);
1795                 dst_start += dst->stride / 4;
1796                 src_start += src->stride / 4;
1797             }
1798         }
1799         break;
1800     }
1801
1802     case 24:
1803     {
1804         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1805
1806         for(y = src_rect->top; y < src_rect->bottom; y++)
1807         {
1808             dst_pixel = dst_start;
1809             src_pixel = src_start;
1810             for(x = src_rect->left; x < src_rect->right; x++)
1811             {
1812                 RGBQUAD rgb;
1813                 rgb.rgbBlue  = *src_pixel++;
1814                 rgb.rgbGreen = *src_pixel++;
1815                 rgb.rgbRed   = *src_pixel++;
1816
1817                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len)   |
1818                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1819                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1820             }
1821             if(pad_size) memset(dst_pixel, 0, pad_size);
1822             dst_start += dst->stride / 4;
1823             src_start += src->stride;
1824         }
1825         break;
1826     }
1827
1828     case 16:
1829     {
1830         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1831         if(src->funcs == &funcs_555)
1832         {
1833             for(y = src_rect->top; y < src_rect->bottom; y++)
1834             {
1835                 dst_pixel = dst_start;
1836                 src_pixel = src_start;
1837                 for(x = src_rect->left; x < src_rect->right; x++)
1838                 {
1839                     src_val = *src_pixel++;
1840                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
1841                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
1842                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
1843                 }
1844                 if(pad_size) memset(dst_pixel, 0, pad_size);
1845                 dst_start += dst->stride / 4;
1846                 src_start += src->stride / 2;
1847             }
1848         }
1849         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1850         {
1851             for(y = src_rect->top; y < src_rect->bottom; y++)
1852             {
1853                 dst_pixel = dst_start;
1854                 src_pixel = src_start;
1855                 for(x = src_rect->left; x < src_rect->right; x++)
1856                 {
1857                     src_val = *src_pixel++;
1858                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1859                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1860                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1861                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1862                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1863                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1864                 }
1865                 if(pad_size) memset(dst_pixel, 0, pad_size);
1866                 dst_start += dst->stride / 4;
1867                 src_start += src->stride / 2;
1868             }
1869         }
1870         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1871         {
1872             for(y = src_rect->top; y < src_rect->bottom; y++)
1873             {
1874                 dst_pixel = dst_start;
1875                 src_pixel = src_start;
1876                 for(x = src_rect->left; x < src_rect->right; x++)
1877                 {
1878                     src_val = *src_pixel++;
1879                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1880                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1881                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1882                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1883                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1884                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1885                 }
1886                 if(pad_size) memset(dst_pixel, 0, pad_size);
1887                 dst_start += dst->stride / 4;
1888                 src_start += src->stride / 2;
1889             }
1890         }
1891         else
1892         {
1893             for(y = src_rect->top; y < src_rect->bottom; y++)
1894             {
1895                 dst_pixel = dst_start;
1896                 src_pixel = src_start;
1897                 for(x = src_rect->left; x < src_rect->right; x++)
1898                 {
1899                     src_val = *src_pixel++;
1900                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
1901                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1902                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
1903                 }
1904                 if(pad_size) memset(dst_pixel, 0, pad_size);
1905                 dst_start += dst->stride / 4;
1906                 src_start += src->stride / 2;
1907             }
1908         }
1909         break;
1910     }
1911
1912     case 8:
1913     {
1914         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1915         for(y = src_rect->top; y < src_rect->bottom; y++)
1916         {
1917             dst_pixel = dst_start;
1918             src_pixel = src_start;
1919             for(x = src_rect->left; x < src_rect->right; x++)
1920             {
1921                 RGBQUAD rgb = src->color_table[*src_pixel++];
1922                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1923                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1924                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1925             }
1926             if(pad_size) memset(dst_pixel, 0, pad_size);
1927             dst_start += dst->stride / 4;
1928             src_start += src->stride;
1929         }
1930         break;
1931     }
1932
1933     case 4:
1934     {
1935         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1936         for(y = src_rect->top; y < src_rect->bottom; y++)
1937         {
1938             int pos = (src->rect.left + src_rect->left) & 1;
1939             src_pixel = src_start;
1940             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1941             {
1942                 RGBQUAD rgb;
1943                 if (pos & 1)
1944                     rgb = src->color_table[*src_pixel++ & 0xf];
1945                 else
1946                     rgb = src->color_table[*src_pixel >> 4];
1947                 dst_start[x] = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1948                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1949                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1950             }
1951             if(pad_size) memset(dst_start + x, 0, pad_size);
1952             dst_start += dst->stride / 4;
1953             src_start += src->stride;
1954         }
1955         break;
1956     }
1957
1958     case 1:
1959     {
1960         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1961         for(y = src_rect->top; y < src_rect->bottom; y++)
1962         {
1963             int pos = (src->rect.left + src_rect->left) & 7;
1964             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1965             {
1966                 RGBQUAD rgb;
1967                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1968                 rgb = src->color_table[src_val];
1969                 dst_start[x] = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1970                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1971                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1972             }
1973             if(pad_size) memset(dst_start + x, 0, pad_size);
1974             dst_start += dst->stride / 4;
1975             src_start += src->stride;
1976         }
1977         break;
1978     }
1979     }
1980 }
1981
1982 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1983 {
1984     BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1985     DWORD src_val;
1986     int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1987
1988     switch(src->bit_count)
1989     {
1990     case 32:
1991     {
1992         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1993         if(src->funcs == &funcs_8888)
1994         {
1995             for(y = src_rect->top; y < src_rect->bottom; y++)
1996             {
1997                 dst_pixel = dst_start;
1998                 src_pixel = src_start;
1999                 for(x = src_rect->left; x < src_rect->right; x++)
2000                 {
2001                     src_val = *src_pixel++;
2002                     *dst_pixel++ =  src_val        & 0xff;
2003                     *dst_pixel++ = (src_val >>  8) & 0xff;
2004                     *dst_pixel++ = (src_val >> 16) & 0xff;
2005                 }
2006                 if(pad_size) memset(dst_pixel, 0, pad_size);
2007                 dst_start += dst->stride;
2008                 src_start += src->stride / 4;
2009             }
2010         }
2011         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2012         {
2013             for(y = src_rect->top; y < src_rect->bottom; y++)
2014             {
2015                 dst_pixel = dst_start;
2016                 src_pixel = src_start;
2017                 for(x = src_rect->left; x < src_rect->right; x++)
2018                 {
2019                     src_val = *src_pixel++;
2020                     *dst_pixel++ = (src_val >> src->blue_shift)  & 0xff;
2021                     *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2022                     *dst_pixel++ = (src_val >> src->red_shift)   & 0xff;
2023                 }
2024                 if(pad_size) memset(dst_pixel, 0, pad_size);
2025                 dst_start += dst->stride;
2026                 src_start += src->stride / 4;
2027             }
2028         }
2029         else
2030         {
2031             for(y = src_rect->top; y < src_rect->bottom; y++)
2032             {
2033                 dst_pixel = dst_start;
2034                 src_pixel = src_start;
2035                 for(x = src_rect->left; x < src_rect->right; x++)
2036                 {
2037                     src_val = *src_pixel++;
2038                     *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2039                     *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2040                     *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2041                 }
2042                 if(pad_size) memset(dst_pixel, 0, pad_size);
2043                 dst_start += dst->stride;
2044                 src_start += src->stride / 4;
2045             }
2046         }
2047         break;
2048     }
2049
2050     case 24:
2051     {
2052         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2053
2054         if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2055             memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2056         else
2057         {
2058             for(y = src_rect->top; y < src_rect->bottom; y++)
2059             {
2060                 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2061                 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2062                 dst_start += dst->stride;
2063                 src_start += src->stride;
2064             }
2065         }
2066         break;
2067     }
2068
2069     case 16:
2070     {
2071         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2072         if(src->funcs == &funcs_555)
2073         {
2074             for(y = src_rect->top; y < src_rect->bottom; y++)
2075             {
2076                 dst_pixel = dst_start;
2077                 src_pixel = src_start;
2078                 for(x = src_rect->left; x < src_rect->right; x++)
2079                 {
2080                     src_val = *src_pixel++;
2081                     *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07);
2082                     *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07);
2083                     *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2084                 }
2085                 if(pad_size) memset(dst_pixel, 0, pad_size);
2086                 dst_start += dst->stride;
2087                 src_start += src->stride / 2;
2088             }
2089         }
2090         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2091         {
2092             for(y = src_rect->top; y < src_rect->bottom; y++)
2093             {
2094                 dst_pixel = dst_start;
2095                 src_pixel = src_start;
2096                 for(x = src_rect->left; x < src_rect->right; x++)
2097                 {
2098                     src_val = *src_pixel++;
2099                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2100                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
2101                     *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2102                                    (((src_val >> src->green_shift) >> 2) & 0x07);
2103                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
2104                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
2105                 }
2106                 if(pad_size) memset(dst_pixel, 0, pad_size);
2107                 dst_start += dst->stride;
2108                 src_start += src->stride / 2;
2109             }
2110         }
2111         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2112         {
2113             for(y = src_rect->top; y < src_rect->bottom; y++)
2114             {
2115                 dst_pixel = dst_start;
2116                 src_pixel = src_start;
2117                 for(x = src_rect->left; x < src_rect->right; x++)
2118                 {
2119                     src_val = *src_pixel++;
2120                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2121                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
2122                     *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2123                                    (((src_val >> src->green_shift) >> 4) & 0x03);
2124                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
2125                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
2126                 }
2127                 if(pad_size) memset(dst_pixel, 0, pad_size);
2128                 dst_start += dst->stride;
2129                 src_start += src->stride / 2;
2130             }
2131         }
2132         else
2133         {
2134             for(y = src_rect->top; y < src_rect->bottom; y++)
2135             {
2136                 dst_pixel = dst_start;
2137                 src_pixel = src_start;
2138                 for(x = src_rect->left; x < src_rect->right; x++)
2139                 {
2140                     src_val = *src_pixel++;
2141                     *dst_pixel++ = get_field(src_val, src->blue_shift,  src->blue_len );
2142                     *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2143                     *dst_pixel++ = get_field(src_val, src->red_shift,   src->red_len );
2144                 }
2145                 if(pad_size) memset(dst_pixel, 0, pad_size);
2146                 dst_start += dst->stride;
2147                 src_start += src->stride / 2;
2148             }
2149         }
2150         break;
2151     }
2152
2153     case 8:
2154     {
2155         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2156         for(y = src_rect->top; y < src_rect->bottom; y++)
2157         {
2158             dst_pixel = dst_start;
2159             src_pixel = src_start;
2160             for(x = src_rect->left; x < src_rect->right; x++)
2161             {
2162                 RGBQUAD rgb = src->color_table[*src_pixel++];
2163                 *dst_pixel++ = rgb.rgbBlue;
2164                 *dst_pixel++ = rgb.rgbGreen;
2165                 *dst_pixel++ = rgb.rgbRed;
2166             }
2167             if(pad_size) memset(dst_pixel, 0, pad_size);
2168             dst_start += dst->stride;
2169             src_start += src->stride;
2170         }
2171         break;
2172     }
2173
2174     case 4:
2175     {
2176         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2177         for(y = src_rect->top; y < src_rect->bottom; y++)
2178         {
2179             int pos = (src->rect.left + src_rect->left) & 1;
2180             src_pixel = src_start;
2181             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2182             {
2183                 RGBQUAD rgb;
2184                 if (pos & 1)
2185                     rgb = src->color_table[*src_pixel++ & 0xf];
2186                 else
2187                     rgb = src->color_table[*src_pixel >> 4];
2188                 dst_start[x * 3] = rgb.rgbBlue;
2189                 dst_start[x * 3 + 1] = rgb.rgbGreen;
2190                 dst_start[x * 3 + 2] = rgb.rgbRed;
2191             }
2192             if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2193             dst_start += dst->stride;
2194             src_start += src->stride;
2195         }
2196         break;
2197     }
2198
2199     case 1:
2200     {
2201         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2202         for(y = src_rect->top; y < src_rect->bottom; y++)
2203         {
2204             int pos = (src->rect.left + src_rect->left) & 7;
2205             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2206             {
2207                 RGBQUAD rgb;
2208                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2209                 rgb = src->color_table[src_val];
2210                 dst_start[x * 3] = rgb.rgbBlue;
2211                 dst_start[x * 3 + 1] = rgb.rgbGreen;
2212                 dst_start[x * 3 + 2] = rgb.rgbRed;
2213             }
2214             if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2215             dst_start += dst->stride;
2216             src_start += src->stride;
2217         }
2218         break;
2219     }
2220     }
2221 }
2222
2223 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
2224 {
2225     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2226     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2227     DWORD src_val;
2228
2229     switch(src->bit_count)
2230     {
2231     case 32:
2232     {
2233         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2234
2235         if(src->funcs == &funcs_8888)
2236         {
2237             for(y = src_rect->top; y < src_rect->bottom; y++)
2238             {
2239                 dst_pixel = dst_start;
2240                 src_pixel = src_start;
2241                 for(x = src_rect->left; x < src_rect->right; x++)
2242                 {
2243                     src_val = *src_pixel++;
2244                     *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2245                                    ((src_val >> 6) & 0x03e0) |
2246                                    ((src_val >> 3) & 0x001f);
2247                 }
2248                 if(pad_size) memset(dst_pixel, 0, pad_size);
2249                 dst_start += dst->stride / 2;
2250                 src_start += src->stride / 4;
2251             }
2252         }
2253         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2254         {
2255             for(y = src_rect->top; y < src_rect->bottom; y++)
2256             {
2257                 dst_pixel = dst_start;
2258                 src_pixel = src_start;
2259                 for(x = src_rect->left; x < src_rect->right; x++)
2260                 {
2261                     src_val = *src_pixel++;
2262                     *dst_pixel++ = (((src_val >> src->red_shift)   << 7) & 0x7c00) |
2263                                    (((src_val >> src->green_shift) << 2) & 0x03e0) |
2264                                    (((src_val >> src->blue_shift)  >> 3) & 0x001f);
2265                 }
2266                 if(pad_size) memset(dst_pixel, 0, pad_size);
2267                 dst_start += dst->stride / 2;
2268                 src_start += src->stride / 4;
2269             }
2270         }
2271         else
2272         {
2273             for(y = src_rect->top; y < src_rect->bottom; y++)
2274             {
2275                 dst_pixel = dst_start;
2276                 src_pixel = src_start;
2277                 for(x = src_rect->left; x < src_rect->right; x++)
2278                 {
2279                     src_val = *src_pixel++;
2280                     *dst_pixel++ = (((get_field(src_val, src->red_shift,   src->red_len )   << 7) & 0x7c00) |
2281                                     ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2282                                     ( get_field(src_val, src->blue_shift,  src->blue_len )  >> 3));
2283                 }
2284                 if(pad_size) memset(dst_pixel, 0, pad_size);
2285                 dst_start += dst->stride / 2;
2286                 src_start += src->stride / 4;
2287             }
2288         }
2289         break;
2290     }
2291
2292     case 24:
2293     {
2294         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2295
2296         for(y = src_rect->top; y < src_rect->bottom; y++)
2297         {
2298             dst_pixel = dst_start;
2299             src_pixel = src_start;
2300             for(x = src_rect->left; x < src_rect->right; x++)
2301             {
2302                 RGBQUAD rgb;
2303                 rgb.rgbBlue  = *src_pixel++;
2304                 rgb.rgbGreen = *src_pixel++;
2305                 rgb.rgbRed   = *src_pixel++;
2306
2307                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2308                                ((rgb.rgbGreen << 2) & 0x03e0) |
2309                                ((rgb.rgbBlue  >> 3) & 0x001f);
2310             }
2311             if(pad_size) memset(dst_pixel, 0, pad_size);
2312             dst_start += dst->stride / 2;
2313             src_start += src->stride;
2314         }
2315         break;
2316     }
2317
2318     case 16:
2319     {
2320         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2321         if(src->funcs == &funcs_555)
2322         {
2323             if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2324                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2325             else
2326             {
2327                 for(y = src_rect->top; y < src_rect->bottom; y++)
2328                 {
2329                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2330                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2331                     dst_start += dst->stride / 2;
2332                     src_start += src->stride / 2;
2333                 }
2334             }
2335         }
2336         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2337         {
2338             for(y = src_rect->top; y < src_rect->bottom; y++)
2339             {
2340                 dst_pixel = dst_start;
2341                 src_pixel = src_start;
2342                 for(x = src_rect->left; x < src_rect->right; x++)
2343                 {
2344                     src_val = *src_pixel++;
2345                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2346                                    (((src_val >> src->green_shift) <<  5) & 0x03e0) |
2347                                    ( (src_val >> src->blue_shift)         & 0x001f);
2348                 }
2349                 if(pad_size) memset(dst_pixel, 0, pad_size);
2350                 dst_start += dst->stride / 2;
2351                 src_start += src->stride / 2;
2352             }
2353         }
2354         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2355         {
2356             for(y = src_rect->top; y < src_rect->bottom; y++)
2357             {
2358                 dst_pixel = dst_start;
2359                 src_pixel = src_start;
2360                 for(x = src_rect->left; x < src_rect->right; x++)
2361                 {
2362                     src_val = *src_pixel++;
2363                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2364                                    (((src_val >> src->green_shift) <<  4) & 0x03e0) |
2365                                    ( (src_val >> src->blue_shift)         & 0x001f);
2366                 }
2367                 if(pad_size) memset(dst_pixel, 0, pad_size);
2368                 dst_start += dst->stride / 2;
2369                 src_start += src->stride / 2;
2370             }
2371         }
2372         else
2373         {
2374             for(y = src_rect->top; y < src_rect->bottom; y++)
2375             {
2376                 dst_pixel = dst_start;
2377                 src_pixel = src_start;
2378                 for(x = src_rect->left; x < src_rect->right; x++)
2379                 {
2380                     src_val = *src_pixel++;
2381                     *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len)     << 7) & 0x7c00) |
2382                                     ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2383                                     ( get_field(src_val, src->blue_shift, src->blue_len)   >> 3));
2384                 }
2385                 if(pad_size) memset(dst_pixel, 0, pad_size);
2386                 dst_start += dst->stride / 2;
2387                 src_start += src->stride / 2;
2388             }
2389         }
2390         break;
2391     }
2392
2393     case 8:
2394     {
2395         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2396         for(y = src_rect->top; y < src_rect->bottom; y++)
2397         {
2398             dst_pixel = dst_start;
2399             src_pixel = src_start;
2400             for(x = src_rect->left; x < src_rect->right; x++)
2401             {
2402                 RGBQUAD rgb = src->color_table[*src_pixel++];
2403                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2404                                ((rgb.rgbGreen << 2) & 0x03e0) |
2405                                ((rgb.rgbBlue  >> 3) & 0x001f);
2406             }
2407             if(pad_size) memset(dst_pixel, 0, pad_size);
2408             dst_start += dst->stride / 2;
2409             src_start += src->stride;
2410         }
2411         break;
2412     }
2413
2414     case 4:
2415     {
2416         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2417         for(y = src_rect->top; y < src_rect->bottom; y++)
2418         {
2419             int pos = (src->rect.left + src_rect->left) & 1;
2420             src_pixel = src_start;
2421             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2422             {
2423                 RGBQUAD rgb;
2424                 if (pos & 1)
2425                     rgb = src->color_table[*src_pixel++ & 0xf];
2426                 else
2427                     rgb = src->color_table[*src_pixel >> 4];
2428                 dst_start[x] = ((rgb.rgbRed   << 7) & 0x7c00) |
2429                                ((rgb.rgbGreen << 2) & 0x03e0) |
2430                                ((rgb.rgbBlue  >> 3) & 0x001f);
2431             }
2432             if(pad_size) memset(dst_start + x, 0, pad_size);
2433             dst_start += dst->stride / 2;
2434             src_start += src->stride;
2435         }
2436         break;
2437     }
2438
2439     case 1:
2440     {
2441         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2442         for(y = src_rect->top; y < src_rect->bottom; y++)
2443         {
2444             int pos = (src->rect.left + src_rect->left) & 7;
2445             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2446             {
2447                 RGBQUAD rgb;
2448                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2449                 rgb = src->color_table[src_val];
2450                 dst_start[x] = ((rgb.rgbRed   << 7) & 0x7c00) |
2451                                ((rgb.rgbGreen << 2) & 0x03e0) |
2452                                ((rgb.rgbBlue  >> 3) & 0x001f);
2453             }
2454             if(pad_size) memset(dst_start + x, 0, pad_size);
2455             dst_start += dst->stride / 2;
2456             src_start += src->stride;
2457         }
2458         break;
2459     }
2460     }
2461 }
2462
2463 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2464 {
2465     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2466     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2467     DWORD src_val;
2468
2469     switch(src->bit_count)
2470     {
2471     case 32:
2472     {
2473         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2474
2475         if(src->funcs == &funcs_8888)
2476         {
2477             for(y = src_rect->top; y < src_rect->bottom; y++)
2478             {
2479                 dst_pixel = dst_start;
2480                 src_pixel = src_start;
2481                 for(x = src_rect->left; x < src_rect->right; x++)
2482                 {
2483                     src_val = *src_pixel++;
2484                     *dst_pixel++ = put_field(src_val >> 16, dst->red_shift,   dst->red_len)   |
2485                                    put_field(src_val >>  8, dst->green_shift, dst->green_len) |
2486                                    put_field(src_val,       dst->blue_shift,  dst->blue_len);
2487                 }
2488                 if(pad_size) memset(dst_pixel, 0, pad_size);
2489                 dst_start += dst->stride / 2;
2490                 src_start += src->stride / 4;
2491             }
2492         }
2493         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2494         {
2495             for(y = src_rect->top; y < src_rect->bottom; y++)
2496             {
2497                 dst_pixel = dst_start;
2498                 src_pixel = src_start;
2499                 for(x = src_rect->left; x < src_rect->right; x++)
2500                 {
2501                     src_val = *src_pixel++;
2502                     *dst_pixel++ = put_field(src_val >> src->red_shift,   dst->red_shift,   dst->red_len)   |
2503                                    put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2504                                    put_field(src_val >> src->blue_shift,  dst->blue_shift,  dst->blue_len);
2505                 }
2506                 if(pad_size) memset(dst_pixel, 0, pad_size);
2507                 dst_start += dst->stride / 2;
2508                 src_start += src->stride / 4;
2509             }
2510         }
2511         else
2512         {
2513             for(y = src_rect->top; y < src_rect->bottom; y++)
2514             {
2515                 dst_pixel = dst_start;
2516                 src_pixel = src_start;
2517                 for(x = src_rect->left; x < src_rect->right; x++)
2518                 {
2519                     src_val = *src_pixel++;
2520                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
2521                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2522                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
2523                 }
2524                 if(pad_size) memset(dst_pixel, 0, pad_size);
2525                 dst_start += dst->stride / 2;
2526                 src_start += src->stride / 4;
2527             }
2528         }
2529         break;
2530     }
2531
2532     case 24:
2533     {
2534         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2535
2536         for(y = src_rect->top; y < src_rect->bottom; y++)
2537         {
2538             dst_pixel = dst_start;
2539             src_pixel = src_start;
2540             for(x = src_rect->left; x < src_rect->right; x++)
2541             {
2542                 RGBQUAD rgb;
2543                 rgb.rgbBlue  = *src_pixel++;
2544                 rgb.rgbGreen = *src_pixel++;
2545                 rgb.rgbRed   = *src_pixel++;
2546
2547                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2548                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2549                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2550             }
2551             if(pad_size) memset(dst_pixel, 0, pad_size);
2552             dst_start += dst->stride / 2;
2553             src_start += src->stride;
2554         }
2555         break;
2556     }
2557
2558     case 16:
2559     {
2560         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2561         if(src->funcs == &funcs_555)
2562         {
2563             for(y = src_rect->top; y < src_rect->bottom; y++)
2564             {
2565                 dst_pixel = dst_start;
2566                 src_pixel = src_start;
2567                 for(x = src_rect->left; x < src_rect->right; x++)
2568                 {
2569                     src_val = *src_pixel++;
2570                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
2571                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
2572                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
2573                 }
2574                 if(pad_size) memset(dst_pixel, 0, pad_size);
2575                 dst_start += dst->stride / 2;
2576                 src_start += src->stride / 2;
2577             }
2578         }
2579         else if(bit_fields_match(src, dst))
2580         {
2581             if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2582                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2583             else
2584             {
2585                 for(y = src_rect->top; y < src_rect->bottom; y++)
2586                 {
2587                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2588                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2589                     dst_start += dst->stride / 2;
2590                     src_start += src->stride / 2;
2591                 }
2592             }
2593         }
2594         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2595         {
2596             for(y = src_rect->top; y < src_rect->bottom; y++)
2597             {
2598                 dst_pixel = dst_start;
2599                 src_pixel = src_start;
2600                 for(x = src_rect->left; x < src_rect->right; x++)
2601                 {
2602                     src_val = *src_pixel++;
2603                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2604                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2605                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2606                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2607                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2608                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2609                 }
2610                 if(pad_size) memset(dst_pixel, 0, pad_size);
2611                 dst_start += dst->stride / 2;
2612                 src_start += src->stride / 2;
2613             }
2614         }
2615         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2616         {
2617             for(y = src_rect->top; y < src_rect->bottom; y++)
2618             {
2619                 dst_pixel = dst_start;
2620                 src_pixel = src_start;
2621                 for(x = src_rect->left; x < src_rect->right; x++)
2622                 {
2623                     src_val = *src_pixel++;
2624                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2625                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2626                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2627                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2628                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2629                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2630                 }
2631                 if(pad_size) memset(dst_pixel, 0, pad_size);
2632                 dst_start += dst->stride / 2;
2633                 src_start += src->stride / 2;
2634             }
2635         }
2636         else
2637         {
2638             for(y = src_rect->top; y < src_rect->bottom; y++)
2639             {
2640                 dst_pixel = dst_start;
2641                 src_pixel = src_start;
2642                 for(x = src_rect->left; x < src_rect->right; x++)
2643                 {
2644                     src_val = *src_pixel++;
2645                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
2646                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2647                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
2648                 }
2649                 if(pad_size) memset(dst_pixel, 0, pad_size);
2650                 dst_start += dst->stride / 2;
2651                 src_start += src->stride / 2;
2652             }
2653         }
2654         break;
2655     }
2656
2657     case 8:
2658     {
2659         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2660         for(y = src_rect->top; y < src_rect->bottom; y++)
2661         {
2662             dst_pixel = dst_start;
2663             src_pixel = src_start;
2664             for(x = src_rect->left; x < src_rect->right; x++)
2665             {
2666                 RGBQUAD rgb = src->color_table[*src_pixel++];
2667                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2668                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2669                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2670             }
2671             if(pad_size) memset(dst_pixel, 0, pad_size);
2672             dst_start += dst->stride / 2;
2673             src_start += src->stride;
2674         }
2675         break;
2676     }
2677
2678     case 4:
2679     {
2680         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2681         for(y = src_rect->top; y < src_rect->bottom; y++)
2682         {
2683             int pos = (src->rect.left + src_rect->left) & 1;
2684             src_pixel = src_start;
2685             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2686             {
2687                 RGBQUAD rgb;
2688                 if (pos & 1)
2689                     rgb = src->color_table[*src_pixel++ & 0xf];
2690                 else
2691                     rgb = src->color_table[*src_pixel >> 4];
2692                 dst_start[x] = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2693                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2694                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2695             }
2696             if(pad_size) memset(dst_start + x, 0, pad_size);
2697             dst_start += dst->stride / 2;
2698             src_start += src->stride;
2699         }
2700         break;
2701     }
2702
2703     case 1:
2704     {
2705         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2706         for(y = src_rect->top; y < src_rect->bottom; y++)
2707         {
2708             int pos = (src->rect.left + src_rect->left) & 7;
2709             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2710             {
2711                 RGBQUAD rgb;
2712                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2713                 rgb = src->color_table[src_val];
2714                 dst_start[x] = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2715                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2716                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2717             }
2718             if(pad_size) memset(dst_start + x, 0, pad_size);
2719             dst_start += dst->stride / 2;
2720             src_start += src->stride;
2721         }
2722         break;
2723     }
2724     }
2725 }
2726
2727 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2728 {
2729     return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
2730 }
2731
2732 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2733 {
2734     /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2735     return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2736 }
2737
2738 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2739 {
2740     BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2741     INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2742     DWORD src_val;
2743
2744     switch(src->bit_count)
2745     {
2746     case 32:
2747     {
2748         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2749
2750         if(src->funcs == &funcs_8888)
2751         {
2752             for(y = src_rect->top; y < src_rect->bottom; y++)
2753             {
2754                 dst_pixel = dst_start;
2755                 src_pixel = src_start;
2756                 for(x = src_rect->left; x < src_rect->right; x++)
2757                 {
2758                     src_val = *src_pixel++;
2759                     *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2760                 }
2761                 if(pad_size) memset(dst_pixel, 0, pad_size);
2762                 dst_start += dst->stride;
2763                 src_start += src->stride / 4;
2764             }
2765         }
2766         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2767         {
2768             for(y = src_rect->top; y < src_rect->bottom; y++)
2769             {
2770                 dst_pixel = dst_start;
2771                 src_pixel = src_start;
2772                 for(x = src_rect->left; x < src_rect->right; x++)
2773                 {
2774                     src_val = *src_pixel++;
2775                     *dst_pixel++ = rgb_lookup_colortable(dst,
2776                                                          src_val >> src->red_shift,
2777                                                          src_val >> src->green_shift,
2778                                                          src_val >> src->blue_shift );
2779                 }
2780                 if(pad_size) memset(dst_pixel, 0, pad_size);
2781                 dst_start += dst->stride;
2782                 src_start += src->stride / 4;
2783             }
2784         }
2785         else
2786         {
2787             for(y = src_rect->top; y < src_rect->bottom; y++)
2788             {
2789                 dst_pixel = dst_start;
2790                 src_pixel = src_start;
2791                 for(x = src_rect->left; x < src_rect->right; x++)
2792                 {
2793                     src_val = *src_pixel++;
2794                     *dst_pixel++ = rgb_lookup_colortable(dst,
2795                                                          get_field(src_val, src->red_shift, src->red_len),
2796                                                          get_field(src_val, src->green_shift, src->green_len),
2797                                                          get_field(src_val, src->blue_shift, src->blue_len));
2798                 }
2799                 if(pad_size) memset(dst_pixel, 0, pad_size);
2800                 dst_start += dst->stride;
2801                 src_start += src->stride / 4;
2802             }
2803         }
2804         break;
2805     }
2806
2807     case 24:
2808     {
2809         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2810
2811         for(y = src_rect->top; y < src_rect->bottom; y++)
2812         {
2813             dst_pixel = dst_start;
2814             src_pixel = src_start;
2815             for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2816             {
2817                 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2818             }
2819             if(pad_size) memset(dst_pixel, 0, pad_size);
2820             dst_start += dst->stride;
2821             src_start += src->stride;
2822         }
2823         break;
2824     }
2825
2826     case 16:
2827     {
2828         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2829         if(src->funcs == &funcs_555)
2830         {
2831             for(y = src_rect->top; y < src_rect->bottom; y++)
2832             {
2833                 dst_pixel = dst_start;
2834                 src_pixel = src_start;
2835                 for(x = src_rect->left; x < src_rect->right; x++)
2836                 {
2837                     src_val = *src_pixel++;
2838                     *dst_pixel++ = rgb_lookup_colortable(dst,
2839                                                          ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2840                                                          ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2841                                                          ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2842                 }
2843                 if(pad_size) memset(dst_pixel, 0, pad_size);
2844                 dst_start += dst->stride;
2845                 src_start += src->stride / 2;
2846             }
2847         }
2848         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2849         {
2850             for(y = src_rect->top; y < src_rect->bottom; y++)
2851             {
2852                 dst_pixel = dst_start;
2853                 src_pixel = src_start;
2854                 for(x = src_rect->left; x < src_rect->right; x++)
2855                 {
2856                     src_val = *src_pixel++;
2857                     *dst_pixel++ = rgb_lookup_colortable(dst,
2858                                                          (((src_val >> src->red_shift)   << 3) & 0xf8) |
2859                                                          (((src_val >> src->red_shift)   >> 2) & 0x07),
2860                                                          (((src_val >> src->green_shift) << 3) & 0xf8) |
2861                                                          (((src_val >> src->green_shift) >> 2) & 0x07),
2862                                                          (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2863                                                          (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2864                 }
2865                 if(pad_size) memset(dst_pixel, 0, pad_size);
2866                 dst_start += dst->stride;
2867                 src_start += src->stride / 2;
2868             }
2869         }
2870         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2871         {
2872             for(y = src_rect->top; y < src_rect->bottom; y++)
2873             {
2874                 dst_pixel = dst_start;
2875                 src_pixel = src_start;
2876                 for(x = src_rect->left; x < src_rect->right; x++)
2877                 {
2878                     src_val = *src_pixel++;
2879                     *dst_pixel++ = rgb_lookup_colortable(dst,
2880                                                          (((src_val >> src->red_shift)   << 3) & 0xf8) |
2881                                                          (((src_val >> src->red_shift)   >> 2) & 0x07),
2882                                                          (((src_val >> src->green_shift) << 2) & 0xfc) |
2883                                                          (((src_val >> src->green_shift) >> 4) & 0x03),
2884                                                          (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2885                                                          (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2886                 }
2887                 if(pad_size) memset(dst_pixel, 0, pad_size);
2888                 dst_start += dst->stride;
2889                 src_start += src->stride / 2;
2890             }
2891         }
2892         else
2893         {
2894             for(y = src_rect->top; y < src_rect->bottom; y++)
2895             {
2896                 dst_pixel = dst_start;
2897                 src_pixel = src_start;
2898                 for(x = src_rect->left; x < src_rect->right; x++)
2899                 {
2900                     src_val = *src_pixel++;
2901                     *dst_pixel++ = rgb_lookup_colortable(dst,
2902                                                          get_field(src_val, src->red_shift, src->red_len),
2903                                                          get_field(src_val, src->green_shift, src->green_len),
2904                                                          get_field(src_val, src->blue_shift, src->blue_len));
2905                 }
2906                 if(pad_size) memset(dst_pixel, 0, pad_size);
2907                 dst_start += dst->stride;
2908                 src_start += src->stride / 2;
2909             }
2910         }
2911         break;
2912     }
2913
2914     case 8:
2915     {
2916         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2917
2918         if(color_tables_match(dst, src))
2919         {
2920             if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2921                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2922             else
2923             {
2924                 for(y = src_rect->top; y < src_rect->bottom; y++)
2925                 {
2926                     memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2927                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2928                     dst_start += dst->stride;
2929                     src_start += src->stride;
2930                 }
2931             }
2932         }
2933         else
2934         {
2935             for(y = src_rect->top; y < src_rect->bottom; y++)
2936             {
2937                 dst_pixel = dst_start;
2938                 src_pixel = src_start;
2939                 for(x = src_rect->left; x < src_rect->right; x++)
2940                 {
2941                     RGBQUAD rgb = src->color_table[*src_pixel++];
2942                     *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2943                 }
2944                 if(pad_size) memset(dst_pixel, 0, pad_size);
2945                 dst_start += dst->stride;
2946                 src_start += src->stride;
2947             }
2948         }
2949         break;
2950     }
2951
2952     case 4:
2953     {
2954         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2955         for(y = src_rect->top; y < src_rect->bottom; y++)
2956         {
2957             int pos = (src->rect.left + src_rect->left) & 1;
2958             src_pixel = src_start;
2959             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2960             {
2961                 RGBQUAD rgb;
2962                 if (pos & 1)
2963                     rgb = src->color_table[*src_pixel++ & 0xf];
2964                 else
2965                     rgb = src->color_table[*src_pixel >> 4];
2966                 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2967             }
2968             if(pad_size) memset(dst_start + x, 0, pad_size);
2969             dst_start += dst->stride;
2970             src_start += src->stride;
2971         }
2972         break;
2973     }
2974
2975     case 1:
2976     {
2977         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2978         for(y = src_rect->top; y < src_rect->bottom; y++)
2979         {
2980             int pos = (src->rect.left + src_rect->left) & 7;
2981             for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2982             {
2983                 RGBQUAD rgb;
2984                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2985                 rgb = src->color_table[src_val];
2986                 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2987             }
2988             if(pad_size) memset(dst_start + x, 0, pad_size);
2989             dst_start += dst->stride;
2990             src_start += src->stride;
2991         }
2992         break;
2993     }
2994     }
2995 }
2996
2997 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2998 {
2999     BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3000     INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3001     DWORD src_val;
3002
3003     switch(src->bit_count)
3004     {
3005     case 32:
3006     {
3007         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3008
3009         if(src->funcs == &funcs_8888)
3010         {
3011             for(y = src_rect->top; y < src_rect->bottom; y++)
3012             {
3013                 dst_pixel = dst_start;
3014                 src_pixel = src_start;
3015                 for(x = src_rect->left; x < src_rect->right; x++)
3016                 {
3017                     src_val = *src_pixel++;
3018                     dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3019                     if((x - src_rect->left) & 1)
3020                     {
3021                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3022                         dst_pixel++;
3023                     }
3024                     else
3025                         *dst_pixel = (dst_val << 4) & 0xf0;
3026                 }
3027                 if(pad_size)
3028                 {
3029                     if((x - src_rect->left) & 1) dst_pixel++;
3030                     memset(dst_pixel, 0, pad_size);
3031                 }
3032                 dst_start += dst->stride;
3033                 src_start += src->stride / 4;
3034             }
3035         }
3036         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3037         {
3038             for(y = src_rect->top; y < src_rect->bottom; y++)
3039             {
3040                 dst_pixel = dst_start;
3041                 src_pixel = src_start;
3042                 for(x = src_rect->left; x < src_rect->right; x++)
3043                 {
3044                     src_val = *src_pixel++;
3045                     dst_val = rgb_to_pixel_colortable(dst,
3046                                                       src_val >> src->red_shift,
3047                                                       src_val >> src->green_shift,
3048                                                       src_val >> src->blue_shift);
3049                     if((x - src_rect->left) & 1)
3050                     {
3051                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3052                         dst_pixel++;
3053                     }
3054                     else
3055                         *dst_pixel = (dst_val << 4) & 0xf0;
3056                 }
3057                 if(pad_size)
3058                 {
3059                     if((x - src_rect->left) & 1) dst_pixel++;
3060                     memset(dst_pixel, 0, pad_size);
3061                 }
3062                 dst_start += dst->stride;
3063                 src_start += src->stride / 4;
3064             }
3065         }
3066         else
3067         {
3068             for(y = src_rect->top; y < src_rect->bottom; y++)
3069             {
3070                 dst_pixel = dst_start;
3071                 src_pixel = src_start;
3072                 for(x = src_rect->left; x < src_rect->right; x++)
3073                 {
3074                     src_val = *src_pixel++;
3075                     dst_val = rgb_to_pixel_colortable(dst,
3076                                                       get_field(src_val, src->red_shift, src->red_len),
3077                                                       get_field(src_val, src->green_shift, src->green_len),
3078                                                       get_field(src_val, src->blue_shift, src->blue_len));
3079                     if((x - src_rect->left) & 1)
3080                     {
3081                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3082                         dst_pixel++;
3083                     }
3084                     else
3085                         *dst_pixel = (dst_val << 4) & 0xf0;
3086                 }
3087                 if(pad_size)
3088                 {
3089                     if((x - src_rect->left) & 1) dst_pixel++;
3090                     memset(dst_pixel, 0, pad_size);
3091                 }
3092                 dst_start += dst->stride;
3093                 src_start += src->stride / 4;
3094             }
3095         }
3096         break;
3097     }
3098
3099     case 24:
3100     {
3101         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3102
3103         for(y = src_rect->top; y < src_rect->bottom; y++)
3104         {
3105             dst_pixel = dst_start;
3106             src_pixel = src_start;
3107             for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3108             {
3109                 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3110
3111                 if((x - src_rect->left) & 1)
3112                 {
3113                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3114                     dst_pixel++;
3115                 }
3116                 else
3117                     *dst_pixel = (dst_val << 4) & 0xf0;
3118             }
3119             if(pad_size)
3120             {
3121                 if((x - src_rect->left) & 1) dst_pixel++;
3122                 memset(dst_pixel, 0, pad_size);
3123             }
3124             dst_start += dst->stride;
3125             src_start += src->stride;
3126         }
3127         break;
3128     }
3129
3130     case 16:
3131     {
3132         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3133         if(src->funcs == &funcs_555)
3134         {
3135             for(y = src_rect->top; y < src_rect->bottom; y++)
3136             {
3137                 dst_pixel = dst_start;
3138                 src_pixel = src_start;
3139                 for(x = src_rect->left; x < src_rect->right; x++)
3140                 {
3141                     src_val = *src_pixel++;
3142                     dst_val = rgb_to_pixel_colortable(dst,
3143                                                       ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3144                                                       ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07),
3145                                                       ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07) );
3146                     if((x - src_rect->left) & 1)
3147                     {
3148                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3149                         dst_pixel++;
3150                     }
3151                     else
3152                         *dst_pixel = (dst_val << 4) & 0xf0;
3153                 }
3154                 if(pad_size)
3155                 {
3156                     if((x - src_rect->left) & 1) dst_pixel++;
3157                     memset(dst_pixel, 0, pad_size);
3158                 }
3159                 dst_start += dst->stride;
3160                 src_start += src->stride / 2;
3161             }
3162         }
3163         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3164         {
3165             for(y = src_rect->top; y < src_rect->bottom; y++)
3166             {
3167                 dst_pixel = dst_start;
3168                 src_pixel = src_start;
3169                 for(x = src_rect->left; x < src_rect->right; x++)
3170                 {
3171                     src_val = *src_pixel++;
3172                     dst_val = rgb_to_pixel_colortable(dst,
3173                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3174                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3175                                                       (((src_val >> src->green_shift) << 3) & 0xf8) |
3176                                                       (((src_val >> src->green_shift) >> 2) & 0x07),
3177                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3178                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) );
3179                     if((x - src_rect->left) & 1)
3180                     {
3181                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3182                         dst_pixel++;
3183                     }
3184                     else
3185                         *dst_pixel = (dst_val << 4) & 0xf0;
3186                 }
3187                 if(pad_size)
3188                 {
3189                     if((x - src_rect->left) & 1) dst_pixel++;
3190                     memset(dst_pixel, 0, pad_size);
3191                 }
3192                 dst_start += dst->stride;
3193                 src_start += src->stride / 2;
3194             }
3195         }
3196         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3197         {
3198             for(y = src_rect->top; y < src_rect->bottom; y++)
3199             {
3200                 dst_pixel = dst_start;
3201                 src_pixel = src_start;
3202                 for(x = src_rect->left; x < src_rect->right; x++)
3203                 {
3204                     src_val = *src_pixel++;
3205                     dst_val = rgb_to_pixel_colortable(dst,
3206                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3207                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3208                                                       (((src_val >> src->green_shift) << 2) & 0xfc) |
3209                                                       (((src_val >> src->green_shift) >> 4) & 0x03),
3210                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3211                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) );
3212                     if((x - src_rect->left) & 1)
3213                     {
3214                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3215                         dst_pixel++;
3216                     }
3217                     else
3218                         *dst_pixel = (dst_val << 4) & 0xf0;
3219                 }
3220                 if(pad_size)
3221                 {
3222                     if((x - src_rect->left) & 1) dst_pixel++;
3223                     memset(dst_pixel, 0, pad_size);
3224                 }
3225                 dst_start += dst->stride;
3226                 src_start += src->stride / 2;
3227             }
3228         }
3229         else
3230         {
3231             for(y = src_rect->top; y < src_rect->bottom; y++)
3232             {
3233                 dst_pixel = dst_start;
3234                 src_pixel = src_start;
3235                 for(x = src_rect->left; x < src_rect->right; x++)
3236                 {
3237                     src_val = *src_pixel++;
3238                     dst_val = rgb_to_pixel_colortable(dst,
3239                                                       get_field(src_val, src->red_shift, src->red_len),
3240                                                       get_field(src_val, src->green_shift, src->green_len),
3241                                                       get_field(src_val, src->blue_shift, src->blue_len));
3242                     if((x - src_rect->left) & 1)
3243                     {
3244                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3245                         dst_pixel++;
3246                     }
3247                     else
3248                         *dst_pixel = (dst_val << 4) & 0xf0;
3249                 }
3250                 if(pad_size)
3251                 {
3252                     if((x - src_rect->left) & 1) dst_pixel++;
3253                     memset(dst_pixel, 0, pad_size);
3254                 }
3255                 dst_start += dst->stride;
3256                 src_start += src->stride / 2;
3257             }
3258         }
3259         break;
3260     }
3261
3262     case 8:
3263     {
3264         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3265
3266         for(y = src_rect->top; y < src_rect->bottom; y++)
3267         {
3268             dst_pixel = dst_start;
3269             src_pixel = src_start;
3270             for(x = src_rect->left; x < src_rect->right; x++)
3271             {
3272                 RGBQUAD rgb = src->color_table[*src_pixel++];
3273                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3274                 if((x - src_rect->left) & 1)
3275                 {
3276                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3277                     dst_pixel++;
3278                 }
3279                 else
3280                     *dst_pixel = (dst_val << 4) & 0xf0;
3281             }
3282             if(pad_size)
3283             {
3284                 if((x - src_rect->left) & 1) dst_pixel++;
3285                 memset(dst_pixel, 0, pad_size);
3286             }
3287             dst_start += dst->stride;
3288             src_start += src->stride;
3289         }
3290         break;
3291     }
3292
3293     case 4:
3294     {
3295         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3296
3297         if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
3298         {
3299             if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3300                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3301             else
3302             {
3303                 for(y = src_rect->top; y < src_rect->bottom; y++)
3304                 {
3305                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3306                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3307                     dst_start += dst->stride;
3308                     src_start += src->stride;
3309                 }
3310             }
3311         }
3312         else
3313         {
3314             for(y = src_rect->top; y < src_rect->bottom; y++)
3315             {
3316                 int pos = (src->rect.left + src_rect->left) & 1;
3317                 dst_pixel = dst_start;
3318                 src_pixel = src_start;
3319                 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3320                 {
3321                     RGBQUAD rgb;
3322                     if(pos & 1)
3323                         rgb = src->color_table[*src_pixel++ & 0xf];
3324                     else
3325                         rgb = src->color_table[*src_pixel >> 4];
3326                     dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3327                     if((x - src_rect->left) & 1)
3328                     {
3329                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3330                         dst_pixel++;
3331                     }
3332                     else
3333                         *dst_pixel = (dst_val << 4) & 0xf0;
3334                 }
3335                 if(pad_size)
3336                 {
3337                     if((x - src_rect->left) & 1) dst_pixel++;
3338                     memset(dst_pixel, 0, pad_size);
3339                 }
3340                 dst_start += dst->stride;
3341                 src_start += src->stride;
3342             }
3343         }
3344         break;
3345     }
3346
3347     case 1:
3348     {
3349         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3350         for(y = src_rect->top; y < src_rect->bottom; y++)
3351         {
3352             int pos = (src->rect.left + src_rect->left) & 7;
3353             dst_pixel = dst_start;
3354             for(x = src_rect->left; x < src_rect->right; x++, pos++)
3355             {
3356                 RGBQUAD rgb;
3357                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3358                 rgb = src->color_table[src_val];
3359                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3360                 if((x - src_rect->left) & 1)
3361                 {
3362                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3363                     dst_pixel++;
3364                 }
3365                 else
3366                     *dst_pixel = (dst_val << 4) & 0xf0;
3367             }
3368             if(pad_size)
3369             {
3370                 if((x - src_rect->left) & 1) dst_pixel++;
3371                 memset(dst_pixel, 0, pad_size);
3372             }
3373             dst_start += dst->stride;
3374             src_start += src->stride;
3375         }
3376         break;
3377     }
3378     }
3379 }
3380
3381 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3382 {
3383     BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3384     INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3385     DWORD src_val;
3386     int bit_pos;
3387
3388     /* FIXME: Brushes should be dithered. */
3389
3390     switch(src->bit_count)
3391     {
3392     case 32:
3393     {
3394         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3395
3396         if(src->funcs == &funcs_8888)
3397         {
3398             for(y = src_rect->top; y < src_rect->bottom; y++)
3399             {
3400                 dst_pixel = dst_start;
3401                 src_pixel = src_start;
3402                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3403                 {
3404                     src_val = *src_pixel++;
3405                     dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3406
3407                     if(bit_pos == 0) *dst_pixel = 0;
3408                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3409
3410                     if(++bit_pos == 8)
3411                     {
3412                         dst_pixel++;
3413                         bit_pos = 0;
3414                     }
3415                 }
3416                 if(pad_size)
3417                 {
3418                     if(bit_pos != 0) dst_pixel++;
3419                     memset(dst_pixel, 0, pad_size);
3420                 }
3421                 dst_start += dst->stride;
3422                 src_start += src->stride / 4;
3423             }
3424         }
3425         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3426         {
3427             for(y = src_rect->top; y < src_rect->bottom; y++)
3428             {
3429                 dst_pixel = dst_start;
3430                 src_pixel = src_start;
3431                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3432                 {
3433                     src_val = *src_pixel++;
3434                     dst_val = rgb_to_pixel_colortable(dst,
3435                                                       src_val >> src->red_shift,
3436                                                       src_val >> src->green_shift,
3437                                                       src_val >> src->blue_shift) ? 0xff : 0;
3438
3439                    if(bit_pos == 0) *dst_pixel = 0;
3440                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3441
3442                     if(++bit_pos == 8)
3443                     {
3444                         dst_pixel++;
3445                         bit_pos = 0;
3446                     }
3447                 }
3448                 if(pad_size)
3449                 {
3450                     if(bit_pos != 0) dst_pixel++;
3451                     memset(dst_pixel, 0, pad_size);
3452                 }
3453                 dst_start += dst->stride;
3454                 src_start += src->stride / 4;
3455             }
3456         }
3457         else
3458         {
3459             for(y = src_rect->top; y < src_rect->bottom; y++)
3460             {
3461                 dst_pixel = dst_start;
3462                 src_pixel = src_start;
3463                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3464                 {
3465                     src_val = *src_pixel++;
3466                     dst_val = rgb_to_pixel_colortable(dst,
3467                                                       get_field(src_val, src->red_shift, src->red_len),
3468                                                       get_field(src_val, src->green_shift, src->green_len),
3469                                                       get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3470
3471                    if(bit_pos == 0) *dst_pixel = 0;
3472                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3473
3474                     if(++bit_pos == 8)
3475                     {
3476                         dst_pixel++;
3477                         bit_pos = 0;
3478                     }
3479                 }
3480                 if(pad_size)
3481                 {
3482                     if(bit_pos != 0) dst_pixel++;
3483                     memset(dst_pixel, 0, pad_size);
3484                 }
3485                 dst_start += dst->stride;
3486                 src_start += src->stride / 4;
3487             }
3488         }
3489         break;
3490     }
3491
3492     case 24:
3493     {
3494         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3495
3496         for(y = src_rect->top; y < src_rect->bottom; y++)
3497         {
3498             dst_pixel = dst_start;
3499             src_pixel = src_start;
3500             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3501             {
3502                 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3503
3504                 if(bit_pos == 0) *dst_pixel = 0;
3505                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3506
3507                 if(++bit_pos == 8)
3508                 {
3509                     dst_pixel++;
3510                     bit_pos = 0;
3511                 }
3512             }
3513             if(pad_size)
3514             {
3515                 if(bit_pos != 0) dst_pixel++;
3516                 memset(dst_pixel, 0, pad_size);
3517             }
3518             dst_start += dst->stride;
3519             src_start += src->stride;
3520         }
3521         break;
3522     }
3523
3524     case 16:
3525     {
3526         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3527         if(src->funcs == &funcs_555)
3528         {
3529             for(y = src_rect->top; y < src_rect->bottom; y++)
3530             {
3531                 dst_pixel = dst_start;
3532                 src_pixel = src_start;
3533                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3534                 {
3535                     src_val = *src_pixel++;
3536                     dst_val = rgb_to_pixel_colortable(dst,
3537                                                       ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3538                                                       ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07),
3539                                                       ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07) ) ? 0xff : 0;
3540
3541                     if(bit_pos == 0) *dst_pixel = 0;
3542                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3543
3544                     if(++bit_pos == 8)
3545                     {
3546                         dst_pixel++;
3547                         bit_pos = 0;
3548                     }
3549                 }
3550                 if(pad_size)
3551                 {
3552                     if(bit_pos != 0) dst_pixel++;
3553                     memset(dst_pixel, 0, pad_size);
3554                 }
3555                 dst_start += dst->stride;
3556                 src_start += src->stride / 2;
3557             }
3558         }
3559         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3560         {
3561             for(y = src_rect->top; y < src_rect->bottom; y++)
3562             {
3563                 dst_pixel = dst_start;
3564                 src_pixel = src_start;
3565                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3566                 {
3567                     src_val = *src_pixel++;
3568                     dst_val = rgb_to_pixel_colortable(dst,
3569                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3570                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3571                                                       (((src_val >> src->green_shift) << 3) & 0xf8) |
3572                                                       (((src_val >> src->green_shift) >> 2) & 0x07),
3573                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3574                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) ) ? 0xff : 0;
3575                     if(bit_pos == 0) *dst_pixel = 0;
3576                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3577
3578                     if(++bit_pos == 8)
3579                     {
3580                         dst_pixel++;
3581                         bit_pos = 0;
3582                     }
3583                 }
3584                 if(pad_size)
3585                 {
3586                     if(bit_pos != 0) dst_pixel++;
3587                     memset(dst_pixel, 0, pad_size);
3588                 }
3589                 dst_start += dst->stride;
3590                 src_start += src->stride / 2;
3591             }
3592         }
3593         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3594         {
3595             for(y = src_rect->top; y < src_rect->bottom; y++)
3596             {
3597                 dst_pixel = dst_start;
3598                 src_pixel = src_start;
3599                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3600                 {
3601                     src_val = *src_pixel++;
3602                     dst_val = rgb_to_pixel_colortable(dst,
3603                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3604                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3605                                                       (((src_val >> src->green_shift) << 2) & 0xfc) |
3606                                                       (((src_val >> src->green_shift) >> 4) & 0x03),
3607                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3608                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) ) ? 0xff : 0;
3609                     if(bit_pos == 0) *dst_pixel = 0;
3610                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3611
3612                     if(++bit_pos == 8)
3613                     {
3614                         dst_pixel++;
3615                         bit_pos = 0;
3616                     }
3617                 }
3618                 if(pad_size)
3619                 {
3620                     if(bit_pos != 0) dst_pixel++;
3621                     memset(dst_pixel, 0, pad_size);
3622                 }
3623                 dst_start += dst->stride;
3624                 src_start += src->stride / 2;
3625             }
3626         }
3627         else
3628         {
3629             for(y = src_rect->top; y < src_rect->bottom; y++)
3630             {
3631                 dst_pixel = dst_start;
3632                 src_pixel = src_start;
3633                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3634                 {
3635                     src_val = *src_pixel++;
3636                     dst_val = rgb_to_pixel_colortable(dst,
3637                                                       get_field(src_val, src->red_shift, src->red_len),
3638                                                       get_field(src_val, src->green_shift, src->green_len),
3639                                                       get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3640                     if(bit_pos == 0) *dst_pixel = 0;
3641                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3642
3643                     if(++bit_pos == 8)
3644                     {
3645                         dst_pixel++;
3646                         bit_pos = 0;
3647                     }
3648                 }
3649                 if(pad_size)
3650                 {
3651                     if(bit_pos != 0) dst_pixel++;
3652                     memset(dst_pixel, 0, pad_size);
3653                 }
3654                 dst_start += dst->stride;
3655                 src_start += src->stride / 2;
3656             }
3657         }
3658         break;
3659     }
3660
3661     case 8:
3662     {
3663         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3664
3665         for(y = src_rect->top; y < src_rect->bottom; y++)
3666         {
3667             dst_pixel = dst_start;
3668             src_pixel = src_start;
3669             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3670             {
3671                 RGBQUAD rgb = src->color_table[*src_pixel++];
3672                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3673
3674                 if(bit_pos == 0) *dst_pixel = 0;
3675                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3676
3677                 if(++bit_pos == 8)
3678                 {
3679                     dst_pixel++;
3680                     bit_pos = 0;
3681                 }
3682             }
3683             if(pad_size)
3684             {
3685                 if(bit_pos != 0) dst_pixel++;
3686                 memset(dst_pixel, 0, pad_size);
3687             }
3688             dst_start += dst->stride;
3689             src_start += src->stride;
3690         }
3691         break;
3692     }
3693
3694     case 4:
3695     {
3696         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3697
3698         for(y = src_rect->top; y < src_rect->bottom; y++)
3699         {
3700             int pos = (src->rect.left + src_rect->left) & 1;
3701             dst_pixel = dst_start;
3702             src_pixel = src_start;
3703             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3704             {
3705                 RGBQUAD rgb;
3706                 if (pos & 1)
3707                     rgb = src->color_table[*src_pixel++ & 0xf];
3708                 else
3709                     rgb = src->color_table[*src_pixel >> 4];
3710                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3711
3712                 if(bit_pos == 0) *dst_pixel = 0;
3713                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3714
3715                 if(++bit_pos == 8)
3716                 {
3717                     dst_pixel++;
3718                     bit_pos = 0;
3719                 }
3720             }
3721             if(pad_size)
3722             {
3723                 if(bit_pos != 0) dst_pixel++;
3724                 memset(dst_pixel, 0, pad_size);
3725             }
3726             dst_start += dst->stride;
3727             src_start += src->stride;
3728         }
3729         break;
3730     }
3731
3732     /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3733        uses text/bkgnd colours instead of the dib's colour table, this
3734        doesn't appear to be the case for a dc backed by a
3735        dibsection. */
3736
3737     case 1:
3738     {
3739         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3740         for(y = src_rect->top; y < src_rect->bottom; y++)
3741         {
3742             int pos = (src->rect.left + src_rect->left) & 7;
3743             dst_pixel = dst_start;
3744             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3745             {
3746                 RGBQUAD rgb;
3747                 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3748                 rgb = src->color_table[src_val];
3749                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3750
3751                 if(bit_pos == 0) *dst_pixel = 0;
3752                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3753
3754                 if(++bit_pos == 8)
3755                 {
3756                     dst_pixel++;
3757                     bit_pos = 0;
3758                 }
3759             }
3760             if(pad_size)
3761             {
3762                 if(bit_pos != 0) dst_pixel++;
3763                 memset(dst_pixel, 0, pad_size);
3764             }
3765             dst_start += dst->stride;
3766             src_start += src->stride;
3767         }
3768         break;
3769     }
3770     }
3771 }
3772
3773 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3774 {
3775 }
3776
3777 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3778 {
3779     return (src * alpha + dst * (255 - alpha) + 127) / 255;
3780 }
3781
3782 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
3783 {
3784     return (blend_color( dst, src, alpha ) |
3785             blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3786             blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3787             blend_color( dst >> 24, src >> 24, alpha ) << 24);
3788 }
3789
3790 static inline DWORD blend_argb( DWORD dst, DWORD src )
3791 {
3792     BYTE b = (BYTE)src;
3793     BYTE g = (BYTE)(src >> 8);
3794     BYTE r = (BYTE)(src >> 16);
3795     DWORD alpha  = (BYTE)(src >> 24);
3796     return ((b     + ((BYTE)dst         * (255 - alpha) + 127) / 255) |
3797             (g     + ((BYTE)(dst >> 8)  * (255 - alpha) + 127) / 255) << 8 |
3798             (r     + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3799             (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3800 }
3801
3802 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3803 {
3804     BYTE b = ((BYTE)src         * alpha + 127) / 255;
3805     BYTE g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3806     BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3807     alpha  = ((BYTE)(src >> 24) * alpha + 127) / 255;
3808     return ((b     + ((BYTE)dst         * (255 - alpha) + 127) / 255) |
3809             (g     + ((BYTE)(dst >> 8)  * (255 - alpha) + 127) / 255) << 8 |
3810             (r     + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3811             (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3812 }
3813
3814 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3815 {
3816     if (blend.AlphaFormat & AC_SRC_ALPHA)
3817     {
3818         DWORD alpha = blend.SourceConstantAlpha;
3819         BYTE src_b = ((BYTE)src         * alpha + 127) / 255;
3820         BYTE src_g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3821         BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3822         alpha      = ((BYTE)(src >> 24) * alpha + 127) / 255;
3823         return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3824                 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3825                 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3826     }
3827     return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3828             blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3829             blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3830 }
3831
3832 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3833                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3834 {
3835     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3836     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3837     int x, y;
3838
3839     if (blend.AlphaFormat & AC_SRC_ALPHA)
3840     {
3841         if (blend.SourceConstantAlpha == 255)
3842             for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3843                 for (x = 0; x < rc->right - rc->left; x++)
3844                     dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
3845         else
3846             for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3847                 for (x = 0; x < rc->right - rc->left; x++)
3848                     dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3849     }
3850     else
3851         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3852             for (x = 0; x < rc->right - rc->left; x++)
3853                 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3854 }
3855
3856 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3857                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3858 {
3859     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3860     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3861     int x, y;
3862
3863     if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3864     {
3865         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3866         {
3867             for (x = 0; x < rc->right - rc->left; x++)
3868             {
3869                 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3870                                        dst_ptr[x] >> dst->green_shift,
3871                                        dst_ptr[x] >> dst->blue_shift,
3872                                        src_ptr[x], blend );
3873                 dst_ptr[x] = ((( val        & 0xff) << dst->blue_shift) |
3874                               (((val >> 8)  & 0xff) << dst->green_shift) |
3875                               (((val >> 16) & 0xff) << dst->red_shift));
3876             }
3877         }
3878     }
3879     else
3880     {
3881         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3882         {
3883             for (x = 0; x < rc->right - rc->left; x++)
3884             {
3885                 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3886                                        get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3887                                        get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3888                                        src_ptr[x], blend );
3889                 dst_ptr[x] = (put_field( val >> 16, dst->red_shift,   dst->red_len )   |
3890                               put_field( val >> 8,  dst->green_shift, dst->green_len ) |
3891                               put_field( val,       dst->blue_shift,  dst->blue_len ));
3892             }
3893         }
3894     }
3895 }
3896
3897 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3898                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3899 {
3900     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3901     BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3902     int x, y;
3903
3904     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3905     {
3906         for (x = 0; x < rc->right - rc->left; x++)
3907         {
3908             DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3909                                    src_ptr[x], blend );
3910             dst_ptr[x * 3]     = val;
3911             dst_ptr[x * 3 + 1] = val >> 8;
3912             dst_ptr[x * 3 + 2] = val >> 16;
3913         }
3914     }
3915 }
3916
3917 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3918                            const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3919 {
3920     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3921     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3922     int x, y;
3923
3924     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3925     {
3926         for (x = 0; x < rc->right - rc->left; x++)
3927         {
3928             DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3929                                    ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
3930                                    ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
3931                                    src_ptr[x], blend );
3932             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3933         }
3934     }
3935 }
3936
3937 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3938                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3939 {
3940     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3941     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3942     int x, y;
3943
3944     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3945     {
3946         for (x = 0; x < rc->right - rc->left; x++)
3947         {
3948             DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3949                                    get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3950                                    get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3951                                    src_ptr[x], blend );
3952             dst_ptr[x] = (put_field((val >> 16), dst->red_shift,   dst->red_len)   |
3953                           put_field((val >>  8), dst->green_shift, dst->green_len) |
3954                           put_field( val,        dst->blue_shift,  dst->blue_len));
3955         }
3956     }
3957 }
3958
3959 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3960                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3961 {
3962     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3963     BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3964     int x, y;
3965
3966     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3967     {
3968         for (x = 0; x < rc->right - rc->left; x++)
3969         {
3970             RGBQUAD rgb = dst->color_table[dst_ptr[x]];
3971             DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3972             dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3973         }
3974     }
3975 }
3976
3977 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3978                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3979 {
3980     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3981     BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
3982     int i, x, y;
3983
3984     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3985     {
3986         for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
3987         {
3988             DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3989             RGBQUAD rgb = dst->color_table[val];
3990             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
3991             val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3992             if (x & 1)
3993                 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3994             else
3995                 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3996         }
3997     }
3998 }
3999
4000 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4001                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4002 {
4003     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4004     BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4005     int i, x, y;
4006
4007     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4008     {
4009         for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4010         {
4011             DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4012             RGBQUAD rgb = dst->color_table[val];
4013             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4014             val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4015             dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4016         }
4017     }
4018 }
4019
4020 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4021                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4022 {
4023 }
4024
4025 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4026 {
4027     BYTE r, g, b, a;
4028     r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 256;
4029     g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4030     b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 256;
4031     a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4032     return a << 24 | r << 16 | g << 8 | b;
4033 }
4034
4035 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4036 {
4037     BYTE r, g, b;
4038     r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 256;
4039     g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4040     b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 256;
4041     return r << 16 | g << 8 | b;
4042 }
4043
4044 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4045                                      unsigned int x, unsigned int y )
4046 {
4047     int r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4048     int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4049     int b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4050     r = min( 31, max( 0, r / 16 ));
4051     g = min( 31, max( 0, g / 16 ));
4052     b = min( 31, max( 0, b / 16 ));
4053     return (r << 10) | (g << 5) | b;
4054 }
4055
4056 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4057                                    unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4058 {
4059     BYTE r = ((v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4060     BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4061     BYTE b = ((v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4062     return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4063 }
4064
4065 /* compute the left/right triangle limit for row y */
4066 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4067 {
4068     int x1, x2;
4069
4070     if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4071     else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4072
4073     x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4074
4075     *left  = max( rc->left, min( x1, x2 ) );
4076     *right = min( rc->right, max( x1, x2 ) );
4077 }
4078
4079 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4080 static inline int triangle_det( const TRIVERTEX *v )
4081 {
4082     return (v[2].y - v[1].y) * (v[2].x - v[0].x) - (v[2].x - v[1].x) * (v[2].y - v[0].y);
4083 }
4084
4085 /* compute the barycentric weights for a given point inside the triangle */
4086 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4087 {
4088     *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4089     *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4090 }
4091
4092 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4093 {
4094     INT64 l1, l2;
4095     BYTE r, g, b, a;
4096
4097     triangle_weights( v, x, y, &l1, &l2 );
4098     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 256;
4099     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4100     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 256;
4101     a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4102     return a << 24 | r << 16 | g << 8 | b;
4103 }
4104
4105 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4106 {
4107     INT64 l1, l2;
4108     BYTE r, g, b;
4109
4110     triangle_weights( v, x, y, &l1, &l2 );
4111     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 256;
4112     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4113     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 256;
4114     return r << 16 | g << 8 | b;
4115 }
4116
4117 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4118 {
4119     INT64 l1, l2;
4120     int r, g, b;
4121
4122     triangle_weights( v, x, y, &l1, &l2 );
4123     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4124     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4125     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4126     r = min( 31, max( 0, r / 16 ));
4127     g = min( 31, max( 0, g / 16 ));
4128     b = min( 31, max( 0, b / 16 ));
4129     return (r << 10) | (g << 5) | b;
4130 }
4131
4132 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4133 {
4134     INT64 l1, l2;
4135     BYTE r, g, b;
4136
4137     triangle_weights( v, x, y, &l1, &l2 );
4138     r = ((v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4139     g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4140     b = ((v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4141     return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4142 }
4143
4144 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4145 {
4146     DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4147     int x, y, left, right, det;
4148
4149     switch (mode)
4150     {
4151     case GRADIENT_FILL_RECT_H:
4152         for (x = 0; x < rc->right - rc->left; x++)
4153             ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4154
4155         for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4156             memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4157         break;
4158
4159     case GRADIENT_FILL_RECT_V:
4160         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4161         {
4162             DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4163             for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4164         }
4165         break;
4166
4167     case GRADIENT_FILL_TRIANGLE:
4168         if (!(det = triangle_det( v ))) return FALSE;
4169         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4170         {
4171             triangle_coords( v, rc, y, &left, &right );
4172             for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4173         }
4174         break;
4175     }
4176     return TRUE;
4177 }
4178
4179 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4180 {
4181     DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4182     int x, y, left, right, det;
4183
4184     switch (mode)
4185     {
4186     case GRADIENT_FILL_RECT_H:
4187         if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4188         {
4189             for (x = 0; x < rc->right - rc->left; x++)
4190             {
4191                 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4192                 ptr[x] = ((( val        & 0xff) << dib->blue_shift) |
4193                           (((val >> 8)  & 0xff) << dib->green_shift) |
4194                           (((val >> 16) & 0xff) << dib->red_shift));
4195             }
4196         }
4197         else
4198         {
4199             for (x = 0; x < rc->right - rc->left; x++)
4200             {
4201                 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4202                 ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4203                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4204                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4205             }
4206         }
4207
4208         for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4209             memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4210         break;
4211
4212     case GRADIENT_FILL_RECT_V:
4213         for (y = rc->top; y < rc->bottom; y++)
4214         {
4215             DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4216             if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4217                 val = ((( val        & 0xff) << dib->blue_shift) |
4218                        (((val >> 8)  & 0xff) << dib->green_shift) |
4219                        (((val >> 16) & 0xff) << dib->red_shift));
4220             else
4221                 val = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4222                        put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4223                        put_field( val,       dib->blue_shift,  dib->blue_len ));
4224
4225             for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4226             ptr += dib->stride / 4;
4227         }
4228         break;
4229
4230     case GRADIENT_FILL_TRIANGLE:
4231         if (!(det = triangle_det( v ))) return FALSE;
4232         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4233         {
4234             triangle_coords( v, rc, y, &left, &right );
4235
4236             if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4237                 for (x = left; x < right; x++)
4238                 {
4239                     DWORD val = gradient_triangle_24( v, x, y, det );
4240                     ptr[x - rc->left] = ((( val        & 0xff) << dib->blue_shift) |
4241                                          (((val >> 8)  & 0xff) << dib->green_shift) |
4242                                          (((val >> 16) & 0xff) << dib->red_shift));
4243                 }
4244             else
4245                 for (x = left; x < right; x++)
4246                 {
4247                     DWORD val = gradient_triangle_24( v, x, y, det );
4248                     ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4249                                          put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4250                                          put_field( val,       dib->blue_shift,  dib->blue_len ));
4251                 }
4252         }
4253         break;
4254     }
4255     return TRUE;
4256 }
4257
4258 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4259 {
4260     BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4261     int x, y, left, right, det;
4262
4263     switch (mode)
4264     {
4265     case GRADIENT_FILL_RECT_H:
4266         for (x = 0; x < rc->right - rc->left; x++)
4267         {
4268             DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4269             ptr[x * 3]     = val;
4270             ptr[x * 3 + 1] = val >> 8;
4271             ptr[x * 3 + 2] = val >> 16;
4272         }
4273
4274         for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4275             memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4276         break;
4277
4278     case GRADIENT_FILL_RECT_V:
4279         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4280         {
4281             DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4282             for (x = 0; x < rc->right - rc->left; x++)
4283             {
4284                 ptr[x * 3]     = val;
4285                 ptr[x * 3 + 1] = val >> 8;
4286                 ptr[x * 3 + 2] = val >> 16;
4287             }
4288         }
4289         break;
4290
4291     case GRADIENT_FILL_TRIANGLE:
4292         if (!(det = triangle_det( v ))) return FALSE;
4293         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4294         {
4295             triangle_coords( v, rc, y, &left, &right );
4296             for (x = left; x < right; x++)
4297             {
4298                 DWORD val = gradient_triangle_24( v, x, y, det );
4299                 ptr[(x - rc->left) * 3]     = val;
4300                 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4301                 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4302             }
4303         }
4304         break;
4305     }
4306     return TRUE;
4307 }
4308
4309 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4310 {
4311     WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4312     int x, y, left, right, det;
4313
4314     switch (mode)
4315     {
4316     case GRADIENT_FILL_RECT_H:
4317         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4318             for (x = rc->left; x < rc->right; x++)
4319                 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4320         for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4321             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4322         break;
4323
4324     case GRADIENT_FILL_RECT_V:
4325         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4326         {
4327             WORD values[4];
4328             for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4329             for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4330         }
4331         break;
4332
4333     case GRADIENT_FILL_TRIANGLE:
4334         if (!(det = triangle_det( v ))) return FALSE;
4335         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4336         {
4337             triangle_coords( v, rc, y, &left, &right );
4338             for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4339         }
4340         break;
4341     }
4342     return TRUE;
4343 }
4344
4345 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4346 {
4347     WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4348     int x, y, left, right, det;
4349
4350     switch (mode)
4351     {
4352     case GRADIENT_FILL_RECT_H:
4353         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4354             for (x = rc->left; x < rc->right; x++)
4355             {
4356                 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4357                 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4358                                      put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4359                                      put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4360             }
4361         for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4362             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4363         break;
4364
4365     case GRADIENT_FILL_RECT_V:
4366         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4367         {
4368             WORD values[4];
4369             for (x = 0; x < 4; x++)
4370             {
4371                 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4372                 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4373                              put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4374                              put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4375             }
4376             for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4377         }
4378         break;
4379
4380     case GRADIENT_FILL_TRIANGLE:
4381         if (!(det = triangle_det( v ))) return FALSE;
4382         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4383         {
4384             triangle_coords( v, rc, y, &left, &right );
4385             for (x = left; x < right; x++)
4386             {
4387                 WORD val = gradient_triangle_555( v, x, y, det );
4388                 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4389                                      put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4390                                      put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4391             }
4392         }
4393         break;
4394     }
4395     return TRUE;
4396 }
4397
4398 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4399 {
4400     BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4401     int x, y, left, right, det;
4402
4403     switch (mode)
4404     {
4405     case GRADIENT_FILL_RECT_H:
4406         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4407             for (x = rc->left; x < rc->right; x++)
4408                 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4409         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4410             memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4411         break;
4412
4413     case GRADIENT_FILL_RECT_V:
4414         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4415         {
4416             BYTE values[16];
4417             for (x = 0; x < 16; x++)
4418                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4419             for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4420         }
4421         break;
4422
4423     case GRADIENT_FILL_TRIANGLE:
4424         if (!(det = triangle_det( v ))) return FALSE;
4425         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4426         {
4427             triangle_coords( v, rc, y, &left, &right );
4428             for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4429         }
4430         break;
4431     }
4432     return TRUE;
4433 }
4434
4435 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4436 {
4437     BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4438     int x, y, left, right, det, pos;
4439
4440     switch (mode)
4441     {
4442     case GRADIENT_FILL_RECT_H:
4443         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4444         {
4445             for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4446             {
4447                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4448                 if (pos & 1)
4449                     ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4450                 else
4451                     ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4452             }
4453         }
4454         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4455         {
4456             x = rc->left;
4457             pos = (dib->rect.left + rc->left) & 1;
4458             if (pos)
4459             {
4460                 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4461                 pos++;
4462                 x++;
4463             }
4464             for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4465             if (x < rc->right)
4466                 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4467         }
4468         break;
4469
4470     case GRADIENT_FILL_RECT_V:
4471         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4472         {
4473             BYTE values[16];
4474             for (x = 0; x < 16; x++)
4475                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4476             for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4477                 if (pos & 1)
4478                     ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4479                 else
4480                     ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4481         }
4482         break;
4483
4484     case GRADIENT_FILL_TRIANGLE:
4485         if (!(det = triangle_det( v ))) return FALSE;
4486         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4487         {
4488             triangle_coords( v, rc, y, &left, &right );
4489             for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4490             {
4491                 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4492                 if (pos & 1)
4493                     ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4494                 else
4495                     ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4496             }
4497         }
4498         break;
4499     }
4500     return TRUE;
4501 }
4502
4503 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4504 {
4505     BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4506     int x, y, left, right, det, pos;
4507
4508     switch (mode)
4509     {
4510     case GRADIENT_FILL_RECT_H:
4511         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4512         {
4513             for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4514             {
4515                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4516                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4517             }
4518         }
4519         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4520             for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4521                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4522                                (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4523         break;
4524
4525     case GRADIENT_FILL_RECT_V:
4526         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4527         {
4528             BYTE values[16];
4529             for (x = 0; x < 16; x++)
4530                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4531             for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4532                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4533                                (values[x % 16] & pixel_masks_1[pos % 8]);
4534         }
4535         break;
4536
4537     case GRADIENT_FILL_TRIANGLE:
4538         if (!(det = triangle_det( v ))) return FALSE;
4539         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4540         {
4541             triangle_coords( v, rc, y, &left, &right );
4542             for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4543             {
4544                 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4545                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4546             }
4547         }
4548         break;
4549     }
4550     return TRUE;
4551 }
4552
4553 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4554 {
4555     return TRUE;
4556 }
4557
4558 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4559 {
4560     if (dst == text) return dst;
4561
4562     if (dst > text)
4563     {
4564         DWORD diff = dst - text;
4565         DWORD range = max_comp - text;
4566         dst = text + (diff * range ) / (0xff - text);
4567         return dst;
4568     }
4569     else
4570     {
4571         DWORD diff = text - dst;
4572         DWORD range = text - min_comp;
4573         dst = text - (diff * range) / text;
4574         return dst;
4575     }
4576 }
4577
4578 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4579 {
4580     return (aa_color( b_dst, text,       range->b_min, range->b_max )      |
4581             aa_color( g_dst, text >> 8,  range->g_min, range->g_max ) << 8 |
4582             aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4583 }
4584
4585 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4586                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4587 {
4588     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4589     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4590     int x, y;
4591
4592     for (y = rect->top; y < rect->bottom; y++)
4593     {
4594         for (x = 0; x < rect->right - rect->left; x++)
4595         {
4596             if (glyph_ptr[x] <= 1) continue;
4597             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4598             dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4599         }
4600         dst_ptr += dib->stride / 4;
4601         glyph_ptr += glyph->stride;
4602     }
4603 }
4604
4605 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4606                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4607 {
4608     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4609     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4610     int x, y;
4611     DWORD text, val;
4612
4613     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4614            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4615            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4616
4617     for (y = rect->top; y < rect->bottom; y++)
4618     {
4619         for (x = 0; x < rect->right - rect->left; x++)
4620         {
4621             if (glyph_ptr[x] <= 1) continue;
4622             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4623             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4624                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4625                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4626                           text, ranges + glyph_ptr[x] );
4627             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4628                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4629                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4630         }
4631         dst_ptr += dib->stride / 4;
4632         glyph_ptr += glyph->stride;
4633     }
4634 }
4635
4636 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4637                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4638 {
4639     BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4640     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4641     int x, y;
4642     DWORD val;
4643
4644     for (y = rect->top; y < rect->bottom; y++)
4645     {
4646         for (x = 0; x < rect->right - rect->left; x++)
4647         {
4648             if (glyph_ptr[x] <= 1) continue;
4649             if (glyph_ptr[x] >= 16)
4650                 val = text_pixel;
4651             else
4652                 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4653                               text_pixel, ranges + glyph_ptr[x] );
4654             dst_ptr[x * 3]     = val;
4655             dst_ptr[x * 3 + 1] = val >> 8;
4656             dst_ptr[x * 3 + 2] = val >> 16;
4657         }
4658         dst_ptr += dib->stride;
4659         glyph_ptr += glyph->stride;
4660     }
4661 }
4662
4663 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4664                             const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4665 {
4666     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4667     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4668     int x, y;
4669     DWORD text, val;
4670
4671     text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4672            ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4673            ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4674
4675     for (y = rect->top; y < rect->bottom; y++)
4676     {
4677         for (x = 0; x < rect->right - rect->left; x++)
4678         {
4679             if (glyph_ptr[x] <= 1) continue;
4680             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4681             val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4682                           ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
4683                           ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
4684                           text, ranges + glyph_ptr[x] );
4685             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4686         }
4687         dst_ptr += dib->stride / 2;
4688         glyph_ptr += glyph->stride;
4689     }
4690 }
4691
4692 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4693                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4694 {
4695     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4696     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4697     int x, y;
4698     DWORD text, val;
4699
4700     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4701            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4702            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4703
4704     for (y = rect->top; y < rect->bottom; y++)
4705     {
4706         for (x = 0; x < rect->right - rect->left; x++)
4707         {
4708             if (glyph_ptr[x] <= 1) continue;
4709             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4710             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4711                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4712                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4713                           text, ranges + glyph_ptr[x] );
4714             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4715                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4716                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4717         }
4718         dst_ptr += dib->stride / 2;
4719         glyph_ptr += glyph->stride;
4720     }
4721 }
4722
4723 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4724                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4725 {
4726     BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4727     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4728     int x, y;
4729
4730     for (y = rect->top; y < rect->bottom; y++)
4731     {
4732         for (x = 0; x < rect->right - rect->left; x++)
4733         {
4734             /* no antialiasing, glyph should only contain 0 or 16. */
4735             if (glyph_ptr[x] >= 16)
4736                 dst_ptr[x] = text_pixel;
4737         }
4738         dst_ptr += dib->stride;
4739         glyph_ptr += glyph->stride;
4740     }
4741 }
4742
4743 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4744                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4745 {
4746     BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
4747     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4748     int x, y, pos;
4749
4750     for (y = rect->top; y < rect->bottom; y++)
4751     {
4752         for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
4753         {
4754             /* no antialiasing, glyph should only contain 0 or 16. */
4755             if (glyph_ptr[x] >= 16)
4756             {
4757                 if (pos & 1)
4758                     dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
4759                 else
4760                     dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
4761             }
4762         }
4763         dst_ptr += dib->stride;
4764         glyph_ptr += glyph->stride;
4765     }
4766 }
4767
4768 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4769                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4770 {
4771     BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
4772     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4773     int x, y, pos;
4774     BYTE text = (text_pixel & 1) ? 0xff : 0;
4775
4776     for (y = rect->top; y < rect->bottom; y++)
4777     {
4778         for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
4779         {
4780             /* no antialiasing, glyph should only contain 0 or 16. */
4781             if (glyph_ptr[x] >= 16)
4782                 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4783                                    (text & pixel_masks_1[pos % 8]);
4784         }
4785         dst_ptr += dib->stride;
4786         glyph_ptr += glyph->stride;
4787     }
4788 }
4789
4790 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4791                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4792 {
4793     return;
4794 }
4795
4796 static BOOL create_rop_masks_32(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4797 {
4798     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4799     DWORD mask_start = 0, mask_offset;
4800     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4801     int x, y;
4802
4803     for(y = 0; y < hatch->height; y++)
4804     {
4805         hatch_ptr = hatch_start;
4806         mask_offset = mask_start;
4807         for(x = 0; x < hatch->width; x++)
4808         {
4809             if(*hatch_ptr & pixel_masks_1[x % 8])
4810             {
4811                 and_bits[mask_offset] = fg->and;
4812                 xor_bits[mask_offset] = fg->xor;
4813             }
4814             else
4815             {
4816                 and_bits[mask_offset] = bg->and;
4817                 xor_bits[mask_offset] = bg->xor;
4818             }
4819             if(x % 8 == 7) hatch_ptr++;
4820             mask_offset++;
4821         }
4822         hatch_start += hatch->stride;
4823         mask_start += dib->stride / 4;
4824     }
4825
4826     return TRUE;
4827 }
4828
4829 static BOOL create_rop_masks_24(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4830 {
4831     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4832     DWORD mask_start = 0, mask_offset;
4833     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4834     int x, y;
4835
4836     for(y = 0; y < hatch->height; y++)
4837     {
4838         hatch_ptr = hatch_start;
4839         mask_offset = mask_start;
4840         for(x = 0; x < hatch->width; x++)
4841         {
4842             if(*hatch_ptr & pixel_masks_1[x % 8])
4843             {
4844                 and_bits[mask_offset]   =  fg->and        & 0xff;
4845                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
4846                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
4847                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
4848                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
4849                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4850             }
4851             else
4852             {
4853                 and_bits[mask_offset]   =  bg->and        & 0xff;
4854                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
4855                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
4856                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
4857                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
4858                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4859             }
4860             if(x % 8 == 7) hatch_ptr++;
4861         }
4862         hatch_start += hatch->stride;
4863         mask_start += dib->stride;
4864     }
4865
4866     return TRUE;
4867 }
4868
4869 static BOOL create_rop_masks_16(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4870 {
4871     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4872     DWORD mask_start = 0, mask_offset;
4873     WORD *and_bits = bits->and, *xor_bits = bits->xor;
4874     int x, y;
4875
4876     for(y = 0; y < hatch->height; y++)
4877     {
4878         hatch_ptr = hatch_start;
4879         mask_offset = mask_start;
4880         for(x = 0; x < hatch->width; x++)
4881         {
4882             if(*hatch_ptr & pixel_masks_1[x % 8])
4883             {
4884                 and_bits[mask_offset] = fg->and;
4885                 xor_bits[mask_offset] = fg->xor;
4886             }
4887             else
4888             {
4889                 and_bits[mask_offset] = bg->and;
4890                 xor_bits[mask_offset] = bg->xor;
4891             }
4892             if(x % 8 == 7) hatch_ptr++;
4893             mask_offset++;
4894         }
4895         hatch_start += hatch->stride;
4896         mask_start += dib->stride / 2;
4897     }
4898
4899     return TRUE;
4900 }
4901
4902 static BOOL create_rop_masks_8(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4903 {
4904     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4905     DWORD mask_start = 0, mask_offset;
4906     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4907     int x, y;
4908
4909     for(y = 0; y < hatch->height; y++)
4910     {
4911         hatch_ptr = hatch_start;
4912         mask_offset = mask_start;
4913         for(x = 0; x < hatch->width; x++)
4914         {
4915             if(*hatch_ptr & pixel_masks_1[x % 8])
4916             {
4917                 and_bits[mask_offset] = fg->and;
4918                 xor_bits[mask_offset] = fg->xor;
4919             }
4920             else
4921             {
4922                 and_bits[mask_offset] = bg->and;
4923                 xor_bits[mask_offset] = bg->xor;
4924             }
4925             if(x % 8 == 7) hatch_ptr++;
4926             mask_offset++;
4927         }
4928         hatch_start += hatch->stride;
4929         mask_start += dib->stride;
4930     }
4931
4932     return TRUE;
4933 }
4934
4935 static BOOL create_rop_masks_4(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4936 {
4937     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4938     DWORD mask_start = 0, mask_offset;
4939     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4940     const rop_mask *rop_mask;
4941     int x, y;
4942
4943     for(y = 0; y < hatch->height; y++)
4944     {
4945         hatch_ptr = hatch_start;
4946         mask_offset = mask_start;
4947         for(x = 0; x < hatch->width; x++)
4948         {
4949             if(*hatch_ptr & pixel_masks_1[x % 8])
4950                 rop_mask = fg;
4951             else
4952                 rop_mask = bg;
4953
4954             if(x & 1)
4955             {
4956                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4957                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4958                 mask_offset++;
4959             }
4960             else
4961             {
4962                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4963                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4964             }
4965
4966             if(x % 8 == 7) hatch_ptr++;
4967         }
4968         hatch_start += hatch->stride;
4969         mask_start += dib->stride;
4970     }
4971
4972     return TRUE;
4973 }
4974
4975 static BOOL create_rop_masks_1(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4976 {
4977     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4978     DWORD mask_start = 0, mask_offset;
4979     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4980     rop_mask rop_mask;
4981     int x, y, bit_pos;
4982
4983     for(y = 0; y < hatch->height; y++)
4984     {
4985         hatch_ptr = hatch_start;
4986         mask_offset = mask_start;
4987         for(x = 0, bit_pos = 0; x < hatch->width; x++)
4988         {
4989             if(*hatch_ptr & pixel_masks_1[x % 8])
4990             {
4991                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4992                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4993             }
4994             else
4995             {
4996                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4997                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4998             }
4999
5000             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
5001
5002             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
5003             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
5004
5005             if(++bit_pos == 8)
5006             {
5007                 mask_offset++;
5008                 hatch_ptr++;
5009                 bit_pos = 0;
5010             }
5011         }
5012         hatch_start += hatch->stride;
5013         mask_start += dib->stride;
5014     }
5015
5016     return TRUE;
5017 }
5018
5019 static BOOL create_rop_masks_null(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5020 {
5021     return FALSE;
5022 }
5023
5024 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5025 {
5026     switch (mode)
5027     {
5028     default:
5029     case STRETCH_DELETESCANS:
5030         get_rop_codes( R2_COPYPEN, codes );
5031         break;
5032     case STRETCH_ORSCANS:
5033         get_rop_codes( R2_MERGEPEN, codes );
5034         break;
5035     case STRETCH_ANDSCANS:
5036         get_rop_codes( R2_MASKPEN, codes );
5037         break;
5038     }
5039     return;
5040 }
5041
5042 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5043                            const dib_info *src_dib, const POINT *src_start,
5044                            const struct stretch_params *params, int mode,
5045                            BOOL keep_dst)
5046 {
5047     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5048     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5049     int err = params->err_start;
5050     int width;
5051     struct rop_codes codes;
5052
5053     rop_codes_from_stretch_mode( mode, &codes );
5054     for (width = params->length; width; width--)
5055     {
5056         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5057         dst_ptr += params->dst_inc;
5058         if (err > 0)
5059         {
5060             src_ptr += params->src_inc;
5061             err += params->err_add_1;
5062         }
5063         else err += params->err_add_2;
5064     }
5065 }
5066
5067 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5068                            const dib_info *src_dib, const POINT *src_start,
5069                            const struct stretch_params *params, int mode,
5070                            BOOL keep_dst)
5071 {
5072     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5073     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5074     int err = params->err_start;
5075     int width;
5076     struct rop_codes codes;
5077
5078     rop_codes_from_stretch_mode( mode, &codes );
5079     for (width = params->length; width; width--)
5080     {
5081         do_rop_codes_8( dst_ptr,     *src_ptr,       &codes );
5082         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5083         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5084         dst_ptr += 3 * params->dst_inc;
5085         if (err > 0)
5086         {
5087             src_ptr += 3 * params->src_inc;
5088             err += params->err_add_1;
5089         }
5090         else err += params->err_add_2;
5091     }
5092 }
5093
5094 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5095                            const dib_info *src_dib, const POINT *src_start,
5096                            const struct stretch_params *params, int mode,
5097                            BOOL keep_dst)
5098 {
5099     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5100     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5101     int err = params->err_start;
5102     int width;
5103     struct rop_codes codes;
5104
5105     rop_codes_from_stretch_mode( mode, &codes );
5106     for (width = params->length; width; width--)
5107     {
5108         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5109         dst_ptr += params->dst_inc;
5110         if (err > 0)
5111         {
5112             src_ptr += params->src_inc;
5113             err += params->err_add_1;
5114         }
5115         else err += params->err_add_2;
5116     }
5117 }
5118
5119 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5120                           const dib_info *src_dib, const POINT *src_start,
5121                           const struct stretch_params *params, int mode,
5122                           BOOL keep_dst)
5123 {
5124     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5125     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5126     int err = params->err_start;
5127     int width;
5128     struct rop_codes codes;
5129
5130     rop_codes_from_stretch_mode( mode, &codes );
5131     for (width = params->length; width; width--)
5132     {
5133         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5134         dst_ptr += params->dst_inc;
5135         if (err > 0)
5136         {
5137             src_ptr += params->src_inc;
5138             err += params->err_add_1;
5139         }
5140         else err += params->err_add_2;
5141     }
5142 }
5143
5144 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5145                           const dib_info *src_dib, const POINT *src_start,
5146                           const struct stretch_params *params, int mode,
5147                           BOOL keep_dst)
5148 {
5149     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5150     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5151     int err = params->err_start;
5152     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5153     struct rop_codes codes;
5154     BYTE src_val;
5155
5156     rop_codes_from_stretch_mode( mode, &codes );
5157     for (width = params->length; width; width--)
5158     {
5159         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5160         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5161
5162         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5163
5164         if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5165             dst_ptr += params->dst_inc;
5166         dst_x += params->dst_inc;
5167
5168         if (err > 0)
5169         {
5170             if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5171                 src_ptr += params->src_inc;
5172             src_x += params->src_inc;
5173             err += params->err_add_1;
5174         }
5175         else err += params->err_add_2;
5176     }
5177 }
5178
5179 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5180                           const dib_info *src_dib, const POINT *src_start,
5181                           const struct stretch_params *params, int mode,
5182                           BOOL keep_dst)
5183 {
5184     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5185     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5186     int err = params->err_start;
5187     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5188     struct rop_codes codes;
5189     BYTE src_val;
5190
5191     rop_codes_from_stretch_mode( mode, &codes );
5192     for (width = params->length; width; width--)
5193     {
5194         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5195         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5196
5197         if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5198             dst_ptr += params->dst_inc;
5199         dst_x += params->dst_inc;
5200
5201         if (err > 0)
5202         {
5203             if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5204                 src_ptr += params->src_inc;
5205             src_x += params->src_inc;
5206             err += params->err_add_1;
5207         }
5208         else err += params->err_add_2;
5209     }
5210 }
5211
5212 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5213                              const dib_info *src_dib, const POINT *src_start,
5214                              const struct stretch_params *params, int mode,
5215                              BOOL keep_dst)
5216 {
5217     FIXME("bit count %d\n", dst_dib->bit_count);
5218     return;
5219 }
5220
5221 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5222                           const dib_info *src_dib, const POINT *src_start,
5223                           const struct stretch_params *params, int mode,
5224                           BOOL keep_dst)
5225 {
5226     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5227     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5228     int err = params->err_start;
5229     int width;
5230     struct rop_codes codes;
5231     DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5232     BOOL new_pix = TRUE;
5233
5234     rop_codes_from_stretch_mode( mode, &codes );
5235     for (width = params->length; width; width--)
5236     {
5237         if (new_pix && !keep_dst) *dst_ptr = init_val;
5238         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5239         new_pix = FALSE;
5240         src_ptr += params->src_inc;
5241         if (err > 0)
5242         {
5243             dst_ptr += params->dst_inc;
5244             new_pix = TRUE;
5245             err += params->err_add_1;
5246         }
5247         else err += params->err_add_2;
5248     }
5249 }
5250
5251 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5252                           const dib_info *src_dib, const POINT *src_start,
5253                           const struct stretch_params *params, int mode,
5254                           BOOL keep_dst)
5255 {
5256     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5257     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5258     int err = params->err_start;
5259     int width;
5260     struct rop_codes codes;
5261     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5262     BOOL new_pix = TRUE;
5263
5264     rop_codes_from_stretch_mode( mode, &codes );
5265     for (width = params->length; width; width--)
5266     {
5267         if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5268         do_rop_codes_8( dst_ptr,      *src_ptr,      &codes );
5269         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5270         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5271         new_pix = FALSE;
5272         src_ptr += 3 * params->src_inc;
5273         if (err > 0)
5274         {
5275             dst_ptr += 3 * params->dst_inc;
5276             new_pix = TRUE;
5277             err += params->err_add_1;
5278         }
5279         else err += params->err_add_2;
5280     }
5281 }
5282
5283 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5284                           const dib_info *src_dib, const POINT *src_start,
5285                           const struct stretch_params *params, int mode,
5286                           BOOL keep_dst)
5287 {
5288     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5289     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5290     int err = params->err_start;
5291     int width;
5292     struct rop_codes codes;
5293     WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5294     BOOL new_pix = TRUE;
5295
5296     rop_codes_from_stretch_mode( mode, &codes );
5297     for (width = params->length; width; width--)
5298     {
5299         if (new_pix && !keep_dst) *dst_ptr = init_val;
5300         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5301         new_pix = FALSE;
5302         src_ptr += params->src_inc;
5303         if (err > 0)
5304         {
5305             dst_ptr += params->dst_inc;
5306             new_pix = TRUE;
5307             err += params->err_add_1;
5308         }
5309         else err += params->err_add_2;
5310     }
5311 }
5312
5313 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5314                          const dib_info *src_dib, const POINT *src_start,
5315                          const struct stretch_params *params, int mode,
5316                          BOOL keep_dst)
5317 {
5318     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5319     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5320     int err = params->err_start;
5321     int width;
5322     struct rop_codes codes;
5323     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5324     BOOL new_pix = TRUE;
5325
5326     rop_codes_from_stretch_mode( mode, &codes );
5327     for (width = params->length; width; width--)
5328     {
5329         if (new_pix && !keep_dst) *dst_ptr = init_val;
5330         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5331         new_pix = FALSE;
5332         src_ptr += params->src_inc;
5333         if (err > 0)
5334         {
5335             dst_ptr += params->dst_inc;
5336             new_pix = TRUE;
5337             err += params->err_add_1;
5338         }
5339         else err += params->err_add_2;
5340     }
5341 }
5342
5343 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5344                          const dib_info *src_dib, const POINT *src_start,
5345                          const struct stretch_params *params, int mode,
5346                          BOOL keep_dst)
5347 {
5348     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5349     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5350     int err = params->err_start;
5351     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5352     struct rop_codes codes;
5353     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5354     BOOL new_pix = TRUE;
5355
5356     rop_codes_from_stretch_mode( mode, &codes );
5357     for (width = params->length; width; width--)
5358     {
5359         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
5360
5361         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5362         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5363
5364         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5365         new_pix = FALSE;
5366
5367         if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5368             src_ptr += params->src_inc;
5369         src_x += params->src_inc;
5370
5371         if (err > 0)
5372         {
5373             if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5374                 dst_ptr += params->dst_inc;
5375             dst_x += params->dst_inc;
5376             new_pix = TRUE;
5377             err += params->err_add_1;
5378         }
5379         else err += params->err_add_2;
5380     }
5381 }
5382
5383 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5384                          const dib_info *src_dib, const POINT *src_start,
5385                          const struct stretch_params *params, int mode,
5386                          BOOL keep_dst)
5387 {
5388     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5389     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5390     int err = params->err_start;
5391     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5392     struct rop_codes codes;
5393     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5394     BOOL new_pix = TRUE;
5395
5396     rop_codes_from_stretch_mode( mode, &codes );
5397     for (width = params->length; width; width--)
5398     {
5399         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5400         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5401         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5402         new_pix = FALSE;
5403
5404         if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5405             src_ptr += params->src_inc;
5406         src_x += params->src_inc;
5407
5408         if (err > 0)
5409         {
5410             if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5411                 dst_ptr += params->dst_inc;
5412             dst_x += params->dst_inc;
5413             new_pix = TRUE;
5414             err += params->err_add_1;
5415         }
5416         else err += params->err_add_2;
5417     }
5418 }
5419
5420 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5421                             const dib_info *src_dib, const POINT *src_start,
5422                             const struct stretch_params *params, int mode,
5423                             BOOL keep_dst)
5424 {
5425     FIXME("bit count %d\n", dst_dib->bit_count);
5426     return;
5427 }
5428
5429 const primitive_funcs funcs_8888 =
5430 {
5431     solid_rects_32,
5432     solid_line_32,
5433     pattern_rects_32,
5434     copy_rect_32,
5435     blend_rect_8888,
5436     gradient_rect_8888,
5437     draw_glyph_8888,
5438     get_pixel_32,
5439     colorref_to_pixel_888,
5440     pixel_to_colorref_888,
5441     convert_to_8888,
5442     create_rop_masks_32,
5443     stretch_row_32,
5444     shrink_row_32
5445 };
5446
5447 const primitive_funcs funcs_32 =
5448 {
5449     solid_rects_32,
5450     solid_line_32,
5451     pattern_rects_32,
5452     copy_rect_32,
5453     blend_rect_32,
5454     gradient_rect_32,
5455     draw_glyph_32,
5456     get_pixel_32,
5457     colorref_to_pixel_masks,
5458     pixel_to_colorref_masks,
5459     convert_to_32,
5460     create_rop_masks_32,
5461     stretch_row_32,
5462     shrink_row_32
5463 };
5464
5465 const primitive_funcs funcs_24 =
5466 {
5467     solid_rects_24,
5468     solid_line_24,
5469     pattern_rects_24,
5470     copy_rect_24,
5471     blend_rect_24,
5472     gradient_rect_24,
5473     draw_glyph_24,
5474     get_pixel_24,
5475     colorref_to_pixel_888,
5476     pixel_to_colorref_888,
5477     convert_to_24,
5478     create_rop_masks_24,
5479     stretch_row_24,
5480     shrink_row_24
5481 };
5482
5483 const primitive_funcs funcs_555 =
5484 {
5485     solid_rects_16,
5486     solid_line_16,
5487     pattern_rects_16,
5488     copy_rect_16,
5489     blend_rect_555,
5490     gradient_rect_555,
5491     draw_glyph_555,
5492     get_pixel_16,
5493     colorref_to_pixel_555,
5494     pixel_to_colorref_555,
5495     convert_to_555,
5496     create_rop_masks_16,
5497     stretch_row_16,
5498     shrink_row_16
5499 };
5500
5501 const primitive_funcs funcs_16 =
5502 {
5503     solid_rects_16,
5504     solid_line_16,
5505     pattern_rects_16,
5506     copy_rect_16,
5507     blend_rect_16,
5508     gradient_rect_16,
5509     draw_glyph_16,
5510     get_pixel_16,
5511     colorref_to_pixel_masks,
5512     pixel_to_colorref_masks,
5513     convert_to_16,
5514     create_rop_masks_16,
5515     stretch_row_16,
5516     shrink_row_16
5517 };
5518
5519 const primitive_funcs funcs_8 =
5520 {
5521     solid_rects_8,
5522     solid_line_8,
5523     pattern_rects_8,
5524     copy_rect_8,
5525     blend_rect_8,
5526     gradient_rect_8,
5527     draw_glyph_8,
5528     get_pixel_8,
5529     colorref_to_pixel_colortable,
5530     pixel_to_colorref_colortable,
5531     convert_to_8,
5532     create_rop_masks_8,
5533     stretch_row_8,
5534     shrink_row_8
5535 };
5536
5537 const primitive_funcs funcs_4 =
5538 {
5539     solid_rects_4,
5540     solid_line_4,
5541     pattern_rects_4,
5542     copy_rect_4,
5543     blend_rect_4,
5544     gradient_rect_4,
5545     draw_glyph_4,
5546     get_pixel_4,
5547     colorref_to_pixel_colortable,
5548     pixel_to_colorref_colortable,
5549     convert_to_4,
5550     create_rop_masks_4,
5551     stretch_row_4,
5552     shrink_row_4
5553 };
5554
5555 const primitive_funcs funcs_1 =
5556 {
5557     solid_rects_1,
5558     solid_line_1,
5559     pattern_rects_1,
5560     copy_rect_1,
5561     blend_rect_1,
5562     gradient_rect_1,
5563     draw_glyph_1,
5564     get_pixel_1,
5565     colorref_to_pixel_colortable,
5566     pixel_to_colorref_colortable,
5567     convert_to_1,
5568     create_rop_masks_1,
5569     stretch_row_1,
5570     shrink_row_1
5571 };
5572
5573 const primitive_funcs funcs_null =
5574 {
5575     solid_rects_null,
5576     solid_line_null,
5577     pattern_rects_null,
5578     copy_rect_null,
5579     blend_rect_null,
5580     gradient_rect_null,
5581     draw_glyph_null,
5582     get_pixel_null,
5583     colorref_to_pixel_null,
5584     pixel_to_colorref_null,
5585     convert_to_null,
5586     create_rop_masks_null,
5587     stretch_row_null,
5588     shrink_row_null
5589 };