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