gdi32: Make blend_subpixel inline.
[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             for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
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++)
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             for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4586             ptr += dib->stride / 4;
4587         }
4588         break;
4589
4590     case GRADIENT_FILL_TRIANGLE:
4591         if (!(det = triangle_det( v ))) return FALSE;
4592         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4593         {
4594             triangle_coords( v, rc, y, &left, &right );
4595
4596             if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4597                 for (x = left; x < right; x++)
4598                 {
4599                     DWORD val = gradient_triangle_24( v, x, y, det );
4600                     ptr[x - rc->left] = ((( val        & 0xff) << dib->blue_shift) |
4601                                          (((val >> 8)  & 0xff) << dib->green_shift) |
4602                                          (((val >> 16) & 0xff) << dib->red_shift));
4603                 }
4604             else
4605                 for (x = left; x < right; x++)
4606                 {
4607                     DWORD val = gradient_triangle_24( v, x, y, det );
4608                     ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4609                                          put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4610                                          put_field( val,       dib->blue_shift,  dib->blue_len ));
4611                 }
4612         }
4613         break;
4614     }
4615     return TRUE;
4616 }
4617
4618 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4619 {
4620     BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4621     int x, y, left, right, det;
4622
4623     switch (mode)
4624     {
4625     case GRADIENT_FILL_RECT_H:
4626         for (x = 0; x < rc->right - rc->left; x++)
4627         {
4628             DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4629             ptr[x * 3]     = val;
4630             ptr[x * 3 + 1] = val >> 8;
4631             ptr[x * 3 + 2] = val >> 16;
4632         }
4633
4634         for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4635             memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4636         break;
4637
4638     case GRADIENT_FILL_RECT_V:
4639         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4640         {
4641             DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4642             for (x = 0; x < rc->right - rc->left; x++)
4643             {
4644                 ptr[x * 3]     = val;
4645                 ptr[x * 3 + 1] = val >> 8;
4646                 ptr[x * 3 + 2] = val >> 16;
4647             }
4648         }
4649         break;
4650
4651     case GRADIENT_FILL_TRIANGLE:
4652         if (!(det = triangle_det( v ))) return FALSE;
4653         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4654         {
4655             triangle_coords( v, rc, y, &left, &right );
4656             for (x = left; x < right; x++)
4657             {
4658                 DWORD val = gradient_triangle_24( v, x, y, det );
4659                 ptr[(x - rc->left) * 3]     = val;
4660                 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4661                 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4662             }
4663         }
4664         break;
4665     }
4666     return TRUE;
4667 }
4668
4669 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4670 {
4671     WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4672     int x, y, left, right, det;
4673
4674     switch (mode)
4675     {
4676     case GRADIENT_FILL_RECT_H:
4677         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4678             for (x = rc->left; x < rc->right; x++)
4679                 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4680         for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4681             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4682         break;
4683
4684     case GRADIENT_FILL_RECT_V:
4685         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4686         {
4687             WORD values[4];
4688             for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4689             for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4690         }
4691         break;
4692
4693     case GRADIENT_FILL_TRIANGLE:
4694         if (!(det = triangle_det( v ))) return FALSE;
4695         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4696         {
4697             triangle_coords( v, rc, y, &left, &right );
4698             for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4699         }
4700         break;
4701     }
4702     return TRUE;
4703 }
4704
4705 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4706 {
4707     WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4708     int x, y, left, right, det;
4709
4710     switch (mode)
4711     {
4712     case GRADIENT_FILL_RECT_H:
4713         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4714             for (x = rc->left; x < rc->right; x++)
4715             {
4716                 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4717                 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4718                                      put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4719                                      put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4720             }
4721         for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4722             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4723         break;
4724
4725     case GRADIENT_FILL_RECT_V:
4726         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4727         {
4728             WORD values[4];
4729             for (x = 0; x < 4; x++)
4730             {
4731                 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4732                 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4733                              put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4734                              put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4735             }
4736             for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4737         }
4738         break;
4739
4740     case GRADIENT_FILL_TRIANGLE:
4741         if (!(det = triangle_det( v ))) return FALSE;
4742         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4743         {
4744             triangle_coords( v, rc, y, &left, &right );
4745             for (x = left; x < right; x++)
4746             {
4747                 WORD val = gradient_triangle_555( v, x, y, det );
4748                 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4749                                      put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4750                                      put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4751             }
4752         }
4753         break;
4754     }
4755     return TRUE;
4756 }
4757
4758 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4759 {
4760     BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4761     int x, y, left, right, det;
4762
4763     switch (mode)
4764     {
4765     case GRADIENT_FILL_RECT_H:
4766         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4767             for (x = rc->left; x < rc->right; x++)
4768                 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4769         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4770             memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4771         break;
4772
4773     case GRADIENT_FILL_RECT_V:
4774         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4775         {
4776             BYTE values[16];
4777             for (x = 0; x < 16; x++)
4778                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4779             for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4780         }
4781         break;
4782
4783     case GRADIENT_FILL_TRIANGLE:
4784         if (!(det = triangle_det( v ))) return FALSE;
4785         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4786         {
4787             triangle_coords( v, rc, y, &left, &right );
4788             for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4789         }
4790         break;
4791     }
4792     return TRUE;
4793 }
4794
4795 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4796 {
4797     BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4798     int x, y, left, right, det, pos;
4799
4800     switch (mode)
4801     {
4802     case GRADIENT_FILL_RECT_H:
4803         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4804         {
4805             for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4806             {
4807                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4808                 if (pos & 1)
4809                     ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4810                 else
4811                     ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4812             }
4813         }
4814         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4815         {
4816             x = rc->left;
4817             pos = (dib->rect.left + rc->left) & 1;
4818             if (pos)
4819             {
4820                 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4821                 pos++;
4822                 x++;
4823             }
4824             for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4825             if (x < rc->right)
4826                 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4827         }
4828         break;
4829
4830     case GRADIENT_FILL_RECT_V:
4831         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4832         {
4833             BYTE values[16];
4834             for (x = 0; x < 16; x++)
4835                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4836             for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4837                 if (pos & 1)
4838                     ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4839                 else
4840                     ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4841         }
4842         break;
4843
4844     case GRADIENT_FILL_TRIANGLE:
4845         if (!(det = triangle_det( v ))) return FALSE;
4846         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4847         {
4848             triangle_coords( v, rc, y, &left, &right );
4849             for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4850             {
4851                 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4852                 if (pos & 1)
4853                     ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4854                 else
4855                     ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4856             }
4857         }
4858         break;
4859     }
4860     return TRUE;
4861 }
4862
4863 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4864 {
4865     BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4866     int x, y, left, right, det, pos;
4867
4868     switch (mode)
4869     {
4870     case GRADIENT_FILL_RECT_H:
4871         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4872         {
4873             for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4874             {
4875                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4876                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4877             }
4878         }
4879         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4880             for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4881                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4882                                (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4883         break;
4884
4885     case GRADIENT_FILL_RECT_V:
4886         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4887         {
4888             BYTE values[16];
4889             for (x = 0; x < 16; x++)
4890                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4891             for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4892                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4893                                (values[x % 16] & pixel_masks_1[pos % 8]);
4894         }
4895         break;
4896
4897     case GRADIENT_FILL_TRIANGLE:
4898         if (!(det = triangle_det( v ))) return FALSE;
4899         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4900         {
4901             triangle_coords( v, rc, y, &left, &right );
4902             for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4903             {
4904                 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4905                 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4906             }
4907         }
4908         break;
4909     }
4910     return TRUE;
4911 }
4912
4913 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4914 {
4915     return TRUE;
4916 }
4917
4918 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4919 {
4920     if (dst == text) return dst;
4921
4922     if (dst > text)
4923     {
4924         DWORD diff = dst - text;
4925         DWORD range = max_comp - text;
4926         dst = text + (diff * range ) / (0xff - text);
4927         return dst;
4928     }
4929     else
4930     {
4931         DWORD diff = text - dst;
4932         DWORD range = text - min_comp;
4933         dst = text - (diff * range) / text;
4934         return dst;
4935     }
4936 }
4937
4938 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4939 {
4940     return (aa_color( b_dst, text,       range->b_min, range->b_max )      |
4941             aa_color( g_dst, text >> 8,  range->g_min, range->g_max ) << 8 |
4942             aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4943 }
4944
4945 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4946                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4947 {
4948     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4949     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4950     int x, y;
4951
4952     for (y = rect->top; y < rect->bottom; y++)
4953     {
4954         for (x = 0; x < rect->right - rect->left; x++)
4955         {
4956             if (glyph_ptr[x] <= 1) continue;
4957             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4958             dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4959         }
4960         dst_ptr += dib->stride / 4;
4961         glyph_ptr += glyph->stride;
4962     }
4963 }
4964
4965 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4966                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4967 {
4968     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4969     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4970     int x, y;
4971     DWORD text, val;
4972
4973     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4974            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4975            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4976
4977     for (y = rect->top; y < rect->bottom; y++)
4978     {
4979         for (x = 0; x < rect->right - rect->left; x++)
4980         {
4981             if (glyph_ptr[x] <= 1) continue;
4982             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4983             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4984                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4985                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4986                           text, ranges + glyph_ptr[x] );
4987             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4988                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4989                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4990         }
4991         dst_ptr += dib->stride / 4;
4992         glyph_ptr += glyph->stride;
4993     }
4994 }
4995
4996 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4997                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4998 {
4999     BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
5000     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5001     int x, y;
5002     DWORD val;
5003
5004     for (y = rect->top; y < rect->bottom; y++)
5005     {
5006         for (x = 0; x < rect->right - rect->left; x++)
5007         {
5008             if (glyph_ptr[x] <= 1) continue;
5009             if (glyph_ptr[x] >= 16)
5010                 val = text_pixel;
5011             else
5012                 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
5013                               text_pixel, ranges + glyph_ptr[x] );
5014             dst_ptr[x * 3]     = val;
5015             dst_ptr[x * 3 + 1] = val >> 8;
5016             dst_ptr[x * 3 + 2] = val >> 16;
5017         }
5018         dst_ptr += dib->stride;
5019         glyph_ptr += glyph->stride;
5020     }
5021 }
5022
5023 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5024                             const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5025 {
5026     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5027     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5028     int x, y;
5029     DWORD text, val;
5030
5031     text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
5032            ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
5033            ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
5034
5035     for (y = rect->top; y < rect->bottom; y++)
5036     {
5037         for (x = 0; x < rect->right - rect->left; x++)
5038         {
5039             if (glyph_ptr[x] <= 1) continue;
5040             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
5041             val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
5042                           ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
5043                           ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
5044                           text, ranges + glyph_ptr[x] );
5045             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
5046         }
5047         dst_ptr += dib->stride / 2;
5048         glyph_ptr += glyph->stride;
5049     }
5050 }
5051
5052 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5053                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5054 {
5055     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5056     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5057     int x, y;
5058     DWORD text, val;
5059
5060     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
5061            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5062            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
5063
5064     for (y = rect->top; y < rect->bottom; y++)
5065     {
5066         for (x = 0; x < rect->right - rect->left; x++)
5067         {
5068             if (glyph_ptr[x] <= 1) continue;
5069             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
5070             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
5071                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5072                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
5073                           text, ranges + glyph_ptr[x] );
5074             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
5075                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
5076                           put_field( val,       dib->blue_shift,  dib->blue_len ));
5077         }
5078         dst_ptr += dib->stride / 2;
5079         glyph_ptr += glyph->stride;
5080     }
5081 }
5082
5083 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5084                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5085 {
5086     BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
5087     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5088     int x, y;
5089
5090     for (y = rect->top; y < rect->bottom; y++)
5091     {
5092         for (x = 0; x < rect->right - rect->left; x++)
5093         {
5094             /* no antialiasing, glyph should only contain 0 or 16. */
5095             if (glyph_ptr[x] >= 16)
5096                 dst_ptr[x] = text_pixel;
5097         }
5098         dst_ptr += dib->stride;
5099         glyph_ptr += glyph->stride;
5100     }
5101 }
5102
5103 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5104                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5105 {
5106     BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
5107     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5108     int x, y, pos;
5109
5110     for (y = rect->top; y < rect->bottom; y++)
5111     {
5112         for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
5113         {
5114             /* no antialiasing, glyph should only contain 0 or 16. */
5115             if (glyph_ptr[x] >= 16)
5116             {
5117                 if (pos & 1)
5118                     dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
5119                 else
5120                     dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
5121             }
5122         }
5123         dst_ptr += dib->stride;
5124         glyph_ptr += glyph->stride;
5125     }
5126 }
5127
5128 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5129                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5130 {
5131     BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
5132     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5133     int x, y, pos;
5134     BYTE text = (text_pixel & 1) ? 0xff : 0;
5135
5136     for (y = rect->top; y < rect->bottom; y++)
5137     {
5138         for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
5139         {
5140             /* no antialiasing, glyph should only contain 0 or 16. */
5141             if (glyph_ptr[x] >= 16)
5142                 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5143                                    (text & pixel_masks_1[pos % 8]);
5144         }
5145         dst_ptr += dib->stride;
5146         glyph_ptr += glyph->stride;
5147     }
5148 }
5149
5150 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5151                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5152 {
5153     return;
5154 }
5155
5156 static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha )
5157 {
5158     return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 |
5159            blend_color( g, text >> 8,  (BYTE)(alpha >> 8) )  << 8  |
5160            blend_color( b, text,       (BYTE) alpha );
5161 }
5162
5163 static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5164                                       const POINT *origin, DWORD text_pixel )
5165 {
5166     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
5167     const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5168     int x, y;
5169
5170     for (y = rect->top; y < rect->bottom; y++)
5171     {
5172         for (x = 0; x < rect->right - rect->left; x++)
5173         {
5174             if (glyph_ptr[x] == 0) continue;
5175             dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, glyph_ptr[x] );
5176         }
5177         dst_ptr += dib->stride / 4;
5178         glyph_ptr += glyph->stride / 4;
5179     }
5180 }
5181
5182 static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5183                                     const POINT *origin, DWORD text_pixel )
5184 {
5185     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
5186     const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5187     int x, y;
5188     DWORD text, val;
5189
5190     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
5191            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5192            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
5193
5194     for (y = rect->top; y < rect->bottom; y++)
5195     {
5196         for (x = 0; x < rect->right - rect->left; x++)
5197         {
5198             if (glyph_ptr[x] == 0) continue;
5199             val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
5200                                   get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5201                                   get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
5202                                   text, glyph_ptr[x] );
5203             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
5204                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
5205                           put_field( val,       dib->blue_shift,  dib->blue_len ));
5206         }
5207         dst_ptr += dib->stride / 4;
5208         glyph_ptr += glyph->stride / 4;
5209     }
5210 }
5211
5212 static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5213                                     const POINT *origin, DWORD text_pixel )
5214 {
5215     BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
5216     const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5217     int x, y;
5218     DWORD val;
5219
5220     for (y = rect->top; y < rect->bottom; y++)
5221     {
5222         for (x = 0; x < rect->right - rect->left; x++)
5223         {
5224             if (glyph_ptr[x] == 0) continue;
5225             val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
5226                                   text_pixel, glyph_ptr[x] );
5227             dst_ptr[x * 3]     = val;
5228             dst_ptr[x * 3 + 1] = val >> 8;
5229             dst_ptr[x * 3 + 2] = val >> 16;
5230         }
5231         dst_ptr += dib->stride;
5232         glyph_ptr += glyph->stride / 4;
5233     }
5234 }
5235
5236 static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5237                                      const POINT *origin, DWORD text_pixel )
5238 {
5239     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5240     const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5241     int x, y;
5242     DWORD text, val;
5243
5244     text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
5245            ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
5246            ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
5247
5248     for (y = rect->top; y < rect->bottom; y++)
5249     {
5250         for (x = 0; x < rect->right - rect->left; x++)
5251         {
5252             if (glyph_ptr[x] == 0) continue;
5253             val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
5254                                   ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
5255                                   ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
5256                                   text, glyph_ptr[x] );
5257             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
5258         }
5259         dst_ptr += dib->stride / 2;
5260         glyph_ptr += glyph->stride / 4;
5261     }
5262 }
5263
5264 static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5265                                     const POINT *origin, DWORD text_pixel )
5266 {
5267     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5268     const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5269     int x, y;
5270     DWORD text, val;
5271
5272     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
5273            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5274            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
5275
5276     for (y = rect->top; y < rect->bottom; y++)
5277     {
5278         for (x = 0; x < rect->right - rect->left; x++)
5279         {
5280             if (glyph_ptr[x] == 0) continue;
5281             val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
5282                                   get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5283                                   get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
5284                                   text, glyph_ptr[x] );
5285             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
5286                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
5287                           put_field( val,       dib->blue_shift,  dib->blue_len ));
5288         }
5289         dst_ptr += dib->stride / 2;
5290         glyph_ptr += glyph->stride / 4;
5291     }
5292 }
5293
5294 static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5295                                       const POINT *origin, DWORD text_pixel )
5296 {
5297     return;
5298 }
5299
5300 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
5301                                 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5302 {
5303     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
5304     int x, y;
5305
5306     /* masks are always 8x8 */
5307     assert( dib->width == 8 );
5308     assert( dib->height == 8 );
5309
5310     for(y = 0; y < 8; y++, hatch_ptr++)
5311     {
5312         for(x = 0; x < 8; x++)
5313         {
5314             if(*hatch_ptr & pixel_masks_1[x])
5315             {
5316                 and_bits[x] = fg->and;
5317                 xor_bits[x] = fg->xor;
5318             }
5319             else
5320             {
5321                 and_bits[x] = bg->and;
5322                 xor_bits[x] = bg->xor;
5323             }
5324         }
5325         and_bits += dib->stride / 4;
5326         xor_bits += dib->stride / 4;
5327     }
5328 }
5329
5330 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
5331                                 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5332 {
5333     DWORD mask_start = 0, mask_offset;
5334     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5335     int x, y;
5336
5337     /* masks are always 8x8 */
5338     assert( dib->width == 8 );
5339     assert( dib->height == 8 );
5340
5341     for(y = 0; y < 8; y++, hatch_ptr++)
5342     {
5343         mask_offset = mask_start;
5344         for(x = 0; x < 8; x++)
5345         {
5346             if(*hatch_ptr & pixel_masks_1[x])
5347             {
5348                 and_bits[mask_offset]   =  fg->and        & 0xff;
5349                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
5350                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
5351                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
5352                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
5353                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
5354             }
5355             else
5356             {
5357                 and_bits[mask_offset]   =  bg->and        & 0xff;
5358                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
5359                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
5360                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
5361                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
5362                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
5363             }
5364         }
5365         mask_start += dib->stride;
5366     }
5367 }
5368
5369 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
5370                                 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5371 {
5372     WORD *and_bits = bits->and, *xor_bits = bits->xor;
5373     int x, y;
5374
5375     /* masks are always 8x8 */
5376     assert( dib->width == 8 );
5377     assert( dib->height == 8 );
5378
5379     for(y = 0; y < 8; y++, hatch_ptr++)
5380     {
5381         for(x = 0; x < 8; x++)
5382         {
5383             if(*hatch_ptr & pixel_masks_1[x])
5384             {
5385                 and_bits[x] = fg->and;
5386                 xor_bits[x] = fg->xor;
5387             }
5388             else
5389             {
5390                 and_bits[x] = bg->and;
5391                 xor_bits[x] = bg->xor;
5392             }
5393         }
5394         and_bits += dib->stride / 2;
5395         xor_bits += dib->stride / 2;
5396     }
5397 }
5398
5399 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
5400                                const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5401 {
5402     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5403     int x, y;
5404
5405     /* masks are always 8x8 */
5406     assert( dib->width == 8 );
5407     assert( dib->height == 8 );
5408
5409     for(y = 0; y < 8; y++, hatch_ptr++)
5410     {
5411         for(x = 0; x < 8; x++)
5412         {
5413             if(*hatch_ptr & pixel_masks_1[x])
5414             {
5415                 and_bits[x] = fg->and;
5416                 xor_bits[x] = fg->xor;
5417             }
5418             else
5419             {
5420                 and_bits[x] = bg->and;
5421                 xor_bits[x] = bg->xor;
5422             }
5423         }
5424         and_bits += dib->stride;
5425         xor_bits += dib->stride;
5426     }
5427 }
5428
5429 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
5430                                const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5431 {
5432     DWORD mask_offset;
5433     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5434     const rop_mask *rop_mask;
5435     int x, y;
5436
5437     /* masks are always 8x8 */
5438     assert( dib->width == 8 );
5439     assert( dib->height == 8 );
5440
5441     for(y = 0; y < 8; y++, hatch_ptr++)
5442     {
5443         for(x = mask_offset = 0; x < 8; x++)
5444         {
5445             if(*hatch_ptr & pixel_masks_1[x])
5446                 rop_mask = fg;
5447             else
5448                 rop_mask = bg;
5449
5450             if(x & 1)
5451             {
5452                 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
5453                 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
5454                 mask_offset++;
5455             }
5456             else
5457             {
5458                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
5459                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
5460             }
5461         }
5462         and_bits += dib->stride;
5463         xor_bits += dib->stride;
5464     }
5465 }
5466
5467 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
5468                                const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5469 {
5470     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5471     rop_mask rop_mask;
5472     int x, y;
5473
5474     /* masks are always 8x8 */
5475     assert( dib->width == 8 );
5476     assert( dib->height == 8 );
5477
5478     for(y = 0; y < 8; y++, hatch_ptr++)
5479     {
5480         *and_bits = *xor_bits = 0;
5481         for(x = 0; x < 8; x++)
5482         {
5483             if(*hatch_ptr & pixel_masks_1[x])
5484             {
5485                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
5486                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
5487             }
5488             else
5489             {
5490                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
5491                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5492             }
5493             *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5494             *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5495         }
5496         and_bits += dib->stride;
5497         xor_bits += dib->stride;
5498     }
5499 }
5500
5501 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
5502                                   const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5503 {
5504 }
5505
5506 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5507 {
5508     /* mapping between RGB triples and the default color table */
5509     static const BYTE mapping[27] =
5510     {
5511         0,   /* 000000 -> 000000 */
5512         4,   /* 00007f -> 000080 */
5513         252, /* 0000ff -> 0000ff */
5514         2,   /* 007f00 -> 008000 */
5515         6,   /* 007f7f -> 008080 */
5516         224, /* 007fff -> 0080c0 */
5517         250, /* 00ff00 -> 00ff00 */
5518         184, /* 00ff7f -> 00e080 */
5519         254, /* 00ffff -> 00ffff */
5520         1,   /* 7f0000 -> 800000 */
5521         5,   /* 7f007f -> 800080 */
5522         196, /* 7f00ff -> 8000c0 */
5523         3,   /* 7f7f00 -> 808000 */
5524         248, /* 7f7f7f -> 808080 */
5525         228, /* 7f7fff -> 8080c0 */
5526         60,  /* 7fff00 -> 80e000 */
5527         188, /* 7fff7f -> 80e080 */
5528         244, /* 7fffff -> 80c0c0 */
5529         249, /* ff0000 -> ff0000 */
5530         135, /* ff007f -> e00080 */
5531         253, /* ff00ff -> ff00ff */
5532         39,  /* ff7f00 -> e08000 */
5533         167, /* ff7f7f -> e08080 */
5534         231, /* ff7fff -> e080c0 */
5535         251, /* ffff00 -> ffff00 */
5536         191, /* ffff7f -> e0e080 */
5537         255  /* ffffff -> ffffff */
5538     };
5539
5540     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5541     struct rop_codes codes;
5542     int x, y;
5543
5544     /* masks are always 8x8 */
5545     assert( dib->width == 8 );
5546     assert( dib->height == 8 );
5547
5548     get_rop_codes( rop2, &codes );
5549
5550     for (y = 0; y < 8; y++)
5551     {
5552         for (x = 0; x < 8; x++)
5553         {
5554             DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5555             DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5556             DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5557             DWORD pixel = mapping[r * 9 + g * 3 + b];
5558             and_bits[x] = (pixel & codes.a1) ^ codes.a2;
5559             xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
5560         }
5561         and_bits += dib->stride;
5562         xor_bits += dib->stride;
5563     }
5564 }
5565
5566 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5567 {
5568     /* mapping between RGB triples and the default color table */
5569     static const BYTE mapping[27] =
5570     {
5571         0,  /* 000000 -> 000000 */
5572         4,  /* 00007f -> 000080 */
5573         12, /* 0000ff -> 0000ff */
5574         2,  /* 007f00 -> 008000 */
5575         6,  /* 007f7f -> 008080 */
5576         6,  /* 007fff -> 008080 */
5577         10, /* 00ff00 -> 00ff00 */
5578         6,  /* 00ff7f -> 008080 */
5579         14, /* 00ffff -> 00ffff */
5580         1,  /* 7f0000 -> 800000 */
5581         5,  /* 7f007f -> 800080 */
5582         5,  /* 7f00ff -> 800080 */
5583         3,  /* 7f7f00 -> 808000 */
5584         7,  /* 7f7f7f -> 808080 */
5585         8,  /* 7f7fff -> c0c0c0 */
5586         3,  /* 7fff00 -> 808000 */
5587         8,  /* 7fff7f -> c0c0c0 */
5588         8,  /* 7fffff -> c0c0c0 */
5589         9,  /* ff0000 -> ff0000 */
5590         5,  /* ff007f -> 800080 */
5591         13, /* ff00ff -> ff00ff */
5592         3,  /* ff7f00 -> 808000 */
5593         8,  /* ff7f7f -> c0c0c0 */
5594         8,  /* ff7fff -> c0c0c0 */
5595         11, /* ffff00 -> ffff00 */
5596         8,  /* ffff7f -> c0c0c0 */
5597         15  /* ffffff -> ffffff */
5598     };
5599
5600     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5601     struct rop_codes codes;
5602     int x, y;
5603
5604     /* masks are always 8x8 */
5605     assert( dib->width == 8 );
5606     assert( dib->height == 8 );
5607
5608     get_rop_codes( rop2, &codes );
5609
5610     for (y = 0; y < 8; y++)
5611     {
5612         for (x = 0; x < 8; x++)
5613         {
5614             DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5615             DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5616             DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5617             DWORD pixel = mapping[r * 9 + g * 3 + b];
5618             if (x & 1)
5619             {
5620                 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
5621                 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
5622             }
5623             else
5624             {
5625                 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
5626                 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
5627             }
5628         }
5629         and_bits += dib->stride;
5630         xor_bits += dib->stride;
5631     }
5632 }
5633
5634 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5635 {
5636     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5637     struct rop_codes codes;
5638     rop_mask rop_mask;
5639     int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
5640
5641     /* masks are always 8x8 */
5642     assert( dib->width == 8 );
5643     assert( dib->height == 8 );
5644
5645     get_rop_codes( rop2, &codes );
5646
5647     for (y = 0; y < 8; y++)
5648     {
5649         *and_bits = *xor_bits = 0;
5650         for (x = 0; x < 8; x++)
5651         {
5652             if (grey + bayer_8x8[y][x] > 63)
5653             {
5654                 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
5655                 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
5656             }
5657             else
5658             {
5659                 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
5660                 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
5661             }
5662             *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5663             *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5664         }
5665         and_bits += dib->stride;
5666         xor_bits += dib->stride;
5667     }
5668 }
5669
5670 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5671 {
5672 }
5673
5674 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5675 {
5676     switch (mode)
5677     {
5678     default:
5679     case STRETCH_DELETESCANS:
5680         get_rop_codes( R2_COPYPEN, codes );
5681         break;
5682     case STRETCH_ORSCANS:
5683         get_rop_codes( R2_MERGEPEN, codes );
5684         break;
5685     case STRETCH_ANDSCANS:
5686         get_rop_codes( R2_MASKPEN, codes );
5687         break;
5688     }
5689     return;
5690 }
5691
5692 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5693                            const dib_info *src_dib, const POINT *src_start,
5694                            const struct stretch_params *params, int mode,
5695                            BOOL keep_dst)
5696 {
5697     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5698     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5699     int err = params->err_start;
5700     int width;
5701     struct rop_codes codes;
5702
5703     rop_codes_from_stretch_mode( mode, &codes );
5704     for (width = params->length; width; width--)
5705     {
5706         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5707         dst_ptr += params->dst_inc;
5708         if (err > 0)
5709         {
5710             src_ptr += params->src_inc;
5711             err += params->err_add_1;
5712         }
5713         else err += params->err_add_2;
5714     }
5715 }
5716
5717 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5718                            const dib_info *src_dib, const POINT *src_start,
5719                            const struct stretch_params *params, int mode,
5720                            BOOL keep_dst)
5721 {
5722     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5723     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5724     int err = params->err_start;
5725     int width;
5726     struct rop_codes codes;
5727
5728     rop_codes_from_stretch_mode( mode, &codes );
5729     for (width = params->length; width; width--)
5730     {
5731         do_rop_codes_8( dst_ptr,     *src_ptr,       &codes );
5732         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5733         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5734         dst_ptr += 3 * params->dst_inc;
5735         if (err > 0)
5736         {
5737             src_ptr += 3 * params->src_inc;
5738             err += params->err_add_1;
5739         }
5740         else err += params->err_add_2;
5741     }
5742 }
5743
5744 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5745                            const dib_info *src_dib, const POINT *src_start,
5746                            const struct stretch_params *params, int mode,
5747                            BOOL keep_dst)
5748 {
5749     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5750     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5751     int err = params->err_start;
5752     int width;
5753     struct rop_codes codes;
5754
5755     rop_codes_from_stretch_mode( mode, &codes );
5756     for (width = params->length; width; width--)
5757     {
5758         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5759         dst_ptr += params->dst_inc;
5760         if (err > 0)
5761         {
5762             src_ptr += params->src_inc;
5763             err += params->err_add_1;
5764         }
5765         else err += params->err_add_2;
5766     }
5767 }
5768
5769 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5770                           const dib_info *src_dib, const POINT *src_start,
5771                           const struct stretch_params *params, int mode,
5772                           BOOL keep_dst)
5773 {
5774     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5775     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5776     int err = params->err_start;
5777     int width;
5778     struct rop_codes codes;
5779
5780     rop_codes_from_stretch_mode( mode, &codes );
5781     for (width = params->length; width; width--)
5782     {
5783         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5784         dst_ptr += params->dst_inc;
5785         if (err > 0)
5786         {
5787             src_ptr += params->src_inc;
5788             err += params->err_add_1;
5789         }
5790         else err += params->err_add_2;
5791     }
5792 }
5793
5794 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5795                           const dib_info *src_dib, const POINT *src_start,
5796                           const struct stretch_params *params, int mode,
5797                           BOOL keep_dst)
5798 {
5799     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5800     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5801     int err = params->err_start;
5802     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5803     struct rop_codes codes;
5804     BYTE src_val;
5805
5806     rop_codes_from_stretch_mode( mode, &codes );
5807     for (width = params->length; width; width--)
5808     {
5809         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5810         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5811
5812         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5813
5814         if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5815             dst_ptr += params->dst_inc;
5816         dst_x += params->dst_inc;
5817
5818         if (err > 0)
5819         {
5820             if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5821                 src_ptr += params->src_inc;
5822             src_x += params->src_inc;
5823             err += params->err_add_1;
5824         }
5825         else err += params->err_add_2;
5826     }
5827 }
5828
5829 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5830                           const dib_info *src_dib, const POINT *src_start,
5831                           const struct stretch_params *params, int mode,
5832                           BOOL keep_dst)
5833 {
5834     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5835     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5836     int err = params->err_start;
5837     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5838     struct rop_codes codes;
5839     BYTE src_val;
5840
5841     rop_codes_from_stretch_mode( mode, &codes );
5842     for (width = params->length; width; width--)
5843     {
5844         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5845         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5846
5847         if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5848             dst_ptr += params->dst_inc;
5849         dst_x += params->dst_inc;
5850
5851         if (err > 0)
5852         {
5853             if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5854                 src_ptr += params->src_inc;
5855             src_x += params->src_inc;
5856             err += params->err_add_1;
5857         }
5858         else err += params->err_add_2;
5859     }
5860 }
5861
5862 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5863                              const dib_info *src_dib, const POINT *src_start,
5864                              const struct stretch_params *params, int mode,
5865                              BOOL keep_dst)
5866 {
5867     FIXME("bit count %d\n", dst_dib->bit_count);
5868     return;
5869 }
5870
5871 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5872                           const dib_info *src_dib, const POINT *src_start,
5873                           const struct stretch_params *params, int mode,
5874                           BOOL keep_dst)
5875 {
5876     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5877     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5878     int err = params->err_start;
5879     int width;
5880     struct rop_codes codes;
5881     DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5882     BOOL new_pix = TRUE;
5883
5884     rop_codes_from_stretch_mode( mode, &codes );
5885     for (width = params->length; width; width--)
5886     {
5887         if (new_pix && !keep_dst) *dst_ptr = init_val;
5888         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5889         new_pix = FALSE;
5890         src_ptr += params->src_inc;
5891         if (err > 0)
5892         {
5893             dst_ptr += params->dst_inc;
5894             new_pix = TRUE;
5895             err += params->err_add_1;
5896         }
5897         else err += params->err_add_2;
5898     }
5899 }
5900
5901 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5902                           const dib_info *src_dib, const POINT *src_start,
5903                           const struct stretch_params *params, int mode,
5904                           BOOL keep_dst)
5905 {
5906     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5907     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5908     int err = params->err_start;
5909     int width;
5910     struct rop_codes codes;
5911     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5912     BOOL new_pix = TRUE;
5913
5914     rop_codes_from_stretch_mode( mode, &codes );
5915     for (width = params->length; width; width--)
5916     {
5917         if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5918         do_rop_codes_8( dst_ptr,      *src_ptr,      &codes );
5919         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5920         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5921         new_pix = FALSE;
5922         src_ptr += 3 * params->src_inc;
5923         if (err > 0)
5924         {
5925             dst_ptr += 3 * params->dst_inc;
5926             new_pix = TRUE;
5927             err += params->err_add_1;
5928         }
5929         else err += params->err_add_2;
5930     }
5931 }
5932
5933 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5934                           const dib_info *src_dib, const POINT *src_start,
5935                           const struct stretch_params *params, int mode,
5936                           BOOL keep_dst)
5937 {
5938     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5939     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5940     int err = params->err_start;
5941     int width;
5942     struct rop_codes codes;
5943     WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5944     BOOL new_pix = TRUE;
5945
5946     rop_codes_from_stretch_mode( mode, &codes );
5947     for (width = params->length; width; width--)
5948     {
5949         if (new_pix && !keep_dst) *dst_ptr = init_val;
5950         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5951         new_pix = FALSE;
5952         src_ptr += params->src_inc;
5953         if (err > 0)
5954         {
5955             dst_ptr += params->dst_inc;
5956             new_pix = TRUE;
5957             err += params->err_add_1;
5958         }
5959         else err += params->err_add_2;
5960     }
5961 }
5962
5963 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5964                          const dib_info *src_dib, const POINT *src_start,
5965                          const struct stretch_params *params, int mode,
5966                          BOOL keep_dst)
5967 {
5968     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5969     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5970     int err = params->err_start;
5971     int width;
5972     struct rop_codes codes;
5973     BYTE 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_8( 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 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5994                          const dib_info *src_dib, const POINT *src_start,
5995                          const struct stretch_params *params, int mode,
5996                          BOOL keep_dst)
5997 {
5998     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5999     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
6000     int err = params->err_start;
6001     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6002     struct rop_codes codes;
6003     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
6004     BOOL new_pix = TRUE;
6005
6006     rop_codes_from_stretch_mode( mode, &codes );
6007     for (width = params->length; width; width--)
6008     {
6009         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
6010
6011         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
6012         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
6013
6014         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
6015         new_pix = FALSE;
6016
6017         if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
6018             src_ptr += params->src_inc;
6019         src_x += params->src_inc;
6020
6021         if (err > 0)
6022         {
6023             if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
6024                 dst_ptr += params->dst_inc;
6025             dst_x += params->dst_inc;
6026             new_pix = TRUE;
6027             err += params->err_add_1;
6028         }
6029         else err += params->err_add_2;
6030     }
6031 }
6032
6033 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
6034                          const dib_info *src_dib, const POINT *src_start,
6035                          const struct stretch_params *params, int mode,
6036                          BOOL keep_dst)
6037 {
6038     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
6039     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
6040     int err = params->err_start;
6041     int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6042     struct rop_codes codes;
6043     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
6044     BOOL new_pix = TRUE;
6045
6046     rop_codes_from_stretch_mode( mode, &codes );
6047     for (width = params->length; width; width--)
6048     {
6049         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
6050         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
6051         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
6052         new_pix = FALSE;
6053
6054         if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
6055             src_ptr += params->src_inc;
6056         src_x += params->src_inc;
6057
6058         if (err > 0)
6059         {
6060             if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
6061                 dst_ptr += params->dst_inc;
6062             dst_x += params->dst_inc;
6063             new_pix = TRUE;
6064             err += params->err_add_1;
6065         }
6066         else err += params->err_add_2;
6067     }
6068 }
6069
6070 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
6071                             const dib_info *src_dib, const POINT *src_start,
6072                             const struct stretch_params *params, int mode,
6073                             BOOL keep_dst)
6074 {
6075     FIXME("bit count %d\n", dst_dib->bit_count);
6076     return;
6077 }
6078
6079 const primitive_funcs funcs_8888 =
6080 {
6081     solid_rects_32,
6082     solid_line_32,
6083     pattern_rects_32,
6084     copy_rect_32,
6085     blend_rect_8888,
6086     gradient_rect_8888,
6087     draw_glyph_8888,
6088     draw_subpixel_glyph_8888,
6089     get_pixel_32,
6090     colorref_to_pixel_888,
6091     pixel_to_colorref_888,
6092     convert_to_8888,
6093     create_rop_masks_32,
6094     create_dither_masks_null,
6095     stretch_row_32,
6096     shrink_row_32
6097 };
6098
6099 const primitive_funcs funcs_32 =
6100 {
6101     solid_rects_32,
6102     solid_line_32,
6103     pattern_rects_32,
6104     copy_rect_32,
6105     blend_rect_32,
6106     gradient_rect_32,
6107     draw_glyph_32,
6108     draw_subpixel_glyph_32,
6109     get_pixel_32,
6110     colorref_to_pixel_masks,
6111     pixel_to_colorref_masks,
6112     convert_to_32,
6113     create_rop_masks_32,
6114     create_dither_masks_null,
6115     stretch_row_32,
6116     shrink_row_32
6117 };
6118
6119 const primitive_funcs funcs_24 =
6120 {
6121     solid_rects_24,
6122     solid_line_24,
6123     pattern_rects_24,
6124     copy_rect_24,
6125     blend_rect_24,
6126     gradient_rect_24,
6127     draw_glyph_24,
6128     draw_subpixel_glyph_24,
6129     get_pixel_24,
6130     colorref_to_pixel_888,
6131     pixel_to_colorref_888,
6132     convert_to_24,
6133     create_rop_masks_24,
6134     create_dither_masks_null,
6135     stretch_row_24,
6136     shrink_row_24
6137 };
6138
6139 const primitive_funcs funcs_555 =
6140 {
6141     solid_rects_16,
6142     solid_line_16,
6143     pattern_rects_16,
6144     copy_rect_16,
6145     blend_rect_555,
6146     gradient_rect_555,
6147     draw_glyph_555,
6148     draw_subpixel_glyph_555,
6149     get_pixel_16,
6150     colorref_to_pixel_555,
6151     pixel_to_colorref_555,
6152     convert_to_555,
6153     create_rop_masks_16,
6154     create_dither_masks_null,
6155     stretch_row_16,
6156     shrink_row_16
6157 };
6158
6159 const primitive_funcs funcs_16 =
6160 {
6161     solid_rects_16,
6162     solid_line_16,
6163     pattern_rects_16,
6164     copy_rect_16,
6165     blend_rect_16,
6166     gradient_rect_16,
6167     draw_glyph_16,
6168     draw_subpixel_glyph_16,
6169     get_pixel_16,
6170     colorref_to_pixel_masks,
6171     pixel_to_colorref_masks,
6172     convert_to_16,
6173     create_rop_masks_16,
6174     create_dither_masks_null,
6175     stretch_row_16,
6176     shrink_row_16
6177 };
6178
6179 const primitive_funcs funcs_8 =
6180 {
6181     solid_rects_8,
6182     solid_line_8,
6183     pattern_rects_8,
6184     copy_rect_8,
6185     blend_rect_8,
6186     gradient_rect_8,
6187     draw_glyph_8,
6188     draw_subpixel_glyph_null,
6189     get_pixel_8,
6190     colorref_to_pixel_colortable,
6191     pixel_to_colorref_colortable,
6192     convert_to_8,
6193     create_rop_masks_8,
6194     create_dither_masks_8,
6195     stretch_row_8,
6196     shrink_row_8
6197 };
6198
6199 const primitive_funcs funcs_4 =
6200 {
6201     solid_rects_4,
6202     solid_line_4,
6203     pattern_rects_4,
6204     copy_rect_4,
6205     blend_rect_4,
6206     gradient_rect_4,
6207     draw_glyph_4,
6208     draw_subpixel_glyph_null,
6209     get_pixel_4,
6210     colorref_to_pixel_colortable,
6211     pixel_to_colorref_colortable,
6212     convert_to_4,
6213     create_rop_masks_4,
6214     create_dither_masks_4,
6215     stretch_row_4,
6216     shrink_row_4
6217 };
6218
6219 const primitive_funcs funcs_1 =
6220 {
6221     solid_rects_1,
6222     solid_line_1,
6223     pattern_rects_1,
6224     copy_rect_1,
6225     blend_rect_1,
6226     gradient_rect_1,
6227     draw_glyph_1,
6228     draw_subpixel_glyph_null,
6229     get_pixel_1,
6230     colorref_to_pixel_colortable,
6231     pixel_to_colorref_colortable,
6232     convert_to_1,
6233     create_rop_masks_1,
6234     create_dither_masks_1,
6235     stretch_row_1,
6236     shrink_row_1
6237 };
6238
6239 const primitive_funcs funcs_null =
6240 {
6241     solid_rects_null,
6242     solid_line_null,
6243     pattern_rects_null,
6244     copy_rect_null,
6245     blend_rect_null,
6246     gradient_rect_null,
6247     draw_glyph_null,
6248     draw_subpixel_glyph_null,
6249     get_pixel_null,
6250     colorref_to_pixel_null,
6251     pixel_to_colorref_null,
6252     convert_to_null,
6253     create_rop_masks_null,
6254     create_dither_masks_null,
6255     stretch_row_null,
6256     shrink_row_null
6257 };