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