Release 1.4.1.
[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_constant_alpha( 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( DWORD dst, DWORD src )
3788 {
3789     BYTE b = (BYTE)src;
3790     BYTE g = (BYTE)(src >> 8);
3791     BYTE r = (BYTE)(src >> 16);
3792     DWORD alpha  = (BYTE)(src >> 24);
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_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3800 {
3801     BYTE b = ((BYTE)src         * alpha + 127) / 255;
3802     BYTE g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3803     BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3804     alpha  = ((BYTE)(src >> 24) * alpha + 127) / 255;
3805     return ((b     + ((BYTE)dst         * (255 - alpha) + 127) / 255) |
3806             (g     + ((BYTE)(dst >> 8)  * (255 - alpha) + 127) / 255) << 8 |
3807             (r     + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3808             (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3809 }
3810
3811 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3812 {
3813     if (blend.AlphaFormat & AC_SRC_ALPHA)
3814     {
3815         DWORD alpha = blend.SourceConstantAlpha;
3816         BYTE src_b = ((BYTE)src         * alpha + 127) / 255;
3817         BYTE src_g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3818         BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3819         alpha      = ((BYTE)(src >> 24) * alpha + 127) / 255;
3820         return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3821                 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3822                 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3823     }
3824     return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3825             blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3826             blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3827 }
3828
3829 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3830                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3831 {
3832     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3833     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3834     int x, y;
3835
3836     if (blend.AlphaFormat & AC_SRC_ALPHA)
3837     {
3838         if (blend.SourceConstantAlpha == 255)
3839             for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3840                 for (x = 0; x < rc->right - rc->left; x++)
3841                     dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
3842         else
3843             for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3844                 for (x = 0; x < rc->right - rc->left; x++)
3845                     dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3846     }
3847     else
3848         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3849             for (x = 0; x < rc->right - rc->left; x++)
3850                 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3851 }
3852
3853 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3854                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3855 {
3856     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3857     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3858     int x, y;
3859
3860     if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3861     {
3862         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3863         {
3864             for (x = 0; x < rc->right - rc->left; x++)
3865             {
3866                 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3867                                        dst_ptr[x] >> dst->green_shift,
3868                                        dst_ptr[x] >> dst->blue_shift,
3869                                        src_ptr[x], blend );
3870                 dst_ptr[x] = ((( val        & 0xff) << dst->blue_shift) |
3871                               (((val >> 8)  & 0xff) << dst->green_shift) |
3872                               (((val >> 16) & 0xff) << dst->red_shift));
3873             }
3874         }
3875     }
3876     else
3877     {
3878         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3879         {
3880             for (x = 0; x < rc->right - rc->left; x++)
3881             {
3882                 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3883                                        get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3884                                        get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3885                                        src_ptr[x], blend );
3886                 dst_ptr[x] = (put_field( val >> 16, dst->red_shift,   dst->red_len )   |
3887                               put_field( val >> 8,  dst->green_shift, dst->green_len ) |
3888                               put_field( val,       dst->blue_shift,  dst->blue_len ));
3889             }
3890         }
3891     }
3892 }
3893
3894 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3895                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3896 {
3897     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3898     BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3899     int x, y;
3900
3901     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3902     {
3903         for (x = 0; x < rc->right - rc->left; x++)
3904         {
3905             DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3906                                    src_ptr[x], blend );
3907             dst_ptr[x * 3]     = val;
3908             dst_ptr[x * 3 + 1] = val >> 8;
3909             dst_ptr[x * 3 + 2] = val >> 16;
3910         }
3911     }
3912 }
3913
3914 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3915                            const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3916 {
3917     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3918     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3919     int x, y;
3920
3921     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3922     {
3923         for (x = 0; x < rc->right - rc->left; x++)
3924         {
3925             DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3926                                    ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
3927                                    ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
3928                                    src_ptr[x], blend );
3929             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3930         }
3931     }
3932 }
3933
3934 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3935                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3936 {
3937     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3938     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3939     int x, y;
3940
3941     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3942     {
3943         for (x = 0; x < rc->right - rc->left; x++)
3944         {
3945             DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3946                                    get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3947                                    get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3948                                    src_ptr[x], blend );
3949             dst_ptr[x] = (put_field((val >> 16), dst->red_shift,   dst->red_len)   |
3950                           put_field((val >>  8), dst->green_shift, dst->green_len) |
3951                           put_field( val,        dst->blue_shift,  dst->blue_len));
3952         }
3953     }
3954 }
3955
3956 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3957                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3958 {
3959     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3960     BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3961     int x, y;
3962
3963     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3964     {
3965         for (x = 0; x < rc->right - rc->left; x++)
3966         {
3967             RGBQUAD rgb = dst->color_table[dst_ptr[x]];
3968             DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3969             dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3970         }
3971     }
3972 }
3973
3974 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3975                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3976 {
3977     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3978     BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3979     int x, y;
3980
3981     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3982     {
3983         for (x = rc->left; x < rc->right; x++)
3984         {
3985             DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3986             RGBQUAD rgb = dst->color_table[val];
3987             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3988             val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3989             if (x & 1)
3990                 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3991             else
3992                 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3993         }
3994     }
3995 }
3996
3997 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3998                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3999 {
4000     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
4001     BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
4002     int x, y;
4003
4004     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4005     {
4006         for (x = rc->left; x < rc->right; x++)
4007         {
4008             DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4009             RGBQUAD rgb = dst->color_table[val];
4010             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4011             val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4012             dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4013         }
4014     }
4015 }
4016
4017 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4018                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4019 {
4020 }
4021
4022 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4023 {
4024     BYTE r, g, b, a;
4025     r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 256;
4026     g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4027     b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 256;
4028     a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4029     return a << 24 | r << 16 | g << 8 | b;
4030 }
4031
4032 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4033 {
4034     BYTE r, g, b;
4035     r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 256;
4036     g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4037     b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 256;
4038     return r << 16 | g << 8 | b;
4039 }
4040
4041 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4042                                      unsigned int x, unsigned int y )
4043 {
4044     int r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4045     int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4046     int b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4047     r = min( 31, max( 0, r / 16 ));
4048     g = min( 31, max( 0, g / 16 ));
4049     b = min( 31, max( 0, b / 16 ));
4050     return (r << 10) | (g << 5) | b;
4051 }
4052
4053 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4054                                    unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4055 {
4056     BYTE r = ((v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4057     BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4058     BYTE b = ((v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4059     return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4060 }
4061
4062 /* compute the left/right triangle limit for row y */
4063 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4064 {
4065     int x1, x2;
4066
4067     if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4068     else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4069
4070     x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4071
4072     *left  = max( rc->left, min( x1, x2 ) );
4073     *right = min( rc->right, max( x1, x2 ) );
4074 }
4075
4076 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4077 static inline int triangle_det( const TRIVERTEX *v )
4078 {
4079     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);
4080 }
4081
4082 /* compute the barycentric weights for a given point inside the triangle */
4083 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4084 {
4085     *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4086     *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4087 }
4088
4089 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4090 {
4091     INT64 l1, l2;
4092     BYTE r, g, b, a;
4093
4094     triangle_weights( v, x, y, &l1, &l2 );
4095     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 256;
4096     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4097     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 256;
4098     a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4099     return a << 24 | r << 16 | g << 8 | b;
4100 }
4101
4102 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4103 {
4104     INT64 l1, l2;
4105     BYTE r, g, b;
4106
4107     triangle_weights( v, x, y, &l1, &l2 );
4108     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 256;
4109     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4110     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 256;
4111     return r << 16 | g << 8 | b;
4112 }
4113
4114 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4115 {
4116     INT64 l1, l2;
4117     int r, g, b;
4118
4119     triangle_weights( v, x, y, &l1, &l2 );
4120     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4121     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4122     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4123     r = min( 31, max( 0, r / 16 ));
4124     g = min( 31, max( 0, g / 16 ));
4125     b = min( 31, max( 0, b / 16 ));
4126     return (r << 10) | (g << 5) | b;
4127 }
4128
4129 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4130 {
4131     INT64 l1, l2;
4132     BYTE r, g, b;
4133
4134     triangle_weights( v, x, y, &l1, &l2 );
4135     r = ((v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4136     g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4137     b = ((v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4138     return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4139 }
4140
4141 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4142 {
4143     DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4144     int x, y, left, right, det;
4145
4146     switch (mode)
4147     {
4148     case GRADIENT_FILL_RECT_H:
4149         for (x = rc->left; x < rc->right; x++)
4150             ptr[x] = gradient_rgb_8888( v, x - v[0].x, v[1].x - v[0].x );
4151
4152         for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4153             memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4154         break;
4155
4156     case GRADIENT_FILL_RECT_V:
4157         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4158         {
4159             DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4160             for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4161         }
4162         break;
4163
4164     case GRADIENT_FILL_TRIANGLE:
4165         if (!(det = triangle_det( v ))) return FALSE;
4166         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4167         {
4168             triangle_coords( v, rc, y, &left, &right );
4169             for (x = left; x < right; x++) ptr[x] = gradient_triangle_8888( v, x, y, det );
4170         }
4171         break;
4172     }
4173     return TRUE;
4174 }
4175
4176 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4177 {
4178     DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4179     int x, y, left, right, det;
4180
4181     switch (mode)
4182     {
4183     case GRADIENT_FILL_RECT_H:
4184         if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4185         {
4186             for (x = rc->left; x < rc->right; x++)
4187             {
4188                 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4189                 ptr[x] = ((( val        & 0xff) << dib->blue_shift) |
4190                           (((val >> 8)  & 0xff) << dib->green_shift) |
4191                           (((val >> 16) & 0xff) << dib->red_shift));
4192             }
4193         }
4194         else
4195         {
4196             for (x = rc->left; x < rc->right; x++)
4197             {
4198                 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4199                 ptr[x] = (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         }
4204
4205         for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4206             memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4207         break;
4208
4209     case GRADIENT_FILL_RECT_V:
4210         for (y = rc->top; y < rc->bottom; y++)
4211         {
4212             DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4213             if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4214                 val = ((( val        & 0xff) << dib->blue_shift) |
4215                        (((val >> 8)  & 0xff) << dib->green_shift) |
4216                        (((val >> 16) & 0xff) << dib->red_shift));
4217             else
4218                 val = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4219                        put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4220                        put_field( val,       dib->blue_shift,  dib->blue_len ));
4221
4222             for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4223             ptr += dib->stride / 4;
4224         }
4225         break;
4226
4227     case GRADIENT_FILL_TRIANGLE:
4228         if (!(det = triangle_det( v ))) return FALSE;
4229         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4230         {
4231             triangle_coords( v, rc, y, &left, &right );
4232
4233             if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4234                 for (x = left; x < right; x++)
4235                 {
4236                     DWORD val = gradient_triangle_24( v, x, y, det );
4237                     ptr[x] = ((( val        & 0xff) << dib->blue_shift) |
4238                               (((val >> 8)  & 0xff) << dib->green_shift) |
4239                               (((val >> 16) & 0xff) << dib->red_shift));
4240                 }
4241             else
4242                 for (x = left; x < right; x++)
4243                 {
4244                     DWORD val = gradient_triangle_24( v, x, y, det );
4245                     ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4246                               put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4247                               put_field( val,       dib->blue_shift,  dib->blue_len ));
4248                 }
4249         }
4250         break;
4251     }
4252     return TRUE;
4253 }
4254
4255 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4256 {
4257     BYTE *ptr = get_pixel_ptr_24( dib, 0, rc->top );
4258     int x, y, left, right, det;
4259
4260     switch (mode)
4261     {
4262     case GRADIENT_FILL_RECT_H:
4263         for (x = rc->left; x < rc->right; x++)
4264         {
4265             DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4266             ptr[x * 3]     = val;
4267             ptr[x * 3 + 1] = val >> 8;
4268             ptr[x * 3 + 2] = val >> 16;
4269         }
4270
4271         for (y = rc->top + 1, ptr += rc->left * 3; y < rc->bottom; y++, ptr += dib->stride)
4272             memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4273         break;
4274
4275     case GRADIENT_FILL_RECT_V:
4276         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4277         {
4278             DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4279             for (x = rc->left; x < rc->right; x++)
4280             {
4281                 ptr[x * 3]     = val;
4282                 ptr[x * 3 + 1] = val >> 8;
4283                 ptr[x * 3 + 2] = val >> 16;
4284             }
4285         }
4286         break;
4287
4288     case GRADIENT_FILL_TRIANGLE:
4289         if (!(det = triangle_det( v ))) return FALSE;
4290         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4291         {
4292             triangle_coords( v, rc, y, &left, &right );
4293             for (x = left; x < right; x++)
4294             {
4295                 DWORD val = gradient_triangle_24( v, x, y, det );
4296                 ptr[x * 3]     = val;
4297                 ptr[x * 3 + 1] = val >> 8;
4298                 ptr[x * 3 + 2] = val >> 16;
4299             }
4300         }
4301         break;
4302     }
4303     return TRUE;
4304 }
4305
4306 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4307 {
4308     WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4309     int x, y, left, right, det;
4310
4311     switch (mode)
4312     {
4313     case GRADIENT_FILL_RECT_H:
4314         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4315             for (x = rc->left; x < rc->right; x++)
4316                 ptr[x] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4317         for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4318             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4319         break;
4320
4321     case GRADIENT_FILL_RECT_V:
4322         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4323         {
4324             WORD values[4];
4325             for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4326             for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4327         }
4328         break;
4329
4330     case GRADIENT_FILL_TRIANGLE:
4331         if (!(det = triangle_det( v ))) return FALSE;
4332         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4333         {
4334             triangle_coords( v, rc, y, &left, &right );
4335             for (x = left; x < right; x++) ptr[x] = gradient_triangle_555( v, x, y, det );
4336         }
4337         break;
4338     }
4339     return TRUE;
4340 }
4341
4342 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4343 {
4344     WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4345     int x, y, left, right, det;
4346
4347     switch (mode)
4348     {
4349     case GRADIENT_FILL_RECT_H:
4350         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4351             for (x = rc->left; x < rc->right; x++)
4352             {
4353                 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4354                 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4355                           put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4356                           put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4357             }
4358         for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4359             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4360         break;
4361
4362     case GRADIENT_FILL_RECT_V:
4363         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4364         {
4365             WORD values[4];
4366             for (x = 0; x < 4; x++)
4367             {
4368                 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4369                 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4370                              put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4371                              put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4372             }
4373             for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4374         }
4375         break;
4376
4377     case GRADIENT_FILL_TRIANGLE:
4378         if (!(det = triangle_det( v ))) return FALSE;
4379         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4380         {
4381             triangle_coords( v, rc, y, &left, &right );
4382             for (x = left; x < right; x++)
4383             {
4384                 WORD val = gradient_triangle_555( v, x, y, det );
4385                 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4386                           put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4387                           put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4388             }
4389         }
4390         break;
4391     }
4392     return TRUE;
4393 }
4394
4395 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4396 {
4397     BYTE *ptr = get_pixel_ptr_8( dib, 0, rc->top );
4398     int x, y, left, right, det;
4399
4400     switch (mode)
4401     {
4402     case GRADIENT_FILL_RECT_H:
4403         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4404             for (x = rc->left; x < rc->right; x++)
4405                 ptr[x] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4406         for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride)
4407             memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4408         break;
4409
4410     case GRADIENT_FILL_RECT_V:
4411         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4412         {
4413             BYTE values[16];
4414             for (x = 0; x < 16; x++)
4415                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4416             for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 16];
4417         }
4418         break;
4419
4420     case GRADIENT_FILL_TRIANGLE:
4421         if (!(det = triangle_det( v ))) return FALSE;
4422         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4423         {
4424             triangle_coords( v, rc, y, &left, &right );
4425             for (x = left; x < right; x++) ptr[x] = gradient_triangle_8( dib, v, x, y, det );
4426         }
4427         break;
4428     }
4429     return TRUE;
4430 }
4431
4432 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4433 {
4434     BYTE *ptr = get_pixel_ptr_4( dib, 0, rc->top );
4435     int x, y, left, right, det;
4436
4437     switch (mode)
4438     {
4439     case GRADIENT_FILL_RECT_H:
4440         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4441         {
4442             for (x = rc->left; x < rc->right; x++)
4443             {
4444                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4445                 if (x & 1)
4446                     ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4447                 else
4448                     ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4449             }
4450         }
4451         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4452         {
4453             x = rc->left;
4454             if (x & 1)
4455             {
4456                 ptr[x / 2] = (ptr[x / 2 - 16 * dib->stride] & 0x0f) | (ptr[x / 2] & 0xf0);
4457                 x++;
4458             }
4459             for (; x < rc->right - 1; x += 2) ptr[x / 2] = ptr[x / 2 - 16 * dib->stride];
4460             if (x < rc->right)
4461                 ptr[x / 2] = (ptr[x / 2] & 0x0f) | (ptr[x / 2 - 16 * dib->stride] & 0xf0);
4462         }
4463         break;
4464
4465     case GRADIENT_FILL_RECT_V:
4466         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4467         {
4468             BYTE values[16];
4469             for (x = 0; x < 16; x++)
4470                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4471             for (x = rc->left; x < rc->right; x++)
4472                 if (x & 1)
4473                     ptr[x / 2] = values[x % 16] | (ptr[x / 2] & 0xf0);
4474                 else
4475                     ptr[x / 2] = (values[x % 16] << 4) | (ptr[x / 2] & 0x0f);
4476         }
4477         break;
4478
4479     case GRADIENT_FILL_TRIANGLE:
4480         if (!(det = triangle_det( v ))) return FALSE;
4481         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4482         {
4483             triangle_coords( v, rc, y, &left, &right );
4484             for (x = left; x < right; x++)
4485             {
4486                 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4487                 if (x & 1)
4488                     ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4489                 else
4490                     ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4491             }
4492         }
4493         break;
4494     }
4495     return TRUE;
4496 }
4497
4498 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4499 {
4500     BYTE *ptr = get_pixel_ptr_1( dib, 0, rc->top );
4501     int x, y, left, right, det;
4502
4503     switch (mode)
4504     {
4505     case GRADIENT_FILL_RECT_H:
4506         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4507         {
4508             for (x = rc->left; x < rc->right; x++)
4509             {
4510                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4511                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4512             }
4513         }
4514         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4515             for (x = rc->left; x < rc->right; x++)
4516                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) |
4517                              (ptr[x / 8 - 16 * dib->stride] & pixel_masks_1[x % 8]);
4518         break;
4519
4520     case GRADIENT_FILL_RECT_V:
4521         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4522         {
4523             BYTE values[16];
4524             for (x = 0; x < 16; x++)
4525                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4526             for (x = rc->left; x < rc->right; x++)
4527                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (values[x % 16] & pixel_masks_1[x % 8]);
4528         }
4529         break;
4530
4531     case GRADIENT_FILL_TRIANGLE:
4532         if (!(det = triangle_det( v ))) return FALSE;
4533         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4534         {
4535             triangle_coords( v, rc, y, &left, &right );
4536             for (x = left; x < right; x++)
4537             {
4538                 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4539                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4540             }
4541         }
4542         break;
4543     }
4544     return TRUE;
4545 }
4546
4547 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4548 {
4549     return TRUE;
4550 }
4551
4552 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4553 {
4554     if (dst == text) return dst;
4555
4556     if (dst > text)
4557     {
4558         DWORD diff = dst - text;
4559         DWORD range = max_comp - text;
4560         dst = text + (diff * range ) / (0xff - text);
4561         return dst;
4562     }
4563     else
4564     {
4565         DWORD diff = text - dst;
4566         DWORD range = text - min_comp;
4567         dst = text - (diff * range) / text;
4568         return dst;
4569     }
4570 }
4571
4572 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4573 {
4574     return (aa_color( b_dst, text,       range->b_min, range->b_max )      |
4575             aa_color( g_dst, text >> 8,  range->g_min, range->g_max ) << 8 |
4576             aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4577 }
4578
4579 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4580                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4581 {
4582     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4583     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4584     int x, y;
4585
4586     for (y = rect->top; y < rect->bottom; y++)
4587     {
4588         for (x = 0; x < rect->right - rect->left; x++)
4589         {
4590             if (glyph_ptr[x] <= 1) continue;
4591             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4592             dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4593         }
4594         dst_ptr += dib->stride / 4;
4595         glyph_ptr += glyph->stride;
4596     }
4597 }
4598
4599 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4600                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4601 {
4602     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4603     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4604     int x, y;
4605     DWORD text, val;
4606
4607     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4608            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4609            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4610
4611     for (y = rect->top; y < rect->bottom; y++)
4612     {
4613         for (x = 0; x < rect->right - rect->left; x++)
4614         {
4615             if (glyph_ptr[x] <= 1) continue;
4616             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4617             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4618                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4619                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4620                           text, ranges + glyph_ptr[x] );
4621             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4622                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4623                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4624         }
4625         dst_ptr += dib->stride / 4;
4626         glyph_ptr += glyph->stride;
4627     }
4628 }
4629
4630 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4631                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4632 {
4633     BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4634     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4635     int x, y;
4636     DWORD val;
4637
4638     for (y = rect->top; y < rect->bottom; y++)
4639     {
4640         for (x = 0; x < rect->right - rect->left; x++)
4641         {
4642             if (glyph_ptr[x] <= 1) continue;
4643             if (glyph_ptr[x] >= 16)
4644                 val = text_pixel;
4645             else
4646                 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4647                               text_pixel, ranges + glyph_ptr[x] );
4648             dst_ptr[x * 3]     = val;
4649             dst_ptr[x * 3 + 1] = val >> 8;
4650             dst_ptr[x * 3 + 2] = val >> 16;
4651         }
4652         dst_ptr += dib->stride;
4653         glyph_ptr += glyph->stride;
4654     }
4655 }
4656
4657 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4658                             const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4659 {
4660     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4661     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4662     int x, y;
4663     DWORD text, val;
4664
4665     text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4666            ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4667            ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4668
4669     for (y = rect->top; y < rect->bottom; y++)
4670     {
4671         for (x = 0; x < rect->right - rect->left; x++)
4672         {
4673             if (glyph_ptr[x] <= 1) continue;
4674             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4675             val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4676                           ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
4677                           ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
4678                           text, ranges + glyph_ptr[x] );
4679             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4680         }
4681         dst_ptr += dib->stride / 2;
4682         glyph_ptr += glyph->stride;
4683     }
4684 }
4685
4686 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4687                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4688 {
4689     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4690     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4691     int x, y;
4692     DWORD text, val;
4693
4694     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4695            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4696            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4697
4698     for (y = rect->top; y < rect->bottom; y++)
4699     {
4700         for (x = 0; x < rect->right - rect->left; x++)
4701         {
4702             if (glyph_ptr[x] <= 1) continue;
4703             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4704             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4705                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4706                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4707                           text, ranges + glyph_ptr[x] );
4708             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4709                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4710                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4711         }
4712         dst_ptr += dib->stride / 2;
4713         glyph_ptr += glyph->stride;
4714     }
4715 }
4716
4717 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4718                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4719 {
4720     BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4721     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4722     int x, y;
4723
4724     for (y = rect->top; y < rect->bottom; y++)
4725     {
4726         for (x = 0; x < rect->right - rect->left; x++)
4727         {
4728             /* no antialiasing, glyph should only contain 0 or 16. */
4729             if (glyph_ptr[x] >= 16)
4730                 dst_ptr[x] = text_pixel;
4731         }
4732         dst_ptr += dib->stride;
4733         glyph_ptr += glyph->stride;
4734     }
4735 }
4736
4737 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4738                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4739 {
4740     BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
4741     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4742     int x, y;
4743
4744     for (y = rect->top; y < rect->bottom; y++)
4745     {
4746         for (x = rect->left; x < rect->right; x++)
4747         {
4748             /* no antialiasing, glyph should only contain 0 or 16. */
4749             if (glyph_ptr[x] >= 16)
4750             {
4751                 if (x & 1)
4752                     dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
4753                 else
4754                     dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
4755             }
4756         }
4757         dst_ptr += dib->stride;
4758         glyph_ptr += glyph->stride;
4759     }
4760 }
4761
4762 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4763                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4764 {
4765     BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
4766     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4767     int x, y;
4768     BYTE text = (text_pixel & 1) ? 0xff : 0;
4769
4770     for (y = rect->top; y < rect->bottom; y++)
4771     {
4772         for (x = rect->left; x < rect->right; x++)
4773         {
4774             /* no antialiasing, glyph should only contain 0 or 16. */
4775             if (glyph_ptr[x] >= 16)
4776                 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
4777         }
4778         dst_ptr += dib->stride;
4779         glyph_ptr += glyph->stride;
4780     }
4781 }
4782
4783 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4784                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4785 {
4786     return;
4787 }
4788
4789 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)
4790 {
4791     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4792     DWORD mask_start = 0, mask_offset;
4793     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4794     int x, y;
4795
4796     for(y = 0; y < hatch->height; y++)
4797     {
4798         hatch_ptr = hatch_start;
4799         mask_offset = mask_start;
4800         for(x = 0; x < hatch->width; x++)
4801         {
4802             if(*hatch_ptr & pixel_masks_1[x % 8])
4803             {
4804                 and_bits[mask_offset] = fg->and;
4805                 xor_bits[mask_offset] = fg->xor;
4806             }
4807             else
4808             {
4809                 and_bits[mask_offset] = bg->and;
4810                 xor_bits[mask_offset] = bg->xor;
4811             }
4812             if(x % 8 == 7) hatch_ptr++;
4813             mask_offset++;
4814         }
4815         hatch_start += hatch->stride;
4816         mask_start += dib->stride / 4;
4817     }
4818
4819     return TRUE;
4820 }
4821
4822 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)
4823 {
4824     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4825     DWORD mask_start = 0, mask_offset;
4826     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4827     int x, y;
4828
4829     for(y = 0; y < hatch->height; y++)
4830     {
4831         hatch_ptr = hatch_start;
4832         mask_offset = mask_start;
4833         for(x = 0; x < hatch->width; x++)
4834         {
4835             if(*hatch_ptr & pixel_masks_1[x % 8])
4836             {
4837                 and_bits[mask_offset]   =  fg->and        & 0xff;
4838                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
4839                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
4840                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
4841                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
4842                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4843             }
4844             else
4845             {
4846                 and_bits[mask_offset]   =  bg->and        & 0xff;
4847                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
4848                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
4849                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
4850                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
4851                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4852             }
4853             if(x % 8 == 7) hatch_ptr++;
4854         }
4855         hatch_start += hatch->stride;
4856         mask_start += dib->stride;
4857     }
4858
4859     return TRUE;
4860 }
4861
4862 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)
4863 {
4864     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4865     DWORD mask_start = 0, mask_offset;
4866     WORD *and_bits = bits->and, *xor_bits = bits->xor;
4867     int x, y;
4868
4869     for(y = 0; y < hatch->height; y++)
4870     {
4871         hatch_ptr = hatch_start;
4872         mask_offset = mask_start;
4873         for(x = 0; x < hatch->width; x++)
4874         {
4875             if(*hatch_ptr & pixel_masks_1[x % 8])
4876             {
4877                 and_bits[mask_offset] = fg->and;
4878                 xor_bits[mask_offset] = fg->xor;
4879             }
4880             else
4881             {
4882                 and_bits[mask_offset] = bg->and;
4883                 xor_bits[mask_offset] = bg->xor;
4884             }
4885             if(x % 8 == 7) hatch_ptr++;
4886             mask_offset++;
4887         }
4888         hatch_start += hatch->stride;
4889         mask_start += dib->stride / 2;
4890     }
4891
4892     return TRUE;
4893 }
4894
4895 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)
4896 {
4897     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4898     DWORD mask_start = 0, mask_offset;
4899     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4900     int x, y;
4901
4902     for(y = 0; y < hatch->height; y++)
4903     {
4904         hatch_ptr = hatch_start;
4905         mask_offset = mask_start;
4906         for(x = 0; x < hatch->width; x++)
4907         {
4908             if(*hatch_ptr & pixel_masks_1[x % 8])
4909             {
4910                 and_bits[mask_offset] = fg->and;
4911                 xor_bits[mask_offset] = fg->xor;
4912             }
4913             else
4914             {
4915                 and_bits[mask_offset] = bg->and;
4916                 xor_bits[mask_offset] = bg->xor;
4917             }
4918             if(x % 8 == 7) hatch_ptr++;
4919             mask_offset++;
4920         }
4921         hatch_start += hatch->stride;
4922         mask_start += dib->stride;
4923     }
4924
4925     return TRUE;
4926 }
4927
4928 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)
4929 {
4930     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4931     DWORD mask_start = 0, mask_offset;
4932     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4933     const rop_mask *rop_mask;
4934     int x, y;
4935
4936     for(y = 0; y < hatch->height; y++)
4937     {
4938         hatch_ptr = hatch_start;
4939         mask_offset = mask_start;
4940         for(x = 0; x < hatch->width; x++)
4941         {
4942             if(*hatch_ptr & pixel_masks_1[x % 8])
4943                 rop_mask = fg;
4944             else
4945                 rop_mask = bg;
4946
4947             if(x & 1)
4948             {
4949                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4950                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4951                 mask_offset++;
4952             }
4953             else
4954             {
4955                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4956                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4957             }
4958
4959             if(x % 8 == 7) hatch_ptr++;
4960         }
4961         hatch_start += hatch->stride;
4962         mask_start += dib->stride;
4963     }
4964
4965     return TRUE;
4966 }
4967
4968 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)
4969 {
4970     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4971     DWORD mask_start = 0, mask_offset;
4972     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4973     rop_mask rop_mask;
4974     int x, y, bit_pos;
4975
4976     for(y = 0; y < hatch->height; y++)
4977     {
4978         hatch_ptr = hatch_start;
4979         mask_offset = mask_start;
4980         for(x = 0, bit_pos = 0; x < hatch->width; x++)
4981         {
4982             if(*hatch_ptr & pixel_masks_1[x % 8])
4983             {
4984                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4985                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4986             }
4987             else
4988             {
4989                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4990                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4991             }
4992
4993             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4994
4995             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4996             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4997
4998             if(++bit_pos == 8)
4999             {
5000                 mask_offset++;
5001                 hatch_ptr++;
5002                 bit_pos = 0;
5003             }
5004         }
5005         hatch_start += hatch->stride;
5006         mask_start += dib->stride;
5007     }
5008
5009     return TRUE;
5010 }
5011
5012 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)
5013 {
5014     return FALSE;
5015 }
5016
5017 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5018 {
5019     switch (mode)
5020     {
5021     default:
5022     case STRETCH_DELETESCANS:
5023         get_rop_codes( R2_COPYPEN, codes );
5024         break;
5025     case STRETCH_ORSCANS:
5026         get_rop_codes( R2_MERGEPEN, codes );
5027         break;
5028     case STRETCH_ANDSCANS:
5029         get_rop_codes( R2_MASKPEN, codes );
5030         break;
5031     }
5032     return;
5033 }
5034
5035 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5036                            const dib_info *src_dib, const POINT *src_start,
5037                            const struct stretch_params *params, int mode,
5038                            BOOL keep_dst)
5039 {
5040     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5041     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5042     int err = params->err_start;
5043     int width;
5044     struct rop_codes codes;
5045
5046     rop_codes_from_stretch_mode( mode, &codes );
5047     for (width = params->length; width; width--)
5048     {
5049         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5050         dst_ptr += params->dst_inc;
5051         if (err > 0)
5052         {
5053             src_ptr += params->src_inc;
5054             err += params->err_add_1;
5055         }
5056         else err += params->err_add_2;
5057     }
5058 }
5059
5060 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5061                            const dib_info *src_dib, const POINT *src_start,
5062                            const struct stretch_params *params, int mode,
5063                            BOOL keep_dst)
5064 {
5065     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5066     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5067     int err = params->err_start;
5068     int width;
5069     struct rop_codes codes;
5070
5071     rop_codes_from_stretch_mode( mode, &codes );
5072     for (width = params->length; width; width--)
5073     {
5074         do_rop_codes_8( dst_ptr,     *src_ptr,       &codes );
5075         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5076         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5077         dst_ptr += 3 * params->dst_inc;
5078         if (err > 0)
5079         {
5080             src_ptr += 3 * params->src_inc;
5081             err += params->err_add_1;
5082         }
5083         else err += params->err_add_2;
5084     }
5085 }
5086
5087 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5088                            const dib_info *src_dib, const POINT *src_start,
5089                            const struct stretch_params *params, int mode,
5090                            BOOL keep_dst)
5091 {
5092     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5093     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5094     int err = params->err_start;
5095     int width;
5096     struct rop_codes codes;
5097
5098     rop_codes_from_stretch_mode( mode, &codes );
5099     for (width = params->length; width; width--)
5100     {
5101         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5102         dst_ptr += params->dst_inc;
5103         if (err > 0)
5104         {
5105             src_ptr += params->src_inc;
5106             err += params->err_add_1;
5107         }
5108         else err += params->err_add_2;
5109     }
5110 }
5111
5112 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5113                           const dib_info *src_dib, const POINT *src_start,
5114                           const struct stretch_params *params, int mode,
5115                           BOOL keep_dst)
5116 {
5117     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5118     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5119     int err = params->err_start;
5120     int width;
5121     struct rop_codes codes;
5122
5123     rop_codes_from_stretch_mode( mode, &codes );
5124     for (width = params->length; width; width--)
5125     {
5126         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5127         dst_ptr += params->dst_inc;
5128         if (err > 0)
5129         {
5130             src_ptr += params->src_inc;
5131             err += params->err_add_1;
5132         }
5133         else err += params->err_add_2;
5134     }
5135 }
5136
5137 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5138                           const dib_info *src_dib, const POINT *src_start,
5139                           const struct stretch_params *params, int mode,
5140                           BOOL keep_dst)
5141 {
5142     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5143     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5144     int err = params->err_start;
5145     int width, dst_x = dst_start->x, src_x = src_start->x;
5146     struct rop_codes codes;
5147     BYTE src_val;
5148
5149     rop_codes_from_stretch_mode( mode, &codes );
5150     for (width = params->length; width; width--)
5151     {
5152         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5153         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5154
5155         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5156
5157         if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5158             dst_ptr += params->dst_inc;
5159         dst_x += params->dst_inc;
5160
5161         if (err > 0)
5162         {
5163             if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5164                 src_ptr += params->src_inc;
5165             src_x += params->src_inc;
5166             err += params->err_add_1;
5167         }
5168         else err += params->err_add_2;
5169     }
5170 }
5171
5172 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5173                           const dib_info *src_dib, const POINT *src_start,
5174                           const struct stretch_params *params, int mode,
5175                           BOOL keep_dst)
5176 {
5177     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5178     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5179     int err = params->err_start;
5180     int width, dst_x = dst_start->x, src_x = src_start->x;
5181     struct rop_codes codes;
5182     BYTE src_val;
5183
5184     rop_codes_from_stretch_mode( mode, &codes );
5185     for (width = params->length; width; width--)
5186     {
5187         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5188         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5189
5190         if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5191             dst_ptr += params->dst_inc;
5192         dst_x += params->dst_inc;
5193
5194         if (err > 0)
5195         {
5196             if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5197                 src_ptr += params->src_inc;
5198             src_x += params->src_inc;
5199             err += params->err_add_1;
5200         }
5201         else err += params->err_add_2;
5202     }
5203 }
5204
5205 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5206                              const dib_info *src_dib, const POINT *src_start,
5207                              const struct stretch_params *params, int mode,
5208                              BOOL keep_dst)
5209 {
5210     FIXME("bit count %d\n", dst_dib->bit_count);
5211     return;
5212 }
5213
5214 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5215                           const dib_info *src_dib, const POINT *src_start,
5216                           const struct stretch_params *params, int mode,
5217                           BOOL keep_dst)
5218 {
5219     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5220     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5221     int err = params->err_start;
5222     int width;
5223     struct rop_codes codes;
5224     DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5225     BOOL new_pix = TRUE;
5226
5227     rop_codes_from_stretch_mode( mode, &codes );
5228     for (width = params->length; width; width--)
5229     {
5230         if (new_pix && !keep_dst) *dst_ptr = init_val;
5231         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5232         new_pix = FALSE;
5233         src_ptr += params->src_inc;
5234         if (err > 0)
5235         {
5236             dst_ptr += params->dst_inc;
5237             new_pix = TRUE;
5238             err += params->err_add_1;
5239         }
5240         else err += params->err_add_2;
5241     }
5242 }
5243
5244 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5245                           const dib_info *src_dib, const POINT *src_start,
5246                           const struct stretch_params *params, int mode,
5247                           BOOL keep_dst)
5248 {
5249     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5250     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5251     int err = params->err_start;
5252     int width;
5253     struct rop_codes codes;
5254     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5255     BOOL new_pix = TRUE;
5256
5257     rop_codes_from_stretch_mode( mode, &codes );
5258     for (width = params->length; width; width--)
5259     {
5260         if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5261         do_rop_codes_8( dst_ptr,      *src_ptr,      &codes );
5262         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5263         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5264         new_pix = FALSE;
5265         src_ptr += 3 * params->src_inc;
5266         if (err > 0)
5267         {
5268             dst_ptr += 3 * params->dst_inc;
5269             new_pix = TRUE;
5270             err += params->err_add_1;
5271         }
5272         else err += params->err_add_2;
5273     }
5274 }
5275
5276 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5277                           const dib_info *src_dib, const POINT *src_start,
5278                           const struct stretch_params *params, int mode,
5279                           BOOL keep_dst)
5280 {
5281     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5282     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5283     int err = params->err_start;
5284     int width;
5285     struct rop_codes codes;
5286     WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5287     BOOL new_pix = TRUE;
5288
5289     rop_codes_from_stretch_mode( mode, &codes );
5290     for (width = params->length; width; width--)
5291     {
5292         if (new_pix && !keep_dst) *dst_ptr = init_val;
5293         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5294         new_pix = FALSE;
5295         src_ptr += params->src_inc;
5296         if (err > 0)
5297         {
5298             dst_ptr += params->dst_inc;
5299             new_pix = TRUE;
5300             err += params->err_add_1;
5301         }
5302         else err += params->err_add_2;
5303     }
5304 }
5305
5306 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5307                          const dib_info *src_dib, const POINT *src_start,
5308                          const struct stretch_params *params, int mode,
5309                          BOOL keep_dst)
5310 {
5311     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5312     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5313     int err = params->err_start;
5314     int width;
5315     struct rop_codes codes;
5316     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5317     BOOL new_pix = TRUE;
5318
5319     rop_codes_from_stretch_mode( mode, &codes );
5320     for (width = params->length; width; width--)
5321     {
5322         if (new_pix && !keep_dst) *dst_ptr = init_val;
5323         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5324         new_pix = FALSE;
5325         src_ptr += params->src_inc;
5326         if (err > 0)
5327         {
5328             dst_ptr += params->dst_inc;
5329             new_pix = TRUE;
5330             err += params->err_add_1;
5331         }
5332         else err += params->err_add_2;
5333     }
5334 }
5335
5336 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5337                          const dib_info *src_dib, const POINT *src_start,
5338                          const struct stretch_params *params, int mode,
5339                          BOOL keep_dst)
5340 {
5341     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5342     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5343     int err = params->err_start;
5344     int width, dst_x = dst_start->x, src_x = src_start->x;
5345     struct rop_codes codes;
5346     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5347     BOOL new_pix = TRUE;
5348
5349     rop_codes_from_stretch_mode( mode, &codes );
5350     for (width = params->length; width; width--)
5351     {
5352         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
5353
5354         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5355         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5356
5357         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5358         new_pix = FALSE;
5359
5360         if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5361             src_ptr += params->src_inc;
5362         src_x += params->src_inc;
5363
5364         if (err > 0)
5365         {
5366             if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5367                 dst_ptr += params->dst_inc;
5368             dst_x += params->dst_inc;
5369             new_pix = TRUE;
5370             err += params->err_add_1;
5371         }
5372         else err += params->err_add_2;
5373     }
5374 }
5375
5376 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5377                          const dib_info *src_dib, const POINT *src_start,
5378                          const struct stretch_params *params, int mode,
5379                          BOOL keep_dst)
5380 {
5381     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5382     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5383     int err = params->err_start;
5384     int width, dst_x = dst_start->x, src_x = src_start->x;
5385     struct rop_codes codes;
5386     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5387     BOOL new_pix = TRUE;
5388
5389     rop_codes_from_stretch_mode( mode, &codes );
5390     for (width = params->length; width; width--)
5391     {
5392         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5393         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5394         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5395         new_pix = FALSE;
5396
5397         if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5398             src_ptr += params->src_inc;
5399         src_x += params->src_inc;
5400
5401         if (err > 0)
5402         {
5403             if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5404                 dst_ptr += params->dst_inc;
5405             dst_x += params->dst_inc;
5406             new_pix = TRUE;
5407             err += params->err_add_1;
5408         }
5409         else err += params->err_add_2;
5410     }
5411 }
5412
5413 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5414                             const dib_info *src_dib, const POINT *src_start,
5415                             const struct stretch_params *params, int mode,
5416                             BOOL keep_dst)
5417 {
5418     FIXME("bit count %d\n", dst_dib->bit_count);
5419     return;
5420 }
5421
5422 const primitive_funcs funcs_8888 =
5423 {
5424     solid_rects_32,
5425     solid_line_32,
5426     pattern_rects_32,
5427     copy_rect_32,
5428     blend_rect_8888,
5429     gradient_rect_8888,
5430     draw_glyph_8888,
5431     get_pixel_32,
5432     colorref_to_pixel_888,
5433     pixel_to_colorref_888,
5434     convert_to_8888,
5435     create_rop_masks_32,
5436     stretch_row_32,
5437     shrink_row_32
5438 };
5439
5440 const primitive_funcs funcs_32 =
5441 {
5442     solid_rects_32,
5443     solid_line_32,
5444     pattern_rects_32,
5445     copy_rect_32,
5446     blend_rect_32,
5447     gradient_rect_32,
5448     draw_glyph_32,
5449     get_pixel_32,
5450     colorref_to_pixel_masks,
5451     pixel_to_colorref_masks,
5452     convert_to_32,
5453     create_rop_masks_32,
5454     stretch_row_32,
5455     shrink_row_32
5456 };
5457
5458 const primitive_funcs funcs_24 =
5459 {
5460     solid_rects_24,
5461     solid_line_24,
5462     pattern_rects_24,
5463     copy_rect_24,
5464     blend_rect_24,
5465     gradient_rect_24,
5466     draw_glyph_24,
5467     get_pixel_24,
5468     colorref_to_pixel_888,
5469     pixel_to_colorref_888,
5470     convert_to_24,
5471     create_rop_masks_24,
5472     stretch_row_24,
5473     shrink_row_24
5474 };
5475
5476 const primitive_funcs funcs_555 =
5477 {
5478     solid_rects_16,
5479     solid_line_16,
5480     pattern_rects_16,
5481     copy_rect_16,
5482     blend_rect_555,
5483     gradient_rect_555,
5484     draw_glyph_555,
5485     get_pixel_16,
5486     colorref_to_pixel_555,
5487     pixel_to_colorref_555,
5488     convert_to_555,
5489     create_rop_masks_16,
5490     stretch_row_16,
5491     shrink_row_16
5492 };
5493
5494 const primitive_funcs funcs_16 =
5495 {
5496     solid_rects_16,
5497     solid_line_16,
5498     pattern_rects_16,
5499     copy_rect_16,
5500     blend_rect_16,
5501     gradient_rect_16,
5502     draw_glyph_16,
5503     get_pixel_16,
5504     colorref_to_pixel_masks,
5505     pixel_to_colorref_masks,
5506     convert_to_16,
5507     create_rop_masks_16,
5508     stretch_row_16,
5509     shrink_row_16
5510 };
5511
5512 const primitive_funcs funcs_8 =
5513 {
5514     solid_rects_8,
5515     solid_line_8,
5516     pattern_rects_8,
5517     copy_rect_8,
5518     blend_rect_8,
5519     gradient_rect_8,
5520     draw_glyph_8,
5521     get_pixel_8,
5522     colorref_to_pixel_colortable,
5523     pixel_to_colorref_colortable,
5524     convert_to_8,
5525     create_rop_masks_8,
5526     stretch_row_8,
5527     shrink_row_8
5528 };
5529
5530 const primitive_funcs funcs_4 =
5531 {
5532     solid_rects_4,
5533     solid_line_4,
5534     pattern_rects_4,
5535     copy_rect_4,
5536     blend_rect_4,
5537     gradient_rect_4,
5538     draw_glyph_4,
5539     get_pixel_4,
5540     colorref_to_pixel_colortable,
5541     pixel_to_colorref_colortable,
5542     convert_to_4,
5543     create_rop_masks_4,
5544     stretch_row_4,
5545     shrink_row_4
5546 };
5547
5548 const primitive_funcs funcs_1 =
5549 {
5550     solid_rects_1,
5551     solid_line_1,
5552     pattern_rects_1,
5553     copy_rect_1,
5554     blend_rect_1,
5555     gradient_rect_1,
5556     draw_glyph_1,
5557     get_pixel_1,
5558     colorref_to_pixel_colortable,
5559     pixel_to_colorref_colortable,
5560     convert_to_1,
5561     create_rop_masks_1,
5562     stretch_row_1,
5563     shrink_row_1
5564 };
5565
5566 const primitive_funcs funcs_null =
5567 {
5568     solid_rects_null,
5569     solid_line_null,
5570     pattern_rects_null,
5571     copy_rect_null,
5572     blend_rect_null,
5573     gradient_rect_null,
5574     draw_glyph_null,
5575     get_pixel_null,
5576     colorref_to_pixel_null,
5577     pixel_to_colorref_null,
5578     convert_to_null,
5579     create_rop_masks_null,
5580     stretch_row_null,
5581     shrink_row_null
5582 };