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