dinput: Stub IDirectInputJoyConfig8 interface.
[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 BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
3981 {
3982     if (dst == text) return dst;
3983
3984     if (dst > text)
3985     {
3986         DWORD diff = dst - text;
3987         DWORD range = max_comp - text;
3988         dst = text + (diff * range ) / (0xff - text);
3989         return dst;
3990     }
3991     else
3992     {
3993         DWORD diff = text - dst;
3994         DWORD range = text - min_comp;
3995         dst = text - (diff * range) / text;
3996         return dst;
3997     }
3998 }
3999
4000 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4001 {
4002     return (aa_color( b_dst, text,       range->b_min, range->b_max )      |
4003             aa_color( g_dst, text >> 8,  range->g_min, range->g_max ) << 8 |
4004             aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4005 }
4006
4007 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4008                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4009 {
4010     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4011     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4012     int x, y;
4013
4014     for (y = rect->top; y < rect->bottom; y++)
4015     {
4016         for (x = 0; x < rect->right - rect->left; x++)
4017         {
4018             if (glyph_ptr[x] <= 1) continue;
4019             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4020             dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4021         }
4022         dst_ptr += dib->stride / 4;
4023         glyph_ptr += glyph->stride;
4024     }
4025 }
4026
4027 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4028                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4029 {
4030     DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4031     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4032     int x, y;
4033     DWORD text, val;
4034
4035     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4036            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4037            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4038
4039     for (y = rect->top; y < rect->bottom; y++)
4040     {
4041         for (x = 0; x < rect->right - rect->left; x++)
4042         {
4043             if (glyph_ptr[x] <= 1) continue;
4044             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4045             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4046                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4047                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4048                           text, ranges + glyph_ptr[x] );
4049             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4050                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4051                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4052         }
4053         dst_ptr += dib->stride / 4;
4054         glyph_ptr += glyph->stride;
4055     }
4056 }
4057
4058 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4059                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4060 {
4061     BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4062     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4063     int x, y;
4064     DWORD val;
4065
4066     for (y = rect->top; y < rect->bottom; y++)
4067     {
4068         for (x = 0; x < rect->right - rect->left; x++)
4069         {
4070             if (glyph_ptr[x] <= 1) continue;
4071             if (glyph_ptr[x] >= 16)
4072                 val = text_pixel;
4073             else
4074                 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4075                               text_pixel, ranges + glyph_ptr[x] );
4076             dst_ptr[x * 3]     = val;
4077             dst_ptr[x * 3 + 1] = val >> 8;
4078             dst_ptr[x * 3 + 2] = val >> 16;
4079         }
4080         dst_ptr += dib->stride;
4081         glyph_ptr += glyph->stride;
4082     }
4083 }
4084
4085 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4086                             const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4087 {
4088     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4089     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4090     int x, y;
4091     DWORD text, val;
4092
4093     text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4094            ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4095            ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4096
4097     for (y = rect->top; y < rect->bottom; y++)
4098     {
4099         for (x = 0; x < rect->right - rect->left; x++)
4100         {
4101             if (glyph_ptr[x] <= 1) continue;
4102             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4103             val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4104                           ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
4105                           ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
4106                           text, ranges + glyph_ptr[x] );
4107             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4108         }
4109         dst_ptr += dib->stride / 2;
4110         glyph_ptr += glyph->stride;
4111     }
4112 }
4113
4114 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4115                            const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4116 {
4117     WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4118     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4119     int x, y;
4120     DWORD text, val;
4121
4122     text = get_field( text_pixel, dib->red_shift,   dib->red_len ) << 16 |
4123            get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4124            get_field( text_pixel, dib->blue_shift,  dib->blue_len );
4125
4126     for (y = rect->top; y < rect->bottom; y++)
4127     {
4128         for (x = 0; x < rect->right - rect->left; x++)
4129         {
4130             if (glyph_ptr[x] <= 1) continue;
4131             if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4132             val = aa_rgb( get_field(dst_ptr[x], dib->red_shift,   dib->red_len),
4133                           get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4134                           get_field(dst_ptr[x], dib->blue_shift,  dib->blue_len),
4135                           text, ranges + glyph_ptr[x] );
4136             dst_ptr[x] = (put_field( val >> 16, dib->red_shift,   dib->red_len )   |
4137                           put_field( val >> 8,  dib->green_shift, dib->green_len ) |
4138                           put_field( val,       dib->blue_shift,  dib->blue_len ));
4139         }
4140         dst_ptr += dib->stride / 2;
4141         glyph_ptr += glyph->stride;
4142     }
4143 }
4144
4145 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4146                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4147 {
4148     BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4149     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4150     int x, y;
4151
4152     for (y = rect->top; y < rect->bottom; y++)
4153     {
4154         for (x = 0; x < rect->right - rect->left; x++)
4155         {
4156             /* no antialiasing, glyph should only contain 0 or 16. */
4157             if (glyph_ptr[x] >= 16)
4158                 dst_ptr[x] = text_pixel;
4159         }
4160         dst_ptr += dib->stride;
4161         glyph_ptr += glyph->stride;
4162     }
4163 }
4164
4165 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4166                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4167 {
4168     BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
4169     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4170     int x, y;
4171
4172     for (y = rect->top; y < rect->bottom; y++)
4173     {
4174         for (x = rect->left; x < rect->right; x++)
4175         {
4176             /* no antialiasing, glyph should only contain 0 or 16. */
4177             if (glyph_ptr[x] >= 16)
4178             {
4179                 if (x & 1)
4180                     dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
4181                 else
4182                     dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
4183             }
4184         }
4185         dst_ptr += dib->stride;
4186         glyph_ptr += glyph->stride;
4187     }
4188 }
4189
4190 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4191                           const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4192 {
4193     BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
4194     const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4195     int x, y;
4196     BYTE text = (text_pixel & 1) ? 0xff : 0;
4197
4198     for (y = rect->top; y < rect->bottom; y++)
4199     {
4200         for (x = rect->left; x < rect->right; x++)
4201         {
4202             /* no antialiasing, glyph should only contain 0 or 16. */
4203             if (glyph_ptr[x] >= 16)
4204                 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
4205         }
4206         dst_ptr += dib->stride;
4207         glyph_ptr += glyph->stride;
4208     }
4209 }
4210
4211 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4212                              const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4213 {
4214     return;
4215 }
4216
4217 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)
4218 {
4219     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4220     DWORD mask_start = 0, mask_offset;
4221     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4222     int x, y;
4223
4224     for(y = 0; y < hatch->height; y++)
4225     {
4226         hatch_ptr = hatch_start;
4227         mask_offset = mask_start;
4228         for(x = 0; x < hatch->width; x++)
4229         {
4230             if(*hatch_ptr & pixel_masks_1[x % 8])
4231             {
4232                 and_bits[mask_offset] = fg->and;
4233                 xor_bits[mask_offset] = fg->xor;
4234             }
4235             else
4236             {
4237                 and_bits[mask_offset] = bg->and;
4238                 xor_bits[mask_offset] = bg->xor;
4239             }
4240             if(x % 8 == 7) hatch_ptr++;
4241             mask_offset++;
4242         }
4243         hatch_start += hatch->stride;
4244         mask_start += dib->stride / 4;
4245     }
4246
4247     return TRUE;
4248 }
4249
4250 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)
4251 {
4252     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4253     DWORD mask_start = 0, mask_offset;
4254     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4255     int x, y;
4256
4257     for(y = 0; y < hatch->height; y++)
4258     {
4259         hatch_ptr = hatch_start;
4260         mask_offset = mask_start;
4261         for(x = 0; x < hatch->width; x++)
4262         {
4263             if(*hatch_ptr & pixel_masks_1[x % 8])
4264             {
4265                 and_bits[mask_offset]   =  fg->and        & 0xff;
4266                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
4267                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
4268                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
4269                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
4270                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4271             }
4272             else
4273             {
4274                 and_bits[mask_offset]   =  bg->and        & 0xff;
4275                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
4276                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
4277                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
4278                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
4279                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4280             }
4281             if(x % 8 == 7) hatch_ptr++;
4282         }
4283         hatch_start += hatch->stride;
4284         mask_start += dib->stride;
4285     }
4286
4287     return TRUE;
4288 }
4289
4290 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)
4291 {
4292     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4293     DWORD mask_start = 0, mask_offset;
4294     WORD *and_bits = bits->and, *xor_bits = bits->xor;
4295     int x, y;
4296
4297     for(y = 0; y < hatch->height; y++)
4298     {
4299         hatch_ptr = hatch_start;
4300         mask_offset = mask_start;
4301         for(x = 0; x < hatch->width; x++)
4302         {
4303             if(*hatch_ptr & pixel_masks_1[x % 8])
4304             {
4305                 and_bits[mask_offset] = fg->and;
4306                 xor_bits[mask_offset] = fg->xor;
4307             }
4308             else
4309             {
4310                 and_bits[mask_offset] = bg->and;
4311                 xor_bits[mask_offset] = bg->xor;
4312             }
4313             if(x % 8 == 7) hatch_ptr++;
4314             mask_offset++;
4315         }
4316         hatch_start += hatch->stride;
4317         mask_start += dib->stride / 2;
4318     }
4319
4320     return TRUE;
4321 }
4322
4323 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)
4324 {
4325     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4326     DWORD mask_start = 0, mask_offset;
4327     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4328     int x, y;
4329
4330     for(y = 0; y < hatch->height; y++)
4331     {
4332         hatch_ptr = hatch_start;
4333         mask_offset = mask_start;
4334         for(x = 0; x < hatch->width; x++)
4335         {
4336             if(*hatch_ptr & pixel_masks_1[x % 8])
4337             {
4338                 and_bits[mask_offset] = fg->and;
4339                 xor_bits[mask_offset] = fg->xor;
4340             }
4341             else
4342             {
4343                 and_bits[mask_offset] = bg->and;
4344                 xor_bits[mask_offset] = bg->xor;
4345             }
4346             if(x % 8 == 7) hatch_ptr++;
4347             mask_offset++;
4348         }
4349         hatch_start += hatch->stride;
4350         mask_start += dib->stride;
4351     }
4352
4353     return TRUE;
4354 }
4355
4356 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)
4357 {
4358     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4359     DWORD mask_start = 0, mask_offset;
4360     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4361     const rop_mask *rop_mask;
4362     int x, y;
4363
4364     for(y = 0; y < hatch->height; y++)
4365     {
4366         hatch_ptr = hatch_start;
4367         mask_offset = mask_start;
4368         for(x = 0; x < hatch->width; x++)
4369         {
4370             if(*hatch_ptr & pixel_masks_1[x % 8])
4371                 rop_mask = fg;
4372             else
4373                 rop_mask = bg;
4374
4375             if(x & 1)
4376             {
4377                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4378                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4379                 mask_offset++;
4380             }
4381             else
4382             {
4383                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4384                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4385             }
4386
4387             if(x % 8 == 7) hatch_ptr++;
4388         }
4389         hatch_start += hatch->stride;
4390         mask_start += dib->stride;
4391     }
4392
4393     return TRUE;
4394 }
4395
4396 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)
4397 {
4398     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4399     DWORD mask_start = 0, mask_offset;
4400     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4401     rop_mask rop_mask;
4402     int x, y, bit_pos;
4403
4404     for(y = 0; y < hatch->height; y++)
4405     {
4406         hatch_ptr = hatch_start;
4407         mask_offset = mask_start;
4408         for(x = 0, bit_pos = 0; x < hatch->width; x++)
4409         {
4410             if(*hatch_ptr & pixel_masks_1[x % 8])
4411             {
4412                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4413                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4414             }
4415             else
4416             {
4417                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4418                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4419             }
4420
4421             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4422
4423             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4424             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4425
4426             if(++bit_pos == 8)
4427             {
4428                 mask_offset++;
4429                 hatch_ptr++;
4430                 bit_pos = 0;
4431             }
4432         }
4433         hatch_start += hatch->stride;
4434         mask_start += dib->stride;
4435     }
4436
4437     return TRUE;
4438 }
4439
4440 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)
4441 {
4442     return FALSE;
4443 }
4444
4445 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
4446 {
4447     switch (mode)
4448     {
4449     default:
4450     case STRETCH_DELETESCANS:
4451         get_rop_codes( R2_COPYPEN, codes );
4452         break;
4453     case STRETCH_ORSCANS:
4454         get_rop_codes( R2_MERGEPEN, codes );
4455         break;
4456     case STRETCH_ANDSCANS:
4457         get_rop_codes( R2_MASKPEN, codes );
4458         break;
4459     }
4460     return;
4461 }
4462
4463 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
4464                            const dib_info *src_dib, const POINT *src_start,
4465                            const struct stretch_params *params, int mode,
4466                            BOOL keep_dst)
4467 {
4468     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4469     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4470     int err = params->err_start;
4471     int width;
4472     struct rop_codes codes;
4473
4474     rop_codes_from_stretch_mode( mode, &codes );
4475     for (width = params->length; width; width--)
4476     {
4477         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4478         dst_ptr += params->dst_inc;
4479         if (err > 0)
4480         {
4481             src_ptr += params->src_inc;
4482             err += params->err_add_1;
4483         }
4484         else err += params->err_add_2;
4485     }
4486 }
4487
4488 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
4489                            const dib_info *src_dib, const POINT *src_start,
4490                            const struct stretch_params *params, int mode,
4491                            BOOL keep_dst)
4492 {
4493     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4494     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4495     int err = params->err_start;
4496     int width;
4497     struct rop_codes codes;
4498
4499     rop_codes_from_stretch_mode( mode, &codes );
4500     for (width = params->length; width; width--)
4501     {
4502         do_rop_codes_8( dst_ptr,     *src_ptr,       &codes );
4503         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4504         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4505         dst_ptr += 3 * params->dst_inc;
4506         if (err > 0)
4507         {
4508             src_ptr += 3 * params->src_inc;
4509             err += params->err_add_1;
4510         }
4511         else err += params->err_add_2;
4512     }
4513 }
4514
4515 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
4516                            const dib_info *src_dib, const POINT *src_start,
4517                            const struct stretch_params *params, int mode,
4518                            BOOL keep_dst)
4519 {
4520     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4521     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4522     int err = params->err_start;
4523     int width;
4524     struct rop_codes codes;
4525
4526     rop_codes_from_stretch_mode( mode, &codes );
4527     for (width = params->length; width; width--)
4528     {
4529         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4530         dst_ptr += params->dst_inc;
4531         if (err > 0)
4532         {
4533             src_ptr += params->src_inc;
4534             err += params->err_add_1;
4535         }
4536         else err += params->err_add_2;
4537     }
4538 }
4539
4540 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
4541                           const dib_info *src_dib, const POINT *src_start,
4542                           const struct stretch_params *params, int mode,
4543                           BOOL keep_dst)
4544 {
4545     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4546     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4547     int err = params->err_start;
4548     int width;
4549     struct rop_codes codes;
4550
4551     rop_codes_from_stretch_mode( mode, &codes );
4552     for (width = params->length; width; width--)
4553     {
4554         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4555         dst_ptr += params->dst_inc;
4556         if (err > 0)
4557         {
4558             src_ptr += params->src_inc;
4559             err += params->err_add_1;
4560         }
4561         else err += params->err_add_2;
4562     }
4563 }
4564
4565 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
4566                           const dib_info *src_dib, const POINT *src_start,
4567                           const struct stretch_params *params, int mode,
4568                           BOOL keep_dst)
4569 {
4570     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
4571     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
4572     int err = params->err_start;
4573     int width, dst_x = dst_start->x, src_x = src_start->x;
4574     struct rop_codes codes;
4575     BYTE src_val;
4576
4577     rop_codes_from_stretch_mode( mode, &codes );
4578     for (width = params->length; width; width--)
4579     {
4580         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4581         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4582
4583         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
4584
4585         if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4586             dst_ptr += params->dst_inc;
4587         dst_x += params->dst_inc;
4588
4589         if (err > 0)
4590         {
4591             if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4592                 src_ptr += params->src_inc;
4593             src_x += params->src_inc;
4594             err += params->err_add_1;
4595         }
4596         else err += params->err_add_2;
4597     }
4598 }
4599
4600 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
4601                           const dib_info *src_dib, const POINT *src_start,
4602                           const struct stretch_params *params, int mode,
4603                           BOOL keep_dst)
4604 {
4605     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4606     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4607     int err = params->err_start;
4608     int width, dst_x = dst_start->x, src_x = src_start->x;
4609     struct rop_codes codes;
4610     BYTE src_val;
4611
4612     rop_codes_from_stretch_mode( mode, &codes );
4613     for (width = params->length; width; width--)
4614     {
4615         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4616         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4617
4618         if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4619             dst_ptr += params->dst_inc;
4620         dst_x += params->dst_inc;
4621
4622         if (err > 0)
4623         {
4624             if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4625                 src_ptr += params->src_inc;
4626             src_x += params->src_inc;
4627             err += params->err_add_1;
4628         }
4629         else err += params->err_add_2;
4630     }
4631 }
4632
4633 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
4634                              const dib_info *src_dib, const POINT *src_start,
4635                              const struct stretch_params *params, int mode,
4636                              BOOL keep_dst)
4637 {
4638     FIXME("bit count %d\n", dst_dib->bit_count);
4639     return;
4640 }
4641
4642 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
4643                           const dib_info *src_dib, const POINT *src_start,
4644                           const struct stretch_params *params, int mode,
4645                           BOOL keep_dst)
4646 {
4647     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4648     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4649     int err = params->err_start;
4650     int width;
4651     struct rop_codes codes;
4652     DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4653     BOOL new_pix = TRUE;
4654
4655     rop_codes_from_stretch_mode( mode, &codes );
4656     for (width = params->length; width; width--)
4657     {
4658         if (new_pix && !keep_dst) *dst_ptr = init_val;
4659         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4660         new_pix = FALSE;
4661         src_ptr += params->src_inc;
4662         if (err > 0)
4663         {
4664             dst_ptr += params->dst_inc;
4665             new_pix = TRUE;
4666             err += params->err_add_1;
4667         }
4668         else err += params->err_add_2;
4669     }
4670 }
4671
4672 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
4673                           const dib_info *src_dib, const POINT *src_start,
4674                           const struct stretch_params *params, int mode,
4675                           BOOL keep_dst)
4676 {
4677     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4678     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4679     int err = params->err_start;
4680     int width;
4681     struct rop_codes codes;
4682     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4683     BOOL new_pix = TRUE;
4684
4685     rop_codes_from_stretch_mode( mode, &codes );
4686     for (width = params->length; width; width--)
4687     {
4688         if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
4689         do_rop_codes_8( dst_ptr,      *src_ptr,      &codes );
4690         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4691         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4692         new_pix = FALSE;
4693         src_ptr += 3 * params->src_inc;
4694         if (err > 0)
4695         {
4696             dst_ptr += 3 * params->dst_inc;
4697             new_pix = TRUE;
4698             err += params->err_add_1;
4699         }
4700         else err += params->err_add_2;
4701     }
4702 }
4703
4704 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
4705                           const dib_info *src_dib, const POINT *src_start,
4706                           const struct stretch_params *params, int mode,
4707                           BOOL keep_dst)
4708 {
4709     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4710     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4711     int err = params->err_start;
4712     int width;
4713     struct rop_codes codes;
4714     WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4715     BOOL new_pix = TRUE;
4716
4717     rop_codes_from_stretch_mode( mode, &codes );
4718     for (width = params->length; width; width--)
4719     {
4720         if (new_pix && !keep_dst) *dst_ptr = init_val;
4721         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4722         new_pix = FALSE;
4723         src_ptr += params->src_inc;
4724         if (err > 0)
4725         {
4726             dst_ptr += params->dst_inc;
4727             new_pix = TRUE;
4728             err += params->err_add_1;
4729         }
4730         else err += params->err_add_2;
4731     }
4732 }
4733
4734 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
4735                          const dib_info *src_dib, const POINT *src_start,
4736                          const struct stretch_params *params, int mode,
4737                          BOOL keep_dst)
4738 {
4739     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4740     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4741     int err = params->err_start;
4742     int width;
4743     struct rop_codes codes;
4744     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4745     BOOL new_pix = TRUE;
4746
4747     rop_codes_from_stretch_mode( mode, &codes );
4748     for (width = params->length; width; width--)
4749     {
4750         if (new_pix && !keep_dst) *dst_ptr = init_val;
4751         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4752         new_pix = FALSE;
4753         src_ptr += params->src_inc;
4754         if (err > 0)
4755         {
4756             dst_ptr += params->dst_inc;
4757             new_pix = TRUE;
4758             err += params->err_add_1;
4759         }
4760         else err += params->err_add_2;
4761     }
4762 }
4763
4764 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
4765                          const dib_info *src_dib, const POINT *src_start,
4766                          const struct stretch_params *params, int mode,
4767                          BOOL keep_dst)
4768 {
4769     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4770     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4771     int err = params->err_start;
4772     int width, dst_x = dst_start->x, src_x = src_start->x;
4773     struct rop_codes codes;
4774     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4775     BOOL new_pix = TRUE;
4776
4777     rop_codes_from_stretch_mode( mode, &codes );
4778     for (width = params->length; width; width--)
4779     {
4780         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4781
4782         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4783         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4784
4785         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4786         new_pix = FALSE;
4787
4788         if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4789             src_ptr += params->src_inc;
4790         src_x += params->src_inc;
4791
4792         if (err > 0)
4793         {
4794             if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4795                 dst_ptr += params->dst_inc;
4796             dst_x += params->dst_inc;
4797             new_pix = TRUE;
4798             err += params->err_add_1;
4799         }
4800         else err += params->err_add_2;
4801     }
4802 }
4803
4804 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4805                          const dib_info *src_dib, const POINT *src_start,
4806                          const struct stretch_params *params, int mode,
4807                          BOOL keep_dst)
4808 {
4809     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4810     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4811     int err = params->err_start;
4812     int width, dst_x = dst_start->x, src_x = src_start->x;
4813     struct rop_codes codes;
4814     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4815     BOOL new_pix = TRUE;
4816
4817     rop_codes_from_stretch_mode( mode, &codes );
4818     for (width = params->length; width; width--)
4819     {
4820         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4821         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4822         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4823         new_pix = FALSE;
4824
4825         if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4826             src_ptr += params->src_inc;
4827         src_x += params->src_inc;
4828
4829         if (err > 0)
4830         {
4831             if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4832                 dst_ptr += params->dst_inc;
4833             dst_x += params->dst_inc;
4834             new_pix = TRUE;
4835             err += params->err_add_1;
4836         }
4837         else err += params->err_add_2;
4838     }
4839 }
4840
4841 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4842                             const dib_info *src_dib, const POINT *src_start,
4843                             const struct stretch_params *params, int mode,
4844                             BOOL keep_dst)
4845 {
4846     FIXME("bit count %d\n", dst_dib->bit_count);
4847     return;
4848 }
4849
4850 const primitive_funcs funcs_8888 =
4851 {
4852     solid_rects_32,
4853     solid_line_32,
4854     pattern_rects_32,
4855     copy_rect_32,
4856     blend_rect_8888,
4857     draw_glyph_8888,
4858     get_pixel_32,
4859     colorref_to_pixel_888,
4860     pixel_to_colorref_888,
4861     convert_to_8888,
4862     create_rop_masks_32,
4863     stretch_row_32,
4864     shrink_row_32
4865 };
4866
4867 const primitive_funcs funcs_32 =
4868 {
4869     solid_rects_32,
4870     solid_line_32,
4871     pattern_rects_32,
4872     copy_rect_32,
4873     blend_rect_32,
4874     draw_glyph_32,
4875     get_pixel_32,
4876     colorref_to_pixel_masks,
4877     pixel_to_colorref_masks,
4878     convert_to_32,
4879     create_rop_masks_32,
4880     stretch_row_32,
4881     shrink_row_32
4882 };
4883
4884 const primitive_funcs funcs_24 =
4885 {
4886     solid_rects_24,
4887     solid_line_24,
4888     pattern_rects_24,
4889     copy_rect_24,
4890     blend_rect_24,
4891     draw_glyph_24,
4892     get_pixel_24,
4893     colorref_to_pixel_888,
4894     pixel_to_colorref_888,
4895     convert_to_24,
4896     create_rop_masks_24,
4897     stretch_row_24,
4898     shrink_row_24
4899 };
4900
4901 const primitive_funcs funcs_555 =
4902 {
4903     solid_rects_16,
4904     solid_line_16,
4905     pattern_rects_16,
4906     copy_rect_16,
4907     blend_rect_555,
4908     draw_glyph_555,
4909     get_pixel_16,
4910     colorref_to_pixel_555,
4911     pixel_to_colorref_555,
4912     convert_to_555,
4913     create_rop_masks_16,
4914     stretch_row_16,
4915     shrink_row_16
4916 };
4917
4918 const primitive_funcs funcs_16 =
4919 {
4920     solid_rects_16,
4921     solid_line_16,
4922     pattern_rects_16,
4923     copy_rect_16,
4924     blend_rect_16,
4925     draw_glyph_16,
4926     get_pixel_16,
4927     colorref_to_pixel_masks,
4928     pixel_to_colorref_masks,
4929     convert_to_16,
4930     create_rop_masks_16,
4931     stretch_row_16,
4932     shrink_row_16
4933 };
4934
4935 const primitive_funcs funcs_8 =
4936 {
4937     solid_rects_8,
4938     solid_line_8,
4939     pattern_rects_8,
4940     copy_rect_8,
4941     blend_rect_8,
4942     draw_glyph_8,
4943     get_pixel_8,
4944     colorref_to_pixel_colortable,
4945     pixel_to_colorref_colortable,
4946     convert_to_8,
4947     create_rop_masks_8,
4948     stretch_row_8,
4949     shrink_row_8
4950 };
4951
4952 const primitive_funcs funcs_4 =
4953 {
4954     solid_rects_4,
4955     solid_line_4,
4956     pattern_rects_4,
4957     copy_rect_4,
4958     blend_rect_4,
4959     draw_glyph_4,
4960     get_pixel_4,
4961     colorref_to_pixel_colortable,
4962     pixel_to_colorref_colortable,
4963     convert_to_4,
4964     create_rop_masks_4,
4965     stretch_row_4,
4966     shrink_row_4
4967 };
4968
4969 const primitive_funcs funcs_1 =
4970 {
4971     solid_rects_1,
4972     solid_line_1,
4973     pattern_rects_1,
4974     copy_rect_1,
4975     blend_rect_1,
4976     draw_glyph_1,
4977     get_pixel_1,
4978     colorref_to_pixel_colortable,
4979     pixel_to_colorref_colortable,
4980     convert_to_1,
4981     create_rop_masks_1,
4982     stretch_row_1,
4983     shrink_row_1
4984 };
4985
4986 const primitive_funcs funcs_null =
4987 {
4988     solid_rects_null,
4989     solid_line_null,
4990     pattern_rects_null,
4991     copy_rect_null,
4992     blend_rect_null,
4993     draw_glyph_null,
4994     get_pixel_null,
4995     colorref_to_pixel_null,
4996     pixel_to_colorref_null,
4997     convert_to_null,
4998     create_rop_masks_null,
4999     stretch_row_null,
5000     shrink_row_null
5001 };