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