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