d3d10core: Fixup HRESULT in a bunch of error cases.
[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_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
66
67 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
68 {
69     *ptr = (*ptr & and) ^ xor;
70 }
71
72 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
73 {
74     *ptr = (*ptr & and) ^ xor;
75 }
76
77 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
78 {
79     *ptr = (*ptr & and) ^ xor;
80 }
81
82 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
83 {
84     *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
85 }
86
87 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
88 {
89     do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
90 }
91
92 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
93 {
94     do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
95 }
96
97 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
98 {
99     do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
100 }
101
102 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
103 {
104     do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
105 }
106
107 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
108 {
109     for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
110 }
111
112 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
113 {
114     for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
115         do_rop_codes_32( dst, *src, codes );
116 }
117
118 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
119 {
120     for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
121 }
122
123 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
124 {
125     for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
126         do_rop_codes_16( dst, *src, codes );
127 }
128
129 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
130 {
131     for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
132 }
133
134 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
135 {
136     for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
137         do_rop_codes_8( dst, *src, codes );
138 }
139
140 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
141                                       struct rop_codes *codes, int len)
142 {
143     BYTE src_val;
144
145     for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
146     {
147         if (dst_x & 1)
148         {
149             if (src_x & 1) src_val = *src++;
150             else           src_val = *src >> 4;
151             do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
152         }
153         else
154         {
155             if (src_x & 1) src_val = *src++ << 4;
156             else           src_val = *src;
157             do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
158         }
159     }
160 }
161
162 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
163                                           struct rop_codes *codes, int len)
164 {
165     BYTE src_val;
166
167     src_x += len - 1;
168     dst_x += len - 1;
169     for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
170     {
171         if (dst_x & 1)
172         {
173             if (src_x & 1) src_val = *src;
174             else           src_val = *src-- >> 4;
175             do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
176         }
177         else
178         {
179             if (src_x & 1) src_val = *src << 4;
180             else           src_val = *src--;
181             do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
182         }
183     }
184 }
185
186 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
187                                       struct rop_codes *codes, int len)
188 {
189     BYTE src_val;
190
191     for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
192     {
193         src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
194         do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
195         if ((src_x & 7) == 7) src++;
196         if ((dst_x & 7) == 7) dst++;
197     }
198 }
199
200 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
201                                           struct rop_codes *codes, int len)
202 {
203     BYTE src_val;
204
205     src_x += len - 1;
206     dst_x += len - 1;
207     for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
208     {
209         src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
210         do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
211         if ((src_x & 7) == 0) src--;
212         if ((dst_x & 7) == 0) dst--;
213     }
214 }
215
216 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
217 {
218     DWORD *ptr, *start;
219     int x, y, i;
220
221     for(i = 0; i < num; i++, rc++)
222     {
223         start = get_pixel_ptr_32(dib, rc->left, rc->top);
224         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
225             for(x = rc->left, ptr = start; x < rc->right; x++)
226                 do_rop_32(ptr++, and, xor);
227     }
228 }
229
230 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
231 {
232     DWORD *ptr, *start;
233     BYTE *byte_ptr, *byte_start;
234     int x, y, i;
235     DWORD and_masks[3], xor_masks[3];
236
237     and_masks[0] = ( and        & 0x00ffffff) | ((and << 24) & 0xff000000);
238     and_masks[1] = ((and >>  8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
239     and_masks[2] = ((and >> 16) & 0x000000ff) | ((and <<  8) & 0xffffff00);
240     xor_masks[0] = ( xor        & 0x00ffffff) | ((xor << 24) & 0xff000000);
241     xor_masks[1] = ((xor >>  8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
242     xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor <<  8) & 0xffffff00);
243
244     for(i = 0; i < num; i++, rc++)
245     {
246         if(rc->left >= rc->right) continue;
247
248         if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
249         {
250             byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
251             for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
252             {
253                 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
254                 {
255                     do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
256                     do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
257                     do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
258                 }
259             }
260         }
261         else
262         {
263             start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
264             for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
265             {
266                 ptr = start;
267
268                 switch(rc->left & 3)
269                 {
270                 case 1:
271                     do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
272                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
273                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
274                     break;
275                 case 2:
276                     do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
277                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
278                     break;
279                 case 3:
280                     do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
281                     break;
282                 }
283
284                 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
285                 {
286                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
287                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
288                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
289                 }
290
291                 switch(rc->right & 3)
292                 {
293                 case 1:
294                     do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
295                     break;
296                 case 2:
297                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
298                     do_rop_32(ptr,   and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
299                     break;
300                 case 3:
301                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
302                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
303                     do_rop_32(ptr,   and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
304                     break;
305                 }
306             }
307         }
308     }
309 }
310
311 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
312 {
313     WORD *ptr, *start;
314     int x, y, i;
315
316     for(i = 0; i < num; i++, rc++)
317     {
318         start = get_pixel_ptr_16(dib, rc->left, rc->top);
319         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
320             for(x = rc->left, ptr = start; x < rc->right; x++)
321                 do_rop_16(ptr++, and, xor);
322     }
323 }
324
325 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
326 {
327     BYTE *ptr, *start;
328     int x, y, i;
329
330     for(i = 0; i < num; i++, rc++)
331     {
332         start = get_pixel_ptr_8(dib, rc->left, rc->top);
333         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
334             for(x = rc->left, ptr = start; x < rc->right; x++)
335                 do_rop_8(ptr++, and, xor);
336     }
337 }
338
339 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
340 {
341     BYTE *ptr, *start;
342     int x, y, i;
343     BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
344     BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
345
346     for(i = 0; i < num; i++, rc++)
347     {
348         if(rc->left >= rc->right) continue;
349         start = get_pixel_ptr_4(dib, rc->left, rc->top);
350         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
351         {
352             ptr = start;
353             if(rc->left & 1) /* upper nibble untouched */
354                 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
355
356             for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
357                 do_rop_8(ptr++, byte_and, byte_xor);
358
359             if(rc->right & 1) /* lower nibble untouched */
360                 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
361         }
362     }
363 }
364
365 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
366 {
367     BYTE *ptr, *start;
368     int x, y, i;
369     BYTE byte_and = (and & 1) ? 0xff : 0;
370     BYTE byte_xor = (xor & 1) ? 0xff : 0;
371     BYTE start_and, start_xor, end_and, end_xor, mask;
372     static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
373
374     for(i = 0; i < num; i++, rc++)
375     {
376         if(rc->left >= rc->right) continue;
377
378         start = get_pixel_ptr_1(dib, rc->left, rc->top);
379
380         if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
381         {
382             mask = masks[rc->left & 7] & ~masks[rc->right & 7];
383
384             start_and = byte_and | ~mask;
385             start_xor = byte_xor & mask;
386             for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
387             {
388                 do_rop_8(start, start_and, start_xor);
389             }
390         }
391         else
392         {
393             mask = masks[rc->left & 7];
394             start_and = byte_and | ~mask;
395             start_xor = byte_xor & mask;
396
397             mask = masks[rc->right & 7];
398             /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
399             end_and = byte_and | mask;
400             end_xor = byte_xor & ~mask;
401
402             for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
403             {
404                 ptr = start;
405
406                 if(rc->left & 7)
407                     do_rop_8(ptr++, start_and, start_xor);
408
409                 for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
410                     do_rop_8(ptr++, byte_and, byte_xor);
411
412                 if(rc->right & 7)
413                     do_rop_8(ptr, end_and, end_xor);
414             }
415         }
416     }
417 }
418
419 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
420 {
421     return;
422 }
423
424 static inline INT calc_offset(INT edge, INT size, INT origin)
425 {
426     INT offset;
427
428     if(edge - origin >= 0)
429         offset = (edge - origin) % size;
430     else
431     {
432         offset = (origin - edge) % size;
433         if(offset) offset = size - offset;
434     }
435     return offset;
436 }
437
438 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
439 {
440     POINT offset;
441
442     offset.x = calc_offset(rc->left, brush->width,  origin->x);
443     offset.y = calc_offset(rc->top,  brush->height, origin->y);
444
445     return offset;
446 }
447
448 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
449                              const dib_info *brush, void *and_bits, void *xor_bits)
450 {
451     DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
452     int x, y, i;
453     POINT offset;
454
455     for(i = 0; i < num; i++, rc++)
456     {
457         offset = calc_brush_offset(rc, brush, origin);
458
459         start = get_pixel_ptr_32(dib, rc->left, rc->top);
460         start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
461         start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
462
463         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
464         {
465             and_ptr = start_and + offset.x;
466             xor_ptr = start_xor + offset.x;
467
468             for(x = rc->left, ptr = start; x < rc->right; x++)
469             {
470                 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
471                 if(and_ptr == start_and + brush->width)
472                 {
473                     and_ptr = start_and;
474                     xor_ptr = start_xor;
475                 }
476             }
477
478             offset.y++;
479             if(offset.y == brush->height)
480             {
481                 start_and = and_bits;
482                 start_xor = xor_bits;
483                 offset.y = 0;
484             }
485             else
486             {
487                 start_and += brush->stride / 4;
488                 start_xor += brush->stride / 4;
489             }
490         }
491     }
492 }
493
494 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
495                              const dib_info *brush, void *and_bits, void *xor_bits)
496 {
497     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
498     int x, y, i;
499     POINT offset;
500
501     for(i = 0; i < num; i++, rc++)
502     {
503         offset = calc_brush_offset(rc, brush, origin);
504
505         start = get_pixel_ptr_24(dib, rc->left, rc->top);
506         start_and = (BYTE*)and_bits + offset.y * brush->stride;
507         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
508
509         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
510         {
511             and_ptr = start_and + offset.x * 3;
512             xor_ptr = start_xor + offset.x * 3;
513
514             for(x = rc->left, ptr = start; x < rc->right; x++)
515             {
516                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
517                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
518                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
519                 if(and_ptr == start_and + brush->width * 3)
520                 {
521                     and_ptr = start_and;
522                     xor_ptr = start_xor;
523                 }
524             }
525
526             offset.y++;
527             if(offset.y == brush->height)
528             {
529                 start_and = and_bits;
530                 start_xor = xor_bits;
531                 offset.y = 0;
532             }
533             else
534             {
535                 start_and += brush->stride;
536                 start_xor += brush->stride;
537             }
538         }
539     }
540 }
541
542 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
543                              const dib_info *brush, void *and_bits, void *xor_bits)
544 {
545     WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
546     int x, y, i;
547     POINT offset;
548
549     for(i = 0; i < num; i++, rc++)
550     {
551         offset = calc_brush_offset(rc, brush, origin);
552
553         start = get_pixel_ptr_16(dib, rc->left, rc->top);
554         start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
555         start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
556
557         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
558         {
559             and_ptr = start_and + offset.x;
560             xor_ptr = start_xor + offset.x;
561
562             for(x = rc->left, ptr = start; x < rc->right; x++)
563             {
564                 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
565                 if(and_ptr == start_and + brush->width)
566                 {
567                     and_ptr = start_and;
568                     xor_ptr = start_xor;
569                 }
570             }
571
572             offset.y++;
573             if(offset.y == brush->height)
574             {
575                 start_and = and_bits;
576                 start_xor = xor_bits;
577                 offset.y = 0;
578             }
579             else
580             {
581                 start_and += brush->stride / 2;
582                 start_xor += brush->stride / 2;
583             }
584         }
585     }
586 }
587
588 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
589                             const dib_info *brush, void *and_bits, void *xor_bits)
590 {
591     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
592     int x, y, i;
593     POINT offset;
594
595     for(i = 0; i < num; i++, rc++)
596     {
597         offset = calc_brush_offset(rc, brush, origin);
598
599         start = get_pixel_ptr_8(dib, rc->left, rc->top);
600         start_and = (BYTE*)and_bits + offset.y * brush->stride;
601         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
602
603         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
604         {
605             and_ptr = start_and + offset.x;
606             xor_ptr = start_xor + offset.x;
607
608             for(x = rc->left, ptr = start; x < rc->right; x++)
609             {
610                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
611                 if(and_ptr == start_and + brush->width)
612                 {
613                     and_ptr = start_and;
614                     xor_ptr = start_xor;
615                 }
616             }
617
618             offset.y++;
619             if(offset.y == brush->height)
620             {
621                 start_and = and_bits;
622                 start_xor = xor_bits;
623                 offset.y = 0;
624             }
625             else
626             {
627                 start_and += brush->stride;
628                 start_xor += brush->stride;
629             }
630         }
631     }
632 }
633
634 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
635                             const dib_info *brush, void *and_bits, void *xor_bits)
636 {
637     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
638     int x, y, i;
639     POINT offset;
640
641     for(i = 0; i < num; i++, rc++)
642     {
643         offset = calc_brush_offset(rc, brush, origin);
644
645         start = get_pixel_ptr_4(dib, rc->left, rc->top);
646         start_and = (BYTE*)and_bits + offset.y * brush->stride;
647         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
648
649         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
650         {
651             INT brush_x = offset.x;
652             BYTE byte_and, byte_xor;
653
654             and_ptr = start_and + brush_x / 2;
655             xor_ptr = start_xor + brush_x / 2;
656
657             for(x = rc->left, ptr = start; x < rc->right; x++)
658             {
659                 /* FIXME: Two pixels at a time */
660                 if(x & 1) /* lower dst nibble */
661                 {
662                     if(brush_x & 1) /* lower pat nibble */
663                     {
664                         byte_and = *and_ptr++ | 0xf0;
665                         byte_xor = *xor_ptr++ & 0x0f;
666                     }
667                     else /* upper pat nibble */
668                     {
669                         byte_and = (*and_ptr >> 4) | 0xf0;
670                         byte_xor = (*xor_ptr >> 4) & 0x0f;
671                     }
672                 }
673                 else /* upper dst nibble */
674                 {
675                     if(brush_x & 1) /* lower pat nibble */
676                     {
677                         byte_and = (*and_ptr++ << 4) | 0x0f;
678                         byte_xor = (*xor_ptr++ << 4) & 0xf0;
679                     }
680                     else /* upper pat nibble */
681                     {
682                         byte_and = *and_ptr | 0x0f;
683                         byte_xor = *xor_ptr & 0xf0;
684                     }
685                 }
686                 do_rop_8(ptr, byte_and, byte_xor);
687
688                 if(x & 1) ptr++;
689
690                 if(++brush_x == brush->width)
691                 {
692                     brush_x = 0;
693                     and_ptr = start_and;
694                     xor_ptr = start_xor;
695                 }
696             }
697
698             offset.y++;
699             if(offset.y == brush->height)
700             {
701                 start_and = and_bits;
702                 start_xor = xor_bits;
703                 offset.y = 0;
704             }
705             else
706             {
707                 start_and += brush->stride;
708                 start_xor += brush->stride;
709             }
710         }
711     }
712 }
713
714 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
715                             const dib_info *brush, void *and_bits, void *xor_bits)
716 {
717     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
718     int x, y, i;
719     POINT offset;
720
721     for(i = 0; i < num; i++, rc++)
722     {
723         offset = calc_brush_offset(rc, brush, origin);
724
725         start = get_pixel_ptr_1(dib, rc->left, rc->top);
726         start_and = (BYTE*)and_bits + offset.y * brush->stride;
727         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
728
729         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
730         {
731             INT brush_x = offset.x;
732             BYTE byte_and, byte_xor;
733
734             and_ptr = start_and + brush_x / 8;
735             xor_ptr = start_xor + brush_x / 8;
736
737             for(x = rc->left, ptr = start; x < rc->right; x++)
738             {
739                 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
740                 byte_and |= ~pixel_masks_1[x % 8];
741                 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
742                 byte_xor &= pixel_masks_1[x % 8];
743
744                 do_rop_8(ptr, byte_and, byte_xor);
745
746                 if((x & 7) == 7) ptr++;
747
748                 if((brush_x & 7) == 7)
749                 {
750                     and_ptr++;
751                     xor_ptr++;
752                 }
753
754                 if(++brush_x == brush->width)
755                 {
756                     brush_x = 0;
757                     and_ptr = start_and;
758                     xor_ptr = start_xor;
759                 }
760             }
761
762             offset.y++;
763             if(offset.y == brush->height)
764             {
765                 start_and = and_bits;
766                 start_xor = xor_bits;
767                 offset.y = 0;
768             }
769             else
770             {
771                 start_and += brush->stride;
772                 start_xor += brush->stride;
773             }
774         }
775     }
776 }
777
778 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
779                                const dib_info *brush, void *and_bits, void *xor_bits)
780 {
781     return;
782 }
783
784 static void copy_rect_32(const dib_info *dst, const RECT *rc,
785                          const dib_info *src, const POINT *origin, int rop2, int overlap)
786 {
787     DWORD *dst_start, *src_start;
788     DWORD and = 0, xor = 0;
789     struct rop_codes codes;
790     int y, dst_stride, src_stride;
791
792     switch (rop2)
793     {
794     case R2_NOP:   return;
795     case R2_NOT:   and = ~0u;
796         /* fall through */
797     case R2_WHITE: xor = ~0u;
798         /* fall through */
799     case R2_BLACK:
800         dst->funcs->solid_rects( dst, 1, rc, and, xor );
801         return;
802     }
803
804     if (overlap & OVERLAP_BELOW)
805     {
806         dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
807         src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
808         dst_stride = -dst->stride / 4;
809         src_stride = -src->stride / 4;
810     }
811     else
812     {
813         dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
814         src_start = get_pixel_ptr_32(src, origin->x, origin->y);
815         dst_stride = dst->stride / 4;
816         src_stride = src->stride / 4;
817     }
818
819     if (rop2 == R2_COPYPEN)
820     {
821         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
822             memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
823         return;
824     }
825
826     get_rop_codes( rop2, &codes );
827     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
828     {
829         if (overlap & OVERLAP_RIGHT)
830             do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
831         else
832             do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
833     }
834 }
835
836 static void copy_rect_24(const dib_info *dst, const RECT *rc,
837                          const dib_info *src, const POINT *origin, int rop2, int overlap)
838 {
839     BYTE *dst_start, *src_start;
840     DWORD and = 0, xor = 0;
841     int y, dst_stride, src_stride;
842     struct rop_codes codes;
843
844     switch (rop2)
845     {
846     case R2_NOP:   return;
847     case R2_NOT:   and = ~0u;
848         /* fall through */
849     case R2_WHITE: xor = ~0u;
850         /* fall through */
851     case R2_BLACK:
852         dst->funcs->solid_rects( dst, 1, rc, and, xor );
853         return;
854     }
855
856     if (overlap & OVERLAP_BELOW)
857     {
858         dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
859         src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
860         dst_stride = -dst->stride;
861         src_stride = -src->stride;
862     }
863     else
864     {
865         dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
866         src_start = get_pixel_ptr_24(src, origin->x, origin->y);
867         dst_stride = dst->stride;
868         src_stride = src->stride;
869     }
870
871     if (rop2 == R2_COPYPEN)
872     {
873         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
874             memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
875         return;
876     }
877
878     get_rop_codes( rop2, &codes );
879     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
880     {
881         if (overlap & OVERLAP_RIGHT)
882             do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
883         else
884             do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
885     }
886 }
887
888 static void copy_rect_16(const dib_info *dst, const RECT *rc,
889                          const dib_info *src, const POINT *origin, int rop2, int overlap)
890 {
891     WORD *dst_start, *src_start;
892     DWORD and = 0, xor = 0;
893     int y, dst_stride, src_stride;
894     struct rop_codes codes;
895
896     switch (rop2)
897     {
898     case R2_NOP:   return;
899     case R2_NOT:   and = ~0u;
900         /* fall through */
901     case R2_WHITE: xor = ~0u;
902         /* fall through */
903     case R2_BLACK:
904         dst->funcs->solid_rects( dst, 1, rc, and, xor );
905         return;
906     }
907
908     if (overlap & OVERLAP_BELOW)
909     {
910         dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
911         src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
912         dst_stride = -dst->stride / 2;
913         src_stride = -src->stride / 2;
914     }
915     else
916     {
917         dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
918         src_start = get_pixel_ptr_16(src, origin->x, origin->y);
919         dst_stride = dst->stride / 2;
920         src_stride = src->stride / 2;
921     }
922
923     if (rop2 == R2_COPYPEN)
924     {
925         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
926             memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
927         return;
928     }
929
930     get_rop_codes( rop2, &codes );
931     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
932     {
933         if (overlap & OVERLAP_RIGHT)
934             do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
935         else
936             do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
937     }
938 }
939
940 static void copy_rect_8(const dib_info *dst, const RECT *rc,
941                         const dib_info *src, const POINT *origin, int rop2, int overlap)
942 {
943     BYTE *dst_start, *src_start;
944     DWORD and = 0, xor = 0;
945     int y, dst_stride, src_stride;
946     struct rop_codes codes;
947
948     switch (rop2)
949     {
950     case R2_NOP:   return;
951     case R2_NOT:   and = ~0u;
952         /* fall through */
953     case R2_WHITE: xor = ~0u;
954         /* fall through */
955     case R2_BLACK:
956         dst->funcs->solid_rects( dst, 1, rc, and, xor );
957         return;
958     }
959
960     if (overlap & OVERLAP_BELOW)
961     {
962         dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
963         src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
964         dst_stride = -dst->stride;
965         src_stride = -src->stride;
966     }
967     else
968     {
969         dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
970         src_start = get_pixel_ptr_8(src, origin->x, origin->y);
971         dst_stride = dst->stride;
972         src_stride = src->stride;
973     }
974
975     if (rop2 == R2_COPYPEN)
976     {
977         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
978             memmove( dst_start, src_start, (rc->right - rc->left) );
979         return;
980     }
981
982     get_rop_codes( rop2, &codes );
983     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
984     {
985         if (overlap & OVERLAP_RIGHT)
986             do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
987         else
988             do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
989     }
990 }
991
992 static void copy_rect_4(const dib_info *dst, const RECT *rc,
993                         const dib_info *src, const POINT *origin, int rop2, int overlap)
994 {
995     BYTE *dst_start, *src_start;
996     DWORD and = 0, xor = 0;
997     int y, dst_stride, src_stride;
998     struct rop_codes codes;
999
1000     switch (rop2)
1001     {
1002     case R2_NOP:   return;
1003     case R2_NOT:   and = ~0u;
1004         /* fall through */
1005     case R2_WHITE: xor = ~0u;
1006         /* fall through */
1007     case R2_BLACK:
1008         dst->funcs->solid_rects( dst, 1, rc, and, xor );
1009         return;
1010     }
1011
1012     if (overlap & OVERLAP_BELOW)
1013     {
1014         dst_start = get_pixel_ptr_4(dst, 0, rc->bottom - 1);
1015         src_start = get_pixel_ptr_4(src, 0, origin->y + rc->bottom - rc->top - 1);
1016         dst_stride = -dst->stride;
1017         src_stride = -src->stride;
1018     }
1019     else
1020     {
1021         dst_start = get_pixel_ptr_4(dst, 0, rc->top);
1022         src_start = get_pixel_ptr_4(src, 0, origin->y);
1023         dst_stride = dst->stride;
1024         src_stride = src->stride;
1025     }
1026
1027     if (rop2 == R2_COPYPEN && (rc->left & 1) == 0 && (origin->x & 1) == 0 && (rc->right & 1) == 0)
1028     {
1029         dst_start += rc->left / 2;
1030         src_start += origin->x / 2;
1031         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1032             memmove( dst_start, src_start, (rc->right - rc->left) / 2 );
1033         return;
1034     }
1035
1036     get_rop_codes( rop2, &codes );
1037     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1038     {
1039         if (overlap & OVERLAP_RIGHT)
1040             do_rop_codes_line_rev_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1041         else
1042             do_rop_codes_line_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1043     }
1044 }
1045
1046 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1047                         const dib_info *src, const POINT *origin, int rop2, int overlap)
1048 {
1049     BYTE *dst_start, *src_start;
1050     DWORD and = 0, xor = 0;
1051     int y, dst_stride, src_stride;
1052     struct rop_codes codes;
1053
1054     switch (rop2)
1055     {
1056     case R2_NOP:   return;
1057     case R2_NOT:   and = ~0u;
1058         /* fall through */
1059     case R2_WHITE: xor = ~0u;
1060         /* fall through */
1061     case R2_BLACK:
1062         dst->funcs->solid_rects( dst, 1, rc, and, xor );
1063         return;
1064     }
1065
1066     if (overlap & OVERLAP_BELOW)
1067     {
1068         dst_start = get_pixel_ptr_1(dst, 0, rc->bottom - 1);
1069         src_start = get_pixel_ptr_1(src, 0, origin->y + rc->bottom - rc->top - 1);
1070         dst_stride = -dst->stride;
1071         src_stride = -src->stride;
1072     }
1073     else
1074     {
1075         dst_start = get_pixel_ptr_1(dst, 0, rc->top);
1076         src_start = get_pixel_ptr_1(src, 0, origin->y);
1077         dst_stride = dst->stride;
1078         src_stride = src->stride;
1079     }
1080
1081     if (rop2 == R2_COPYPEN && (rc->left & 7) == 0 && (origin->x & 7) == 0 && (rc->right & 7) == 0)
1082     {
1083         dst_start += rc->left / 8;
1084         src_start += origin->x / 8;
1085         for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1086             memmove( dst_start, src_start, (rc->right - rc->left) / 8 );
1087         return;
1088     }
1089
1090     get_rop_codes( rop2, &codes );
1091     for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1092     {
1093         if (overlap & OVERLAP_RIGHT)
1094             do_rop_codes_line_rev_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1095         else
1096             do_rop_codes_line_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1097     }
1098 }
1099
1100 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1101                            const dib_info *src, const POINT *origin, int rop2, int overlap)
1102 {
1103     return;
1104 }
1105
1106 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1107 {
1108     return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1109 }
1110
1111 static inline DWORD put_field(DWORD field, int shift, int len)
1112 {
1113     shift = shift - (8 - len);
1114     if (len <= 8)
1115         field &= (((1 << len) - 1) << (8 - len));
1116     if (shift < 0)
1117         field >>= -shift;
1118     else
1119         field <<= shift;
1120     return field;
1121 }
1122
1123 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1124 {
1125     DWORD r,g,b;
1126
1127     r = GetRValue(colour);
1128     g = GetGValue(colour);
1129     b = GetBValue(colour);
1130
1131     return put_field(r, dib->red_shift,   dib->red_len) |
1132            put_field(g, dib->green_shift, dib->green_len) |
1133            put_field(b, dib->blue_shift,  dib->blue_len);
1134 }
1135
1136 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1137 {
1138     return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1139 }
1140
1141 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1142 {
1143     int i, best_index = 0;
1144     RGBQUAD rgb;
1145     DWORD diff, best_diff = 0xffffffff;
1146
1147     rgb.rgbRed = GetRValue(color);
1148     rgb.rgbGreen = GetGValue(color);
1149     rgb.rgbBlue = GetBValue(color);
1150
1151     /* special case for conversion to 1-bpp without a color table:
1152      * we get a 1-entry table containing the background color
1153      */
1154     if (dib->bit_count == 1 && dib->color_table_size == 1)
1155         return (rgb.rgbRed == dib->color_table[0].rgbRed &&
1156                 rgb.rgbGreen == dib->color_table[0].rgbGreen &&
1157                 rgb.rgbBlue == dib->color_table[0].rgbBlue);
1158
1159     for(i = 0; i < dib->color_table_size; i++)
1160     {
1161         RGBQUAD *cur = dib->color_table + i;
1162         diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
1163             +  (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
1164             +  (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
1165
1166         if(diff == 0)
1167         {
1168             best_index = i;
1169             break;
1170         }
1171
1172         if(diff < best_diff)
1173         {
1174             best_diff = diff;
1175             best_index = i;
1176         }
1177     }
1178     return best_index;
1179 }
1180
1181 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1182 {
1183     return 0;
1184 }
1185
1186 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1187 {
1188     assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1189
1190     return d1->red_mask   == d2->red_mask &&
1191            d1->green_mask == d2->green_mask &&
1192            d1->blue_mask  == d2->blue_mask;
1193 }
1194
1195 static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1196 {
1197     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1198     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1199
1200     switch(src->bit_count)
1201     {
1202     case 32:
1203     {
1204         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1205         if(src->funcs == &funcs_8888)
1206         {
1207             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1208                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1209             else
1210             {
1211                 for(y = src_rect->top; y < src_rect->bottom; y++)
1212                 {
1213                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1214                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1215                     dst_start += dst->stride / 4;
1216                     src_start += src->stride / 4;
1217                 }
1218             }
1219         }
1220         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1221         {
1222             for(y = src_rect->top; y < src_rect->bottom; y++)
1223             {
1224                 dst_pixel = dst_start;
1225                 src_pixel = src_start;
1226                 for(x = src_rect->left; x < src_rect->right; x++)
1227                 {
1228                     src_val = *src_pixel++;
1229                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << 16) |
1230                                    (((src_val >> src->green_shift) & 0xff) <<  8) |
1231                                     ((src_val >> src->blue_shift)  & 0xff);
1232                 }
1233                 if(pad_size) memset(dst_pixel, 0, pad_size);
1234                 dst_start += dst->stride / 4;
1235                 src_start += src->stride / 4;
1236             }
1237         }
1238         else
1239         {
1240             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
1241             return FALSE;
1242         }
1243         break;
1244     }
1245
1246     case 24:
1247     {
1248         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1249
1250         for(y = src_rect->top; y < src_rect->bottom; y++)
1251         {
1252             dst_pixel = dst_start;
1253             src_pixel = src_start;
1254             for(x = src_rect->left; x < src_rect->right; x++)
1255             {
1256                 RGBQUAD rgb;
1257                 rgb.rgbBlue  = *src_pixel++;
1258                 rgb.rgbGreen = *src_pixel++;
1259                 rgb.rgbRed   = *src_pixel++;
1260
1261                 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1262             }
1263             if(pad_size) memset(dst_pixel, 0, pad_size);
1264             dst_start += dst->stride / 4;
1265             src_start += src->stride;
1266         }
1267         break;
1268     }
1269
1270     case 16:
1271     {
1272         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1273         if(src->funcs == &funcs_555)
1274         {
1275             for(y = src_rect->top; y < src_rect->bottom; y++)
1276             {
1277                 dst_pixel = dst_start;
1278                 src_pixel = src_start;
1279                 for(x = src_rect->left; x < src_rect->right; x++)
1280                 {
1281                     src_val = *src_pixel++;
1282                     *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1283                                    ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1284                                    ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1285                 }
1286                 if(pad_size) memset(dst_pixel, 0, pad_size);
1287                 dst_start += dst->stride / 4;
1288                 src_start += src->stride / 2;
1289             }
1290         }
1291         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1292         {
1293             for(y = src_rect->top; y < src_rect->bottom; y++)
1294             {
1295                 dst_pixel = dst_start;
1296                 src_pixel = src_start;
1297                 for(x = src_rect->left; x < src_rect->right; x++)
1298                 {
1299                     src_val = *src_pixel++;
1300                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1301                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1302                                    (((src_val >> src->green_shift) << 11) & 0x00f800) |
1303                                    (((src_val >> src->green_shift) <<  6) & 0x000700) |
1304                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1305                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1306                 }
1307                 if(pad_size) memset(dst_pixel, 0, pad_size);
1308                 dst_start += dst->stride / 4;
1309                 src_start += src->stride / 2;
1310             }
1311         }
1312         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1313         {
1314             for(y = src_rect->top; y < src_rect->bottom; y++)
1315             {
1316                 dst_pixel = dst_start;
1317                 src_pixel = src_start;
1318                 for(x = src_rect->left; x < src_rect->right; x++)
1319                 {
1320                     src_val = *src_pixel++;
1321                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1322                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1323                                    (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1324                                    (((src_val >> src->green_shift) <<  4) & 0x000300) |
1325                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1326                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1327                 }
1328                 if(pad_size) memset(dst_pixel, 0, pad_size);
1329                 dst_start += dst->stride / 4;
1330                 src_start += src->stride / 2;
1331             }
1332         }
1333         else
1334         {
1335             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
1336             return FALSE;
1337         }
1338         break;
1339     }
1340
1341     case 8:
1342     {
1343         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1344         for(y = src_rect->top; y < src_rect->bottom; y++)
1345         {
1346             dst_pixel = dst_start;
1347             src_pixel = src_start;
1348             for(x = src_rect->left; x < src_rect->right; x++)
1349             {
1350                 RGBQUAD rgb;
1351                 src_val = *src_pixel++;
1352                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1353                 rgb = src->color_table[src_val];
1354                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1355             }
1356             if(pad_size) memset(dst_pixel, 0, pad_size);
1357             dst_start += dst->stride / 4;
1358             src_start += src->stride;
1359         }
1360         break;
1361     }
1362
1363     case 4:
1364     {
1365         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1366         for(y = src_rect->top; y < src_rect->bottom; y++)
1367         {
1368             dst_pixel = dst_start;
1369             src_pixel = src_start;
1370             for(x = src_rect->left; x < src_rect->right; x++)
1371             {
1372                 RGBQUAD rgb;
1373                 if(x & 1)
1374                     src_val = *src_pixel++ & 0xf;
1375                 else
1376                     src_val = (*src_pixel >> 4) & 0xf;
1377                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1378                 rgb = src->color_table[src_val];
1379                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1380             }
1381             if(pad_size) memset(dst_pixel, 0, pad_size);
1382             dst_start += dst->stride / 4;
1383             src_start += src->stride;
1384         }
1385         break;
1386     }
1387
1388     case 1:
1389     {
1390         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1391         for(y = src_rect->top; y < src_rect->bottom; y++)
1392         {
1393             dst_pixel = dst_start;
1394             src_pixel = src_start;
1395             for(x = src_rect->left; x < src_rect->right; x++)
1396             {
1397                 RGBQUAD rgb;
1398                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1399                 if((x % 8) == 7) src_pixel++;
1400                 rgb = src->color_table[src_val];
1401                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1402             }
1403             if(pad_size) memset(dst_pixel, 0, pad_size);
1404             dst_start += dst->stride / 4;
1405             src_start += src->stride;
1406         }
1407         break;
1408     }
1409
1410     default:
1411         FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
1412         return FALSE;
1413     }
1414
1415     return TRUE;
1416 }
1417
1418 static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1419 {
1420     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1421     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1422
1423     switch(src->bit_count)
1424     {
1425     case 32:
1426     {
1427         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1428
1429         if(src->funcs == &funcs_8888)
1430         {
1431             for(y = src_rect->top; y < src_rect->bottom; y++)
1432             {
1433                 dst_pixel = dst_start;
1434                 src_pixel = src_start;
1435                 for(x = src_rect->left; x < src_rect->right; x++)
1436                 {
1437                     src_val = *src_pixel++;
1438                     *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift,   dst->red_len)   |
1439                                    put_field((src_val >>  8) & 0xff, dst->green_shift, dst->green_len) |
1440                                    put_field( src_val        & 0xff, dst->blue_shift,  dst->blue_len);
1441                 }
1442                 if(pad_size) memset(dst_pixel, 0, pad_size);
1443                 dst_start += dst->stride / 4;
1444                 src_start += src->stride / 4;
1445             }
1446         }
1447         else if(bit_fields_match(src, dst))
1448         {
1449             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1450                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1451             else
1452             {
1453                 for(y = src_rect->top; y < src_rect->bottom; y++)
1454                 {
1455                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1456                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1457                     dst_start += dst->stride / 4;
1458                     src_start += src->stride / 4;
1459                 }
1460             }
1461         }
1462         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1463                 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1464         {
1465             for(y = src_rect->top; y < src_rect->bottom; y++)
1466             {
1467                 dst_pixel = dst_start;
1468                 src_pixel = src_start;
1469                 for(x = src_rect->left; x < src_rect->right; x++)
1470                 {
1471                     src_val = *src_pixel++;
1472                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << dst->red_shift)   |
1473                                    (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1474                                    (((src_val >> src->blue_shift)  & 0xff) << dst->blue_shift);
1475                 }
1476                 if(pad_size) memset(dst_pixel, 0, pad_size);
1477                 dst_start += dst->stride / 4;
1478                 src_start += src->stride / 4;
1479             }
1480         }
1481         else
1482         {
1483             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 32 (%08x, %08x, %08x)\n",
1484                   src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask);
1485             return FALSE;
1486         }
1487         break;
1488     }
1489
1490     case 24:
1491     {
1492         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1493
1494         for(y = src_rect->top; y < src_rect->bottom; y++)
1495         {
1496             dst_pixel = dst_start;
1497             src_pixel = src_start;
1498             for(x = src_rect->left; x < src_rect->right; x++)
1499             {
1500                 RGBQUAD rgb;
1501                 rgb.rgbBlue  = *src_pixel++;
1502                 rgb.rgbGreen = *src_pixel++;
1503                 rgb.rgbRed   = *src_pixel++;
1504
1505                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len)   |
1506                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1507                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1508             }
1509             if(pad_size) memset(dst_pixel, 0, pad_size);
1510             dst_start += dst->stride / 4;
1511             src_start += src->stride;
1512         }
1513         break;
1514     }
1515
1516     case 16:
1517     {
1518         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1519         if(src->funcs == &funcs_555)
1520         {
1521             for(y = src_rect->top; y < src_rect->bottom; y++)
1522             {
1523                 dst_pixel = dst_start;
1524                 src_pixel = src_start;
1525                 for(x = src_rect->left; x < src_rect->right; x++)
1526                 {
1527                     src_val = *src_pixel++;
1528                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
1529                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
1530                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
1531                 }
1532                 if(pad_size) memset(dst_pixel, 0, pad_size);
1533                 dst_start += dst->stride / 4;
1534                 src_start += src->stride / 2;
1535             }
1536         }
1537         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1538         {
1539             for(y = src_rect->top; y < src_rect->bottom; y++)
1540             {
1541                 dst_pixel = dst_start;
1542                 src_pixel = src_start;
1543                 for(x = src_rect->left; x < src_rect->right; x++)
1544                 {
1545                     src_val = *src_pixel++;
1546                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1547                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1548                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1549                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1550                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1551                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1552                 }
1553                 if(pad_size) memset(dst_pixel, 0, pad_size);
1554                 dst_start += dst->stride / 4;
1555                 src_start += src->stride / 2;
1556             }
1557         }
1558         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1559         {
1560             for(y = src_rect->top; y < src_rect->bottom; y++)
1561             {
1562                 dst_pixel = dst_start;
1563                 src_pixel = src_start;
1564                 for(x = src_rect->left; x < src_rect->right; x++)
1565                 {
1566                     src_val = *src_pixel++;
1567                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1568                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1569                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1570                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1571                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1572                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1573                 }
1574                 if(pad_size) memset(dst_pixel, 0, pad_size);
1575                 dst_start += dst->stride / 4;
1576                 src_start += src->stride / 2;
1577             }
1578         }
1579         else
1580         {
1581             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 32\n", src->red_mask, src->green_mask, src->blue_mask);
1582             return FALSE;
1583         }
1584         break;
1585     }
1586
1587     case 8:
1588     {
1589         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1590         for(y = src_rect->top; y < src_rect->bottom; y++)
1591         {
1592             dst_pixel = dst_start;
1593             src_pixel = src_start;
1594             for(x = src_rect->left; x < src_rect->right; x++)
1595             {
1596                 RGBQUAD rgb;
1597                 src_val = *src_pixel++;
1598                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1599                 rgb = src->color_table[src_val];
1600                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1601                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1602                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1603             }
1604             if(pad_size) memset(dst_pixel, 0, pad_size);
1605             dst_start += dst->stride / 4;
1606             src_start += src->stride;
1607         }
1608         break;
1609     }
1610
1611     case 4:
1612     {
1613         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1614         for(y = src_rect->top; y < src_rect->bottom; y++)
1615         {
1616             dst_pixel = dst_start;
1617             src_pixel = src_start;
1618             for(x = src_rect->left; x < src_rect->right; x++)
1619             {
1620                 RGBQUAD rgb;
1621                 if(x & 1)
1622                     src_val = *src_pixel++ & 0xf;
1623                 else
1624                     src_val = (*src_pixel >> 4) & 0xf;
1625                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1626                 rgb = src->color_table[src_val];
1627                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1628                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1629                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1630             }
1631             if(pad_size) memset(dst_pixel, 0, pad_size);
1632             dst_start += dst->stride / 4;
1633             src_start += src->stride;
1634         }
1635         break;
1636     }
1637
1638     case 1:
1639     {
1640         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1641         for(y = src_rect->top; y < src_rect->bottom; y++)
1642         {
1643             dst_pixel = dst_start;
1644             src_pixel = src_start;
1645             for(x = src_rect->left; x < src_rect->right; x++)
1646             {
1647                 RGBQUAD rgb;
1648                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1649                 if((x % 8) == 7) src_pixel++;
1650                 rgb = src->color_table[src_val];
1651                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1652                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1653                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1654             }
1655             if(pad_size) memset(dst_pixel, 0, pad_size);
1656             dst_start += dst->stride / 4;
1657             src_start += src->stride;
1658         }
1659         break;
1660     }
1661
1662     default:
1663         FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
1664         return FALSE;
1665     }
1666
1667     return TRUE;
1668 }
1669
1670 static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1671 {
1672     BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1673     DWORD src_val;
1674     int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1675
1676     switch(src->bit_count)
1677     {
1678     case 32:
1679     {
1680         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1681         if(src->funcs == &funcs_8888)
1682         {
1683             for(y = src_rect->top; y < src_rect->bottom; y++)
1684             {
1685                 dst_pixel = dst_start;
1686                 src_pixel = src_start;
1687                 for(x = src_rect->left; x < src_rect->right; x++)
1688                 {
1689                     src_val = *src_pixel++;
1690                     *dst_pixel++ =  src_val        & 0xff;
1691                     *dst_pixel++ = (src_val >>  8) & 0xff;
1692                     *dst_pixel++ = (src_val >> 16) & 0xff;
1693                 }
1694                 if(pad_size) memset(dst_pixel, 0, pad_size);
1695                 dst_start += dst->stride;
1696                 src_start += src->stride / 4;
1697             }
1698         }
1699         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1700         {
1701             for(y = src_rect->top; y < src_rect->bottom; y++)
1702             {
1703                 dst_pixel = dst_start;
1704                 src_pixel = src_start;
1705                 for(x = src_rect->left; x < src_rect->right; x++)
1706                 {
1707                     src_val = *src_pixel++;
1708                     *dst_pixel++ = (src_val >> src->blue_shift)  & 0xff;
1709                     *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1710                     *dst_pixel++ = (src_val >> src->red_shift)   & 0xff;
1711                 }
1712                 if(pad_size) memset(dst_pixel, 0, pad_size);
1713                 dst_start += dst->stride;
1714                 src_start += src->stride / 4;
1715             }
1716         }
1717         else
1718         {
1719             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask);
1720             return FALSE;
1721         }
1722         break;
1723     }
1724
1725     case 24:
1726     {
1727         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1728
1729         if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1730             memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1731         else
1732         {
1733             for(y = src_rect->top; y < src_rect->bottom; y++)
1734             {
1735                 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1736                 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1737                 dst_start += dst->stride;
1738                 src_start += src->stride;
1739             }
1740         }
1741         break;
1742     }
1743
1744     case 16:
1745     {
1746         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1747         if(src->funcs == &funcs_555)
1748         {
1749             for(y = src_rect->top; y < src_rect->bottom; y++)
1750             {
1751                 dst_pixel = dst_start;
1752                 src_pixel = src_start;
1753                 for(x = src_rect->left; x < src_rect->right; x++)
1754                 {
1755                     src_val = *src_pixel++;
1756                     *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07);
1757                     *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07);
1758                     *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1759                 }
1760                 if(pad_size) memset(dst_pixel, 0, pad_size);
1761                 dst_start += dst->stride;
1762                 src_start += src->stride / 2;
1763             }
1764         }
1765         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
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                     src_val = *src_pixel++;
1774                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1775                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
1776                     *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1777                                    (((src_val >> src->green_shift) >> 2) & 0x07);
1778                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
1779                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
1780                 }
1781                 if(pad_size) memset(dst_pixel, 0, pad_size);
1782                 dst_start += dst->stride;
1783                 src_start += src->stride / 2;
1784             }
1785         }
1786         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1787         {
1788             for(y = src_rect->top; y < src_rect->bottom; y++)
1789             {
1790                 dst_pixel = dst_start;
1791                 src_pixel = src_start;
1792                 for(x = src_rect->left; x < src_rect->right; x++)
1793                 {
1794                     src_val = *src_pixel++;
1795                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1796                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
1797                     *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1798                                    (((src_val >> src->green_shift) >> 4) & 0x03);
1799                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
1800                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
1801                 }
1802                 if(pad_size) memset(dst_pixel, 0, pad_size);
1803                 dst_start += dst->stride;
1804                 src_start += src->stride / 2;
1805             }
1806         }
1807         else
1808         {
1809             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask);
1810             return FALSE;
1811         }
1812         break;
1813     }
1814
1815     case 8:
1816     {
1817         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1818         for(y = src_rect->top; y < src_rect->bottom; y++)
1819         {
1820             dst_pixel = dst_start;
1821             src_pixel = src_start;
1822             for(x = src_rect->left; x < src_rect->right; x++)
1823             {
1824                 RGBQUAD rgb;
1825                 src_val = *src_pixel++;
1826                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1827                 rgb = src->color_table[src_val];
1828                 *dst_pixel++ = rgb.rgbBlue;
1829                 *dst_pixel++ = rgb.rgbGreen;
1830                 *dst_pixel++ = rgb.rgbRed;
1831             }
1832             if(pad_size) memset(dst_pixel, 0, pad_size);
1833             dst_start += dst->stride;
1834             src_start += src->stride;
1835         }
1836         break;
1837     }
1838
1839     case 4:
1840     {
1841         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1842         for(y = src_rect->top; y < src_rect->bottom; y++)
1843         {
1844             dst_pixel = dst_start;
1845             src_pixel = src_start;
1846             for(x = src_rect->left; x < src_rect->right; x++)
1847             {
1848                 RGBQUAD rgb;
1849                 if(x & 1)
1850                     src_val = *src_pixel++ & 0xf;
1851                 else
1852                     src_val = (*src_pixel >> 4) & 0xf;
1853                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1854                 rgb = src->color_table[src_val];
1855                 *dst_pixel++ = rgb.rgbBlue;
1856                 *dst_pixel++ = rgb.rgbGreen;
1857                 *dst_pixel++ = rgb.rgbRed;
1858             }
1859             if(pad_size) memset(dst_pixel, 0, pad_size);
1860             dst_start += dst->stride;
1861             src_start += src->stride;
1862         }
1863         break;
1864     }
1865
1866     case 1:
1867     {
1868         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1869         for(y = src_rect->top; y < src_rect->bottom; y++)
1870         {
1871             dst_pixel = dst_start;
1872             src_pixel = src_start;
1873             for(x = src_rect->left; x < src_rect->right; x++)
1874             {
1875                 RGBQUAD rgb;
1876                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1877                 if((x % 8) == 7) src_pixel++;
1878                 rgb = src->color_table[src_val];
1879                 *dst_pixel++ = rgb.rgbBlue;
1880                 *dst_pixel++ = rgb.rgbGreen;
1881                 *dst_pixel++ = rgb.rgbRed;
1882             }
1883             if(pad_size) memset(dst_pixel, 0, pad_size);
1884             dst_start += dst->stride;
1885             src_start += src->stride;
1886         }
1887         break;
1888     }
1889
1890     default:
1891         FIXME("Unsupported conversion: %d -> 24\n", src->bit_count);
1892         return FALSE;
1893     }
1894
1895     return TRUE;
1896 }
1897
1898 static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1899 {
1900     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
1901     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1902     DWORD src_val;
1903
1904     switch(src->bit_count)
1905     {
1906     case 32:
1907     {
1908         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1909
1910         if(src->funcs == &funcs_8888)
1911         {
1912             for(y = src_rect->top; y < src_rect->bottom; y++)
1913             {
1914                 dst_pixel = dst_start;
1915                 src_pixel = src_start;
1916                 for(x = src_rect->left; x < src_rect->right; x++)
1917                 {
1918                     src_val = *src_pixel++;
1919                     *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1920                                    ((src_val >> 6) & 0x03e0) |
1921                                    ((src_val >> 3) & 0x001f);
1922                 }
1923                 if(pad_size) memset(dst_pixel, 0, pad_size);
1924                 dst_start += dst->stride / 2;
1925                 src_start += src->stride / 4;
1926             }
1927         }
1928         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1929         {
1930             for(y = src_rect->top; y < src_rect->bottom; y++)
1931             {
1932                 dst_pixel = dst_start;
1933                 src_pixel = src_start;
1934                 for(x = src_rect->left; x < src_rect->right; x++)
1935                 {
1936                     src_val = *src_pixel++;
1937                     *dst_pixel++ = (((src_val >> src->red_shift)   << 7) & 0x7c00) |
1938                                    (((src_val >> src->green_shift) << 2) & 0x03e0) |
1939                                    (((src_val >> src->blue_shift)  >> 3) & 0x001f);
1940                 }
1941                 if(pad_size) memset(dst_pixel, 0, pad_size);
1942                 dst_start += dst->stride / 2;
1943                 src_start += src->stride / 4;
1944             }
1945         }
1946         else
1947         {
1948             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask);
1949             return FALSE;
1950         }
1951         break;
1952     }
1953
1954     case 24:
1955     {
1956         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
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                 RGBQUAD rgb;
1965                 rgb.rgbBlue  = *src_pixel++;
1966                 rgb.rgbGreen = *src_pixel++;
1967                 rgb.rgbRed   = *src_pixel++;
1968
1969                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1970                                ((rgb.rgbGreen << 2) & 0x03e0) |
1971                                ((rgb.rgbBlue  >> 3) & 0x001f);
1972             }
1973             if(pad_size) memset(dst_pixel, 0, pad_size);
1974             dst_start += dst->stride / 2;
1975             src_start += src->stride;
1976         }
1977         break;
1978     }
1979
1980     case 16:
1981     {
1982         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1983         if(src->funcs == &funcs_555)
1984         {
1985             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1986                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1987             else
1988             {
1989                 for(y = src_rect->top; y < src_rect->bottom; y++)
1990                 {
1991                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1992                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1993                     dst_start += dst->stride / 2;
1994                     src_start += src->stride / 2;
1995                 }
1996             }
1997         }
1998         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1999         {
2000             for(y = src_rect->top; y < src_rect->bottom; y++)
2001             {
2002                 dst_pixel = dst_start;
2003                 src_pixel = src_start;
2004                 for(x = src_rect->left; x < src_rect->right; x++)
2005                 {
2006                     src_val = *src_pixel++;
2007                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2008                                    (((src_val >> src->green_shift) <<  5) & 0x03e0) |
2009                                    ( (src_val >> src->blue_shift)         & 0x001f);
2010                 }
2011                 if(pad_size) memset(dst_pixel, 0, pad_size);
2012                 dst_start += dst->stride / 2;
2013                 src_start += src->stride / 2;
2014             }
2015         }
2016         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2017         {
2018             for(y = src_rect->top; y < src_rect->bottom; y++)
2019             {
2020                 dst_pixel = dst_start;
2021                 src_pixel = src_start;
2022                 for(x = src_rect->left; x < src_rect->right; x++)
2023                 {
2024                     src_val = *src_pixel++;
2025                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2026                                    (((src_val >> src->green_shift) <<  4) & 0x03e0) |
2027                                    ( (src_val >> src->blue_shift)         & 0x001f);
2028                 }
2029                 if(pad_size) memset(dst_pixel, 0, pad_size);
2030                 dst_start += dst->stride / 2;
2031                 src_start += src->stride / 2;
2032             }
2033         }
2034         else
2035         {
2036             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask);
2037             return FALSE;
2038         }
2039         break;
2040     }
2041
2042     case 8:
2043     {
2044         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2045         for(y = src_rect->top; y < src_rect->bottom; y++)
2046         {
2047             dst_pixel = dst_start;
2048             src_pixel = src_start;
2049             for(x = src_rect->left; x < src_rect->right; x++)
2050             {
2051                 RGBQUAD rgb;
2052                 src_val = *src_pixel++;
2053                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2054                 rgb = src->color_table[src_val];
2055                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2056                                ((rgb.rgbGreen << 2) & 0x03e0) |
2057                                ((rgb.rgbBlue  >> 3) & 0x001f);
2058             }
2059             if(pad_size) memset(dst_pixel, 0, pad_size);
2060             dst_start += dst->stride / 2;
2061             src_start += src->stride;
2062         }
2063         break;
2064     }
2065
2066     case 4:
2067     {
2068         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2069         for(y = src_rect->top; y < src_rect->bottom; y++)
2070         {
2071             dst_pixel = dst_start;
2072             src_pixel = src_start;
2073             for(x = src_rect->left; x < src_rect->right; x++)
2074             {
2075                 RGBQUAD rgb;
2076                 if(x & 1)
2077                     src_val = *src_pixel++ & 0xf;
2078                 else
2079                     src_val = (*src_pixel >> 4) & 0xf;
2080                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2081                 rgb = src->color_table[src_val];
2082                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2083                                ((rgb.rgbGreen << 2) & 0x03e0) |
2084                                ((rgb.rgbBlue  >> 3) & 0x001f);
2085             }
2086             if(pad_size) memset(dst_pixel, 0, pad_size);
2087             dst_start += dst->stride / 2;
2088             src_start += src->stride;
2089         }
2090         break;
2091     }
2092
2093     case 1:
2094     {
2095         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2096         for(y = src_rect->top; y < src_rect->bottom; y++)
2097         {
2098             dst_pixel = dst_start;
2099             src_pixel = src_start;
2100             for(x = src_rect->left; x < src_rect->right; x++)
2101             {
2102                 RGBQUAD rgb;
2103                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2104                 if((x % 8) == 7) src_pixel++;
2105                 rgb = src->color_table[src_val];
2106                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2107                                ((rgb.rgbGreen << 2) & 0x03e0) |
2108                                ((rgb.rgbBlue  >> 3) & 0x001f);
2109             }
2110             if(pad_size) memset(dst_pixel, 0, pad_size);
2111             dst_start += dst->stride / 2;
2112             src_start += src->stride;
2113         }
2114         break;
2115     }
2116
2117     default:
2118         FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
2119         return FALSE;
2120
2121     }
2122     return TRUE;
2123 }
2124
2125 static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2126 {
2127     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2128     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2129     DWORD src_val;
2130
2131     switch(src->bit_count)
2132     {
2133     case 32:
2134     {
2135         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2136
2137         if(src->funcs == &funcs_8888)
2138         {
2139             for(y = src_rect->top; y < src_rect->bottom; y++)
2140             {
2141                 dst_pixel = dst_start;
2142                 src_pixel = src_start;
2143                 for(x = src_rect->left; x < src_rect->right; x++)
2144                 {
2145                     src_val = *src_pixel++;
2146                     *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift,   dst->red_len)   |
2147                                    put_field((src_val >>  8) & 0xff, dst->green_shift, dst->green_len) |
2148                                    put_field( src_val        & 0xff, dst->blue_shift,  dst->blue_len);
2149                 }
2150                 if(pad_size) memset(dst_pixel, 0, pad_size);
2151                 dst_start += dst->stride / 2;
2152                 src_start += src->stride / 4;
2153             }
2154         }
2155         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2156         {
2157             for(y = src_rect->top; y < src_rect->bottom; y++)
2158             {
2159                 dst_pixel = dst_start;
2160                 src_pixel = src_start;
2161                 for(x = src_rect->left; x < src_rect->right; x++)
2162                 {
2163                     src_val = *src_pixel++;
2164                     *dst_pixel++ = put_field((src_val >> src->red_shift)   & 0xff, dst->red_shift,   dst->red_len)   |
2165                                    put_field((src_val >> src->green_shift) & 0xff, dst->green_shift, dst->green_len) |
2166                                    put_field((src_val >> src->blue_shift)  & 0xff, dst->blue_shift,  dst->blue_len);
2167                 }
2168                 if(pad_size) memset(dst_pixel, 0, pad_size);
2169                 dst_start += dst->stride / 2;
2170                 src_start += src->stride / 4;
2171             }
2172         }
2173         else
2174         {
2175             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 16\n", src->red_mask, src->green_mask, src->blue_mask);
2176             return FALSE;
2177         }
2178         break;
2179     }
2180
2181     case 24:
2182     {
2183         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2184
2185         for(y = src_rect->top; y < src_rect->bottom; y++)
2186         {
2187             dst_pixel = dst_start;
2188             src_pixel = src_start;
2189             for(x = src_rect->left; x < src_rect->right; x++)
2190             {
2191                 RGBQUAD rgb;
2192                 rgb.rgbBlue  = *src_pixel++;
2193                 rgb.rgbGreen = *src_pixel++;
2194                 rgb.rgbRed   = *src_pixel++;
2195
2196                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2197                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2198                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2199             }
2200             if(pad_size) memset(dst_pixel, 0, pad_size);
2201             dst_start += dst->stride / 2;
2202             src_start += src->stride;
2203         }
2204         break;
2205     }
2206
2207     case 16:
2208     {
2209         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2210         if(src->funcs == &funcs_555)
2211         {
2212             for(y = src_rect->top; y < src_rect->bottom; y++)
2213             {
2214                 dst_pixel = dst_start;
2215                 src_pixel = src_start;
2216                 for(x = src_rect->left; x < src_rect->right; x++)
2217                 {
2218                     src_val = *src_pixel++;
2219                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
2220                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
2221                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
2222                 }
2223                 if(pad_size) memset(dst_pixel, 0, pad_size);
2224                 dst_start += dst->stride / 2;
2225                 src_start += src->stride / 2;
2226             }
2227         }
2228         else if(bit_fields_match(src, dst))
2229         {
2230             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2231                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2232             else
2233             {
2234                 for(y = src_rect->top; y < src_rect->bottom; y++)
2235                 {
2236                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2237                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2238                     dst_start += dst->stride / 2;
2239                     src_start += src->stride / 2;
2240                 }
2241             }
2242         }
2243         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2244         {
2245             for(y = src_rect->top; y < src_rect->bottom; y++)
2246             {
2247                 dst_pixel = dst_start;
2248                 src_pixel = src_start;
2249                 for(x = src_rect->left; x < src_rect->right; x++)
2250                 {
2251                     src_val = *src_pixel++;
2252                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2253                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2254                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2255                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2256                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2257                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2258                 }
2259                 if(pad_size) memset(dst_pixel, 0, pad_size);
2260                 dst_start += dst->stride / 2;
2261                 src_start += src->stride / 2;
2262             }
2263         }
2264         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2265         {
2266             for(y = src_rect->top; y < src_rect->bottom; y++)
2267             {
2268                 dst_pixel = dst_start;
2269                 src_pixel = src_start;
2270                 for(x = src_rect->left; x < src_rect->right; x++)
2271                 {
2272                     src_val = *src_pixel++;
2273                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2274                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2275                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2276                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2277                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2278                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2279                 }
2280                 if(pad_size) memset(dst_pixel, 0, pad_size);
2281                 dst_start += dst->stride / 2;
2282                 src_start += src->stride / 2;
2283             }
2284         }
2285         else
2286         {
2287             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 16 (%08x, %08x, %08x)\n",
2288                   src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask);
2289             return FALSE;
2290         }
2291         break;
2292     }
2293
2294     case 8:
2295     {
2296         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2297         for(y = src_rect->top; y < src_rect->bottom; y++)
2298         {
2299             dst_pixel = dst_start;
2300             src_pixel = src_start;
2301             for(x = src_rect->left; x < src_rect->right; x++)
2302             {
2303                 RGBQUAD rgb;
2304                 src_val = *src_pixel++;
2305                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2306                 rgb = src->color_table[src_val];
2307                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2308                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2309                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2310             }
2311             if(pad_size) memset(dst_pixel, 0, pad_size);
2312             dst_start += dst->stride / 2;
2313             src_start += src->stride;
2314         }
2315         break;
2316     }
2317
2318     case 4:
2319     {
2320         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
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                 RGBQUAD rgb;
2328                 if(x & 1)
2329                     src_val = *src_pixel++ & 0xf;
2330                 else
2331                     src_val = (*src_pixel >> 4) & 0xf;
2332                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2333                 rgb = src->color_table[src_val];
2334                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2335                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2336                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2337             }
2338             if(pad_size) memset(dst_pixel, 0, pad_size);
2339             dst_start += dst->stride / 2;
2340             src_start += src->stride;
2341         }
2342         break;
2343     }
2344
2345     case 1:
2346     {
2347         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2348         for(y = src_rect->top; y < src_rect->bottom; y++)
2349         {
2350             dst_pixel = dst_start;
2351             src_pixel = src_start;
2352             for(x = src_rect->left; x < src_rect->right; x++)
2353             {
2354                 RGBQUAD rgb;
2355                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2356                 if((x % 8) == 7) src_pixel++;
2357                 rgb = src->color_table[src_val];
2358                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2359                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2360                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2361             }
2362             if(pad_size) memset(dst_pixel, 0, pad_size);
2363             dst_start += dst->stride / 2;
2364             src_start += src->stride;
2365         }
2366         break;
2367     }
2368
2369     default:
2370         FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
2371         return FALSE;
2372
2373     }
2374     return TRUE;
2375 }
2376
2377 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2378 {
2379     assert(d1->color_table_size && d2->color_table_size);
2380
2381     if(d1->color_table_size != d2->color_table_size) return FALSE;
2382     return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2383 }
2384
2385 static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2386 {
2387     BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2388     INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2389     DWORD src_val;
2390
2391     switch(src->bit_count)
2392     {
2393     case 32:
2394     {
2395         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2396
2397         if(src->funcs == &funcs_8888)
2398         {
2399             for(y = src_rect->top; y < src_rect->bottom; y++)
2400             {
2401                 dst_pixel = dst_start;
2402                 src_pixel = src_start;
2403                 for(x = src_rect->left; x < src_rect->right; x++)
2404                 {
2405                     src_val = *src_pixel++;
2406                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
2407                                                                      ( src_val        & 0x00ff00) |
2408                                                                      ((src_val << 16) & 0xff0000) );
2409                 }
2410                 if(pad_size) memset(dst_pixel, 0, pad_size);
2411                 dst_start += dst->stride;
2412                 src_start += src->stride / 4;
2413             }
2414         }
2415         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2416         {
2417             for(y = src_rect->top; y < src_rect->bottom; y++)
2418             {
2419                 dst_pixel = dst_start;
2420                 src_pixel = src_start;
2421                 for(x = src_rect->left; x < src_rect->right; x++)
2422                 {
2423                     src_val = *src_pixel++;
2424                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift)          & 0x0000ff) |
2425                                                                      (((src_val >> src->green_shift) <<  8) & 0x00ff00) |
2426                                                                      (((src_val >> src->blue_shift)  << 16) & 0xff0000) );
2427                 }
2428                 if(pad_size) memset(dst_pixel, 0, pad_size);
2429                 dst_start += dst->stride;
2430                 src_start += src->stride / 4;
2431             }
2432         }
2433         else
2434         {
2435             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask);
2436             return FALSE;
2437         }
2438         break;
2439     }
2440
2441     case 24:
2442     {
2443         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2444
2445         for(y = src_rect->top; y < src_rect->bottom; y++)
2446         {
2447             dst_pixel = dst_start;
2448             src_pixel = src_start;
2449             for(x = src_rect->left; x < src_rect->right; x++)
2450             {
2451                 RGBQUAD rgb;
2452                 rgb.rgbBlue  = *src_pixel++;
2453                 rgb.rgbGreen = *src_pixel++;
2454                 rgb.rgbRed   = *src_pixel++;
2455
2456                 *dst_pixel++ = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
2457                                                                  ((rgb.rgbGreen << 8) & 0x00ff00) |
2458                                                                  ((rgb.rgbBlue << 16) & 0xff0000));
2459             }
2460             if(pad_size) memset(dst_pixel, 0, pad_size);
2461             dst_start += dst->stride;
2462             src_start += src->stride;
2463         }
2464         break;
2465     }
2466
2467     case 16:
2468     {
2469         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2470         if(src->funcs == &funcs_555)
2471         {
2472             for(y = src_rect->top; y < src_rect->bottom; y++)
2473             {
2474                 dst_pixel = dst_start;
2475                 src_pixel = src_start;
2476                 for(x = src_rect->left; x < src_rect->right; x++)
2477                 {
2478                     src_val = *src_pixel++;
2479                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2480                                                                      ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
2481                                                                      ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
2482                 }
2483                 if(pad_size) memset(dst_pixel, 0, pad_size);
2484                 dst_start += dst->stride;
2485                 src_start += src->stride / 2;
2486             }
2487         }
2488         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2489         {
2490             for(y = src_rect->top; y < src_rect->bottom; y++)
2491             {
2492                 dst_pixel = dst_start;
2493                 src_pixel = src_start;
2494                 for(x = src_rect->left; x < src_rect->right; x++)
2495                 {
2496                     src_val = *src_pixel++;
2497                     *dst_pixel++ = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2498                                                                      (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2499                                                                      (((src_val >> src->green_shift) << 11) & 0x00f800) |
2500                                                                      (((src_val >> src->green_shift) <<  6) & 0x000700) |
2501                                                                      (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2502                                                                      (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2503                 }
2504                 if(pad_size) memset(dst_pixel, 0, pad_size);
2505                 dst_start += dst->stride;
2506                 src_start += src->stride / 2;
2507             }
2508         }
2509         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2510         {
2511             for(y = src_rect->top; y < src_rect->bottom; y++)
2512             {
2513                 dst_pixel = dst_start;
2514                 src_pixel = src_start;
2515                 for(x = src_rect->left; x < src_rect->right; x++)
2516                 {
2517                     src_val = *src_pixel++;
2518                     *dst_pixel++ = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2519                                                                      (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2520                                                                      (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2521                                                                      (((src_val >> src->green_shift) <<  4) & 0x000300) |
2522                                                                      (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2523                                                                      (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2524                 }
2525                 if(pad_size) memset(dst_pixel, 0, pad_size);
2526                 dst_start += dst->stride;
2527                 src_start += src->stride / 2;
2528             }
2529         }
2530         else
2531         {
2532             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask);
2533             return FALSE;
2534         }
2535         break;
2536     }
2537
2538     case 8:
2539     {
2540         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2541
2542         if(color_tables_match(dst, src))
2543         {
2544             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2545                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2546             else
2547             {
2548                 for(y = src_rect->top; y < src_rect->bottom; y++)
2549                 {
2550                     memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2551                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2552                     dst_start += dst->stride;
2553                     src_start += src->stride;
2554                 }
2555             }
2556         }
2557         else
2558         {
2559             for(y = src_rect->top; y < src_rect->bottom; y++)
2560             {
2561                 dst_pixel = dst_start;
2562                 src_pixel = src_start;
2563                 for(x = src_rect->left; x < src_rect->right; x++)
2564                 {
2565                     RGBQUAD rgb;
2566                     src_val = *src_pixel++;
2567                     if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2568                     rgb = src->color_table[src_val];
2569                     *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2570                 }
2571                 if(pad_size) memset(dst_pixel, 0, pad_size);
2572                 dst_start += dst->stride;
2573                 src_start += src->stride;
2574             }
2575         }
2576         break;
2577     }
2578
2579     case 4:
2580     {
2581         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2582         for(y = src_rect->top; y < src_rect->bottom; y++)
2583         {
2584             dst_pixel = dst_start;
2585             src_pixel = src_start;
2586             for(x = src_rect->left; x < src_rect->right; x++)
2587             {
2588                 RGBQUAD rgb;
2589                 if(x & 1)
2590                     src_val = *src_pixel++ & 0xf;
2591                 else
2592                     src_val = (*src_pixel >> 4) & 0xf;
2593                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2594                 rgb = src->color_table[src_val];
2595                 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2596             }
2597             if(pad_size) memset(dst_pixel, 0, pad_size);
2598             dst_start += dst->stride;
2599             src_start += src->stride;
2600         }
2601         break;
2602     }
2603
2604     case 1:
2605     {
2606         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2607         for(y = src_rect->top; y < src_rect->bottom; y++)
2608         {
2609             dst_pixel = dst_start;
2610             src_pixel = src_start;
2611             for(x = src_rect->left; x < src_rect->right; x++)
2612             {
2613                 RGBQUAD rgb;
2614                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2615                 if((x % 8) == 7) src_pixel++;
2616                 rgb = src->color_table[src_val];
2617                 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2618             }
2619             if(pad_size) memset(dst_pixel, 0, pad_size);
2620             dst_start += dst->stride;
2621             src_start += src->stride;
2622         }
2623         break;
2624     }
2625
2626     default:
2627         FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
2628         return FALSE;
2629
2630     }
2631     return TRUE;
2632 }
2633
2634 static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2635 {
2636     BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2637     INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2638     DWORD src_val;
2639
2640     switch(src->bit_count)
2641     {
2642     case 32:
2643     {
2644         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2645
2646         if(src->funcs == &funcs_8888)
2647         {
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                     src_val = *src_pixel++;
2655                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
2656                                                                 ( src_val        & 0x00ff00) |
2657                                                                 ((src_val << 16) & 0xff0000) );
2658                     if((x - src_rect->left) & 1)
2659                     {
2660                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2661                         dst_pixel++;
2662                     }
2663                     else
2664                         *dst_pixel = (dst_val << 4) & 0xf0;
2665                 }
2666                 if(pad_size)
2667                 {
2668                     if((x - src_rect->left) & 1) dst_pixel++;
2669                     memset(dst_pixel, 0, pad_size);
2670                 }
2671                 dst_start += dst->stride;
2672                 src_start += src->stride / 4;
2673             }
2674         }
2675         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2676         {
2677             for(y = src_rect->top; y < src_rect->bottom; y++)
2678             {
2679                 dst_pixel = dst_start;
2680                 src_pixel = src_start;
2681                 for(x = src_rect->left; x < src_rect->right; x++)
2682                 {
2683                     src_val = *src_pixel++;
2684                     dst_val = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift)          & 0x0000ff) |
2685                                                                 (((src_val >> src->green_shift) <<  8) & 0x00ff00) |
2686                                                                 (((src_val >> src->blue_shift)  << 16) & 0xff0000) );
2687                     if((x - src_rect->left) & 1)
2688                     {
2689                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2690                         dst_pixel++;
2691                     }
2692                     else
2693                         *dst_pixel = (dst_val << 4) & 0xf0;
2694                 }
2695                 if(pad_size)
2696                 {
2697                     if((x - src_rect->left) & 1) dst_pixel++;
2698                     memset(dst_pixel, 0, pad_size);
2699                 }
2700                 dst_start += dst->stride;
2701                 src_start += src->stride / 4;
2702             }
2703         }
2704         else
2705         {
2706             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask);
2707             return FALSE;
2708         }
2709         break;
2710     }
2711
2712     case 24:
2713     {
2714         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2715
2716         for(y = src_rect->top; y < src_rect->bottom; y++)
2717         {
2718             dst_pixel = dst_start;
2719             src_pixel = src_start;
2720             for(x = src_rect->left; x < src_rect->right; x++)
2721             {
2722                 RGBQUAD rgb;
2723                 rgb.rgbBlue  = *src_pixel++;
2724                 rgb.rgbGreen = *src_pixel++;
2725                 rgb.rgbRed   = *src_pixel++;
2726
2727                 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
2728                                                             ((rgb.rgbGreen << 8) & 0x00ff00) |
2729                                                             ((rgb.rgbBlue << 16) & 0xff0000));
2730
2731                 if((x - src_rect->left) & 1)
2732                 {
2733                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2734                     dst_pixel++;
2735                 }
2736                 else
2737                     *dst_pixel = (dst_val << 4) & 0xf0;
2738             }
2739             if(pad_size)
2740             {
2741                 if((x - src_rect->left) & 1) dst_pixel++;
2742                 memset(dst_pixel, 0, pad_size);
2743             }
2744             dst_start += dst->stride;
2745             src_start += src->stride;
2746         }
2747         break;
2748     }
2749
2750     case 16:
2751     {
2752         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2753         if(src->funcs == &funcs_555)
2754         {
2755             for(y = src_rect->top; y < src_rect->bottom; y++)
2756             {
2757                 dst_pixel = dst_start;
2758                 src_pixel = src_start;
2759                 for(x = src_rect->left; x < src_rect->right; x++)
2760                 {
2761                     src_val = *src_pixel++;
2762                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2763                                                                 ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
2764                                                                 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
2765                     if((x - src_rect->left) & 1)
2766                     {
2767                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2768                         dst_pixel++;
2769                     }
2770                     else
2771                         *dst_pixel = (dst_val << 4) & 0xf0;
2772                 }
2773                 if(pad_size)
2774                 {
2775                     if((x - src_rect->left) & 1) dst_pixel++;
2776                     memset(dst_pixel, 0, pad_size);
2777                 }
2778                 dst_start += dst->stride;
2779                 src_start += src->stride / 2;
2780             }
2781         }
2782         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2783         {
2784             for(y = src_rect->top; y < src_rect->bottom; y++)
2785             {
2786                 dst_pixel = dst_start;
2787                 src_pixel = src_start;
2788                 for(x = src_rect->left; x < src_rect->right; x++)
2789                 {
2790                     src_val = *src_pixel++;
2791                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2792                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2793                                                                 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2794                                                                 (((src_val >> src->green_shift) <<  6) & 0x000700) |
2795                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2796                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2797                     if((x - src_rect->left) & 1)
2798                     {
2799                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2800                         dst_pixel++;
2801                     }
2802                     else
2803                         *dst_pixel = (dst_val << 4) & 0xf0;
2804                 }
2805                 if(pad_size)
2806                 {
2807                     if((x - src_rect->left) & 1) dst_pixel++;
2808                     memset(dst_pixel, 0, pad_size);
2809                 }
2810                 dst_start += dst->stride;
2811                 src_start += src->stride / 2;
2812             }
2813         }
2814         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2815         {
2816             for(y = src_rect->top; y < src_rect->bottom; y++)
2817             {
2818                 dst_pixel = dst_start;
2819                 src_pixel = src_start;
2820                 for(x = src_rect->left; x < src_rect->right; x++)
2821                 {
2822                     src_val = *src_pixel++;
2823                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2824                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2825                                                                 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2826                                                                 (((src_val >> src->green_shift) <<  4) & 0x000300) |
2827                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2828                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2829                     if((x - src_rect->left) & 1)
2830                     {
2831                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2832                         dst_pixel++;
2833                     }
2834                     else
2835                         *dst_pixel = (dst_val << 4) & 0xf0;
2836                 }
2837                 if(pad_size)
2838                 {
2839                     if((x - src_rect->left) & 1) dst_pixel++;
2840                     memset(dst_pixel, 0, pad_size);
2841                 }
2842                 dst_start += dst->stride;
2843                 src_start += src->stride / 2;
2844             }
2845         }
2846         else
2847         {
2848             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask);
2849             return FALSE;
2850         }
2851         break;
2852     }
2853
2854     case 8:
2855     {
2856         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2857
2858         for(y = src_rect->top; y < src_rect->bottom; y++)
2859         {
2860             dst_pixel = dst_start;
2861             src_pixel = src_start;
2862             for(x = src_rect->left; x < src_rect->right; x++)
2863             {
2864                 RGBQUAD rgb;
2865                 src_val = *src_pixel++;
2866                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2867                 rgb = src->color_table[src_val];
2868                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2869                 if((x - src_rect->left) & 1)
2870                 {
2871                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2872                     dst_pixel++;
2873                 }
2874                 else
2875                     *dst_pixel = (dst_val << 4) & 0xf0;
2876             }
2877             if(pad_size)
2878             {
2879                 if((x - src_rect->left) & 1) dst_pixel++;
2880                 memset(dst_pixel, 0, pad_size);
2881             }
2882             dst_start += dst->stride;
2883             src_start += src->stride;
2884         }
2885         break;
2886     }
2887
2888     case 4:
2889     {
2890         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2891
2892         if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
2893         {
2894             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2895                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2896             else
2897             {
2898                 for(y = src_rect->top; y < src_rect->bottom; y++)
2899                 {
2900                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
2901                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
2902                     dst_start += dst->stride;
2903                     src_start += src->stride;
2904                 }
2905             }
2906         }
2907         else
2908         {
2909             for(y = src_rect->top; y < src_rect->bottom; y++)
2910             {
2911                 dst_pixel = dst_start;
2912                 src_pixel = src_start;
2913                 for(x = src_rect->left; x < src_rect->right; x++)
2914                 {
2915                     RGBQUAD rgb;
2916                     if(x & 1)
2917                         src_val = *src_pixel++ & 0xf;
2918                     else
2919                         src_val = (*src_pixel >> 4) & 0xf;
2920                     if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2921                     rgb = src->color_table[src_val];
2922                     dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2923                     if((x - src_rect->left) & 1)
2924                     {
2925                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2926                         dst_pixel++;
2927                     }
2928                     else
2929                         *dst_pixel = (dst_val << 4) & 0xf0;
2930                 }
2931                 if(pad_size)
2932                 {
2933                     if((x - src_rect->left) & 1) dst_pixel++;
2934                     memset(dst_pixel, 0, pad_size);
2935                 }
2936                 dst_start += dst->stride;
2937                 src_start += src->stride;
2938             }
2939         }
2940         break;
2941     }
2942
2943     case 1:
2944     {
2945         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2946         for(y = src_rect->top; y < src_rect->bottom; y++)
2947         {
2948             dst_pixel = dst_start;
2949             src_pixel = src_start;
2950             for(x = src_rect->left; x < src_rect->right; x++)
2951             {
2952                 RGBQUAD rgb;
2953                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2954                 if((x % 8) == 7) src_pixel++;
2955                 rgb = src->color_table[src_val];
2956                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2957                 if((x - src_rect->left) & 1)
2958                 {
2959                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2960                     dst_pixel++;
2961                 }
2962                 else
2963                     *dst_pixel = (dst_val << 4) & 0xf0;
2964             }
2965             if(pad_size)
2966             {
2967                 if((x - src_rect->left) & 1) dst_pixel++;
2968                 memset(dst_pixel, 0, pad_size);
2969             }
2970             dst_start += dst->stride;
2971             src_start += src->stride;
2972         }
2973         break;
2974     }
2975
2976     default:
2977         FIXME("Unsupported conversion: %d -> 4\n", src->bit_count);
2978         return FALSE;
2979
2980     }
2981
2982     return TRUE;
2983 }
2984
2985 static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
2986 {
2987     BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
2988     INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
2989     DWORD src_val;
2990     int bit_pos;
2991
2992     /* FIXME: Brushes should be dithered. */
2993
2994     switch(src->bit_count)
2995     {
2996     case 32:
2997     {
2998         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2999
3000         if(src->funcs == &funcs_8888)
3001         {
3002             for(y = src_rect->top; y < src_rect->bottom; y++)
3003             {
3004                 dst_pixel = dst_start;
3005                 src_pixel = src_start;
3006                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3007                 {
3008                     src_val = *src_pixel++;
3009                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
3010                                                                 ( src_val        & 0x00ff00) |
3011                                                                 ((src_val << 16) & 0xff0000) ) ? 0xff : 0;
3012
3013                     if(bit_pos == 0) *dst_pixel = 0;
3014                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3015
3016                     if(++bit_pos == 8)
3017                     {
3018                         dst_pixel++;
3019                         bit_pos = 0;
3020                     }
3021                 }
3022                 if(pad_size)
3023                 {
3024                     if(bit_pos != 0) dst_pixel++;
3025                     memset(dst_pixel, 0, pad_size);
3026                 }
3027                 dst_start += dst->stride;
3028                 src_start += src->stride / 4;
3029             }
3030         }
3031         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3032         {
3033             for(y = src_rect->top; y < src_rect->bottom; y++)
3034             {
3035                 dst_pixel = dst_start;
3036                 src_pixel = src_start;
3037                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3038                 {
3039                     src_val = *src_pixel++;
3040                     dst_val = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift)          & 0x0000ff) |
3041                                                                 (((src_val >> src->green_shift) <<  8) & 0x00ff00) |
3042                                                                 (((src_val >> src->blue_shift)  << 16) & 0xff0000) ) ? 0xff : 0;
3043
3044                    if(bit_pos == 0) *dst_pixel = 0;
3045                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3046
3047                     if(++bit_pos == 8)
3048                     {
3049                         dst_pixel++;
3050                         bit_pos = 0;
3051                     }
3052                 }
3053                 if(pad_size)
3054                 {
3055                     if(bit_pos != 0) dst_pixel++;
3056                     memset(dst_pixel, 0, pad_size);
3057                 }
3058                 dst_start += dst->stride;
3059                 src_start += src->stride / 4;
3060             }
3061         }
3062         else
3063         {
3064             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask);
3065             return FALSE;
3066         }
3067         break;
3068     }
3069
3070     case 24:
3071     {
3072         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3073
3074         for(y = src_rect->top; y < src_rect->bottom; y++)
3075         {
3076             dst_pixel = dst_start;
3077             src_pixel = src_start;
3078             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3079             {
3080                 RGBQUAD rgb;
3081                 rgb.rgbBlue  = *src_pixel++;
3082                 rgb.rgbGreen = *src_pixel++;
3083                 rgb.rgbRed   = *src_pixel++;
3084
3085                 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
3086                                                             ((rgb.rgbGreen << 8) & 0x00ff00) |
3087                                                             ((rgb.rgbBlue << 16) & 0xff0000)) ? 0xff : 0;
3088
3089                 if(bit_pos == 0) *dst_pixel = 0;
3090                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3091
3092                 if(++bit_pos == 8)
3093                 {
3094                     dst_pixel++;
3095                     bit_pos = 0;
3096                 }
3097             }
3098             if(pad_size)
3099             {
3100                 if(bit_pos != 0) dst_pixel++;
3101                 memset(dst_pixel, 0, pad_size);
3102             }
3103             dst_start += dst->stride;
3104             src_start += src->stride;
3105         }
3106         break;
3107     }
3108
3109     case 16:
3110     {
3111         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3112         if(src->funcs == &funcs_555)
3113         {
3114             for(y = src_rect->top; y < src_rect->bottom; y++)
3115             {
3116                 dst_pixel = dst_start;
3117                 src_pixel = src_start;
3118                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3119                 {
3120                     src_val = *src_pixel++;
3121                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
3122                                                                 ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
3123                                                                 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) ) ? 0xff : 0;
3124
3125                     if(bit_pos == 0) *dst_pixel = 0;
3126                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3127
3128                     if(++bit_pos == 8)
3129                     {
3130                         dst_pixel++;
3131                         bit_pos = 0;
3132                     }
3133                 }
3134                 if(pad_size)
3135                 {
3136                     if(bit_pos != 0) dst_pixel++;
3137                     memset(dst_pixel, 0, pad_size);
3138                 }
3139                 dst_start += dst->stride;
3140                 src_start += src->stride / 2;
3141             }
3142         }
3143         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3144         {
3145             for(y = src_rect->top; y < src_rect->bottom; y++)
3146             {
3147                 dst_pixel = dst_start;
3148                 src_pixel = src_start;
3149                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3150                 {
3151                     src_val = *src_pixel++;
3152                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
3153                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
3154                                                                 (((src_val >> src->green_shift) << 11) & 0x00f800) |
3155                                                                 (((src_val >> src->green_shift) <<  6) & 0x000700) |
3156                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
3157                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) ) ? 0xff : 0;
3158                     if(bit_pos == 0) *dst_pixel = 0;
3159                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3160
3161                     if(++bit_pos == 8)
3162                     {
3163                         dst_pixel++;
3164                         bit_pos = 0;
3165                     }
3166                 }
3167                 if(pad_size)
3168                 {
3169                     if(bit_pos != 0) dst_pixel++;
3170                     memset(dst_pixel, 0, pad_size);
3171                 }
3172                 dst_start += dst->stride;
3173                 src_start += src->stride / 2;
3174             }
3175         }
3176         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3177         {
3178             for(y = src_rect->top; y < src_rect->bottom; y++)
3179             {
3180                 dst_pixel = dst_start;
3181                 src_pixel = src_start;
3182                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3183                 {
3184                     src_val = *src_pixel++;
3185                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
3186                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
3187                                                                 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
3188                                                                 (((src_val >> src->green_shift) <<  4) & 0x000300) |
3189                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
3190                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) );
3191                     if(bit_pos == 0) *dst_pixel = 0;
3192                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3193
3194                     if(++bit_pos == 8)
3195                     {
3196                         dst_pixel++;
3197                         bit_pos = 0;
3198                     }
3199                 }
3200                 if(pad_size)
3201                 {
3202                     if(bit_pos != 0) dst_pixel++;
3203                     memset(dst_pixel, 0, pad_size);
3204                 }
3205                 dst_start += dst->stride;
3206                 src_start += src->stride / 2;
3207             }
3208         }
3209         else
3210         {
3211             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask);
3212             return FALSE;
3213         }
3214         break;
3215     }
3216
3217     case 8:
3218     {
3219         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3220
3221         for(y = src_rect->top; y < src_rect->bottom; y++)
3222         {
3223             dst_pixel = dst_start;
3224             src_pixel = src_start;
3225             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3226             {
3227                 RGBQUAD rgb;
3228                 src_val = *src_pixel++;
3229                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
3230                 rgb = src->color_table[src_val];
3231                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
3232
3233                 if(bit_pos == 0) *dst_pixel = 0;
3234                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3235
3236                 if(++bit_pos == 8)
3237                 {
3238                     dst_pixel++;
3239                     bit_pos = 0;
3240                 }
3241             }
3242             if(pad_size)
3243             {
3244                 if(bit_pos != 0) dst_pixel++;
3245                 memset(dst_pixel, 0, pad_size);
3246             }
3247             dst_start += dst->stride;
3248             src_start += src->stride;
3249         }
3250         break;
3251     }
3252
3253     case 4:
3254     {
3255         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3256
3257         for(y = src_rect->top; y < src_rect->bottom; y++)
3258         {
3259             dst_pixel = dst_start;
3260             src_pixel = src_start;
3261             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3262             {
3263                 RGBQUAD rgb;
3264                 if(x & 1)
3265                     src_val = *src_pixel++ & 0xf;
3266                 else
3267                     src_val = (*src_pixel >> 4) & 0xf;
3268                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
3269                 rgb = src->color_table[src_val];
3270                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
3271
3272                 if(bit_pos == 0) *dst_pixel = 0;
3273                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3274
3275                 if(++bit_pos == 8)
3276                 {
3277                     dst_pixel++;
3278                     bit_pos = 0;
3279                 }
3280             }
3281             if(pad_size)
3282             {
3283                 if(bit_pos != 0) dst_pixel++;
3284                 memset(dst_pixel, 0, pad_size);
3285             }
3286             dst_start += dst->stride;
3287             src_start += src->stride;
3288         }
3289         break;
3290     }
3291
3292     /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3293        uses text/bkgnd colours instead of the dib's colour table, this
3294        doesn't appear to be the case for a dc backed by a
3295        dibsection. */
3296
3297     case 1:
3298     {
3299         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3300         for(y = src_rect->top; y < src_rect->bottom; y++)
3301         {
3302             dst_pixel = dst_start;
3303             src_pixel = src_start;
3304             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3305             {
3306                 RGBQUAD rgb;
3307                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3308                 if((x % 8) == 7) src_pixel++;
3309                 rgb = src->color_table[src_val];
3310                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
3311
3312                 if(bit_pos == 0) *dst_pixel = 0;
3313                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3314
3315                 if(++bit_pos == 8)
3316                 {
3317                     dst_pixel++;
3318                     bit_pos = 0;
3319                 }
3320             }
3321             if(pad_size)
3322             {
3323                 if(bit_pos != 0) dst_pixel++;
3324                 memset(dst_pixel, 0, pad_size);
3325             }
3326             dst_start += dst->stride;
3327             src_start += src->stride;
3328         }
3329         break;
3330     }
3331
3332     default:
3333         FIXME("Unsupported conversion: %d -> 1\n", src->bit_count);
3334         return FALSE;
3335
3336     }
3337     return TRUE;
3338 }
3339
3340 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3341 {
3342     return FALSE;
3343 }
3344
3345 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)
3346 {
3347     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3348     DWORD mask_start = 0, mask_offset;
3349     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
3350     int x, y;
3351
3352     for(y = 0; y < hatch->height; y++)
3353     {
3354         hatch_ptr = hatch_start;
3355         mask_offset = mask_start;
3356         for(x = 0; x < hatch->width; x++)
3357         {
3358             if(*hatch_ptr & pixel_masks_1[x % 8])
3359             {
3360                 and_bits[mask_offset] = fg->and;
3361                 xor_bits[mask_offset] = fg->xor;
3362             }
3363             else
3364             {
3365                 and_bits[mask_offset] = bg->and;
3366                 xor_bits[mask_offset] = bg->xor;
3367             }
3368             if(x % 8 == 7) hatch_ptr++;
3369             mask_offset++;
3370         }
3371         hatch_start += hatch->stride;
3372         mask_start += dib->stride / 4;
3373     }
3374
3375     return TRUE;
3376 }
3377
3378 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)
3379 {
3380     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3381     DWORD mask_start = 0, mask_offset;
3382     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3383     int x, y;
3384
3385     for(y = 0; y < hatch->height; y++)
3386     {
3387         hatch_ptr = hatch_start;
3388         mask_offset = mask_start;
3389         for(x = 0; x < hatch->width; x++)
3390         {
3391             if(*hatch_ptr & pixel_masks_1[x % 8])
3392             {
3393                 and_bits[mask_offset]   =  fg->and        & 0xff;
3394                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
3395                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
3396                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
3397                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
3398                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
3399             }
3400             else
3401             {
3402                 and_bits[mask_offset]   =  bg->and        & 0xff;
3403                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
3404                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
3405                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
3406                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
3407                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
3408             }
3409             if(x % 8 == 7) hatch_ptr++;
3410         }
3411         hatch_start += hatch->stride;
3412         mask_start += dib->stride;
3413     }
3414
3415     return TRUE;
3416 }
3417
3418 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)
3419 {
3420     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3421     DWORD mask_start = 0, mask_offset;
3422     WORD *and_bits = bits->and, *xor_bits = bits->xor;
3423     int x, y;
3424
3425     for(y = 0; y < hatch->height; y++)
3426     {
3427         hatch_ptr = hatch_start;
3428         mask_offset = mask_start;
3429         for(x = 0; x < hatch->width; x++)
3430         {
3431             if(*hatch_ptr & pixel_masks_1[x % 8])
3432             {
3433                 and_bits[mask_offset] = fg->and;
3434                 xor_bits[mask_offset] = fg->xor;
3435             }
3436             else
3437             {
3438                 and_bits[mask_offset] = bg->and;
3439                 xor_bits[mask_offset] = bg->xor;
3440             }
3441             if(x % 8 == 7) hatch_ptr++;
3442             mask_offset++;
3443         }
3444         hatch_start += hatch->stride;
3445         mask_start += dib->stride / 2;
3446     }
3447
3448     return TRUE;
3449 }
3450
3451 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)
3452 {
3453     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3454     DWORD mask_start = 0, mask_offset;
3455     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3456     int x, y;
3457
3458     for(y = 0; y < hatch->height; y++)
3459     {
3460         hatch_ptr = hatch_start;
3461         mask_offset = mask_start;
3462         for(x = 0; x < hatch->width; x++)
3463         {
3464             if(*hatch_ptr & pixel_masks_1[x % 8])
3465             {
3466                 and_bits[mask_offset] = fg->and;
3467                 xor_bits[mask_offset] = fg->xor;
3468             }
3469             else
3470             {
3471                 and_bits[mask_offset] = bg->and;
3472                 xor_bits[mask_offset] = bg->xor;
3473             }
3474             if(x % 8 == 7) hatch_ptr++;
3475             mask_offset++;
3476         }
3477         hatch_start += hatch->stride;
3478         mask_start += dib->stride;
3479     }
3480
3481     return TRUE;
3482 }
3483
3484 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)
3485 {
3486     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3487     DWORD mask_start = 0, mask_offset;
3488     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3489     const rop_mask *rop_mask;
3490     int x, y;
3491
3492     for(y = 0; y < hatch->height; y++)
3493     {
3494         hatch_ptr = hatch_start;
3495         mask_offset = mask_start;
3496         for(x = 0; x < hatch->width; x++)
3497         {
3498             if(*hatch_ptr & pixel_masks_1[x % 8])
3499                 rop_mask = fg;
3500             else
3501                 rop_mask = bg;
3502
3503             if(x & 1)
3504             {
3505                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3506                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3507                 mask_offset++;
3508             }
3509             else
3510             {
3511                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3512                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3513             }
3514
3515             if(x % 8 == 7) hatch_ptr++;
3516         }
3517         hatch_start += hatch->stride;
3518         mask_start += dib->stride;
3519     }
3520
3521     return TRUE;
3522 }
3523
3524 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)
3525 {
3526     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3527     DWORD mask_start = 0, mask_offset;
3528     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3529     rop_mask rop_mask;
3530     int x, y, bit_pos;
3531
3532     for(y = 0; y < hatch->height; y++)
3533     {
3534         hatch_ptr = hatch_start;
3535         mask_offset = mask_start;
3536         for(x = 0, bit_pos = 0; x < hatch->width; x++)
3537         {
3538             if(*hatch_ptr & pixel_masks_1[x % 8])
3539             {
3540                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3541                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3542             }
3543             else
3544             {
3545                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3546                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3547             }
3548
3549             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3550
3551             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3552             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3553
3554             if(++bit_pos == 8)
3555             {
3556                 mask_offset++;
3557                 hatch_ptr++;
3558                 bit_pos = 0;
3559             }
3560         }
3561         hatch_start += hatch->stride;
3562         mask_start += dib->stride;
3563     }
3564
3565     return TRUE;
3566 }
3567
3568 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)
3569 {
3570     return FALSE;
3571 }
3572
3573 const primitive_funcs funcs_8888 =
3574 {
3575     solid_rects_32,
3576     pattern_rects_32,
3577     copy_rect_32,
3578     colorref_to_pixel_888,
3579     convert_to_8888,
3580     create_rop_masks_32
3581 };
3582
3583 const primitive_funcs funcs_32 =
3584 {
3585     solid_rects_32,
3586     pattern_rects_32,
3587     copy_rect_32,
3588     colorref_to_pixel_masks,
3589     convert_to_32,
3590     create_rop_masks_32
3591 };
3592
3593 const primitive_funcs funcs_24 =
3594 {
3595     solid_rects_24,
3596     pattern_rects_24,
3597     copy_rect_24,
3598     colorref_to_pixel_888,
3599     convert_to_24,
3600     create_rop_masks_24
3601 };
3602
3603 const primitive_funcs funcs_555 =
3604 {
3605     solid_rects_16,
3606     pattern_rects_16,
3607     copy_rect_16,
3608     colorref_to_pixel_555,
3609     convert_to_555,
3610     create_rop_masks_16
3611 };
3612
3613 const primitive_funcs funcs_16 =
3614 {
3615     solid_rects_16,
3616     pattern_rects_16,
3617     copy_rect_16,
3618     colorref_to_pixel_masks,
3619     convert_to_16,
3620     create_rop_masks_16
3621 };
3622
3623 const primitive_funcs funcs_8 =
3624 {
3625     solid_rects_8,
3626     pattern_rects_8,
3627     copy_rect_8,
3628     colorref_to_pixel_colortable,
3629     convert_to_8,
3630     create_rop_masks_8
3631 };
3632
3633 const primitive_funcs funcs_4 =
3634 {
3635     solid_rects_4,
3636     pattern_rects_4,
3637     copy_rect_4,
3638     colorref_to_pixel_colortable,
3639     convert_to_4,
3640     create_rop_masks_4
3641 };
3642
3643 const primitive_funcs funcs_1 =
3644 {
3645     solid_rects_1,
3646     pattern_rects_1,
3647     copy_rect_1,
3648     colorref_to_pixel_colortable,
3649     convert_to_1,
3650     create_rop_masks_1
3651 };
3652
3653 const primitive_funcs funcs_null =
3654 {
3655     solid_rects_null,
3656     pattern_rects_null,
3657     copy_rect_null,
3658     colorref_to_pixel_null,
3659     convert_to_null,
3660     create_rop_masks_null
3661 };