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