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