jscript: Use bytecode for '|=' expression.
[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, const POINT *pt)
1280 {
1281     DWORD *ptr = get_pixel_ptr_32( dib, pt->x, pt->y );
1282     return *ptr;
1283 }
1284
1285 static DWORD get_pixel_24(const dib_info *dib, const POINT *pt)
1286 {
1287     BYTE *ptr = get_pixel_ptr_24( dib, pt->x, pt->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, const POINT *pt)
1292 {
1293     WORD *ptr = get_pixel_ptr_16( dib, pt->x, pt->y );
1294     return *ptr;
1295 }
1296
1297 static DWORD get_pixel_8(const dib_info *dib, const POINT *pt)
1298 {
1299     BYTE *ptr = get_pixel_ptr_8( dib, pt->x, pt->y );
1300     return *ptr;
1301 }
1302
1303 static DWORD get_pixel_4(const dib_info *dib, const POINT *pt)
1304 {
1305     BYTE *ptr = get_pixel_ptr_4( dib, pt->x, pt->y );
1306
1307     if (pt->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, const POINT *pt)
1314 {
1315     BYTE *ptr = get_pixel_ptr_1( dib, pt->x, pt->y );
1316     return (*ptr & pixel_masks_1[pt->x & 0x7]) ? 1 : 0;
1317 }
1318
1319 static DWORD get_pixel_null(const dib_info *dib, const POINT *pt)
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         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 inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1425 {
1426     static const RGBQUAD default_rgb;
1427     if (index < dib->color_table_size) return dib->color_table[index];
1428     return default_rgb;
1429 }
1430
1431 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1432 {
1433     return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1434 }
1435
1436 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1437 {
1438     return RGB( get_field( pixel, dib->red_shift,   dib->red_len ),
1439                 get_field( pixel, dib->green_shift, dib->green_len ),
1440                 get_field( pixel, dib->blue_shift,  dib->blue_len ) );
1441 }
1442
1443 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1444 {
1445     return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1446                 ((pixel >> 2) & 0xf8) | ((pixel >>  7) & 0x07),
1447                 ((pixel << 3) & 0xf8) | ((pixel >>  2) & 0x07) );
1448 }
1449
1450 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1451 {
1452     RGBQUAD quad = colortable_entry( dib, pixel );
1453
1454     return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1455 }
1456
1457 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1458 {
1459     return 0;
1460 }
1461
1462 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1463 {
1464     assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1465
1466     return d1->red_mask   == d2->red_mask &&
1467            d1->green_mask == d2->green_mask &&
1468            d1->blue_mask  == d2->blue_mask;
1469 }
1470
1471 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1472 {
1473     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1474     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1475
1476     switch(src->bit_count)
1477     {
1478     case 32:
1479     {
1480         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1481         if(src->funcs == &funcs_8888)
1482         {
1483             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1484                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1485             else
1486             {
1487                 for(y = src_rect->top; y < src_rect->bottom; y++)
1488                 {
1489                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1490                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1491                     dst_start += dst->stride / 4;
1492                     src_start += src->stride / 4;
1493                 }
1494             }
1495         }
1496         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1497         {
1498             for(y = src_rect->top; y < src_rect->bottom; y++)
1499             {
1500                 dst_pixel = dst_start;
1501                 src_pixel = src_start;
1502                 for(x = src_rect->left; x < src_rect->right; x++)
1503                 {
1504                     src_val = *src_pixel++;
1505                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << 16) |
1506                                    (((src_val >> src->green_shift) & 0xff) <<  8) |
1507                                     ((src_val >> src->blue_shift)  & 0xff);
1508                 }
1509                 if(pad_size) memset(dst_pixel, 0, pad_size);
1510                 dst_start += dst->stride / 4;
1511                 src_start += src->stride / 4;
1512             }
1513         }
1514         else
1515         {
1516             for(y = src_rect->top; y < src_rect->bottom; y++)
1517             {
1518                 dst_pixel = dst_start;
1519                 src_pixel = src_start;
1520                 for(x = src_rect->left; x < src_rect->right; x++)
1521                 {
1522                     src_val = *src_pixel++;
1523                     *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1524                                     get_field( src_val, src->green_shift, src->green_len ) << 8 |
1525                                     get_field( src_val, src->blue_shift, src->blue_len ));
1526                 }
1527                 if(pad_size) memset(dst_pixel, 0, pad_size);
1528                 dst_start += dst->stride / 4;
1529                 src_start += src->stride / 4;
1530             }
1531         }
1532         break;
1533     }
1534
1535     case 24:
1536     {
1537         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1538
1539         for(y = src_rect->top; y < src_rect->bottom; y++)
1540         {
1541             dst_pixel = dst_start;
1542             src_pixel = src_start;
1543             for(x = src_rect->left; x < src_rect->right; x++)
1544             {
1545                 RGBQUAD rgb;
1546                 rgb.rgbBlue  = *src_pixel++;
1547                 rgb.rgbGreen = *src_pixel++;
1548                 rgb.rgbRed   = *src_pixel++;
1549
1550                 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1551             }
1552             if(pad_size) memset(dst_pixel, 0, pad_size);
1553             dst_start += dst->stride / 4;
1554             src_start += src->stride;
1555         }
1556         break;
1557     }
1558
1559     case 16:
1560     {
1561         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1562         if(src->funcs == &funcs_555)
1563         {
1564             for(y = src_rect->top; y < src_rect->bottom; y++)
1565             {
1566                 dst_pixel = dst_start;
1567                 src_pixel = src_start;
1568                 for(x = src_rect->left; x < src_rect->right; x++)
1569                 {
1570                     src_val = *src_pixel++;
1571                     *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1572                                    ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1573                                    ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1574                 }
1575                 if(pad_size) memset(dst_pixel, 0, pad_size);
1576                 dst_start += dst->stride / 4;
1577                 src_start += src->stride / 2;
1578             }
1579         }
1580         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1581         {
1582             for(y = src_rect->top; y < src_rect->bottom; y++)
1583             {
1584                 dst_pixel = dst_start;
1585                 src_pixel = src_start;
1586                 for(x = src_rect->left; x < src_rect->right; x++)
1587                 {
1588                     src_val = *src_pixel++;
1589                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1590                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1591                                    (((src_val >> src->green_shift) << 11) & 0x00f800) |
1592                                    (((src_val >> src->green_shift) <<  6) & 0x000700) |
1593                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1594                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1595                 }
1596                 if(pad_size) memset(dst_pixel, 0, pad_size);
1597                 dst_start += dst->stride / 4;
1598                 src_start += src->stride / 2;
1599             }
1600         }
1601         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1602         {
1603             for(y = src_rect->top; y < src_rect->bottom; y++)
1604             {
1605                 dst_pixel = dst_start;
1606                 src_pixel = src_start;
1607                 for(x = src_rect->left; x < src_rect->right; x++)
1608                 {
1609                     src_val = *src_pixel++;
1610                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1611                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1612                                    (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1613                                    (((src_val >> src->green_shift) <<  4) & 0x000300) |
1614                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1615                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1616                 }
1617                 if(pad_size) memset(dst_pixel, 0, pad_size);
1618                 dst_start += dst->stride / 4;
1619                 src_start += src->stride / 2;
1620             }
1621         }
1622         else
1623         {
1624             for(y = src_rect->top; y < src_rect->bottom; y++)
1625             {
1626                 dst_pixel = dst_start;
1627                 src_pixel = src_start;
1628                 for(x = src_rect->left; x < src_rect->right; x++)
1629                 {
1630                     src_val = *src_pixel++;
1631                     *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1632                                     get_field( src_val, src->green_shift, src->green_len ) << 8 |
1633                                     get_field( src_val, src->blue_shift, src->blue_len ));
1634                 }
1635                 if(pad_size) memset(dst_pixel, 0, pad_size);
1636                 dst_start += dst->stride / 4;
1637                 src_start += src->stride / 2;
1638             }
1639         }
1640         break;
1641     }
1642
1643     case 8:
1644     {
1645         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1646         for(y = src_rect->top; y < src_rect->bottom; y++)
1647         {
1648             dst_pixel = dst_start;
1649             src_pixel = src_start;
1650             for(x = src_rect->left; x < src_rect->right; x++)
1651             {
1652                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1653                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1654             }
1655             if(pad_size) memset(dst_pixel, 0, pad_size);
1656             dst_start += dst->stride / 4;
1657             src_start += src->stride;
1658         }
1659         break;
1660     }
1661
1662     case 4:
1663     {
1664         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1665         for(y = src_rect->top; y < src_rect->bottom; y++)
1666         {
1667             dst_pixel = dst_start;
1668             src_pixel = src_start;
1669             for(x = src_rect->left; x < src_rect->right; x++)
1670             {
1671                 RGBQUAD rgb;
1672                 if(x & 1)
1673                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
1674                 else
1675                     rgb = colortable_entry( src, *src_pixel >> 4 );
1676                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1677             }
1678             if(pad_size) memset(dst_pixel, 0, pad_size);
1679             dst_start += dst->stride / 4;
1680             src_start += src->stride;
1681         }
1682         break;
1683     }
1684
1685     case 1:
1686     {
1687         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1688         for(y = src_rect->top; y < src_rect->bottom; y++)
1689         {
1690             dst_pixel = dst_start;
1691             src_pixel = src_start;
1692             for(x = src_rect->left; x < src_rect->right; x++)
1693             {
1694                 RGBQUAD rgb;
1695                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1696                 if((x % 8) == 7) src_pixel++;
1697                 rgb = src->color_table[src_val];
1698                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1699             }
1700             if(pad_size) memset(dst_pixel, 0, pad_size);
1701             dst_start += dst->stride / 4;
1702             src_start += src->stride;
1703         }
1704         break;
1705     }
1706     }
1707 }
1708
1709 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1710 {
1711     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1712     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1713
1714     switch(src->bit_count)
1715     {
1716     case 32:
1717     {
1718         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1719
1720         if(src->funcs == &funcs_8888)
1721         {
1722             for(y = src_rect->top; y < src_rect->bottom; y++)
1723             {
1724                 dst_pixel = dst_start;
1725                 src_pixel = src_start;
1726                 for(x = src_rect->left; x < src_rect->right; x++)
1727                 {
1728                     src_val = *src_pixel++;
1729                     *dst_pixel++ = put_field(src_val >> 16, dst->red_shift,   dst->red_len)   |
1730                                    put_field(src_val >>  8, dst->green_shift, dst->green_len) |
1731                                    put_field(src_val,       dst->blue_shift,  dst->blue_len);
1732                 }
1733                 if(pad_size) memset(dst_pixel, 0, pad_size);
1734                 dst_start += dst->stride / 4;
1735                 src_start += src->stride / 4;
1736             }
1737         }
1738         else if(bit_fields_match(src, dst))
1739         {
1740             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1741                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1742             else
1743             {
1744                 for(y = src_rect->top; y < src_rect->bottom; y++)
1745                 {
1746                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1747                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1748                     dst_start += dst->stride / 4;
1749                     src_start += src->stride / 4;
1750                 }
1751             }
1752         }
1753         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1754                 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1755         {
1756             for(y = src_rect->top; y < src_rect->bottom; y++)
1757             {
1758                 dst_pixel = dst_start;
1759                 src_pixel = src_start;
1760                 for(x = src_rect->left; x < src_rect->right; x++)
1761                 {
1762                     src_val = *src_pixel++;
1763                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << dst->red_shift)   |
1764                                    (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1765                                    (((src_val >> src->blue_shift)  & 0xff) << dst->blue_shift);
1766                 }
1767                 if(pad_size) memset(dst_pixel, 0, pad_size);
1768                 dst_start += dst->stride / 4;
1769                 src_start += src->stride / 4;
1770             }
1771         }
1772         else
1773         {
1774             for(y = src_rect->top; y < src_rect->bottom; y++)
1775             {
1776                 dst_pixel = dst_start;
1777                 src_pixel = src_start;
1778                 for(x = src_rect->left; x < src_rect->right; x++)
1779                 {
1780                     src_val = *src_pixel++;
1781                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
1782                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1783                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
1784                 }
1785                 if(pad_size) memset(dst_pixel, 0, pad_size);
1786                 dst_start += dst->stride / 4;
1787                 src_start += src->stride / 4;
1788             }
1789         }
1790         break;
1791     }
1792
1793     case 24:
1794     {
1795         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1796
1797         for(y = src_rect->top; y < src_rect->bottom; y++)
1798         {
1799             dst_pixel = dst_start;
1800             src_pixel = src_start;
1801             for(x = src_rect->left; x < src_rect->right; x++)
1802             {
1803                 RGBQUAD rgb;
1804                 rgb.rgbBlue  = *src_pixel++;
1805                 rgb.rgbGreen = *src_pixel++;
1806                 rgb.rgbRed   = *src_pixel++;
1807
1808                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len)   |
1809                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1810                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1811             }
1812             if(pad_size) memset(dst_pixel, 0, pad_size);
1813             dst_start += dst->stride / 4;
1814             src_start += src->stride;
1815         }
1816         break;
1817     }
1818
1819     case 16:
1820     {
1821         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1822         if(src->funcs == &funcs_555)
1823         {
1824             for(y = src_rect->top; y < src_rect->bottom; y++)
1825             {
1826                 dst_pixel = dst_start;
1827                 src_pixel = src_start;
1828                 for(x = src_rect->left; x < src_rect->right; x++)
1829                 {
1830                     src_val = *src_pixel++;
1831                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
1832                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
1833                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
1834                 }
1835                 if(pad_size) memset(dst_pixel, 0, pad_size);
1836                 dst_start += dst->stride / 4;
1837                 src_start += src->stride / 2;
1838             }
1839         }
1840         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1841         {
1842             for(y = src_rect->top; y < src_rect->bottom; y++)
1843             {
1844                 dst_pixel = dst_start;
1845                 src_pixel = src_start;
1846                 for(x = src_rect->left; x < src_rect->right; x++)
1847                 {
1848                     src_val = *src_pixel++;
1849                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1850                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1851                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1852                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1853                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1854                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1855                 }
1856                 if(pad_size) memset(dst_pixel, 0, pad_size);
1857                 dst_start += dst->stride / 4;
1858                 src_start += src->stride / 2;
1859             }
1860         }
1861         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1862         {
1863             for(y = src_rect->top; y < src_rect->bottom; y++)
1864             {
1865                 dst_pixel = dst_start;
1866                 src_pixel = src_start;
1867                 for(x = src_rect->left; x < src_rect->right; x++)
1868                 {
1869                     src_val = *src_pixel++;
1870                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1871                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1872                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1873                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1874                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1875                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1876                 }
1877                 if(pad_size) memset(dst_pixel, 0, pad_size);
1878                 dst_start += dst->stride / 4;
1879                 src_start += src->stride / 2;
1880             }
1881         }
1882         else
1883         {
1884             for(y = src_rect->top; y < src_rect->bottom; y++)
1885             {
1886                 dst_pixel = dst_start;
1887                 src_pixel = src_start;
1888                 for(x = src_rect->left; x < src_rect->right; x++)
1889                 {
1890                     src_val = *src_pixel++;
1891                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
1892                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1893                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
1894                 }
1895                 if(pad_size) memset(dst_pixel, 0, pad_size);
1896                 dst_start += dst->stride / 4;
1897                 src_start += src->stride / 2;
1898             }
1899         }
1900         break;
1901     }
1902
1903     case 8:
1904     {
1905         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1906         for(y = src_rect->top; y < src_rect->bottom; y++)
1907         {
1908             dst_pixel = dst_start;
1909             src_pixel = src_start;
1910             for(x = src_rect->left; x < src_rect->right; x++)
1911             {
1912                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1913                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1914                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1915                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1916             }
1917             if(pad_size) memset(dst_pixel, 0, pad_size);
1918             dst_start += dst->stride / 4;
1919             src_start += src->stride;
1920         }
1921         break;
1922     }
1923
1924     case 4:
1925     {
1926         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1927         for(y = src_rect->top; y < src_rect->bottom; y++)
1928         {
1929             dst_pixel = dst_start;
1930             src_pixel = src_start;
1931             for(x = src_rect->left; x < src_rect->right; x++)
1932             {
1933                 RGBQUAD rgb;
1934                 if(x & 1)
1935                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
1936                 else
1937                     rgb = colortable_entry( src, *src_pixel >> 4 );
1938                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1939                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1940                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1941             }
1942             if(pad_size) memset(dst_pixel, 0, pad_size);
1943             dst_start += dst->stride / 4;
1944             src_start += src->stride;
1945         }
1946         break;
1947     }
1948
1949     case 1:
1950     {
1951         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1952         for(y = src_rect->top; y < src_rect->bottom; y++)
1953         {
1954             dst_pixel = dst_start;
1955             src_pixel = src_start;
1956             for(x = src_rect->left; x < src_rect->right; x++)
1957             {
1958                 RGBQUAD rgb;
1959                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1960                 if((x % 8) == 7) src_pixel++;
1961                 rgb = src->color_table[src_val];
1962                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1963                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1964                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1965             }
1966             if(pad_size) memset(dst_pixel, 0, pad_size);
1967             dst_start += dst->stride / 4;
1968             src_start += src->stride;
1969         }
1970         break;
1971     }
1972     }
1973 }
1974
1975 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1976 {
1977     BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1978     DWORD src_val;
1979     int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1980
1981     switch(src->bit_count)
1982     {
1983     case 32:
1984     {
1985         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1986         if(src->funcs == &funcs_8888)
1987         {
1988             for(y = src_rect->top; y < src_rect->bottom; y++)
1989             {
1990                 dst_pixel = dst_start;
1991                 src_pixel = src_start;
1992                 for(x = src_rect->left; x < src_rect->right; x++)
1993                 {
1994                     src_val = *src_pixel++;
1995                     *dst_pixel++ =  src_val        & 0xff;
1996                     *dst_pixel++ = (src_val >>  8) & 0xff;
1997                     *dst_pixel++ = (src_val >> 16) & 0xff;
1998                 }
1999                 if(pad_size) memset(dst_pixel, 0, pad_size);
2000                 dst_start += dst->stride;
2001                 src_start += src->stride / 4;
2002             }
2003         }
2004         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2005         {
2006             for(y = src_rect->top; y < src_rect->bottom; y++)
2007             {
2008                 dst_pixel = dst_start;
2009                 src_pixel = src_start;
2010                 for(x = src_rect->left; x < src_rect->right; x++)
2011                 {
2012                     src_val = *src_pixel++;
2013                     *dst_pixel++ = (src_val >> src->blue_shift)  & 0xff;
2014                     *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2015                     *dst_pixel++ = (src_val >> src->red_shift)   & 0xff;
2016                 }
2017                 if(pad_size) memset(dst_pixel, 0, pad_size);
2018                 dst_start += dst->stride;
2019                 src_start += src->stride / 4;
2020             }
2021         }
2022         else
2023         {
2024             for(y = src_rect->top; y < src_rect->bottom; y++)
2025             {
2026                 dst_pixel = dst_start;
2027                 src_pixel = src_start;
2028                 for(x = src_rect->left; x < src_rect->right; x++)
2029                 {
2030                     src_val = *src_pixel++;
2031                     *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2032                     *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2033                     *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2034                 }
2035                 if(pad_size) memset(dst_pixel, 0, pad_size);
2036                 dst_start += dst->stride;
2037                 src_start += src->stride / 4;
2038             }
2039         }
2040         break;
2041     }
2042
2043     case 24:
2044     {
2045         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2046
2047         if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2048             memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2049         else
2050         {
2051             for(y = src_rect->top; y < src_rect->bottom; y++)
2052             {
2053                 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2054                 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2055                 dst_start += dst->stride;
2056                 src_start += src->stride;
2057             }
2058         }
2059         break;
2060     }
2061
2062     case 16:
2063     {
2064         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2065         if(src->funcs == &funcs_555)
2066         {
2067             for(y = src_rect->top; y < src_rect->bottom; y++)
2068             {
2069                 dst_pixel = dst_start;
2070                 src_pixel = src_start;
2071                 for(x = src_rect->left; x < src_rect->right; x++)
2072                 {
2073                     src_val = *src_pixel++;
2074                     *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07);
2075                     *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07);
2076                     *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2077                 }
2078                 if(pad_size) memset(dst_pixel, 0, pad_size);
2079                 dst_start += dst->stride;
2080                 src_start += src->stride / 2;
2081             }
2082         }
2083         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2084         {
2085             for(y = src_rect->top; y < src_rect->bottom; y++)
2086             {
2087                 dst_pixel = dst_start;
2088                 src_pixel = src_start;
2089                 for(x = src_rect->left; x < src_rect->right; x++)
2090                 {
2091                     src_val = *src_pixel++;
2092                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2093                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
2094                     *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2095                                    (((src_val >> src->green_shift) >> 2) & 0x07);
2096                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
2097                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
2098                 }
2099                 if(pad_size) memset(dst_pixel, 0, pad_size);
2100                 dst_start += dst->stride;
2101                 src_start += src->stride / 2;
2102             }
2103         }
2104         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2105         {
2106             for(y = src_rect->top; y < src_rect->bottom; y++)
2107             {
2108                 dst_pixel = dst_start;
2109                 src_pixel = src_start;
2110                 for(x = src_rect->left; x < src_rect->right; x++)
2111                 {
2112                     src_val = *src_pixel++;
2113                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2114                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
2115                     *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2116                                    (((src_val >> src->green_shift) >> 4) & 0x03);
2117                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
2118                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
2119                 }
2120                 if(pad_size) memset(dst_pixel, 0, pad_size);
2121                 dst_start += dst->stride;
2122                 src_start += src->stride / 2;
2123             }
2124         }
2125         else
2126         {
2127             for(y = src_rect->top; y < src_rect->bottom; y++)
2128             {
2129                 dst_pixel = dst_start;
2130                 src_pixel = src_start;
2131                 for(x = src_rect->left; x < src_rect->right; x++)
2132                 {
2133                     src_val = *src_pixel++;
2134                     *dst_pixel++ = get_field(src_val, src->blue_shift,  src->blue_len );
2135                     *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2136                     *dst_pixel++ = get_field(src_val, src->red_shift,   src->red_len );
2137                 }
2138                 if(pad_size) memset(dst_pixel, 0, pad_size);
2139                 dst_start += dst->stride;
2140                 src_start += src->stride / 2;
2141             }
2142         }
2143         break;
2144     }
2145
2146     case 8:
2147     {
2148         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2149         for(y = src_rect->top; y < src_rect->bottom; y++)
2150         {
2151             dst_pixel = dst_start;
2152             src_pixel = src_start;
2153             for(x = src_rect->left; x < src_rect->right; x++)
2154             {
2155                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2156                 *dst_pixel++ = rgb.rgbBlue;
2157                 *dst_pixel++ = rgb.rgbGreen;
2158                 *dst_pixel++ = rgb.rgbRed;
2159             }
2160             if(pad_size) memset(dst_pixel, 0, pad_size);
2161             dst_start += dst->stride;
2162             src_start += src->stride;
2163         }
2164         break;
2165     }
2166
2167     case 4:
2168     {
2169         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2170         for(y = src_rect->top; y < src_rect->bottom; y++)
2171         {
2172             dst_pixel = dst_start;
2173             src_pixel = src_start;
2174             for(x = src_rect->left; x < src_rect->right; x++)
2175             {
2176                 RGBQUAD rgb;
2177                 if(x & 1)
2178                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
2179                 else
2180                     rgb = colortable_entry( src, *src_pixel >> 4 );
2181                 *dst_pixel++ = rgb.rgbBlue;
2182                 *dst_pixel++ = rgb.rgbGreen;
2183                 *dst_pixel++ = rgb.rgbRed;
2184             }
2185             if(pad_size) memset(dst_pixel, 0, pad_size);
2186             dst_start += dst->stride;
2187             src_start += src->stride;
2188         }
2189         break;
2190     }
2191
2192     case 1:
2193     {
2194         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2195         for(y = src_rect->top; y < src_rect->bottom; y++)
2196         {
2197             dst_pixel = dst_start;
2198             src_pixel = src_start;
2199             for(x = src_rect->left; x < src_rect->right; x++)
2200             {
2201                 RGBQUAD rgb;
2202                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2203                 if((x % 8) == 7) src_pixel++;
2204                 rgb = src->color_table[src_val];
2205                 *dst_pixel++ = rgb.rgbBlue;
2206                 *dst_pixel++ = rgb.rgbGreen;
2207                 *dst_pixel++ = rgb.rgbRed;
2208             }
2209             if(pad_size) memset(dst_pixel, 0, pad_size);
2210             dst_start += dst->stride;
2211             src_start += src->stride;
2212         }
2213         break;
2214     }
2215     }
2216 }
2217
2218 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
2219 {
2220     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2221     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2222     DWORD src_val;
2223
2224     switch(src->bit_count)
2225     {
2226     case 32:
2227     {
2228         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2229
2230         if(src->funcs == &funcs_8888)
2231         {
2232             for(y = src_rect->top; y < src_rect->bottom; y++)
2233             {
2234                 dst_pixel = dst_start;
2235                 src_pixel = src_start;
2236                 for(x = src_rect->left; x < src_rect->right; x++)
2237                 {
2238                     src_val = *src_pixel++;
2239                     *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2240                                    ((src_val >> 6) & 0x03e0) |
2241                                    ((src_val >> 3) & 0x001f);
2242                 }
2243                 if(pad_size) memset(dst_pixel, 0, pad_size);
2244                 dst_start += dst->stride / 2;
2245                 src_start += src->stride / 4;
2246             }
2247         }
2248         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2249         {
2250             for(y = src_rect->top; y < src_rect->bottom; y++)
2251             {
2252                 dst_pixel = dst_start;
2253                 src_pixel = src_start;
2254                 for(x = src_rect->left; x < src_rect->right; x++)
2255                 {
2256                     src_val = *src_pixel++;
2257                     *dst_pixel++ = (((src_val >> src->red_shift)   << 7) & 0x7c00) |
2258                                    (((src_val >> src->green_shift) << 2) & 0x03e0) |
2259                                    (((src_val >> src->blue_shift)  >> 3) & 0x001f);
2260                 }
2261                 if(pad_size) memset(dst_pixel, 0, pad_size);
2262                 dst_start += dst->stride / 2;
2263                 src_start += src->stride / 4;
2264             }
2265         }
2266         else
2267         {
2268             for(y = src_rect->top; y < src_rect->bottom; y++)
2269             {
2270                 dst_pixel = dst_start;
2271                 src_pixel = src_start;
2272                 for(x = src_rect->left; x < src_rect->right; x++)
2273                 {
2274                     src_val = *src_pixel++;
2275                     *dst_pixel++ = (((get_field(src_val, src->red_shift,   src->red_len )   << 7) & 0x7c00) |
2276                                     ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2277                                     ( get_field(src_val, src->blue_shift,  src->blue_len )  >> 3));
2278                 }
2279                 if(pad_size) memset(dst_pixel, 0, pad_size);
2280                 dst_start += dst->stride / 2;
2281                 src_start += src->stride / 4;
2282             }
2283         }
2284         break;
2285     }
2286
2287     case 24:
2288     {
2289         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2290
2291         for(y = src_rect->top; y < src_rect->bottom; y++)
2292         {
2293             dst_pixel = dst_start;
2294             src_pixel = src_start;
2295             for(x = src_rect->left; x < src_rect->right; x++)
2296             {
2297                 RGBQUAD rgb;
2298                 rgb.rgbBlue  = *src_pixel++;
2299                 rgb.rgbGreen = *src_pixel++;
2300                 rgb.rgbRed   = *src_pixel++;
2301
2302                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2303                                ((rgb.rgbGreen << 2) & 0x03e0) |
2304                                ((rgb.rgbBlue  >> 3) & 0x001f);
2305             }
2306             if(pad_size) memset(dst_pixel, 0, pad_size);
2307             dst_start += dst->stride / 2;
2308             src_start += src->stride;
2309         }
2310         break;
2311     }
2312
2313     case 16:
2314     {
2315         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2316         if(src->funcs == &funcs_555)
2317         {
2318             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2319                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2320             else
2321             {
2322                 for(y = src_rect->top; y < src_rect->bottom; y++)
2323                 {
2324                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2325                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2326                     dst_start += dst->stride / 2;
2327                     src_start += src->stride / 2;
2328                 }
2329             }
2330         }
2331         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2332         {
2333             for(y = src_rect->top; y < src_rect->bottom; y++)
2334             {
2335                 dst_pixel = dst_start;
2336                 src_pixel = src_start;
2337                 for(x = src_rect->left; x < src_rect->right; x++)
2338                 {
2339                     src_val = *src_pixel++;
2340                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2341                                    (((src_val >> src->green_shift) <<  5) & 0x03e0) |
2342                                    ( (src_val >> src->blue_shift)         & 0x001f);
2343                 }
2344                 if(pad_size) memset(dst_pixel, 0, pad_size);
2345                 dst_start += dst->stride / 2;
2346                 src_start += src->stride / 2;
2347             }
2348         }
2349         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2350         {
2351             for(y = src_rect->top; y < src_rect->bottom; y++)
2352             {
2353                 dst_pixel = dst_start;
2354                 src_pixel = src_start;
2355                 for(x = src_rect->left; x < src_rect->right; x++)
2356                 {
2357                     src_val = *src_pixel++;
2358                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2359                                    (((src_val >> src->green_shift) <<  4) & 0x03e0) |
2360                                    ( (src_val >> src->blue_shift)         & 0x001f);
2361                 }
2362                 if(pad_size) memset(dst_pixel, 0, pad_size);
2363                 dst_start += dst->stride / 2;
2364                 src_start += src->stride / 2;
2365             }
2366         }
2367         else
2368         {
2369             for(y = src_rect->top; y < src_rect->bottom; y++)
2370             {
2371                 dst_pixel = dst_start;
2372                 src_pixel = src_start;
2373                 for(x = src_rect->left; x < src_rect->right; x++)
2374                 {
2375                     src_val = *src_pixel++;
2376                     *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len)     << 7) & 0x7c00) |
2377                                     ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2378                                     ( get_field(src_val, src->blue_shift, src->blue_len)   >> 3));
2379                 }
2380                 if(pad_size) memset(dst_pixel, 0, pad_size);
2381                 dst_start += dst->stride / 2;
2382                 src_start += src->stride / 2;
2383             }
2384         }
2385         break;
2386     }
2387
2388     case 8:
2389     {
2390         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2391         for(y = src_rect->top; y < src_rect->bottom; y++)
2392         {
2393             dst_pixel = dst_start;
2394             src_pixel = src_start;
2395             for(x = src_rect->left; x < src_rect->right; x++)
2396             {
2397                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2398                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2399                                ((rgb.rgbGreen << 2) & 0x03e0) |
2400                                ((rgb.rgbBlue  >> 3) & 0x001f);
2401             }
2402             if(pad_size) memset(dst_pixel, 0, pad_size);
2403             dst_start += dst->stride / 2;
2404             src_start += src->stride;
2405         }
2406         break;
2407     }
2408
2409     case 4:
2410     {
2411         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2412         for(y = src_rect->top; y < src_rect->bottom; y++)
2413         {
2414             dst_pixel = dst_start;
2415             src_pixel = src_start;
2416             for(x = src_rect->left; x < src_rect->right; x++)
2417             {
2418                 RGBQUAD rgb;
2419                 if(x & 1)
2420                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
2421                 else
2422                     rgb = colortable_entry( src, *src_pixel >> 4 );
2423                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2424                                ((rgb.rgbGreen << 2) & 0x03e0) |
2425                                ((rgb.rgbBlue  >> 3) & 0x001f);
2426             }
2427             if(pad_size) memset(dst_pixel, 0, pad_size);
2428             dst_start += dst->stride / 2;
2429             src_start += src->stride;
2430         }
2431         break;
2432     }
2433
2434     case 1:
2435     {
2436         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2437         for(y = src_rect->top; y < src_rect->bottom; y++)
2438         {
2439             dst_pixel = dst_start;
2440             src_pixel = src_start;
2441             for(x = src_rect->left; x < src_rect->right; x++)
2442             {
2443                 RGBQUAD rgb;
2444                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2445                 if((x % 8) == 7) src_pixel++;
2446                 rgb = src->color_table[src_val];
2447                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2448                                ((rgb.rgbGreen << 2) & 0x03e0) |
2449                                ((rgb.rgbBlue  >> 3) & 0x001f);
2450             }
2451             if(pad_size) memset(dst_pixel, 0, pad_size);
2452             dst_start += dst->stride / 2;
2453             src_start += src->stride;
2454         }
2455         break;
2456     }
2457     }
2458 }
2459
2460 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2461 {
2462     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2463     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2464     DWORD src_val;
2465
2466     switch(src->bit_count)
2467     {
2468     case 32:
2469     {
2470         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2471
2472         if(src->funcs == &funcs_8888)
2473         {
2474             for(y = src_rect->top; y < src_rect->bottom; y++)
2475             {
2476                 dst_pixel = dst_start;
2477                 src_pixel = src_start;
2478                 for(x = src_rect->left; x < src_rect->right; x++)
2479                 {
2480                     src_val = *src_pixel++;
2481                     *dst_pixel++ = put_field(src_val >> 16, dst->red_shift,   dst->red_len)   |
2482                                    put_field(src_val >>  8, dst->green_shift, dst->green_len) |
2483                                    put_field(src_val,       dst->blue_shift,  dst->blue_len);
2484                 }
2485                 if(pad_size) memset(dst_pixel, 0, pad_size);
2486                 dst_start += dst->stride / 2;
2487                 src_start += src->stride / 4;
2488             }
2489         }
2490         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2491         {
2492             for(y = src_rect->top; y < src_rect->bottom; y++)
2493             {
2494                 dst_pixel = dst_start;
2495                 src_pixel = src_start;
2496                 for(x = src_rect->left; x < src_rect->right; x++)
2497                 {
2498                     src_val = *src_pixel++;
2499                     *dst_pixel++ = put_field(src_val >> src->red_shift,   dst->red_shift,   dst->red_len)   |
2500                                    put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2501                                    put_field(src_val >> src->blue_shift,  dst->blue_shift,  dst->blue_len);
2502                 }
2503                 if(pad_size) memset(dst_pixel, 0, pad_size);
2504                 dst_start += dst->stride / 2;
2505                 src_start += src->stride / 4;
2506             }
2507         }
2508         else
2509         {
2510             for(y = src_rect->top; y < src_rect->bottom; y++)
2511             {
2512                 dst_pixel = dst_start;
2513                 src_pixel = src_start;
2514                 for(x = src_rect->left; x < src_rect->right; x++)
2515                 {
2516                     src_val = *src_pixel++;
2517                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
2518                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2519                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
2520                 }
2521                 if(pad_size) memset(dst_pixel, 0, pad_size);
2522                 dst_start += dst->stride / 2;
2523                 src_start += src->stride / 4;
2524             }
2525         }
2526         break;
2527     }
2528
2529     case 24:
2530     {
2531         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2532
2533         for(y = src_rect->top; y < src_rect->bottom; y++)
2534         {
2535             dst_pixel = dst_start;
2536             src_pixel = src_start;
2537             for(x = src_rect->left; x < src_rect->right; x++)
2538             {
2539                 RGBQUAD rgb;
2540                 rgb.rgbBlue  = *src_pixel++;
2541                 rgb.rgbGreen = *src_pixel++;
2542                 rgb.rgbRed   = *src_pixel++;
2543
2544                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2545                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2546                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2547             }
2548             if(pad_size) memset(dst_pixel, 0, pad_size);
2549             dst_start += dst->stride / 2;
2550             src_start += src->stride;
2551         }
2552         break;
2553     }
2554
2555     case 16:
2556     {
2557         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2558         if(src->funcs == &funcs_555)
2559         {
2560             for(y = src_rect->top; y < src_rect->bottom; y++)
2561             {
2562                 dst_pixel = dst_start;
2563                 src_pixel = src_start;
2564                 for(x = src_rect->left; x < src_rect->right; x++)
2565                 {
2566                     src_val = *src_pixel++;
2567                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
2568                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
2569                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
2570                 }
2571                 if(pad_size) memset(dst_pixel, 0, pad_size);
2572                 dst_start += dst->stride / 2;
2573                 src_start += src->stride / 2;
2574             }
2575         }
2576         else if(bit_fields_match(src, dst))
2577         {
2578             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2579                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2580             else
2581             {
2582                 for(y = src_rect->top; y < src_rect->bottom; y++)
2583                 {
2584                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2585                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2586                     dst_start += dst->stride / 2;
2587                     src_start += src->stride / 2;
2588                 }
2589             }
2590         }
2591         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2592         {
2593             for(y = src_rect->top; y < src_rect->bottom; y++)
2594             {
2595                 dst_pixel = dst_start;
2596                 src_pixel = src_start;
2597                 for(x = src_rect->left; x < src_rect->right; x++)
2598                 {
2599                     src_val = *src_pixel++;
2600                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2601                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2602                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2603                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2604                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2605                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2606                 }
2607                 if(pad_size) memset(dst_pixel, 0, pad_size);
2608                 dst_start += dst->stride / 2;
2609                 src_start += src->stride / 2;
2610             }
2611         }
2612         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2613         {
2614             for(y = src_rect->top; y < src_rect->bottom; y++)
2615             {
2616                 dst_pixel = dst_start;
2617                 src_pixel = src_start;
2618                 for(x = src_rect->left; x < src_rect->right; x++)
2619                 {
2620                     src_val = *src_pixel++;
2621                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2622                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2623                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2624                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2625                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2626                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2627                 }
2628                 if(pad_size) memset(dst_pixel, 0, pad_size);
2629                 dst_start += dst->stride / 2;
2630                 src_start += src->stride / 2;
2631             }
2632         }
2633         else
2634         {
2635             for(y = src_rect->top; y < src_rect->bottom; y++)
2636             {
2637                 dst_pixel = dst_start;
2638                 src_pixel = src_start;
2639                 for(x = src_rect->left; x < src_rect->right; x++)
2640                 {
2641                     src_val = *src_pixel++;
2642                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
2643                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2644                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
2645                 }
2646                 if(pad_size) memset(dst_pixel, 0, pad_size);
2647                 dst_start += dst->stride / 2;
2648                 src_start += src->stride / 2;
2649             }
2650         }
2651         break;
2652     }
2653
2654     case 8:
2655     {
2656         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2657         for(y = src_rect->top; y < src_rect->bottom; y++)
2658         {
2659             dst_pixel = dst_start;
2660             src_pixel = src_start;
2661             for(x = src_rect->left; x < src_rect->right; x++)
2662             {
2663                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2664                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2665                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2666                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2667             }
2668             if(pad_size) memset(dst_pixel, 0, pad_size);
2669             dst_start += dst->stride / 2;
2670             src_start += src->stride;
2671         }
2672         break;
2673     }
2674
2675     case 4:
2676     {
2677         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2678         for(y = src_rect->top; y < src_rect->bottom; y++)
2679         {
2680             dst_pixel = dst_start;
2681             src_pixel = src_start;
2682             for(x = src_rect->left; x < src_rect->right; x++)
2683             {
2684                 RGBQUAD rgb;
2685                 if(x & 1)
2686                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
2687                 else
2688                     rgb = colortable_entry( src, *src_pixel >> 4 );
2689                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2690                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2691                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2692             }
2693             if(pad_size) memset(dst_pixel, 0, pad_size);
2694             dst_start += dst->stride / 2;
2695             src_start += src->stride;
2696         }
2697         break;
2698     }
2699
2700     case 1:
2701     {
2702         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2703         for(y = src_rect->top; y < src_rect->bottom; y++)
2704         {
2705             dst_pixel = dst_start;
2706             src_pixel = src_start;
2707             for(x = src_rect->left; x < src_rect->right; x++)
2708             {
2709                 RGBQUAD rgb;
2710                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2711                 if((x % 8) == 7) src_pixel++;
2712                 rgb = src->color_table[src_val];
2713                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2714                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2715                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2716             }
2717             if(pad_size) memset(dst_pixel, 0, pad_size);
2718             dst_start += dst->stride / 2;
2719             src_start += src->stride;
2720         }
2721         break;
2722     }
2723     }
2724 }
2725
2726 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2727 {
2728     assert(d1->color_table_size && d2->color_table_size);
2729
2730     if(d1->color_table_size != d2->color_table_size) return FALSE;
2731     return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2732 }
2733
2734 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2735 {
2736     /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2737     return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2738 }
2739
2740 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2741 {
2742     BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2743     INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2744     DWORD src_val;
2745
2746     switch(src->bit_count)
2747     {
2748     case 32:
2749     {
2750         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2751
2752         if(src->funcs == &funcs_8888)
2753         {
2754             for(y = src_rect->top; y < src_rect->bottom; y++)
2755             {
2756                 dst_pixel = dst_start;
2757                 src_pixel = src_start;
2758                 for(x = src_rect->left; x < src_rect->right; x++)
2759                 {
2760                     src_val = *src_pixel++;
2761                     *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2762                 }
2763                 if(pad_size) memset(dst_pixel, 0, pad_size);
2764                 dst_start += dst->stride;
2765                 src_start += src->stride / 4;
2766             }
2767         }
2768         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2769         {
2770             for(y = src_rect->top; y < src_rect->bottom; y++)
2771             {
2772                 dst_pixel = dst_start;
2773                 src_pixel = src_start;
2774                 for(x = src_rect->left; x < src_rect->right; x++)
2775                 {
2776                     src_val = *src_pixel++;
2777                     *dst_pixel++ = rgb_lookup_colortable(dst,
2778                                                          src_val >> src->red_shift,
2779                                                          src_val >> src->green_shift,
2780                                                          src_val >> src->blue_shift );
2781                 }
2782                 if(pad_size) memset(dst_pixel, 0, pad_size);
2783                 dst_start += dst->stride;
2784                 src_start += src->stride / 4;
2785             }
2786         }
2787         else
2788         {
2789             for(y = src_rect->top; y < src_rect->bottom; y++)
2790             {
2791                 dst_pixel = dst_start;
2792                 src_pixel = src_start;
2793                 for(x = src_rect->left; x < src_rect->right; x++)
2794                 {
2795                     src_val = *src_pixel++;
2796                     *dst_pixel++ = rgb_lookup_colortable(dst,
2797                                                          get_field(src_val, src->red_shift, src->red_len),
2798                                                          get_field(src_val, src->green_shift, src->green_len),
2799                                                          get_field(src_val, src->blue_shift, src->blue_len));
2800                 }
2801                 if(pad_size) memset(dst_pixel, 0, pad_size);
2802                 dst_start += dst->stride;
2803                 src_start += src->stride / 4;
2804             }
2805         }
2806         break;
2807     }
2808
2809     case 24:
2810     {
2811         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2812
2813         for(y = src_rect->top; y < src_rect->bottom; y++)
2814         {
2815             dst_pixel = dst_start;
2816             src_pixel = src_start;
2817             for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2818             {
2819                 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2820             }
2821             if(pad_size) memset(dst_pixel, 0, pad_size);
2822             dst_start += dst->stride;
2823             src_start += src->stride;
2824         }
2825         break;
2826     }
2827
2828     case 16:
2829     {
2830         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2831         if(src->funcs == &funcs_555)
2832         {
2833             for(y = src_rect->top; y < src_rect->bottom; y++)
2834             {
2835                 dst_pixel = dst_start;
2836                 src_pixel = src_start;
2837                 for(x = src_rect->left; x < src_rect->right; x++)
2838                 {
2839                     src_val = *src_pixel++;
2840                     *dst_pixel++ = rgb_lookup_colortable(dst,
2841                                                          ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2842                                                          ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2843                                                          ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2844                 }
2845                 if(pad_size) memset(dst_pixel, 0, pad_size);
2846                 dst_start += dst->stride;
2847                 src_start += src->stride / 2;
2848             }
2849         }
2850         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2851         {
2852             for(y = src_rect->top; y < src_rect->bottom; y++)
2853             {
2854                 dst_pixel = dst_start;
2855                 src_pixel = src_start;
2856                 for(x = src_rect->left; x < src_rect->right; x++)
2857                 {
2858                     src_val = *src_pixel++;
2859                     *dst_pixel++ = rgb_lookup_colortable(dst,
2860                                                          (((src_val >> src->red_shift)   << 3) & 0xf8) |
2861                                                          (((src_val >> src->red_shift)   >> 2) & 0x07),
2862                                                          (((src_val >> src->green_shift) << 3) & 0xf8) |
2863                                                          (((src_val >> src->green_shift) >> 2) & 0x07),
2864                                                          (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2865                                                          (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2866                 }
2867                 if(pad_size) memset(dst_pixel, 0, pad_size);
2868                 dst_start += dst->stride;
2869                 src_start += src->stride / 2;
2870             }
2871         }
2872         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2873         {
2874             for(y = src_rect->top; y < src_rect->bottom; y++)
2875             {
2876                 dst_pixel = dst_start;
2877                 src_pixel = src_start;
2878                 for(x = src_rect->left; x < src_rect->right; x++)
2879                 {
2880                     src_val = *src_pixel++;
2881                     *dst_pixel++ = rgb_lookup_colortable(dst,
2882                                                          (((src_val >> src->red_shift)   << 3) & 0xf8) |
2883                                                          (((src_val >> src->red_shift)   >> 2) & 0x07),
2884                                                          (((src_val >> src->green_shift) << 2) & 0xfc) |
2885                                                          (((src_val >> src->green_shift) >> 4) & 0x03),
2886                                                          (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2887                                                          (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2888                 }
2889                 if(pad_size) memset(dst_pixel, 0, pad_size);
2890                 dst_start += dst->stride;
2891                 src_start += src->stride / 2;
2892             }
2893         }
2894         else
2895         {
2896             for(y = src_rect->top; y < src_rect->bottom; y++)
2897             {
2898                 dst_pixel = dst_start;
2899                 src_pixel = src_start;
2900                 for(x = src_rect->left; x < src_rect->right; x++)
2901                 {
2902                     src_val = *src_pixel++;
2903                     *dst_pixel++ = rgb_lookup_colortable(dst,
2904                                                          get_field(src_val, src->red_shift, src->red_len),
2905                                                          get_field(src_val, src->green_shift, src->green_len),
2906                                                          get_field(src_val, src->blue_shift, src->blue_len));
2907                 }
2908                 if(pad_size) memset(dst_pixel, 0, pad_size);
2909                 dst_start += dst->stride;
2910                 src_start += src->stride / 2;
2911             }
2912         }
2913         break;
2914     }
2915
2916     case 8:
2917     {
2918         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2919
2920         if(color_tables_match(dst, src))
2921         {
2922             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2923                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2924             else
2925             {
2926                 for(y = src_rect->top; y < src_rect->bottom; y++)
2927                 {
2928                     memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2929                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2930                     dst_start += dst->stride;
2931                     src_start += src->stride;
2932                 }
2933             }
2934         }
2935         else
2936         {
2937             for(y = src_rect->top; y < src_rect->bottom; y++)
2938             {
2939                 dst_pixel = dst_start;
2940                 src_pixel = src_start;
2941                 for(x = src_rect->left; x < src_rect->right; x++)
2942                 {
2943                     RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2944                     *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2945                 }
2946                 if(pad_size) memset(dst_pixel, 0, pad_size);
2947                 dst_start += dst->stride;
2948                 src_start += src->stride;
2949             }
2950         }
2951         break;
2952     }
2953
2954     case 4:
2955     {
2956         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2957         for(y = src_rect->top; y < src_rect->bottom; y++)
2958         {
2959             dst_pixel = dst_start;
2960             src_pixel = src_start;
2961             for(x = src_rect->left; x < src_rect->right; x++)
2962             {
2963                 RGBQUAD rgb;
2964                 if(x & 1)
2965                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
2966                 else
2967                     rgb = colortable_entry( src, *src_pixel >> 4 );
2968                 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2969             }
2970             if(pad_size) memset(dst_pixel, 0, pad_size);
2971             dst_start += dst->stride;
2972             src_start += src->stride;
2973         }
2974         break;
2975     }
2976
2977     case 1:
2978     {
2979         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2980         for(y = src_rect->top; y < src_rect->bottom; y++)
2981         {
2982             dst_pixel = dst_start;
2983             src_pixel = src_start;
2984             for(x = src_rect->left; x < src_rect->right; x++)
2985             {
2986                 RGBQUAD rgb;
2987                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2988                 if((x % 8) == 7) src_pixel++;
2989                 rgb = src->color_table[src_val];
2990                 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2991             }
2992             if(pad_size) memset(dst_pixel, 0, pad_size);
2993             dst_start += dst->stride;
2994             src_start += src->stride;
2995         }
2996         break;
2997     }
2998     }
2999 }
3000
3001 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
3002 {
3003     BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3004     INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3005     DWORD src_val;
3006
3007     switch(src->bit_count)
3008     {
3009     case 32:
3010     {
3011         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3012
3013         if(src->funcs == &funcs_8888)
3014         {
3015             for(y = src_rect->top; y < src_rect->bottom; y++)
3016             {
3017                 dst_pixel = dst_start;
3018                 src_pixel = src_start;
3019                 for(x = src_rect->left; x < src_rect->right; x++)
3020                 {
3021                     src_val = *src_pixel++;
3022                     dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3023                     if((x - src_rect->left) & 1)
3024                     {
3025                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3026                         dst_pixel++;
3027                     }
3028                     else
3029                         *dst_pixel = (dst_val << 4) & 0xf0;
3030                 }
3031                 if(pad_size)
3032                 {
3033                     if((x - src_rect->left) & 1) dst_pixel++;
3034                     memset(dst_pixel, 0, pad_size);
3035                 }
3036                 dst_start += dst->stride;
3037                 src_start += src->stride / 4;
3038             }
3039         }
3040         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3041         {
3042             for(y = src_rect->top; y < src_rect->bottom; y++)
3043             {
3044                 dst_pixel = dst_start;
3045                 src_pixel = src_start;
3046                 for(x = src_rect->left; x < src_rect->right; x++)
3047                 {
3048                     src_val = *src_pixel++;
3049                     dst_val = rgb_to_pixel_colortable(dst,
3050                                                       src_val >> src->red_shift,
3051                                                       src_val >> src->green_shift,
3052                                                       src_val >> src->blue_shift);
3053                     if((x - src_rect->left) & 1)
3054                     {
3055                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3056                         dst_pixel++;
3057                     }
3058                     else
3059                         *dst_pixel = (dst_val << 4) & 0xf0;
3060                 }
3061                 if(pad_size)
3062                 {
3063                     if((x - src_rect->left) & 1) dst_pixel++;
3064                     memset(dst_pixel, 0, pad_size);
3065                 }
3066                 dst_start += dst->stride;
3067                 src_start += src->stride / 4;
3068             }
3069         }
3070         else
3071         {
3072             for(y = src_rect->top; y < src_rect->bottom; y++)
3073             {
3074                 dst_pixel = dst_start;
3075                 src_pixel = src_start;
3076                 for(x = src_rect->left; x < src_rect->right; x++)
3077                 {
3078                     src_val = *src_pixel++;
3079                     dst_val = rgb_to_pixel_colortable(dst,
3080                                                       get_field(src_val, src->red_shift, src->red_len),
3081                                                       get_field(src_val, src->green_shift, src->green_len),
3082                                                       get_field(src_val, src->blue_shift, src->blue_len));
3083                     if((x - src_rect->left) & 1)
3084                     {
3085                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3086                         dst_pixel++;
3087                     }
3088                     else
3089                         *dst_pixel = (dst_val << 4) & 0xf0;
3090                 }
3091                 if(pad_size)
3092                 {
3093                     if((x - src_rect->left) & 1) dst_pixel++;
3094                     memset(dst_pixel, 0, pad_size);
3095                 }
3096                 dst_start += dst->stride;
3097                 src_start += src->stride / 4;
3098             }
3099         }
3100         break;
3101     }
3102
3103     case 24:
3104     {
3105         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3106
3107         for(y = src_rect->top; y < src_rect->bottom; y++)
3108         {
3109             dst_pixel = dst_start;
3110             src_pixel = src_start;
3111             for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3112             {
3113                 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3114
3115                 if((x - src_rect->left) & 1)
3116                 {
3117                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3118                     dst_pixel++;
3119                 }
3120                 else
3121                     *dst_pixel = (dst_val << 4) & 0xf0;
3122             }
3123             if(pad_size)
3124             {
3125                 if((x - src_rect->left) & 1) dst_pixel++;
3126                 memset(dst_pixel, 0, pad_size);
3127             }
3128             dst_start += dst->stride;
3129             src_start += src->stride;
3130         }
3131         break;
3132     }
3133
3134     case 16:
3135     {
3136         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3137         if(src->funcs == &funcs_555)
3138         {
3139             for(y = src_rect->top; y < src_rect->bottom; y++)
3140             {
3141                 dst_pixel = dst_start;
3142                 src_pixel = src_start;
3143                 for(x = src_rect->left; x < src_rect->right; x++)
3144                 {
3145                     src_val = *src_pixel++;
3146                     dst_val = rgb_to_pixel_colortable(dst,
3147                                                       ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3148                                                       ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07),
3149                                                       ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07) );
3150                     if((x - src_rect->left) & 1)
3151                     {
3152                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3153                         dst_pixel++;
3154                     }
3155                     else
3156                         *dst_pixel = (dst_val << 4) & 0xf0;
3157                 }
3158                 if(pad_size)
3159                 {
3160                     if((x - src_rect->left) & 1) dst_pixel++;
3161                     memset(dst_pixel, 0, pad_size);
3162                 }
3163                 dst_start += dst->stride;
3164                 src_start += src->stride / 2;
3165             }
3166         }
3167         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3168         {
3169             for(y = src_rect->top; y < src_rect->bottom; y++)
3170             {
3171                 dst_pixel = dst_start;
3172                 src_pixel = src_start;
3173                 for(x = src_rect->left; x < src_rect->right; x++)
3174                 {
3175                     src_val = *src_pixel++;
3176                     dst_val = rgb_to_pixel_colortable(dst,
3177                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3178                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3179                                                       (((src_val >> src->green_shift) << 3) & 0xf8) |
3180                                                       (((src_val >> src->green_shift) >> 2) & 0x07),
3181                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3182                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) );
3183                     if((x - src_rect->left) & 1)
3184                     {
3185                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3186                         dst_pixel++;
3187                     }
3188                     else
3189                         *dst_pixel = (dst_val << 4) & 0xf0;
3190                 }
3191                 if(pad_size)
3192                 {
3193                     if((x - src_rect->left) & 1) dst_pixel++;
3194                     memset(dst_pixel, 0, pad_size);
3195                 }
3196                 dst_start += dst->stride;
3197                 src_start += src->stride / 2;
3198             }
3199         }
3200         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3201         {
3202             for(y = src_rect->top; y < src_rect->bottom; y++)
3203             {
3204                 dst_pixel = dst_start;
3205                 src_pixel = src_start;
3206                 for(x = src_rect->left; x < src_rect->right; x++)
3207                 {
3208                     src_val = *src_pixel++;
3209                     dst_val = rgb_to_pixel_colortable(dst,
3210                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3211                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3212                                                       (((src_val >> src->green_shift) << 2) & 0xfc) |
3213                                                       (((src_val >> src->green_shift) >> 4) & 0x03),
3214                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3215                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) );
3216                     if((x - src_rect->left) & 1)
3217                     {
3218                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3219                         dst_pixel++;
3220                     }
3221                     else
3222                         *dst_pixel = (dst_val << 4) & 0xf0;
3223                 }
3224                 if(pad_size)
3225                 {
3226                     if((x - src_rect->left) & 1) dst_pixel++;
3227                     memset(dst_pixel, 0, pad_size);
3228                 }
3229                 dst_start += dst->stride;
3230                 src_start += src->stride / 2;
3231             }
3232         }
3233         else
3234         {
3235             for(y = src_rect->top; y < src_rect->bottom; y++)
3236             {
3237                 dst_pixel = dst_start;
3238                 src_pixel = src_start;
3239                 for(x = src_rect->left; x < src_rect->right; x++)
3240                 {
3241                     src_val = *src_pixel++;
3242                     dst_val = rgb_to_pixel_colortable(dst,
3243                                                       get_field(src_val, src->red_shift, src->red_len),
3244                                                       get_field(src_val, src->green_shift, src->green_len),
3245                                                       get_field(src_val, src->blue_shift, src->blue_len));
3246                     if((x - src_rect->left) & 1)
3247                     {
3248                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3249                         dst_pixel++;
3250                     }
3251                     else
3252                         *dst_pixel = (dst_val << 4) & 0xf0;
3253                 }
3254                 if(pad_size)
3255                 {
3256                     if((x - src_rect->left) & 1) dst_pixel++;
3257                     memset(dst_pixel, 0, pad_size);
3258                 }
3259                 dst_start += dst->stride;
3260                 src_start += src->stride / 2;
3261             }
3262         }
3263         break;
3264     }
3265
3266     case 8:
3267     {
3268         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3269
3270         for(y = src_rect->top; y < src_rect->bottom; y++)
3271         {
3272             dst_pixel = dst_start;
3273             src_pixel = src_start;
3274             for(x = src_rect->left; x < src_rect->right; x++)
3275             {
3276                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3277                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3278                 if((x - src_rect->left) & 1)
3279                 {
3280                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3281                     dst_pixel++;
3282                 }
3283                 else
3284                     *dst_pixel = (dst_val << 4) & 0xf0;
3285             }
3286             if(pad_size)
3287             {
3288                 if((x - src_rect->left) & 1) dst_pixel++;
3289                 memset(dst_pixel, 0, pad_size);
3290             }
3291             dst_start += dst->stride;
3292             src_start += src->stride;
3293         }
3294         break;
3295     }
3296
3297     case 4:
3298     {
3299         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3300
3301         if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
3302         {
3303             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
3304                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3305             else
3306             {
3307                 for(y = src_rect->top; y < src_rect->bottom; y++)
3308                 {
3309                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3310                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3311                     dst_start += dst->stride;
3312                     src_start += src->stride;
3313                 }
3314             }
3315         }
3316         else
3317         {
3318             for(y = src_rect->top; y < src_rect->bottom; y++)
3319             {
3320                 dst_pixel = dst_start;
3321                 src_pixel = src_start;
3322                 for(x = src_rect->left; x < src_rect->right; x++)
3323                 {
3324                     RGBQUAD rgb;
3325                     if(x & 1)
3326                         rgb = colortable_entry( src, *src_pixel++ & 0xf );
3327                     else
3328                         rgb = colortable_entry( src, *src_pixel >> 4 );
3329                     dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3330                     if((x - src_rect->left) & 1)
3331                     {
3332                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3333                         dst_pixel++;
3334                     }
3335                     else
3336                         *dst_pixel = (dst_val << 4) & 0xf0;
3337                 }
3338                 if(pad_size)
3339                 {
3340                     if((x - src_rect->left) & 1) dst_pixel++;
3341                     memset(dst_pixel, 0, pad_size);
3342                 }
3343                 dst_start += dst->stride;
3344                 src_start += src->stride;
3345             }
3346         }
3347         break;
3348     }
3349
3350     case 1:
3351     {
3352         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3353         for(y = src_rect->top; y < src_rect->bottom; y++)
3354         {
3355             dst_pixel = dst_start;
3356             src_pixel = src_start;
3357             for(x = src_rect->left; x < src_rect->right; x++)
3358             {
3359                 RGBQUAD rgb;
3360                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3361                 if((x % 8) == 7) src_pixel++;
3362                 rgb = src->color_table[src_val];
3363                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3364                 if((x - src_rect->left) & 1)
3365                 {
3366                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3367                     dst_pixel++;
3368                 }
3369                 else
3370                     *dst_pixel = (dst_val << 4) & 0xf0;
3371             }
3372             if(pad_size)
3373             {
3374                 if((x - src_rect->left) & 1) dst_pixel++;
3375                 memset(dst_pixel, 0, pad_size);
3376             }
3377             dst_start += dst->stride;
3378             src_start += src->stride;
3379         }
3380         break;
3381     }
3382     }
3383 }
3384
3385 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3386 {
3387     BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3388     INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3389     DWORD src_val;
3390     int bit_pos;
3391
3392     /* FIXME: Brushes should be dithered. */
3393
3394     switch(src->bit_count)
3395     {
3396     case 32:
3397     {
3398         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3399
3400         if(src->funcs == &funcs_8888)
3401         {
3402             for(y = src_rect->top; y < src_rect->bottom; y++)
3403             {
3404                 dst_pixel = dst_start;
3405                 src_pixel = src_start;
3406                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3407                 {
3408                     src_val = *src_pixel++;
3409                     dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3410
3411                     if(bit_pos == 0) *dst_pixel = 0;
3412                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3413
3414                     if(++bit_pos == 8)
3415                     {
3416                         dst_pixel++;
3417                         bit_pos = 0;
3418                     }
3419                 }
3420                 if(pad_size)
3421                 {
3422                     if(bit_pos != 0) dst_pixel++;
3423                     memset(dst_pixel, 0, pad_size);
3424                 }
3425                 dst_start += dst->stride;
3426                 src_start += src->stride / 4;
3427             }
3428         }
3429         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3430         {
3431             for(y = src_rect->top; y < src_rect->bottom; y++)
3432             {
3433                 dst_pixel = dst_start;
3434                 src_pixel = src_start;
3435                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3436                 {
3437                     src_val = *src_pixel++;
3438                     dst_val = rgb_to_pixel_colortable(dst,
3439                                                       src_val >> src->red_shift,
3440                                                       src_val >> src->green_shift,
3441                                                       src_val >> src->blue_shift) ? 0xff : 0;
3442
3443                    if(bit_pos == 0) *dst_pixel = 0;
3444                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3445
3446                     if(++bit_pos == 8)
3447                     {
3448                         dst_pixel++;
3449                         bit_pos = 0;
3450                     }
3451                 }
3452                 if(pad_size)
3453                 {
3454                     if(bit_pos != 0) dst_pixel++;
3455                     memset(dst_pixel, 0, pad_size);
3456                 }
3457                 dst_start += dst->stride;
3458                 src_start += src->stride / 4;
3459             }
3460         }
3461         else
3462         {
3463             for(y = src_rect->top; y < src_rect->bottom; y++)
3464             {
3465                 dst_pixel = dst_start;
3466                 src_pixel = src_start;
3467                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3468                 {
3469                     src_val = *src_pixel++;
3470                     dst_val = rgb_to_pixel_colortable(dst,
3471                                                       get_field(src_val, src->red_shift, src->red_len),
3472                                                       get_field(src_val, src->green_shift, src->green_len),
3473                                                       get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3474
3475                    if(bit_pos == 0) *dst_pixel = 0;
3476                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3477
3478                     if(++bit_pos == 8)
3479                     {
3480                         dst_pixel++;
3481                         bit_pos = 0;
3482                     }
3483                 }
3484                 if(pad_size)
3485                 {
3486                     if(bit_pos != 0) dst_pixel++;
3487                     memset(dst_pixel, 0, pad_size);
3488                 }
3489                 dst_start += dst->stride;
3490                 src_start += src->stride / 4;
3491             }
3492         }
3493         break;
3494     }
3495
3496     case 24:
3497     {
3498         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3499
3500         for(y = src_rect->top; y < src_rect->bottom; y++)
3501         {
3502             dst_pixel = dst_start;
3503             src_pixel = src_start;
3504             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3505             {
3506                 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3507
3508                 if(bit_pos == 0) *dst_pixel = 0;
3509                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3510
3511                 if(++bit_pos == 8)
3512                 {
3513                     dst_pixel++;
3514                     bit_pos = 0;
3515                 }
3516             }
3517             if(pad_size)
3518             {
3519                 if(bit_pos != 0) dst_pixel++;
3520                 memset(dst_pixel, 0, pad_size);
3521             }
3522             dst_start += dst->stride;
3523             src_start += src->stride;
3524         }
3525         break;
3526     }
3527
3528     case 16:
3529     {
3530         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3531         if(src->funcs == &funcs_555)
3532         {
3533             for(y = src_rect->top; y < src_rect->bottom; y++)
3534             {
3535                 dst_pixel = dst_start;
3536                 src_pixel = src_start;
3537                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3538                 {
3539                     src_val = *src_pixel++;
3540                     dst_val = rgb_to_pixel_colortable(dst,
3541                                                       ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3542                                                       ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07),
3543                                                       ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07) ) ? 0xff : 0;
3544
3545                     if(bit_pos == 0) *dst_pixel = 0;
3546                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3547
3548                     if(++bit_pos == 8)
3549                     {
3550                         dst_pixel++;
3551                         bit_pos = 0;
3552                     }
3553                 }
3554                 if(pad_size)
3555                 {
3556                     if(bit_pos != 0) dst_pixel++;
3557                     memset(dst_pixel, 0, pad_size);
3558                 }
3559                 dst_start += dst->stride;
3560                 src_start += src->stride / 2;
3561             }
3562         }
3563         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3564         {
3565             for(y = src_rect->top; y < src_rect->bottom; y++)
3566             {
3567                 dst_pixel = dst_start;
3568                 src_pixel = src_start;
3569                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3570                 {
3571                     src_val = *src_pixel++;
3572                     dst_val = rgb_to_pixel_colortable(dst,
3573                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3574                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3575                                                       (((src_val >> src->green_shift) << 3) & 0xf8) |
3576                                                       (((src_val >> src->green_shift) >> 2) & 0x07),
3577                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3578                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) ) ? 0xff : 0;
3579                     if(bit_pos == 0) *dst_pixel = 0;
3580                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3581
3582                     if(++bit_pos == 8)
3583                     {
3584                         dst_pixel++;
3585                         bit_pos = 0;
3586                     }
3587                 }
3588                 if(pad_size)
3589                 {
3590                     if(bit_pos != 0) dst_pixel++;
3591                     memset(dst_pixel, 0, pad_size);
3592                 }
3593                 dst_start += dst->stride;
3594                 src_start += src->stride / 2;
3595             }
3596         }
3597         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3598         {
3599             for(y = src_rect->top; y < src_rect->bottom; y++)
3600             {
3601                 dst_pixel = dst_start;
3602                 src_pixel = src_start;
3603                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3604                 {
3605                     src_val = *src_pixel++;
3606                     dst_val = rgb_to_pixel_colortable(dst,
3607                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3608                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3609                                                       (((src_val >> src->green_shift) << 2) & 0xfc) |
3610                                                       (((src_val >> src->green_shift) >> 4) & 0x03),
3611                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3612                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) ) ? 0xff : 0;
3613                     if(bit_pos == 0) *dst_pixel = 0;
3614                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3615
3616                     if(++bit_pos == 8)
3617                     {
3618                         dst_pixel++;
3619                         bit_pos = 0;
3620                     }
3621                 }
3622                 if(pad_size)
3623                 {
3624                     if(bit_pos != 0) dst_pixel++;
3625                     memset(dst_pixel, 0, pad_size);
3626                 }
3627                 dst_start += dst->stride;
3628                 src_start += src->stride / 2;
3629             }
3630         }
3631         else
3632         {
3633             for(y = src_rect->top; y < src_rect->bottom; y++)
3634             {
3635                 dst_pixel = dst_start;
3636                 src_pixel = src_start;
3637                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3638                 {
3639                     src_val = *src_pixel++;
3640                     dst_val = rgb_to_pixel_colortable(dst,
3641                                                       get_field(src_val, src->red_shift, src->red_len),
3642                                                       get_field(src_val, src->green_shift, src->green_len),
3643                                                       get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3644                     if(bit_pos == 0) *dst_pixel = 0;
3645                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3646
3647                     if(++bit_pos == 8)
3648                     {
3649                         dst_pixel++;
3650                         bit_pos = 0;
3651                     }
3652                 }
3653                 if(pad_size)
3654                 {
3655                     if(bit_pos != 0) dst_pixel++;
3656                     memset(dst_pixel, 0, pad_size);
3657                 }
3658                 dst_start += dst->stride;
3659                 src_start += src->stride / 2;
3660             }
3661         }
3662         break;
3663     }
3664
3665     case 8:
3666     {
3667         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3668
3669         for(y = src_rect->top; y < src_rect->bottom; y++)
3670         {
3671             dst_pixel = dst_start;
3672             src_pixel = src_start;
3673             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3674             {
3675                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3676                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3677
3678                 if(bit_pos == 0) *dst_pixel = 0;
3679                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3680
3681                 if(++bit_pos == 8)
3682                 {
3683                     dst_pixel++;
3684                     bit_pos = 0;
3685                 }
3686             }
3687             if(pad_size)
3688             {
3689                 if(bit_pos != 0) dst_pixel++;
3690                 memset(dst_pixel, 0, pad_size);
3691             }
3692             dst_start += dst->stride;
3693             src_start += src->stride;
3694         }
3695         break;
3696     }
3697
3698     case 4:
3699     {
3700         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3701
3702         for(y = src_rect->top; y < src_rect->bottom; y++)
3703         {
3704             dst_pixel = dst_start;
3705             src_pixel = src_start;
3706             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3707             {
3708                 RGBQUAD rgb;
3709                 if(x & 1)
3710                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
3711                 else
3712                     rgb = colortable_entry( src, *src_pixel >> 4 );
3713                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3714
3715                 if(bit_pos == 0) *dst_pixel = 0;
3716                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3717
3718                 if(++bit_pos == 8)
3719                 {
3720                     dst_pixel++;
3721                     bit_pos = 0;
3722                 }
3723             }
3724             if(pad_size)
3725             {
3726                 if(bit_pos != 0) dst_pixel++;
3727                 memset(dst_pixel, 0, pad_size);
3728             }
3729             dst_start += dst->stride;
3730             src_start += src->stride;
3731         }
3732         break;
3733     }
3734
3735     /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3736        uses text/bkgnd colours instead of the dib's colour table, this
3737        doesn't appear to be the case for a dc backed by a
3738        dibsection. */
3739
3740     case 1:
3741     {
3742         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3743         for(y = src_rect->top; y < src_rect->bottom; y++)
3744         {
3745             dst_pixel = dst_start;
3746             src_pixel = src_start;
3747             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3748             {
3749                 RGBQUAD rgb;
3750                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3751                 if((x % 8) == 7) src_pixel++;
3752                 rgb = src->color_table[src_val];
3753                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3754
3755                 if(bit_pos == 0) *dst_pixel = 0;
3756                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3757
3758                 if(++bit_pos == 8)
3759                 {
3760                     dst_pixel++;
3761                     bit_pos = 0;
3762                 }
3763             }
3764             if(pad_size)
3765             {
3766                 if(bit_pos != 0) dst_pixel++;
3767                 memset(dst_pixel, 0, pad_size);
3768             }
3769             dst_start += dst->stride;
3770             src_start += src->stride;
3771         }
3772         break;
3773     }
3774     }
3775 }
3776
3777 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3778 {
3779 }
3780
3781 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3782 {
3783     return (src * alpha + dst * (255 - alpha) + 127) / 255;
3784 }
3785
3786 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3787 {
3788     return (blend_color( dst, src, alpha ) |
3789             blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3790             blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3791             blend_color( dst >> 24, src >> 24, alpha ) << 24);
3792 }
3793
3794 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3795 {
3796     BYTE b = ((BYTE)src         * alpha + 127) / 255;
3797     BYTE g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3798     BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3799     alpha  = ((BYTE)(src >> 24) * alpha + 127) / 255;
3800     return ((b     + ((BYTE)dst         * (255 - alpha) + 127) / 255) |
3801             (g     + ((BYTE)(dst >> 8)  * (255 - alpha) + 127) / 255) << 8 |
3802             (r     + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3803             (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3804 }
3805
3806 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3807 {
3808     if (blend.AlphaFormat & AC_SRC_ALPHA)
3809     {
3810         DWORD alpha = blend.SourceConstantAlpha;
3811         BYTE src_b = ((BYTE)src         * alpha + 127) / 255;
3812         BYTE src_g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3813         BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3814         alpha      = ((BYTE)(src >> 24) * alpha + 127) / 255;
3815         return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3816                 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3817                 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3818     }
3819     return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3820             blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3821             blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3822 }
3823
3824 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3825                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3826 {
3827     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3828     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3829     int x, y;
3830
3831     if (blend.AlphaFormat & AC_SRC_ALPHA)
3832         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3833             for (x = 0; x < rc->right - rc->left; x++)
3834                 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3835     else
3836         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3837             for (x = 0; x < rc->right - rc->left; x++)
3838                 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3839 }
3840
3841 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3842                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3843 {
3844     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3845     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3846     int x, y;
3847
3848     if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3849     {
3850         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3851         {
3852             for (x = 0; x < rc->right - rc->left; x++)
3853             {
3854                 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3855                                        dst_ptr[x] >> dst->green_shift,
3856                                        dst_ptr[x] >> dst->blue_shift,
3857                                        src_ptr[x], blend );
3858                 dst_ptr[x] = ((( val        & 0xff) << dst->blue_shift) |
3859                               (((val >> 8)  & 0xff) << dst->green_shift) |
3860                               (((val >> 16) & 0xff) << dst->red_shift));
3861             }
3862         }
3863     }
3864     else
3865     {
3866         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3867         {
3868             for (x = 0; x < rc->right - rc->left; x++)
3869             {
3870                 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3871                                        get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3872                                        get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3873                                        src_ptr[x], blend );
3874                 dst_ptr[x] = (put_field( val >> 16, dst->red_shift,   dst->red_len )   |
3875                               put_field( val >> 8,  dst->green_shift, dst->green_len ) |
3876                               put_field( val,       dst->blue_shift,  dst->blue_len ));
3877             }
3878         }
3879     }
3880 }
3881
3882 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3883                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3884 {
3885     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3886     BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3887     int x, y;
3888
3889     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3890     {
3891         for (x = 0; x < rc->right - rc->left; x++)
3892         {
3893             DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3894                                    src_ptr[x], blend );
3895             dst_ptr[x * 3]     = val;
3896             dst_ptr[x * 3 + 1] = val >> 8;
3897             dst_ptr[x * 3 + 2] = val >> 16;
3898         }
3899     }
3900 }
3901
3902 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3903                            const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3904 {
3905     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3906     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3907     int x, y;
3908
3909     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3910     {
3911         for (x = 0; x < rc->right - rc->left; x++)
3912         {
3913             DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3914                                    ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
3915                                    ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
3916                                    src_ptr[x], blend );
3917             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3918         }
3919     }
3920 }
3921
3922 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3923                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3924 {
3925     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3926     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3927     int x, y;
3928
3929     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3930     {
3931         for (x = 0; x < rc->right - rc->left; x++)
3932         {
3933             DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3934                                    get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3935                                    get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3936                                    src_ptr[x], blend );
3937             dst_ptr[x] = (put_field((val >> 16), dst->red_shift,   dst->red_len)   |
3938                           put_field((val >>  8), dst->green_shift, dst->green_len) |
3939                           put_field( val,        dst->blue_shift,  dst->blue_len));
3940         }
3941     }
3942 }
3943
3944 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3945                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3946 {
3947     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3948     BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3949     int x, y;
3950
3951     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3952     {
3953         for (x = 0; x < rc->right - rc->left; x++)
3954         {
3955             RGBQUAD rgb = colortable_entry( dst, dst_ptr[x] );
3956             DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3957             dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3958         }
3959     }
3960 }
3961
3962 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3963                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3964 {
3965     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3966     BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3967     int x, y;
3968
3969     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3970     {
3971         for (x = rc->left; x < rc->right; x++)
3972         {
3973             DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3974             RGBQUAD rgb = colortable_entry( dst, val );
3975             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3976             val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3977             if (x & 1)
3978                 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3979             else
3980                 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3981         }
3982     }
3983 }
3984
3985 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3986                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3987 {
3988     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3989     BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
3990     int x, y;
3991
3992     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3993     {
3994         for (x = rc->left; x < rc->right; x++)
3995         {
3996             DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3997             RGBQUAD rgb = dst->color_table[val];
3998             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3999             val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4000             dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4001         }
4002     }
4003 }
4004
4005 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4006                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4007 {
4008 }
4009
4010 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4011 {
4012     BYTE r, g, b, a;
4013     r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 256;
4014     g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4015     b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 256;
4016     a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4017     return a << 24 | r << 16 | g << 8 | b;
4018 }
4019
4020 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4021 {
4022     BYTE r, g, b;
4023     r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 256;
4024     g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4025     b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 256;
4026     return r << 16 | g << 8 | b;
4027 }
4028
4029 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4030                                      unsigned int x, unsigned int y )
4031 {
4032     int r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4033     int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4034     int b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4035     r = min( 31, max( 0, r / 16 ));
4036     g = min( 31, max( 0, g / 16 ));
4037     b = min( 31, max( 0, b / 16 ));
4038     return (r << 10) | (g << 5) | b;
4039 }
4040
4041 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4042                                    unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4043 {
4044     BYTE r = ((v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4045     BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4046     BYTE b = ((v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4047     return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4048 }
4049
4050 /* compute the left/right triangle limit for row y */
4051 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4052 {
4053     int x1, x2;
4054
4055     if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4056     else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4057
4058     x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4059
4060     *left  = max( rc->left, min( x1, x2 ) );
4061     *right = min( rc->right, max( x1, x2 ) );
4062 }
4063
4064 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4065 static inline int triangle_det( const TRIVERTEX *v )
4066 {
4067     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);
4068 }
4069
4070 /* compute the barycentric weights for a given point inside the triangle */
4071 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4072 {
4073     *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4074     *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4075 }
4076
4077 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4078 {
4079     INT64 l1, l2;
4080     BYTE r, g, b, a;
4081
4082     triangle_weights( v, x, y, &l1, &l2 );
4083     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 256;
4084     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4085     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 256;
4086     a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4087     return a << 24 | r << 16 | g << 8 | b;
4088 }
4089
4090 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4091 {
4092     INT64 l1, l2;
4093     BYTE r, g, b;
4094
4095     triangle_weights( v, x, y, &l1, &l2 );
4096     r = (v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 256;
4097     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4098     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 256;
4099     return r << 16 | g << 8 | b;
4100 }
4101
4102 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4103 {
4104     INT64 l1, l2;
4105     int 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 / 128 + bayer_4x4[y % 4][x % 4];
4109     g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4110     b = (v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4111     r = min( 31, max( 0, r / 16 ));
4112     g = min( 31, max( 0, g / 16 ));
4113     b = min( 31, max( 0, b / 16 ));
4114     return (r << 10) | (g << 5) | b;
4115 }
4116
4117 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4118 {
4119     INT64 l1, l2;
4120     BYTE r, g, b;
4121
4122     triangle_weights( v, x, y, &l1, &l2 );
4123     r = ((v[0].Red   * l1 + v[1].Red   * l2 + v[2].Red   * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4124     g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4125     b = ((v[0].Blue  * l1 + v[1].Blue  * l2 + v[2].Blue  * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4126     return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4127 }
4128
4129 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4130 {
4131     DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4132     int x, y, left, right, det;
4133
4134     switch (mode)
4135     {
4136     case GRADIENT_FILL_RECT_H:
4137         for (x = rc->left; x < rc->right; x++)
4138             ptr[x] = gradient_rgb_8888( v, x - v[0].x, v[1].x - v[0].x );
4139
4140         for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4141             memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4142         break;
4143
4144     case GRADIENT_FILL_RECT_V:
4145         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4146         {
4147             DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4148             for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4149         }
4150         break;
4151
4152     case GRADIENT_FILL_TRIANGLE:
4153         if (!(det = triangle_det( v ))) return FALSE;
4154         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4155         {
4156             triangle_coords( v, rc, y, &left, &right );
4157             for (x = left; x < right; x++) ptr[x] = gradient_triangle_8888( v, x, y, det );
4158         }
4159         break;
4160     }
4161     return TRUE;
4162 }
4163
4164 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4165 {
4166     DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4167     int x, y, left, right, det;
4168
4169     switch (mode)
4170     {
4171     case GRADIENT_FILL_RECT_H:
4172         if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4173         {
4174             for (x = rc->left; x < rc->right; x++)
4175             {
4176                 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4177                 ptr[x] = ((( val        & 0xff) << dib->blue_shift) |
4178                           (((val >> 8)  & 0xff) << dib->green_shift) |
4179                           (((val >> 16) & 0xff) << dib->red_shift));
4180             }
4181         }
4182         else
4183         {
4184             for (x = rc->left; x < rc->right; x++)
4185             {
4186                 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4187                 ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4188                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4189                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4190             }
4191         }
4192
4193         for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4194             memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4195         break;
4196
4197     case GRADIENT_FILL_RECT_V:
4198         for (y = rc->top; y < rc->bottom; y++)
4199         {
4200             DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4201             if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4202                 val = ((( val        & 0xff) << dib->blue_shift) |
4203                        (((val >> 8)  & 0xff) << dib->green_shift) |
4204                        (((val >> 16) & 0xff) << dib->red_shift));
4205             else
4206                 val = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4207                        put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4208                        put_field( val,       dib->blue_shift,  dib->blue_len ));
4209
4210             for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4211             ptr += dib->stride / 4;
4212         }
4213         break;
4214
4215     case GRADIENT_FILL_TRIANGLE:
4216         if (!(det = triangle_det( v ))) return FALSE;
4217         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4218         {
4219             triangle_coords( v, rc, y, &left, &right );
4220
4221             if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4222                 for (x = left; x < right; x++)
4223                 {
4224                     DWORD val = gradient_triangle_24( v, x, y, det );
4225                     ptr[x] = ((( val        & 0xff) << dib->blue_shift) |
4226                               (((val >> 8)  & 0xff) << dib->green_shift) |
4227                               (((val >> 16) & 0xff) << dib->red_shift));
4228                 }
4229             else
4230                 for (x = left; x < right; x++)
4231                 {
4232                     DWORD val = gradient_triangle_24( v, x, y, det );
4233                     ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4234                               put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4235                               put_field( val,       dib->blue_shift,  dib->blue_len ));
4236                 }
4237         }
4238         break;
4239     }
4240     return TRUE;
4241 }
4242
4243 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4244 {
4245     BYTE *ptr = get_pixel_ptr_24( dib, 0, rc->top );
4246     int x, y, left, right, det;
4247
4248     switch (mode)
4249     {
4250     case GRADIENT_FILL_RECT_H:
4251         for (x = rc->left; x < rc->right; x++)
4252         {
4253             DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4254             ptr[x * 3]     = val;
4255             ptr[x * 3 + 1] = val >> 8;
4256             ptr[x * 3 + 2] = val >> 16;
4257         }
4258
4259         for (y = rc->top + 1, ptr += rc->left * 3; y < rc->bottom; y++, ptr += dib->stride)
4260             memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4261         break;
4262
4263     case GRADIENT_FILL_RECT_V:
4264         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4265         {
4266             DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4267             for (x = rc->left; x < rc->right; x++)
4268             {
4269                 ptr[x * 3]     = val;
4270                 ptr[x * 3 + 1] = val >> 8;
4271                 ptr[x * 3 + 2] = val >> 16;
4272             }
4273         }
4274         break;
4275
4276     case GRADIENT_FILL_TRIANGLE:
4277         if (!(det = triangle_det( v ))) return FALSE;
4278         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4279         {
4280             triangle_coords( v, rc, y, &left, &right );
4281             for (x = left; x < right; x++)
4282             {
4283                 DWORD val = gradient_triangle_24( v, x, y, det );
4284                 ptr[x * 3]     = val;
4285                 ptr[x * 3 + 1] = val >> 8;
4286                 ptr[x * 3 + 2] = val >> 16;
4287             }
4288         }
4289         break;
4290     }
4291     return TRUE;
4292 }
4293
4294 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4295 {
4296     WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4297     int x, y, left, right, det;
4298
4299     switch (mode)
4300     {
4301     case GRADIENT_FILL_RECT_H:
4302         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4303             for (x = rc->left; x < rc->right; x++)
4304                 ptr[x] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4305         for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4306             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4307         break;
4308
4309     case GRADIENT_FILL_RECT_V:
4310         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4311         {
4312             WORD values[4];
4313             for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4314             for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4315         }
4316         break;
4317
4318     case GRADIENT_FILL_TRIANGLE:
4319         if (!(det = triangle_det( v ))) return FALSE;
4320         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4321         {
4322             triangle_coords( v, rc, y, &left, &right );
4323             for (x = left; x < right; x++) ptr[x] = gradient_triangle_555( v, x, y, det );
4324         }
4325         break;
4326     }
4327     return TRUE;
4328 }
4329
4330 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4331 {
4332     WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4333     int x, y, left, right, det;
4334
4335     switch (mode)
4336     {
4337     case GRADIENT_FILL_RECT_H:
4338         for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4339             for (x = rc->left; x < rc->right; x++)
4340             {
4341                 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4342                 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4343                           put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4344                           put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4345             }
4346         for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4347             memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4348         break;
4349
4350     case GRADIENT_FILL_RECT_V:
4351         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4352         {
4353             WORD values[4];
4354             for (x = 0; x < 4; x++)
4355             {
4356                 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4357                 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4358                              put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4359                              put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4360             }
4361             for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4362         }
4363         break;
4364
4365     case GRADIENT_FILL_TRIANGLE:
4366         if (!(det = triangle_det( v ))) return FALSE;
4367         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4368         {
4369             triangle_coords( v, rc, y, &left, &right );
4370             for (x = left; x < right; x++)
4371             {
4372                 WORD val = gradient_triangle_555( v, x, y, det );
4373                 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
4374                           put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
4375                           put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
4376             }
4377         }
4378         break;
4379     }
4380     return TRUE;
4381 }
4382
4383 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4384 {
4385     BYTE *ptr = get_pixel_ptr_8( dib, 0, rc->top );
4386     int x, y, left, right, det;
4387
4388     switch (mode)
4389     {
4390     case GRADIENT_FILL_RECT_H:
4391         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4392             for (x = rc->left; x < rc->right; x++)
4393                 ptr[x] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4394         for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride)
4395             memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4396         break;
4397
4398     case GRADIENT_FILL_RECT_V:
4399         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4400         {
4401             BYTE values[16];
4402             for (x = 0; x < 16; x++)
4403                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4404             for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 16];
4405         }
4406         break;
4407
4408     case GRADIENT_FILL_TRIANGLE:
4409         if (!(det = triangle_det( v ))) return FALSE;
4410         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4411         {
4412             triangle_coords( v, rc, y, &left, &right );
4413             for (x = left; x < right; x++) ptr[x] = gradient_triangle_8( dib, v, x, y, det );
4414         }
4415         break;
4416     }
4417     return TRUE;
4418 }
4419
4420 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4421 {
4422     BYTE *ptr = get_pixel_ptr_4( dib, 0, rc->top );
4423     int x, y, left, right, det;
4424
4425     switch (mode)
4426     {
4427     case GRADIENT_FILL_RECT_H:
4428         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4429         {
4430             for (x = rc->left; x < rc->right; x++)
4431             {
4432                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4433                 if (x & 1)
4434                     ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4435                 else
4436                     ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4437             }
4438         }
4439         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4440         {
4441             x = rc->left;
4442             if (x & 1)
4443             {
4444                 ptr[x / 2] = (ptr[x / 2 - 16 * dib->stride] & 0x0f) | (ptr[x / 2] & 0xf0);
4445                 x++;
4446             }
4447             for (; x < rc->right - 1; x += 2) ptr[x / 2] = ptr[x / 2 - 16 * dib->stride];
4448             if (x < rc->right)
4449                 ptr[x / 2] = (ptr[x / 2] & 0x0f) | (ptr[x / 2 - 16 * dib->stride] & 0xf0);
4450         }
4451         break;
4452
4453     case GRADIENT_FILL_RECT_V:
4454         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4455         {
4456             BYTE values[16];
4457             for (x = 0; x < 16; x++)
4458                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4459             for (x = rc->left; x < rc->right; x++)
4460                 if (x & 1)
4461                     ptr[x / 2] = values[x % 16] | (ptr[x / 2] & 0xf0);
4462                 else
4463                     ptr[x / 2] = (values[x % 16] << 4) | (ptr[x / 2] & 0x0f);
4464         }
4465         break;
4466
4467     case GRADIENT_FILL_TRIANGLE:
4468         if (!(det = triangle_det( v ))) return FALSE;
4469         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4470         {
4471             triangle_coords( v, rc, y, &left, &right );
4472             for (x = left; x < right; x++)
4473             {
4474                 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4475                 if (x & 1)
4476                     ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4477                 else
4478                     ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4479             }
4480         }
4481         break;
4482     }
4483     return TRUE;
4484 }
4485
4486 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4487 {
4488     BYTE *ptr = get_pixel_ptr_1( dib, 0, rc->top );
4489     int x, y, left, right, det;
4490
4491     switch (mode)
4492     {
4493     case GRADIENT_FILL_RECT_H:
4494         for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4495         {
4496             for (x = rc->left; x < rc->right; x++)
4497             {
4498                 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4499                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4500             }
4501         }
4502         for ( ; y < rc->bottom; y++, ptr += dib->stride)
4503             for (x = rc->left; x < rc->right; x++)
4504                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) |
4505                              (ptr[x / 8 - 16 * dib->stride] & pixel_masks_1[x % 8]);
4506         break;
4507
4508     case GRADIENT_FILL_RECT_V:
4509         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4510         {
4511             BYTE values[16];
4512             for (x = 0; x < 16; x++)
4513                 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4514             for (x = rc->left; x < rc->right; x++)
4515                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (values[x % 16] & pixel_masks_1[x % 8]);
4516         }
4517         break;
4518
4519     case GRADIENT_FILL_TRIANGLE:
4520         if (!(det = triangle_det( v ))) return FALSE;
4521         for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4522         {
4523             triangle_coords( v, rc, y, &left, &right );
4524             for (x = left; x < right; x++)
4525             {
4526                 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4527                 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4528             }
4529         }
4530         break;
4531     }
4532     return TRUE;
4533 }
4534
4535 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4536 {
4537     return TRUE;
4538 }
4539
4540 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4541 {
4542     if (dst == text) return dst;
4543
4544     if (dst > text)
4545     {
4546         DWORD diff = dst - text;
4547         DWORD range = max_comp - text;
4548         dst = text + (diff * range ) / (0xff - text);
4549         return dst;
4550     }
4551     else
4552     {
4553         DWORD diff = text - dst;
4554         DWORD range = text - min_comp;
4555         dst = text - (diff * range) / text;
4556         return dst;
4557     }
4558 }
4559
4560 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4561 {
4562     return (aa_color( b_dst, text,       range->b_min, range->b_max )      |
4563             aa_color( g_dst, text >> 8,  range->g_min, range->g_max ) << 8 |
4564             aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4565 }
4566
4567 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4568                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4569 {
4570     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4571     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4572     int x, y;
4573
4574     for (y = rect->top; y < rect->bottom; y++)
4575     {
4576         for (x = 0; x < rect->right - rect->left; x++)
4577         {
4578             if (glyph_ptr[x] <= 1) continue;
4579             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4580             dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4581         }
4582         dst_ptr += dib->stride / 4;
4583         glyph_ptr += glyph->stride;
4584     }
4585 }
4586
4587 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4588                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4589 {
4590     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4591     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4592     int x, y;
4593     DWORD text, val;
4594
4595     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4596            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4597            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4598
4599     for (y = rect->top; y < rect->bottom; y++)
4600     {
4601         for (x = 0; x < rect->right - rect->left; x++)
4602         {
4603             if (glyph_ptr[x] <= 1) continue;
4604             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4605             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4606                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4607                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4608                           text, ranges + glyph_ptr[x] );
4609             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4610                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4611                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4612         }
4613         dst_ptr += dib->stride / 4;
4614         glyph_ptr += glyph->stride;
4615     }
4616 }
4617
4618 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4619                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4620 {
4621     BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4622     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4623     int x, y;
4624     DWORD val;
4625
4626     for (y = rect->top; y < rect->bottom; y++)
4627     {
4628         for (x = 0; x < rect->right - rect->left; x++)
4629         {
4630             if (glyph_ptr[x] <= 1) continue;
4631             if (glyph_ptr[x] >= 16)
4632                 val = text_pixel;
4633             else
4634                 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4635                               text_pixel, ranges + glyph_ptr[x] );
4636             dst_ptr[x * 3]     = val;
4637             dst_ptr[x * 3 + 1] = val >> 8;
4638             dst_ptr[x * 3 + 2] = val >> 16;
4639         }
4640         dst_ptr += dib->stride;
4641         glyph_ptr += glyph->stride;
4642     }
4643 }
4644
4645 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4646                             const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4647 {
4648     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4649     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4650     int x, y;
4651     DWORD text, val;
4652
4653     text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4654            ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4655            ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4656
4657     for (y = rect->top; y < rect->bottom; y++)
4658     {
4659         for (x = 0; x < rect->right - rect->left; x++)
4660         {
4661             if (glyph_ptr[x] <= 1) continue;
4662             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4663             val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4664                           ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
4665                           ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
4666                           text, ranges + glyph_ptr[x] );
4667             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4668         }
4669         dst_ptr += dib->stride / 2;
4670         glyph_ptr += glyph->stride;
4671     }
4672 }
4673
4674 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4675                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4676 {
4677     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4678     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4679     int x, y;
4680     DWORD text, val;
4681
4682     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4683            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4684            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4685
4686     for (y = rect->top; y < rect->bottom; y++)
4687     {
4688         for (x = 0; x < rect->right - rect->left; x++)
4689         {
4690             if (glyph_ptr[x] <= 1) continue;
4691             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4692             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4693                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4694                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4695                           text, ranges + glyph_ptr[x] );
4696             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4697                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4698                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4699         }
4700         dst_ptr += dib->stride / 2;
4701         glyph_ptr += glyph->stride;
4702     }
4703 }
4704
4705 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4706                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4707 {
4708     BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4709     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4710     int x, y;
4711
4712     for (y = rect->top; y < rect->bottom; y++)
4713     {
4714         for (x = 0; x < rect->right - rect->left; x++)
4715         {
4716             /* no antialiasing, glyph should only contain 0 or 16. */
4717             if (glyph_ptr[x] >= 16)
4718                 dst_ptr[x] = text_pixel;
4719         }
4720         dst_ptr += dib->stride;
4721         glyph_ptr += glyph->stride;
4722     }
4723 }
4724
4725 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4726                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4727 {
4728     BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
4729     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4730     int x, y;
4731
4732     for (y = rect->top; y < rect->bottom; y++)
4733     {
4734         for (x = rect->left; x < rect->right; x++)
4735         {
4736             /* no antialiasing, glyph should only contain 0 or 16. */
4737             if (glyph_ptr[x] >= 16)
4738             {
4739                 if (x & 1)
4740                     dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
4741                 else
4742                     dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
4743             }
4744         }
4745         dst_ptr += dib->stride;
4746         glyph_ptr += glyph->stride;
4747     }
4748 }
4749
4750 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4751                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4752 {
4753     BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
4754     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4755     int x, y;
4756     BYTE text = (text_pixel & 1) ? 0xff : 0;
4757
4758     for (y = rect->top; y < rect->bottom; y++)
4759     {
4760         for (x = rect->left; x < rect->right; x++)
4761         {
4762             /* no antialiasing, glyph should only contain 0 or 16. */
4763             if (glyph_ptr[x] >= 16)
4764                 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
4765         }
4766         dst_ptr += dib->stride;
4767         glyph_ptr += glyph->stride;
4768     }
4769 }
4770
4771 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4772                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4773 {
4774     return;
4775 }
4776
4777 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)
4778 {
4779     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4780     DWORD mask_start = 0, mask_offset;
4781     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4782     int x, y;
4783
4784     for(y = 0; y < hatch->height; y++)
4785     {
4786         hatch_ptr = hatch_start;
4787         mask_offset = mask_start;
4788         for(x = 0; x < hatch->width; x++)
4789         {
4790             if(*hatch_ptr & pixel_masks_1[x % 8])
4791             {
4792                 and_bits[mask_offset] = fg->and;
4793                 xor_bits[mask_offset] = fg->xor;
4794             }
4795             else
4796             {
4797                 and_bits[mask_offset] = bg->and;
4798                 xor_bits[mask_offset] = bg->xor;
4799             }
4800             if(x % 8 == 7) hatch_ptr++;
4801             mask_offset++;
4802         }
4803         hatch_start += hatch->stride;
4804         mask_start += dib->stride / 4;
4805     }
4806
4807     return TRUE;
4808 }
4809
4810 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)
4811 {
4812     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4813     DWORD mask_start = 0, mask_offset;
4814     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4815     int x, y;
4816
4817     for(y = 0; y < hatch->height; y++)
4818     {
4819         hatch_ptr = hatch_start;
4820         mask_offset = mask_start;
4821         for(x = 0; x < hatch->width; x++)
4822         {
4823             if(*hatch_ptr & pixel_masks_1[x % 8])
4824             {
4825                 and_bits[mask_offset]   =  fg->and        & 0xff;
4826                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
4827                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
4828                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
4829                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
4830                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4831             }
4832             else
4833             {
4834                 and_bits[mask_offset]   =  bg->and        & 0xff;
4835                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
4836                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
4837                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
4838                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
4839                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4840             }
4841             if(x % 8 == 7) hatch_ptr++;
4842         }
4843         hatch_start += hatch->stride;
4844         mask_start += dib->stride;
4845     }
4846
4847     return TRUE;
4848 }
4849
4850 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)
4851 {
4852     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4853     DWORD mask_start = 0, mask_offset;
4854     WORD *and_bits = bits->and, *xor_bits = bits->xor;
4855     int x, y;
4856
4857     for(y = 0; y < hatch->height; y++)
4858     {
4859         hatch_ptr = hatch_start;
4860         mask_offset = mask_start;
4861         for(x = 0; x < hatch->width; x++)
4862         {
4863             if(*hatch_ptr & pixel_masks_1[x % 8])
4864             {
4865                 and_bits[mask_offset] = fg->and;
4866                 xor_bits[mask_offset] = fg->xor;
4867             }
4868             else
4869             {
4870                 and_bits[mask_offset] = bg->and;
4871                 xor_bits[mask_offset] = bg->xor;
4872             }
4873             if(x % 8 == 7) hatch_ptr++;
4874             mask_offset++;
4875         }
4876         hatch_start += hatch->stride;
4877         mask_start += dib->stride / 2;
4878     }
4879
4880     return TRUE;
4881 }
4882
4883 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)
4884 {
4885     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4886     DWORD mask_start = 0, mask_offset;
4887     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4888     int x, y;
4889
4890     for(y = 0; y < hatch->height; y++)
4891     {
4892         hatch_ptr = hatch_start;
4893         mask_offset = mask_start;
4894         for(x = 0; x < hatch->width; x++)
4895         {
4896             if(*hatch_ptr & pixel_masks_1[x % 8])
4897             {
4898                 and_bits[mask_offset] = fg->and;
4899                 xor_bits[mask_offset] = fg->xor;
4900             }
4901             else
4902             {
4903                 and_bits[mask_offset] = bg->and;
4904                 xor_bits[mask_offset] = bg->xor;
4905             }
4906             if(x % 8 == 7) hatch_ptr++;
4907             mask_offset++;
4908         }
4909         hatch_start += hatch->stride;
4910         mask_start += dib->stride;
4911     }
4912
4913     return TRUE;
4914 }
4915
4916 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)
4917 {
4918     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4919     DWORD mask_start = 0, mask_offset;
4920     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4921     const rop_mask *rop_mask;
4922     int x, y;
4923
4924     for(y = 0; y < hatch->height; y++)
4925     {
4926         hatch_ptr = hatch_start;
4927         mask_offset = mask_start;
4928         for(x = 0; x < hatch->width; x++)
4929         {
4930             if(*hatch_ptr & pixel_masks_1[x % 8])
4931                 rop_mask = fg;
4932             else
4933                 rop_mask = bg;
4934
4935             if(x & 1)
4936             {
4937                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4938                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4939                 mask_offset++;
4940             }
4941             else
4942             {
4943                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4944                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4945             }
4946
4947             if(x % 8 == 7) hatch_ptr++;
4948         }
4949         hatch_start += hatch->stride;
4950         mask_start += dib->stride;
4951     }
4952
4953     return TRUE;
4954 }
4955
4956 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)
4957 {
4958     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4959     DWORD mask_start = 0, mask_offset;
4960     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4961     rop_mask rop_mask;
4962     int x, y, bit_pos;
4963
4964     for(y = 0; y < hatch->height; y++)
4965     {
4966         hatch_ptr = hatch_start;
4967         mask_offset = mask_start;
4968         for(x = 0, bit_pos = 0; x < hatch->width; x++)
4969         {
4970             if(*hatch_ptr & pixel_masks_1[x % 8])
4971             {
4972                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4973                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4974             }
4975             else
4976             {
4977                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4978                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4979             }
4980
4981             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4982
4983             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4984             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4985
4986             if(++bit_pos == 8)
4987             {
4988                 mask_offset++;
4989                 hatch_ptr++;
4990                 bit_pos = 0;
4991             }
4992         }
4993         hatch_start += hatch->stride;
4994         mask_start += dib->stride;
4995     }
4996
4997     return TRUE;
4998 }
4999
5000 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)
5001 {
5002     return FALSE;
5003 }
5004
5005 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5006 {
5007     switch (mode)
5008     {
5009     default:
5010     case STRETCH_DELETESCANS:
5011         get_rop_codes( R2_COPYPEN, codes );
5012         break;
5013     case STRETCH_ORSCANS:
5014         get_rop_codes( R2_MERGEPEN, codes );
5015         break;
5016     case STRETCH_ANDSCANS:
5017         get_rop_codes( R2_MASKPEN, codes );
5018         break;
5019     }
5020     return;
5021 }
5022
5023 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5024                            const dib_info *src_dib, const POINT *src_start,
5025                            const struct stretch_params *params, int mode,
5026                            BOOL keep_dst)
5027 {
5028     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5029     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5030     int err = params->err_start;
5031     int width;
5032     struct rop_codes codes;
5033
5034     rop_codes_from_stretch_mode( mode, &codes );
5035     for (width = params->length; width; width--)
5036     {
5037         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5038         dst_ptr += params->dst_inc;
5039         if (err > 0)
5040         {
5041             src_ptr += params->src_inc;
5042             err += params->err_add_1;
5043         }
5044         else err += params->err_add_2;
5045     }
5046 }
5047
5048 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5049                            const dib_info *src_dib, const POINT *src_start,
5050                            const struct stretch_params *params, int mode,
5051                            BOOL keep_dst)
5052 {
5053     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5054     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5055     int err = params->err_start;
5056     int width;
5057     struct rop_codes codes;
5058
5059     rop_codes_from_stretch_mode( mode, &codes );
5060     for (width = params->length; width; width--)
5061     {
5062         do_rop_codes_8( dst_ptr,     *src_ptr,       &codes );
5063         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5064         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5065         dst_ptr += 3 * params->dst_inc;
5066         if (err > 0)
5067         {
5068             src_ptr += 3 * params->src_inc;
5069             err += params->err_add_1;
5070         }
5071         else err += params->err_add_2;
5072     }
5073 }
5074
5075 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5076                            const dib_info *src_dib, const POINT *src_start,
5077                            const struct stretch_params *params, int mode,
5078                            BOOL keep_dst)
5079 {
5080     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5081     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5082     int err = params->err_start;
5083     int width;
5084     struct rop_codes codes;
5085
5086     rop_codes_from_stretch_mode( mode, &codes );
5087     for (width = params->length; width; width--)
5088     {
5089         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5090         dst_ptr += params->dst_inc;
5091         if (err > 0)
5092         {
5093             src_ptr += params->src_inc;
5094             err += params->err_add_1;
5095         }
5096         else err += params->err_add_2;
5097     }
5098 }
5099
5100 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5101                           const dib_info *src_dib, const POINT *src_start,
5102                           const struct stretch_params *params, int mode,
5103                           BOOL keep_dst)
5104 {
5105     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5106     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5107     int err = params->err_start;
5108     int width;
5109     struct rop_codes codes;
5110
5111     rop_codes_from_stretch_mode( mode, &codes );
5112     for (width = params->length; width; width--)
5113     {
5114         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5115         dst_ptr += params->dst_inc;
5116         if (err > 0)
5117         {
5118             src_ptr += params->src_inc;
5119             err += params->err_add_1;
5120         }
5121         else err += params->err_add_2;
5122     }
5123 }
5124
5125 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5126                           const dib_info *src_dib, const POINT *src_start,
5127                           const struct stretch_params *params, int mode,
5128                           BOOL keep_dst)
5129 {
5130     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5131     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5132     int err = params->err_start;
5133     int width, dst_x = dst_start->x, src_x = src_start->x;
5134     struct rop_codes codes;
5135     BYTE src_val;
5136
5137     rop_codes_from_stretch_mode( mode, &codes );
5138     for (width = params->length; width; width--)
5139     {
5140         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5141         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5142
5143         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5144
5145         if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5146             dst_ptr += params->dst_inc;
5147         dst_x += params->dst_inc;
5148
5149         if (err > 0)
5150         {
5151             if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5152                 src_ptr += params->src_inc;
5153             src_x += params->src_inc;
5154             err += params->err_add_1;
5155         }
5156         else err += params->err_add_2;
5157     }
5158 }
5159
5160 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5161                           const dib_info *src_dib, const POINT *src_start,
5162                           const struct stretch_params *params, int mode,
5163                           BOOL keep_dst)
5164 {
5165     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5166     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5167     int err = params->err_start;
5168     int width, dst_x = dst_start->x, src_x = src_start->x;
5169     struct rop_codes codes;
5170     BYTE src_val;
5171
5172     rop_codes_from_stretch_mode( mode, &codes );
5173     for (width = params->length; width; width--)
5174     {
5175         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5176         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5177
5178         if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5179             dst_ptr += params->dst_inc;
5180         dst_x += params->dst_inc;
5181
5182         if (err > 0)
5183         {
5184             if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5185                 src_ptr += params->src_inc;
5186             src_x += params->src_inc;
5187             err += params->err_add_1;
5188         }
5189         else err += params->err_add_2;
5190     }
5191 }
5192
5193 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5194                              const dib_info *src_dib, const POINT *src_start,
5195                              const struct stretch_params *params, int mode,
5196                              BOOL keep_dst)
5197 {
5198     FIXME("bit count %d\n", dst_dib->bit_count);
5199     return;
5200 }
5201
5202 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5203                           const dib_info *src_dib, const POINT *src_start,
5204                           const struct stretch_params *params, int mode,
5205                           BOOL keep_dst)
5206 {
5207     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5208     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5209     int err = params->err_start;
5210     int width;
5211     struct rop_codes codes;
5212     DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5213     BOOL new_pix = TRUE;
5214
5215     rop_codes_from_stretch_mode( mode, &codes );
5216     for (width = params->length; width; width--)
5217     {
5218         if (new_pix && !keep_dst) *dst_ptr = init_val;
5219         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5220         new_pix = FALSE;
5221         src_ptr += params->src_inc;
5222         if (err > 0)
5223         {
5224             dst_ptr += params->dst_inc;
5225             new_pix = TRUE;
5226             err += params->err_add_1;
5227         }
5228         else err += params->err_add_2;
5229     }
5230 }
5231
5232 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5233                           const dib_info *src_dib, const POINT *src_start,
5234                           const struct stretch_params *params, int mode,
5235                           BOOL keep_dst)
5236 {
5237     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5238     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5239     int err = params->err_start;
5240     int width;
5241     struct rop_codes codes;
5242     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5243     BOOL new_pix = TRUE;
5244
5245     rop_codes_from_stretch_mode( mode, &codes );
5246     for (width = params->length; width; width--)
5247     {
5248         if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5249         do_rop_codes_8( dst_ptr,      *src_ptr,      &codes );
5250         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5251         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5252         new_pix = FALSE;
5253         src_ptr += 3 * params->src_inc;
5254         if (err > 0)
5255         {
5256             dst_ptr += 3 * params->dst_inc;
5257             new_pix = TRUE;
5258             err += params->err_add_1;
5259         }
5260         else err += params->err_add_2;
5261     }
5262 }
5263
5264 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5265                           const dib_info *src_dib, const POINT *src_start,
5266                           const struct stretch_params *params, int mode,
5267                           BOOL keep_dst)
5268 {
5269     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5270     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5271     int err = params->err_start;
5272     int width;
5273     struct rop_codes codes;
5274     WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5275     BOOL new_pix = TRUE;
5276
5277     rop_codes_from_stretch_mode( mode, &codes );
5278     for (width = params->length; width; width--)
5279     {
5280         if (new_pix && !keep_dst) *dst_ptr = init_val;
5281         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5282         new_pix = FALSE;
5283         src_ptr += params->src_inc;
5284         if (err > 0)
5285         {
5286             dst_ptr += params->dst_inc;
5287             new_pix = TRUE;
5288             err += params->err_add_1;
5289         }
5290         else err += params->err_add_2;
5291     }
5292 }
5293
5294 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5295                          const dib_info *src_dib, const POINT *src_start,
5296                          const struct stretch_params *params, int mode,
5297                          BOOL keep_dst)
5298 {
5299     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5300     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5301     int err = params->err_start;
5302     int width;
5303     struct rop_codes codes;
5304     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5305     BOOL new_pix = TRUE;
5306
5307     rop_codes_from_stretch_mode( mode, &codes );
5308     for (width = params->length; width; width--)
5309     {
5310         if (new_pix && !keep_dst) *dst_ptr = init_val;
5311         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5312         new_pix = FALSE;
5313         src_ptr += params->src_inc;
5314         if (err > 0)
5315         {
5316             dst_ptr += params->dst_inc;
5317             new_pix = TRUE;
5318             err += params->err_add_1;
5319         }
5320         else err += params->err_add_2;
5321     }
5322 }
5323
5324 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5325                          const dib_info *src_dib, const POINT *src_start,
5326                          const struct stretch_params *params, int mode,
5327                          BOOL keep_dst)
5328 {
5329     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5330     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5331     int err = params->err_start;
5332     int width, dst_x = dst_start->x, src_x = src_start->x;
5333     struct rop_codes codes;
5334     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5335     BOOL new_pix = TRUE;
5336
5337     rop_codes_from_stretch_mode( mode, &codes );
5338     for (width = params->length; width; width--)
5339     {
5340         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
5341
5342         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5343         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5344
5345         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
5346         new_pix = FALSE;
5347
5348         if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5349             src_ptr += params->src_inc;
5350         src_x += params->src_inc;
5351
5352         if (err > 0)
5353         {
5354             if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5355                 dst_ptr += params->dst_inc;
5356             dst_x += params->dst_inc;
5357             new_pix = TRUE;
5358             err += params->err_add_1;
5359         }
5360         else err += params->err_add_2;
5361     }
5362 }
5363
5364 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5365                          const dib_info *src_dib, const POINT *src_start,
5366                          const struct stretch_params *params, int mode,
5367                          BOOL keep_dst)
5368 {
5369     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5370     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5371     int err = params->err_start;
5372     int width, dst_x = dst_start->x, src_x = src_start->x;
5373     struct rop_codes codes;
5374     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5375     BOOL new_pix = TRUE;
5376
5377     rop_codes_from_stretch_mode( mode, &codes );
5378     for (width = params->length; width; width--)
5379     {
5380         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5381         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5382         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5383         new_pix = FALSE;
5384
5385         if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5386             src_ptr += params->src_inc;
5387         src_x += params->src_inc;
5388
5389         if (err > 0)
5390         {
5391             if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5392                 dst_ptr += params->dst_inc;
5393             dst_x += params->dst_inc;
5394             new_pix = TRUE;
5395             err += params->err_add_1;
5396         }
5397         else err += params->err_add_2;
5398     }
5399 }
5400
5401 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5402                             const dib_info *src_dib, const POINT *src_start,
5403                             const struct stretch_params *params, int mode,
5404                             BOOL keep_dst)
5405 {
5406     FIXME("bit count %d\n", dst_dib->bit_count);
5407     return;
5408 }
5409
5410 const primitive_funcs funcs_8888 =
5411 {
5412     solid_rects_32,
5413     solid_line_32,
5414     pattern_rects_32,
5415     copy_rect_32,
5416     blend_rect_8888,
5417     gradient_rect_8888,
5418     draw_glyph_8888,
5419     get_pixel_32,
5420     colorref_to_pixel_888,
5421     pixel_to_colorref_888,
5422     convert_to_8888,
5423     create_rop_masks_32,
5424     stretch_row_32,
5425     shrink_row_32
5426 };
5427
5428 const primitive_funcs funcs_32 =
5429 {
5430     solid_rects_32,
5431     solid_line_32,
5432     pattern_rects_32,
5433     copy_rect_32,
5434     blend_rect_32,
5435     gradient_rect_32,
5436     draw_glyph_32,
5437     get_pixel_32,
5438     colorref_to_pixel_masks,
5439     pixel_to_colorref_masks,
5440     convert_to_32,
5441     create_rop_masks_32,
5442     stretch_row_32,
5443     shrink_row_32
5444 };
5445
5446 const primitive_funcs funcs_24 =
5447 {
5448     solid_rects_24,
5449     solid_line_24,
5450     pattern_rects_24,
5451     copy_rect_24,
5452     blend_rect_24,
5453     gradient_rect_24,
5454     draw_glyph_24,
5455     get_pixel_24,
5456     colorref_to_pixel_888,
5457     pixel_to_colorref_888,
5458     convert_to_24,
5459     create_rop_masks_24,
5460     stretch_row_24,
5461     shrink_row_24
5462 };
5463
5464 const primitive_funcs funcs_555 =
5465 {
5466     solid_rects_16,
5467     solid_line_16,
5468     pattern_rects_16,
5469     copy_rect_16,
5470     blend_rect_555,
5471     gradient_rect_555,
5472     draw_glyph_555,
5473     get_pixel_16,
5474     colorref_to_pixel_555,
5475     pixel_to_colorref_555,
5476     convert_to_555,
5477     create_rop_masks_16,
5478     stretch_row_16,
5479     shrink_row_16
5480 };
5481
5482 const primitive_funcs funcs_16 =
5483 {
5484     solid_rects_16,
5485     solid_line_16,
5486     pattern_rects_16,
5487     copy_rect_16,
5488     blend_rect_16,
5489     gradient_rect_16,
5490     draw_glyph_16,
5491     get_pixel_16,
5492     colorref_to_pixel_masks,
5493     pixel_to_colorref_masks,
5494     convert_to_16,
5495     create_rop_masks_16,
5496     stretch_row_16,
5497     shrink_row_16
5498 };
5499
5500 const primitive_funcs funcs_8 =
5501 {
5502     solid_rects_8,
5503     solid_line_8,
5504     pattern_rects_8,
5505     copy_rect_8,
5506     blend_rect_8,
5507     gradient_rect_8,
5508     draw_glyph_8,
5509     get_pixel_8,
5510     colorref_to_pixel_colortable,
5511     pixel_to_colorref_colortable,
5512     convert_to_8,
5513     create_rop_masks_8,
5514     stretch_row_8,
5515     shrink_row_8
5516 };
5517
5518 const primitive_funcs funcs_4 =
5519 {
5520     solid_rects_4,
5521     solid_line_4,
5522     pattern_rects_4,
5523     copy_rect_4,
5524     blend_rect_4,
5525     gradient_rect_4,
5526     draw_glyph_4,
5527     get_pixel_4,
5528     colorref_to_pixel_colortable,
5529     pixel_to_colorref_colortable,
5530     convert_to_4,
5531     create_rop_masks_4,
5532     stretch_row_4,
5533     shrink_row_4
5534 };
5535
5536 const primitive_funcs funcs_1 =
5537 {
5538     solid_rects_1,
5539     solid_line_1,
5540     pattern_rects_1,
5541     copy_rect_1,
5542     blend_rect_1,
5543     gradient_rect_1,
5544     draw_glyph_1,
5545     get_pixel_1,
5546     colorref_to_pixel_colortable,
5547     pixel_to_colorref_colortable,
5548     convert_to_1,
5549     create_rop_masks_1,
5550     stretch_row_1,
5551     shrink_row_1
5552 };
5553
5554 const primitive_funcs funcs_null =
5555 {
5556     solid_rects_null,
5557     solid_line_null,
5558     pattern_rects_null,
5559     copy_rect_null,
5560     blend_rect_null,
5561     gradient_rect_null,
5562     draw_glyph_null,
5563     get_pixel_null,
5564     colorref_to_pixel_null,
5565     pixel_to_colorref_null,
5566     convert_to_null,
5567     create_rop_masks_null,
5568     stretch_row_null,
5569     shrink_row_null
5570 };