mshtml: Rename call_event to fire_event.
[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     /* special case for conversion to 1-bpp without a color table:
696      * we get a 1-entry table containing the background color
697      */
698     if (dib->bit_count == 1 && dib->color_table_size == 1)
699         return (rgb.rgbRed == dib->color_table[0].rgbRed &&
700                 rgb.rgbGreen == dib->color_table[0].rgbGreen &&
701                 rgb.rgbBlue == dib->color_table[0].rgbBlue);
702
703     for(i = 0; i < dib->color_table_size; i++)
704     {
705         RGBQUAD *cur = dib->color_table + i;
706         diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
707             +  (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
708             +  (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
709
710         if(diff == 0)
711         {
712             best_index = i;
713             break;
714         }
715
716         if(diff < best_diff)
717         {
718             best_diff = diff;
719             best_index = i;
720         }
721     }
722     return best_index;
723 }
724
725 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
726 {
727     return 0;
728 }
729
730 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
731 {
732     assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
733
734     return d1->red_mask   == d2->red_mask &&
735            d1->green_mask == d2->green_mask &&
736            d1->blue_mask  == d2->blue_mask;
737 }
738
739 static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
740 {
741     DWORD *dst_start = dst->bits, *dst_pixel, src_val;
742     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
743
744     switch(src->bit_count)
745     {
746     case 32:
747     {
748         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
749         if(src->funcs == &funcs_8888)
750         {
751             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
752                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
753             else
754             {
755                 for(y = src_rect->top; y < src_rect->bottom; y++)
756                 {
757                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
758                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
759                     dst_start += dst->stride / 4;
760                     src_start += src->stride / 4;
761                 }
762             }
763         }
764         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
765         {
766             for(y = src_rect->top; y < src_rect->bottom; y++)
767             {
768                 dst_pixel = dst_start;
769                 src_pixel = src_start;
770                 for(x = src_rect->left; x < src_rect->right; x++)
771                 {
772                     src_val = *src_pixel++;
773                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << 16) |
774                                    (((src_val >> src->green_shift) & 0xff) <<  8) |
775                                     ((src_val >> src->blue_shift)  & 0xff);
776                 }
777                 if(pad_size) memset(dst_pixel, 0, pad_size);
778                 dst_start += dst->stride / 4;
779                 src_start += src->stride / 4;
780             }
781         }
782         else
783         {
784             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
785             return FALSE;
786         }
787         break;
788     }
789
790     case 24:
791     {
792         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
793
794         for(y = src_rect->top; y < src_rect->bottom; y++)
795         {
796             dst_pixel = dst_start;
797             src_pixel = src_start;
798             for(x = src_rect->left; x < src_rect->right; x++)
799             {
800                 RGBQUAD rgb;
801                 rgb.rgbBlue  = *src_pixel++;
802                 rgb.rgbGreen = *src_pixel++;
803                 rgb.rgbRed   = *src_pixel++;
804
805                 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
806             }
807             if(pad_size) memset(dst_pixel, 0, pad_size);
808             dst_start += dst->stride / 4;
809             src_start += src->stride;
810         }
811         break;
812     }
813
814     case 16:
815     {
816         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
817         if(src->funcs == &funcs_555)
818         {
819             for(y = src_rect->top; y < src_rect->bottom; y++)
820             {
821                 dst_pixel = dst_start;
822                 src_pixel = src_start;
823                 for(x = src_rect->left; x < src_rect->right; x++)
824                 {
825                     src_val = *src_pixel++;
826                     *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
827                                    ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
828                                    ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
829                 }
830                 if(pad_size) memset(dst_pixel, 0, pad_size);
831                 dst_start += dst->stride / 4;
832                 src_start += src->stride / 2;
833             }
834         }
835         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
836         {
837             for(y = src_rect->top; y < src_rect->bottom; y++)
838             {
839                 dst_pixel = dst_start;
840                 src_pixel = src_start;
841                 for(x = src_rect->left; x < src_rect->right; x++)
842                 {
843                     src_val = *src_pixel++;
844                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
845                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
846                                    (((src_val >> src->green_shift) << 11) & 0x00f800) |
847                                    (((src_val >> src->green_shift) <<  6) & 0x000700) |
848                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
849                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
850                 }
851                 if(pad_size) memset(dst_pixel, 0, pad_size);
852                 dst_start += dst->stride / 4;
853                 src_start += src->stride / 2;
854             }
855         }
856         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
857         {
858             for(y = src_rect->top; y < src_rect->bottom; y++)
859             {
860                 dst_pixel = dst_start;
861                 src_pixel = src_start;
862                 for(x = src_rect->left; x < src_rect->right; x++)
863                 {
864                     src_val = *src_pixel++;
865                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
866                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
867                                    (((src_val >> src->green_shift) << 10) & 0x00fc00) |
868                                    (((src_val >> src->green_shift) <<  4) & 0x000300) |
869                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
870                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
871                 }
872                 if(pad_size) memset(dst_pixel, 0, pad_size);
873                 dst_start += dst->stride / 4;
874                 src_start += src->stride / 2;
875             }
876         }
877         else
878         {
879             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
880             return FALSE;
881         }
882         break;
883     }
884
885     case 8:
886     {
887         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
888         for(y = src_rect->top; y < src_rect->bottom; y++)
889         {
890             dst_pixel = dst_start;
891             src_pixel = src_start;
892             for(x = src_rect->left; x < src_rect->right; x++)
893             {
894                 RGBQUAD rgb;
895                 src_val = *src_pixel++;
896                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
897                 rgb = src->color_table[src_val];
898                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
899             }
900             if(pad_size) memset(dst_pixel, 0, pad_size);
901             dst_start += dst->stride / 4;
902             src_start += src->stride;
903         }
904         break;
905     }
906
907     case 4:
908     {
909         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
910         for(y = src_rect->top; y < src_rect->bottom; y++)
911         {
912             dst_pixel = dst_start;
913             src_pixel = src_start;
914             for(x = src_rect->left; x < src_rect->right; x++)
915             {
916                 RGBQUAD rgb;
917                 if(x & 1)
918                     src_val = *src_pixel++ & 0xf;
919                 else
920                     src_val = (*src_pixel >> 4) & 0xf;
921                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
922                 rgb = src->color_table[src_val];
923                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
924             }
925             if(pad_size) memset(dst_pixel, 0, pad_size);
926             dst_start += dst->stride / 4;
927             src_start += src->stride;
928         }
929         break;
930     }
931
932     case 1:
933     {
934         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
935         for(y = src_rect->top; y < src_rect->bottom; y++)
936         {
937             dst_pixel = dst_start;
938             src_pixel = src_start;
939             for(x = src_rect->left; x < src_rect->right; x++)
940             {
941                 RGBQUAD rgb;
942                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
943                 if((x % 8) == 7) src_pixel++;
944                 rgb = src->color_table[src_val];
945                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
946             }
947             if(pad_size) memset(dst_pixel, 0, pad_size);
948             dst_start += dst->stride / 4;
949             src_start += src->stride;
950         }
951         break;
952     }
953
954     default:
955         FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
956         return FALSE;
957     }
958
959     return TRUE;
960 }
961
962 static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
963 {
964     DWORD *dst_start = dst->bits, *dst_pixel, src_val;
965     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
966
967     switch(src->bit_count)
968     {
969     case 32:
970     {
971         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
972
973         if(src->funcs == &funcs_8888)
974         {
975             for(y = src_rect->top; y < src_rect->bottom; y++)
976             {
977                 dst_pixel = dst_start;
978                 src_pixel = src_start;
979                 for(x = src_rect->left; x < src_rect->right; x++)
980                 {
981                     src_val = *src_pixel++;
982                     *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift,   dst->red_len)   |
983                                    put_field((src_val >>  8) & 0xff, dst->green_shift, dst->green_len) |
984                                    put_field( src_val        & 0xff, dst->blue_shift,  dst->blue_len);
985                 }
986                 if(pad_size) memset(dst_pixel, 0, pad_size);
987                 dst_start += dst->stride / 4;
988                 src_start += src->stride / 4;
989             }
990         }
991         else if(bit_fields_match(src, dst))
992         {
993             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
994                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
995             else
996             {
997                 for(y = src_rect->top; y < src_rect->bottom; y++)
998                 {
999                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1000                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1001                     dst_start += dst->stride / 4;
1002                     src_start += src->stride / 4;
1003                 }
1004             }
1005         }
1006         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1007                 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1008         {
1009             for(y = src_rect->top; y < src_rect->bottom; y++)
1010             {
1011                 dst_pixel = dst_start;
1012                 src_pixel = src_start;
1013                 for(x = src_rect->left; x < src_rect->right; x++)
1014                 {
1015                     src_val = *src_pixel++;
1016                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << dst->red_shift)   |
1017                                    (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1018                                    (((src_val >> src->blue_shift)  & 0xff) << dst->blue_shift);
1019                 }
1020                 if(pad_size) memset(dst_pixel, 0, pad_size);
1021                 dst_start += dst->stride / 4;
1022                 src_start += src->stride / 4;
1023             }
1024         }
1025         else
1026         {
1027             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 32 (%08x, %08x, %08x)\n",
1028                   src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask);
1029             return FALSE;
1030         }
1031         break;
1032     }
1033
1034     case 24:
1035     {
1036         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1037
1038         for(y = src_rect->top; y < src_rect->bottom; y++)
1039         {
1040             dst_pixel = dst_start;
1041             src_pixel = src_start;
1042             for(x = src_rect->left; x < src_rect->right; x++)
1043             {
1044                 RGBQUAD rgb;
1045                 rgb.rgbBlue  = *src_pixel++;
1046                 rgb.rgbGreen = *src_pixel++;
1047                 rgb.rgbRed   = *src_pixel++;
1048
1049                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len)   |
1050                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1051                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1052             }
1053             if(pad_size) memset(dst_pixel, 0, pad_size);
1054             dst_start += dst->stride / 4;
1055             src_start += src->stride;
1056         }
1057         break;
1058     }
1059
1060     case 16:
1061     {
1062         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1063         if(src->funcs == &funcs_555)
1064         {
1065             for(y = src_rect->top; y < src_rect->bottom; y++)
1066             {
1067                 dst_pixel = dst_start;
1068                 src_pixel = src_start;
1069                 for(x = src_rect->left; x < src_rect->right; x++)
1070                 {
1071                     src_val = *src_pixel++;
1072                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
1073                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
1074                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
1075                 }
1076                 if(pad_size) memset(dst_pixel, 0, pad_size);
1077                 dst_start += dst->stride / 4;
1078                 src_start += src->stride / 2;
1079             }
1080         }
1081         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1082         {
1083             for(y = src_rect->top; y < src_rect->bottom; y++)
1084             {
1085                 dst_pixel = dst_start;
1086                 src_pixel = src_start;
1087                 for(x = src_rect->left; x < src_rect->right; x++)
1088                 {
1089                     src_val = *src_pixel++;
1090                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1091                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1092                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1093                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1094                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1095                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1096                 }
1097                 if(pad_size) memset(dst_pixel, 0, pad_size);
1098                 dst_start += dst->stride / 4;
1099                 src_start += src->stride / 2;
1100             }
1101         }
1102         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1103         {
1104             for(y = src_rect->top; y < src_rect->bottom; y++)
1105             {
1106                 dst_pixel = dst_start;
1107                 src_pixel = src_start;
1108                 for(x = src_rect->left; x < src_rect->right; x++)
1109                 {
1110                     src_val = *src_pixel++;
1111                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1112                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1113                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1114                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1115                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1116                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1117                 }
1118                 if(pad_size) memset(dst_pixel, 0, pad_size);
1119                 dst_start += dst->stride / 4;
1120                 src_start += src->stride / 2;
1121             }
1122         }
1123         else
1124         {
1125             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 32\n", src->red_mask, src->green_mask, src->blue_mask);
1126             return FALSE;
1127         }
1128         break;
1129     }
1130
1131     case 8:
1132     {
1133         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1134         for(y = src_rect->top; y < src_rect->bottom; y++)
1135         {
1136             dst_pixel = dst_start;
1137             src_pixel = src_start;
1138             for(x = src_rect->left; x < src_rect->right; x++)
1139             {
1140                 RGBQUAD rgb;
1141                 src_val = *src_pixel++;
1142                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1143                 rgb = src->color_table[src_val];
1144                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1145                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1146                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1147             }
1148             if(pad_size) memset(dst_pixel, 0, pad_size);
1149             dst_start += dst->stride / 4;
1150             src_start += src->stride;
1151         }
1152         break;
1153     }
1154
1155     case 4:
1156     {
1157         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1158         for(y = src_rect->top; y < src_rect->bottom; y++)
1159         {
1160             dst_pixel = dst_start;
1161             src_pixel = src_start;
1162             for(x = src_rect->left; x < src_rect->right; x++)
1163             {
1164                 RGBQUAD rgb;
1165                 if(x & 1)
1166                     src_val = *src_pixel++ & 0xf;
1167                 else
1168                     src_val = (*src_pixel >> 4) & 0xf;
1169                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1170                 rgb = src->color_table[src_val];
1171                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1172                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1173                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1174             }
1175             if(pad_size) memset(dst_pixel, 0, pad_size);
1176             dst_start += dst->stride / 4;
1177             src_start += src->stride;
1178         }
1179         break;
1180     }
1181
1182     case 1:
1183     {
1184         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1185         for(y = src_rect->top; y < src_rect->bottom; y++)
1186         {
1187             dst_pixel = dst_start;
1188             src_pixel = src_start;
1189             for(x = src_rect->left; x < src_rect->right; x++)
1190             {
1191                 RGBQUAD rgb;
1192                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1193                 if((x % 8) == 7) src_pixel++;
1194                 rgb = src->color_table[src_val];
1195                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1196                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1197                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1198             }
1199             if(pad_size) memset(dst_pixel, 0, pad_size);
1200             dst_start += dst->stride / 4;
1201             src_start += src->stride;
1202         }
1203         break;
1204     }
1205
1206     default:
1207         FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
1208         return FALSE;
1209     }
1210
1211     return TRUE;
1212 }
1213
1214 static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1215 {
1216     BYTE *dst_start = dst->bits, *dst_pixel;
1217     DWORD src_val;
1218     int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1219
1220     switch(src->bit_count)
1221     {
1222     case 32:
1223     {
1224         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1225         if(src->funcs == &funcs_8888)
1226         {
1227             for(y = src_rect->top; y < src_rect->bottom; y++)
1228             {
1229                 dst_pixel = dst_start;
1230                 src_pixel = src_start;
1231                 for(x = src_rect->left; x < src_rect->right; x++)
1232                 {
1233                     src_val = *src_pixel++;
1234                     *dst_pixel++ =  src_val        & 0xff;
1235                     *dst_pixel++ = (src_val >>  8) & 0xff;
1236                     *dst_pixel++ = (src_val >> 16) & 0xff;
1237                 }
1238                 if(pad_size) memset(dst_pixel, 0, pad_size);
1239                 dst_start += dst->stride;
1240                 src_start += src->stride / 4;
1241             }
1242         }
1243         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1244         {
1245             for(y = src_rect->top; y < src_rect->bottom; y++)
1246             {
1247                 dst_pixel = dst_start;
1248                 src_pixel = src_start;
1249                 for(x = src_rect->left; x < src_rect->right; x++)
1250                 {
1251                     src_val = *src_pixel++;
1252                     *dst_pixel++ = (src_val >> src->blue_shift)  & 0xff;
1253                     *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1254                     *dst_pixel++ = (src_val >> src->red_shift)   & 0xff;
1255                 }
1256                 if(pad_size) memset(dst_pixel, 0, pad_size);
1257                 dst_start += dst->stride;
1258                 src_start += src->stride / 4;
1259             }
1260         }
1261         else
1262         {
1263             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask);
1264             return FALSE;
1265         }
1266         break;
1267     }
1268
1269     case 24:
1270     {
1271         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1272
1273         if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1274             memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1275         else
1276         {
1277             for(y = src_rect->top; y < src_rect->bottom; y++)
1278             {
1279                 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1280                 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1281                 dst_start += dst->stride;
1282                 src_start += src->stride;
1283             }
1284         }
1285         break;
1286     }
1287
1288     case 16:
1289     {
1290         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1291         if(src->funcs == &funcs_555)
1292         {
1293             for(y = src_rect->top; y < src_rect->bottom; y++)
1294             {
1295                 dst_pixel = dst_start;
1296                 src_pixel = src_start;
1297                 for(x = src_rect->left; x < src_rect->right; x++)
1298                 {
1299                     src_val = *src_pixel++;
1300                     *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07);
1301                     *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07);
1302                     *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1303                 }
1304                 if(pad_size) memset(dst_pixel, 0, pad_size);
1305                 dst_start += dst->stride;
1306                 src_start += src->stride / 2;
1307             }
1308         }
1309         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1310         {
1311             for(y = src_rect->top; y < src_rect->bottom; y++)
1312             {
1313                 dst_pixel = dst_start;
1314                 src_pixel = src_start;
1315                 for(x = src_rect->left; x < src_rect->right; x++)
1316                 {
1317                     src_val = *src_pixel++;
1318                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1319                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
1320                     *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1321                                    (((src_val >> src->green_shift) >> 2) & 0x07);
1322                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
1323                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
1324                 }
1325                 if(pad_size) memset(dst_pixel, 0, pad_size);
1326                 dst_start += dst->stride;
1327                 src_start += src->stride / 2;
1328             }
1329         }
1330         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1331         {
1332             for(y = src_rect->top; y < src_rect->bottom; y++)
1333             {
1334                 dst_pixel = dst_start;
1335                 src_pixel = src_start;
1336                 for(x = src_rect->left; x < src_rect->right; x++)
1337                 {
1338                     src_val = *src_pixel++;
1339                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1340                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
1341                     *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1342                                    (((src_val >> src->green_shift) >> 4) & 0x03);
1343                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
1344                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
1345                 }
1346                 if(pad_size) memset(dst_pixel, 0, pad_size);
1347                 dst_start += dst->stride;
1348                 src_start += src->stride / 2;
1349             }
1350         }
1351         else
1352         {
1353             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask);
1354             return FALSE;
1355         }
1356         break;
1357     }
1358
1359     case 8:
1360     {
1361         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1362         for(y = src_rect->top; y < src_rect->bottom; y++)
1363         {
1364             dst_pixel = dst_start;
1365             src_pixel = src_start;
1366             for(x = src_rect->left; x < src_rect->right; x++)
1367             {
1368                 RGBQUAD rgb;
1369                 src_val = *src_pixel++;
1370                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1371                 rgb = src->color_table[src_val];
1372                 *dst_pixel++ = rgb.rgbBlue;
1373                 *dst_pixel++ = rgb.rgbGreen;
1374                 *dst_pixel++ = rgb.rgbRed;
1375             }
1376             if(pad_size) memset(dst_pixel, 0, pad_size);
1377             dst_start += dst->stride;
1378             src_start += src->stride;
1379         }
1380         break;
1381     }
1382
1383     case 4:
1384     {
1385         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1386         for(y = src_rect->top; y < src_rect->bottom; y++)
1387         {
1388             dst_pixel = dst_start;
1389             src_pixel = src_start;
1390             for(x = src_rect->left; x < src_rect->right; x++)
1391             {
1392                 RGBQUAD rgb;
1393                 if(x & 1)
1394                     src_val = *src_pixel++ & 0xf;
1395                 else
1396                     src_val = (*src_pixel >> 4) & 0xf;
1397                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1398                 rgb = src->color_table[src_val];
1399                 *dst_pixel++ = rgb.rgbBlue;
1400                 *dst_pixel++ = rgb.rgbGreen;
1401                 *dst_pixel++ = rgb.rgbRed;
1402             }
1403             if(pad_size) memset(dst_pixel, 0, pad_size);
1404             dst_start += dst->stride;
1405             src_start += src->stride;
1406         }
1407         break;
1408     }
1409
1410     case 1:
1411     {
1412         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1413         for(y = src_rect->top; y < src_rect->bottom; y++)
1414         {
1415             dst_pixel = dst_start;
1416             src_pixel = src_start;
1417             for(x = src_rect->left; x < src_rect->right; x++)
1418             {
1419                 RGBQUAD rgb;
1420                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1421                 if((x % 8) == 7) src_pixel++;
1422                 rgb = src->color_table[src_val];
1423                 *dst_pixel++ = rgb.rgbBlue;
1424                 *dst_pixel++ = rgb.rgbGreen;
1425                 *dst_pixel++ = rgb.rgbRed;
1426             }
1427             if(pad_size) memset(dst_pixel, 0, pad_size);
1428             dst_start += dst->stride;
1429             src_start += src->stride;
1430         }
1431         break;
1432     }
1433
1434     default:
1435         FIXME("Unsupported conversion: %d -> 24\n", src->bit_count);
1436         return FALSE;
1437     }
1438
1439     return TRUE;
1440 }
1441
1442 static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1443 {
1444     WORD *dst_start = dst->bits, *dst_pixel;
1445     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1446     DWORD src_val;
1447
1448     switch(src->bit_count)
1449     {
1450     case 32:
1451     {
1452         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1453
1454         if(src->funcs == &funcs_8888)
1455         {
1456             for(y = src_rect->top; y < src_rect->bottom; y++)
1457             {
1458                 dst_pixel = dst_start;
1459                 src_pixel = src_start;
1460                 for(x = src_rect->left; x < src_rect->right; x++)
1461                 {
1462                     src_val = *src_pixel++;
1463                     *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1464                                    ((src_val >> 6) & 0x03e0) |
1465                                    ((src_val >> 3) & 0x001f);
1466                 }
1467                 if(pad_size) memset(dst_pixel, 0, pad_size);
1468                 dst_start += dst->stride / 2;
1469                 src_start += src->stride / 4;
1470             }
1471         }
1472         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1473         {
1474             for(y = src_rect->top; y < src_rect->bottom; y++)
1475             {
1476                 dst_pixel = dst_start;
1477                 src_pixel = src_start;
1478                 for(x = src_rect->left; x < src_rect->right; x++)
1479                 {
1480                     src_val = *src_pixel++;
1481                     *dst_pixel++ = (((src_val >> src->red_shift)   << 7) & 0x7c00) |
1482                                    (((src_val >> src->green_shift) << 2) & 0x03e0) |
1483                                    (((src_val >> src->blue_shift)  >> 3) & 0x001f);
1484                 }
1485                 if(pad_size) memset(dst_pixel, 0, pad_size);
1486                 dst_start += dst->stride / 2;
1487                 src_start += src->stride / 4;
1488             }
1489         }
1490         else
1491         {
1492             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask);
1493             return FALSE;
1494         }
1495         break;
1496     }
1497
1498     case 24:
1499     {
1500         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1501
1502         for(y = src_rect->top; y < src_rect->bottom; y++)
1503         {
1504             dst_pixel = dst_start;
1505             src_pixel = src_start;
1506             for(x = src_rect->left; x < src_rect->right; x++)
1507             {
1508                 RGBQUAD rgb;
1509                 rgb.rgbBlue  = *src_pixel++;
1510                 rgb.rgbGreen = *src_pixel++;
1511                 rgb.rgbRed   = *src_pixel++;
1512
1513                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1514                                ((rgb.rgbGreen << 2) & 0x03e0) |
1515                                ((rgb.rgbBlue  >> 3) & 0x001f);
1516             }
1517             if(pad_size) memset(dst_pixel, 0, pad_size);
1518             dst_start += dst->stride / 2;
1519             src_start += src->stride;
1520         }
1521         break;
1522     }
1523
1524     case 16:
1525     {
1526         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1527         if(src->funcs == &funcs_555)
1528         {
1529             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1530                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1531             else
1532             {
1533                 for(y = src_rect->top; y < src_rect->bottom; y++)
1534                 {
1535                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1536                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1537                     dst_start += dst->stride / 2;
1538                     src_start += src->stride / 2;
1539                 }
1540             }
1541         }
1542         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1543         {
1544             for(y = src_rect->top; y < src_rect->bottom; y++)
1545             {
1546                 dst_pixel = dst_start;
1547                 src_pixel = src_start;
1548                 for(x = src_rect->left; x < src_rect->right; x++)
1549                 {
1550                     src_val = *src_pixel++;
1551                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
1552                                    (((src_val >> src->green_shift) <<  5) & 0x03e0) |
1553                                    ( (src_val >> src->blue_shift)         & 0x001f);
1554                 }
1555                 if(pad_size) memset(dst_pixel, 0, pad_size);
1556                 dst_start += dst->stride / 2;
1557                 src_start += src->stride / 2;
1558             }
1559         }
1560         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1561         {
1562             for(y = src_rect->top; y < src_rect->bottom; y++)
1563             {
1564                 dst_pixel = dst_start;
1565                 src_pixel = src_start;
1566                 for(x = src_rect->left; x < src_rect->right; x++)
1567                 {
1568                     src_val = *src_pixel++;
1569                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
1570                                    (((src_val >> src->green_shift) <<  4) & 0x03e0) |
1571                                    ( (src_val >> src->blue_shift)         & 0x001f);
1572                 }
1573                 if(pad_size) memset(dst_pixel, 0, pad_size);
1574                 dst_start += dst->stride / 2;
1575                 src_start += src->stride / 2;
1576             }
1577         }
1578         else
1579         {
1580             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask);
1581             return FALSE;
1582         }
1583         break;
1584     }
1585
1586     case 8:
1587     {
1588         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1589         for(y = src_rect->top; y < src_rect->bottom; y++)
1590         {
1591             dst_pixel = dst_start;
1592             src_pixel = src_start;
1593             for(x = src_rect->left; x < src_rect->right; x++)
1594             {
1595                 RGBQUAD rgb;
1596                 src_val = *src_pixel++;
1597                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1598                 rgb = src->color_table[src_val];
1599                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1600                                ((rgb.rgbGreen << 2) & 0x03e0) |
1601                                ((rgb.rgbBlue  >> 3) & 0x001f);
1602             }
1603             if(pad_size) memset(dst_pixel, 0, pad_size);
1604             dst_start += dst->stride / 2;
1605             src_start += src->stride;
1606         }
1607         break;
1608     }
1609
1610     case 4:
1611     {
1612         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1613         for(y = src_rect->top; y < src_rect->bottom; y++)
1614         {
1615             dst_pixel = dst_start;
1616             src_pixel = src_start;
1617             for(x = src_rect->left; x < src_rect->right; x++)
1618             {
1619                 RGBQUAD rgb;
1620                 if(x & 1)
1621                     src_val = *src_pixel++ & 0xf;
1622                 else
1623                     src_val = (*src_pixel >> 4) & 0xf;
1624                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1625                 rgb = src->color_table[src_val];
1626                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1627                                ((rgb.rgbGreen << 2) & 0x03e0) |
1628                                ((rgb.rgbBlue  >> 3) & 0x001f);
1629             }
1630             if(pad_size) memset(dst_pixel, 0, pad_size);
1631             dst_start += dst->stride / 2;
1632             src_start += src->stride;
1633         }
1634         break;
1635     }
1636
1637     case 1:
1638     {
1639         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1640         for(y = src_rect->top; y < src_rect->bottom; y++)
1641         {
1642             dst_pixel = dst_start;
1643             src_pixel = src_start;
1644             for(x = src_rect->left; x < src_rect->right; x++)
1645             {
1646                 RGBQUAD rgb;
1647                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1648                 if((x % 8) == 7) src_pixel++;
1649                 rgb = src->color_table[src_val];
1650                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1651                                ((rgb.rgbGreen << 2) & 0x03e0) |
1652                                ((rgb.rgbBlue  >> 3) & 0x001f);
1653             }
1654             if(pad_size) memset(dst_pixel, 0, pad_size);
1655             dst_start += dst->stride / 2;
1656             src_start += src->stride;
1657         }
1658         break;
1659     }
1660
1661     default:
1662         FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
1663         return FALSE;
1664
1665     }
1666     return TRUE;
1667 }
1668
1669 static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
1670 {
1671     WORD *dst_start = dst->bits, *dst_pixel;
1672     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1673     DWORD src_val;
1674
1675     switch(src->bit_count)
1676     {
1677     case 32:
1678     {
1679         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1680
1681         if(src->funcs == &funcs_8888)
1682         {
1683             for(y = src_rect->top; y < src_rect->bottom; y++)
1684             {
1685                 dst_pixel = dst_start;
1686                 src_pixel = src_start;
1687                 for(x = src_rect->left; x < src_rect->right; x++)
1688                 {
1689                     src_val = *src_pixel++;
1690                     *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift,   dst->red_len)   |
1691                                    put_field((src_val >>  8) & 0xff, dst->green_shift, dst->green_len) |
1692                                    put_field( src_val        & 0xff, dst->blue_shift,  dst->blue_len);
1693                 }
1694                 if(pad_size) memset(dst_pixel, 0, pad_size);
1695                 dst_start += dst->stride / 2;
1696                 src_start += src->stride / 4;
1697             }
1698         }
1699         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1700         {
1701             for(y = src_rect->top; y < src_rect->bottom; y++)
1702             {
1703                 dst_pixel = dst_start;
1704                 src_pixel = src_start;
1705                 for(x = src_rect->left; x < src_rect->right; x++)
1706                 {
1707                     src_val = *src_pixel++;
1708                     *dst_pixel++ = put_field((src_val >> src->red_shift)   & 0xff, dst->red_shift,   dst->red_len)   |
1709                                    put_field((src_val >> src->green_shift) & 0xff, dst->green_shift, dst->green_len) |
1710                                    put_field((src_val >> src->blue_shift)  & 0xff, dst->blue_shift,  dst->blue_len);
1711                 }
1712                 if(pad_size) memset(dst_pixel, 0, pad_size);
1713                 dst_start += dst->stride / 2;
1714                 src_start += src->stride / 4;
1715             }
1716         }
1717         else
1718         {
1719             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 16\n", src->red_mask, src->green_mask, src->blue_mask);
1720             return FALSE;
1721         }
1722         break;
1723     }
1724
1725     case 24:
1726     {
1727         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1728
1729         for(y = src_rect->top; y < src_rect->bottom; y++)
1730         {
1731             dst_pixel = dst_start;
1732             src_pixel = src_start;
1733             for(x = src_rect->left; x < src_rect->right; x++)
1734             {
1735                 RGBQUAD rgb;
1736                 rgb.rgbBlue  = *src_pixel++;
1737                 rgb.rgbGreen = *src_pixel++;
1738                 rgb.rgbRed   = *src_pixel++;
1739
1740                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1741                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1742                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1743             }
1744             if(pad_size) memset(dst_pixel, 0, pad_size);
1745             dst_start += dst->stride / 2;
1746             src_start += src->stride;
1747         }
1748         break;
1749     }
1750
1751     case 16:
1752     {
1753         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1754         if(src->funcs == &funcs_555)
1755         {
1756             for(y = src_rect->top; y < src_rect->bottom; y++)
1757             {
1758                 dst_pixel = dst_start;
1759                 src_pixel = src_start;
1760                 for(x = src_rect->left; x < src_rect->right; x++)
1761                 {
1762                     src_val = *src_pixel++;
1763                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
1764                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
1765                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
1766                 }
1767                 if(pad_size) memset(dst_pixel, 0, pad_size);
1768                 dst_start += dst->stride / 2;
1769                 src_start += src->stride / 2;
1770             }
1771         }
1772         else if(bit_fields_match(src, dst))
1773         {
1774             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1775                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1776             else
1777             {
1778                 for(y = src_rect->top; y < src_rect->bottom; y++)
1779                 {
1780                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1781                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1782                     dst_start += dst->stride / 2;
1783                     src_start += src->stride / 2;
1784                 }
1785             }
1786         }
1787         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1788         {
1789             for(y = src_rect->top; y < src_rect->bottom; y++)
1790             {
1791                 dst_pixel = dst_start;
1792                 src_pixel = src_start;
1793                 for(x = src_rect->left; x < src_rect->right; x++)
1794                 {
1795                     src_val = *src_pixel++;
1796                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1797                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1798                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1799                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1800                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1801                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1802                 }
1803                 if(pad_size) memset(dst_pixel, 0, pad_size);
1804                 dst_start += dst->stride / 2;
1805                 src_start += src->stride / 2;
1806             }
1807         }
1808         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1809         {
1810             for(y = src_rect->top; y < src_rect->bottom; y++)
1811             {
1812                 dst_pixel = dst_start;
1813                 src_pixel = src_start;
1814                 for(x = src_rect->left; x < src_rect->right; x++)
1815                 {
1816                     src_val = *src_pixel++;
1817                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1818                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1819                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1820                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1821                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1822                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1823                 }
1824                 if(pad_size) memset(dst_pixel, 0, pad_size);
1825                 dst_start += dst->stride / 2;
1826                 src_start += src->stride / 2;
1827             }
1828         }
1829         else
1830         {
1831             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 16 (%08x, %08x, %08x)\n",
1832                   src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask);
1833             return FALSE;
1834         }
1835         break;
1836     }
1837
1838     case 8:
1839     {
1840         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1841         for(y = src_rect->top; y < src_rect->bottom; y++)
1842         {
1843             dst_pixel = dst_start;
1844             src_pixel = src_start;
1845             for(x = src_rect->left; x < src_rect->right; x++)
1846             {
1847                 RGBQUAD rgb;
1848                 src_val = *src_pixel++;
1849                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1850                 rgb = src->color_table[src_val];
1851                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1852                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1853                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1854             }
1855             if(pad_size) memset(dst_pixel, 0, pad_size);
1856             dst_start += dst->stride / 2;
1857             src_start += src->stride;
1858         }
1859         break;
1860     }
1861
1862     case 4:
1863     {
1864         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1865         for(y = src_rect->top; y < src_rect->bottom; y++)
1866         {
1867             dst_pixel = dst_start;
1868             src_pixel = src_start;
1869             for(x = src_rect->left; x < src_rect->right; x++)
1870             {
1871                 RGBQUAD rgb;
1872                 if(x & 1)
1873                     src_val = *src_pixel++ & 0xf;
1874                 else
1875                     src_val = (*src_pixel >> 4) & 0xf;
1876                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1877                 rgb = src->color_table[src_val];
1878                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1879                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1880                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1881             }
1882             if(pad_size) memset(dst_pixel, 0, pad_size);
1883             dst_start += dst->stride / 2;
1884             src_start += src->stride;
1885         }
1886         break;
1887     }
1888
1889     case 1:
1890     {
1891         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1892         for(y = src_rect->top; y < src_rect->bottom; y++)
1893         {
1894             dst_pixel = dst_start;
1895             src_pixel = src_start;
1896             for(x = src_rect->left; x < src_rect->right; x++)
1897             {
1898                 RGBQUAD rgb;
1899                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1900                 if((x % 8) == 7) src_pixel++;
1901                 rgb = src->color_table[src_val];
1902                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1903                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1904                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1905             }
1906             if(pad_size) memset(dst_pixel, 0, pad_size);
1907             dst_start += dst->stride / 2;
1908             src_start += src->stride;
1909         }
1910         break;
1911     }
1912
1913     default:
1914         FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
1915         return FALSE;
1916
1917     }
1918     return TRUE;
1919 }
1920
1921 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
1922 {
1923     assert(d1->color_table_size && d2->color_table_size);
1924
1925     if(d1->color_table_size != d2->color_table_size) return FALSE;
1926     return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
1927 }
1928
1929 static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
1930 {
1931     BYTE *dst_start = dst->bits, *dst_pixel;
1932     INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
1933     DWORD src_val;
1934
1935     switch(src->bit_count)
1936     {
1937     case 32:
1938     {
1939         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1940
1941         if(src->funcs == &funcs_8888)
1942         {
1943             for(y = src_rect->top; y < src_rect->bottom; y++)
1944             {
1945                 dst_pixel = dst_start;
1946                 src_pixel = src_start;
1947                 for(x = src_rect->left; x < src_rect->right; x++)
1948                 {
1949                     src_val = *src_pixel++;
1950                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1951                                                                      ( src_val        & 0x00ff00) |
1952                                                                      ((src_val << 16) & 0xff0000) );
1953                 }
1954                 if(pad_size) memset(dst_pixel, 0, pad_size);
1955                 dst_start += dst->stride;
1956                 src_start += src->stride / 4;
1957             }
1958         }
1959         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1960         {
1961             for(y = src_rect->top; y < src_rect->bottom; y++)
1962             {
1963                 dst_pixel = dst_start;
1964                 src_pixel = src_start;
1965                 for(x = src_rect->left; x < src_rect->right; x++)
1966                 {
1967                     src_val = *src_pixel++;
1968                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift)          & 0x0000ff) |
1969                                                                      (((src_val >> src->green_shift) <<  8) & 0x00ff00) |
1970                                                                      (((src_val >> src->blue_shift)  << 16) & 0xff0000) );
1971                 }
1972                 if(pad_size) memset(dst_pixel, 0, pad_size);
1973                 dst_start += dst->stride;
1974                 src_start += src->stride / 4;
1975             }
1976         }
1977         else
1978         {
1979             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask);
1980             return FALSE;
1981         }
1982         break;
1983     }
1984
1985     case 24:
1986     {
1987         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1988
1989         for(y = src_rect->top; y < src_rect->bottom; y++)
1990         {
1991             dst_pixel = dst_start;
1992             src_pixel = src_start;
1993             for(x = src_rect->left; x < src_rect->right; x++)
1994             {
1995                 RGBQUAD rgb;
1996                 rgb.rgbBlue  = *src_pixel++;
1997                 rgb.rgbGreen = *src_pixel++;
1998                 rgb.rgbRed   = *src_pixel++;
1999
2000                 *dst_pixel++ = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
2001                                                                  ((rgb.rgbGreen << 8) & 0x00ff00) |
2002                                                                  ((rgb.rgbBlue << 16) & 0xff0000));
2003             }
2004             if(pad_size) memset(dst_pixel, 0, pad_size);
2005             dst_start += dst->stride;
2006             src_start += src->stride;
2007         }
2008         break;
2009     }
2010
2011     case 16:
2012     {
2013         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2014         if(src->funcs == &funcs_555)
2015         {
2016             for(y = src_rect->top; y < src_rect->bottom; y++)
2017             {
2018                 dst_pixel = dst_start;
2019                 src_pixel = src_start;
2020                 for(x = src_rect->left; x < src_rect->right; x++)
2021                 {
2022                     src_val = *src_pixel++;
2023                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2024                                                                      ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
2025                                                                      ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
2026                 }
2027                 if(pad_size) memset(dst_pixel, 0, pad_size);
2028                 dst_start += dst->stride;
2029                 src_start += src->stride / 2;
2030             }
2031         }
2032         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2033         {
2034             for(y = src_rect->top; y < src_rect->bottom; y++)
2035             {
2036                 dst_pixel = dst_start;
2037                 src_pixel = src_start;
2038                 for(x = src_rect->left; x < src_rect->right; x++)
2039                 {
2040                     src_val = *src_pixel++;
2041                     *dst_pixel++ = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2042                                                                      (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2043                                                                      (((src_val >> src->green_shift) << 11) & 0x00f800) |
2044                                                                      (((src_val >> src->green_shift) <<  6) & 0x000700) |
2045                                                                      (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2046                                                                      (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2047                 }
2048                 if(pad_size) memset(dst_pixel, 0, pad_size);
2049                 dst_start += dst->stride;
2050                 src_start += src->stride / 2;
2051             }
2052         }
2053         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2054         {
2055             for(y = src_rect->top; y < src_rect->bottom; y++)
2056             {
2057                 dst_pixel = dst_start;
2058                 src_pixel = src_start;
2059                 for(x = src_rect->left; x < src_rect->right; x++)
2060                 {
2061                     src_val = *src_pixel++;
2062                     *dst_pixel++ = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2063                                                                      (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2064                                                                      (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2065                                                                      (((src_val >> src->green_shift) <<  4) & 0x000300) |
2066                                                                      (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2067                                                                      (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2068                 }
2069                 if(pad_size) memset(dst_pixel, 0, pad_size);
2070                 dst_start += dst->stride;
2071                 src_start += src->stride / 2;
2072             }
2073         }
2074         else
2075         {
2076             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask);
2077             return FALSE;
2078         }
2079         break;
2080     }
2081
2082     case 8:
2083     {
2084         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2085
2086         if(color_tables_match(dst, src))
2087         {
2088             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2089                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2090             else
2091             {
2092                 for(y = src_rect->top; y < src_rect->bottom; y++)
2093                 {
2094                     memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2095                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2096                     dst_start += dst->stride;
2097                     src_start += src->stride;
2098                 }
2099             }
2100         }
2101         else
2102         {
2103             for(y = src_rect->top; y < src_rect->bottom; y++)
2104             {
2105                 dst_pixel = dst_start;
2106                 src_pixel = src_start;
2107                 for(x = src_rect->left; x < src_rect->right; x++)
2108                 {
2109                     RGBQUAD rgb;
2110                     src_val = *src_pixel++;
2111                     if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2112                     rgb = src->color_table[src_val];
2113                     *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2114                 }
2115                 if(pad_size) memset(dst_pixel, 0, pad_size);
2116                 dst_start += dst->stride;
2117                 src_start += src->stride;
2118             }
2119         }
2120         break;
2121     }
2122
2123     case 4:
2124     {
2125         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2126         for(y = src_rect->top; y < src_rect->bottom; y++)
2127         {
2128             dst_pixel = dst_start;
2129             src_pixel = src_start;
2130             for(x = src_rect->left; x < src_rect->right; x++)
2131             {
2132                 RGBQUAD rgb;
2133                 if(x & 1)
2134                     src_val = *src_pixel++ & 0xf;
2135                 else
2136                     src_val = (*src_pixel >> 4) & 0xf;
2137                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2138                 rgb = src->color_table[src_val];
2139                 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2140             }
2141             if(pad_size) memset(dst_pixel, 0, pad_size);
2142             dst_start += dst->stride;
2143             src_start += src->stride;
2144         }
2145         break;
2146     }
2147
2148     case 1:
2149     {
2150         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2151         for(y = src_rect->top; y < src_rect->bottom; y++)
2152         {
2153             dst_pixel = dst_start;
2154             src_pixel = src_start;
2155             for(x = src_rect->left; x < src_rect->right; x++)
2156             {
2157                 RGBQUAD rgb;
2158                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2159                 if((x % 8) == 7) src_pixel++;
2160                 rgb = src->color_table[src_val];
2161                 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2162             }
2163             if(pad_size) memset(dst_pixel, 0, pad_size);
2164             dst_start += dst->stride;
2165             src_start += src->stride;
2166         }
2167         break;
2168     }
2169
2170     default:
2171         FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
2172         return FALSE;
2173
2174     }
2175     return TRUE;
2176 }
2177
2178 static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2179 {
2180     BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
2181     INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2182     DWORD src_val;
2183
2184     switch(src->bit_count)
2185     {
2186     case 32:
2187     {
2188         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2189
2190         if(src->funcs == &funcs_8888)
2191         {
2192             for(y = src_rect->top; y < src_rect->bottom; y++)
2193             {
2194                 dst_pixel = dst_start;
2195                 src_pixel = src_start;
2196                 for(x = src_rect->left; x < src_rect->right; x++)
2197                 {
2198                     src_val = *src_pixel++;
2199                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
2200                                                                 ( src_val        & 0x00ff00) |
2201                                                                 ((src_val << 16) & 0xff0000) );
2202                     if((x - src_rect->left) & 1)
2203                     {
2204                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2205                         dst_pixel++;
2206                     }
2207                     else
2208                         *dst_pixel = (dst_val << 4) & 0xf0;
2209                 }
2210                 if(pad_size)
2211                 {
2212                     if((x - src_rect->left) & 1) dst_pixel++;
2213                     memset(dst_pixel, 0, pad_size);
2214                 }
2215                 dst_start += dst->stride;
2216                 src_start += src->stride / 4;
2217             }
2218         }
2219         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2220         {
2221             for(y = src_rect->top; y < src_rect->bottom; y++)
2222             {
2223                 dst_pixel = dst_start;
2224                 src_pixel = src_start;
2225                 for(x = src_rect->left; x < src_rect->right; x++)
2226                 {
2227                     src_val = *src_pixel++;
2228                     dst_val = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift)          & 0x0000ff) |
2229                                                                 (((src_val >> src->green_shift) <<  8) & 0x00ff00) |
2230                                                                 (((src_val >> src->blue_shift)  << 16) & 0xff0000) );
2231                     if((x - src_rect->left) & 1)
2232                     {
2233                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2234                         dst_pixel++;
2235                     }
2236                     else
2237                         *dst_pixel = (dst_val << 4) & 0xf0;
2238                 }
2239                 if(pad_size)
2240                 {
2241                     if((x - src_rect->left) & 1) dst_pixel++;
2242                     memset(dst_pixel, 0, pad_size);
2243                 }
2244                 dst_start += dst->stride;
2245                 src_start += src->stride / 4;
2246             }
2247         }
2248         else
2249         {
2250             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask);
2251             return FALSE;
2252         }
2253         break;
2254     }
2255
2256     case 24:
2257     {
2258         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2259
2260         for(y = src_rect->top; y < src_rect->bottom; y++)
2261         {
2262             dst_pixel = dst_start;
2263             src_pixel = src_start;
2264             for(x = src_rect->left; x < src_rect->right; x++)
2265             {
2266                 RGBQUAD rgb;
2267                 rgb.rgbBlue  = *src_pixel++;
2268                 rgb.rgbGreen = *src_pixel++;
2269                 rgb.rgbRed   = *src_pixel++;
2270
2271                 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
2272                                                             ((rgb.rgbGreen << 8) & 0x00ff00) |
2273                                                             ((rgb.rgbBlue << 16) & 0xff0000));
2274
2275                 if((x - src_rect->left) & 1)
2276                 {
2277                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2278                     dst_pixel++;
2279                 }
2280                 else
2281                     *dst_pixel = (dst_val << 4) & 0xf0;
2282             }
2283             if(pad_size)
2284             {
2285                 if((x - src_rect->left) & 1) dst_pixel++;
2286                 memset(dst_pixel, 0, pad_size);
2287             }
2288             dst_start += dst->stride;
2289             src_start += src->stride;
2290         }
2291         break;
2292     }
2293
2294     case 16:
2295     {
2296         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2297         if(src->funcs == &funcs_555)
2298         {
2299             for(y = src_rect->top; y < src_rect->bottom; y++)
2300             {
2301                 dst_pixel = dst_start;
2302                 src_pixel = src_start;
2303                 for(x = src_rect->left; x < src_rect->right; x++)
2304                 {
2305                     src_val = *src_pixel++;
2306                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2307                                                                 ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
2308                                                                 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
2309                     if((x - src_rect->left) & 1)
2310                     {
2311                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2312                         dst_pixel++;
2313                     }
2314                     else
2315                         *dst_pixel = (dst_val << 4) & 0xf0;
2316                 }
2317                 if(pad_size)
2318                 {
2319                     if((x - src_rect->left) & 1) dst_pixel++;
2320                     memset(dst_pixel, 0, pad_size);
2321                 }
2322                 dst_start += dst->stride;
2323                 src_start += src->stride / 2;
2324             }
2325         }
2326         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2327         {
2328             for(y = src_rect->top; y < src_rect->bottom; y++)
2329             {
2330                 dst_pixel = dst_start;
2331                 src_pixel = src_start;
2332                 for(x = src_rect->left; x < src_rect->right; x++)
2333                 {
2334                     src_val = *src_pixel++;
2335                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2336                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2337                                                                 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2338                                                                 (((src_val >> src->green_shift) <<  6) & 0x000700) |
2339                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2340                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2341                     if((x - src_rect->left) & 1)
2342                     {
2343                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2344                         dst_pixel++;
2345                     }
2346                     else
2347                         *dst_pixel = (dst_val << 4) & 0xf0;
2348                 }
2349                 if(pad_size)
2350                 {
2351                     if((x - src_rect->left) & 1) dst_pixel++;
2352                     memset(dst_pixel, 0, pad_size);
2353                 }
2354                 dst_start += dst->stride;
2355                 src_start += src->stride / 2;
2356             }
2357         }
2358         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2359         {
2360             for(y = src_rect->top; y < src_rect->bottom; y++)
2361             {
2362                 dst_pixel = dst_start;
2363                 src_pixel = src_start;
2364                 for(x = src_rect->left; x < src_rect->right; x++)
2365                 {
2366                     src_val = *src_pixel++;
2367                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2368                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2369                                                                 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2370                                                                 (((src_val >> src->green_shift) <<  4) & 0x000300) |
2371                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2372                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2373                     if((x - src_rect->left) & 1)
2374                     {
2375                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2376                         dst_pixel++;
2377                     }
2378                     else
2379                         *dst_pixel = (dst_val << 4) & 0xf0;
2380                 }
2381                 if(pad_size)
2382                 {
2383                     if((x - src_rect->left) & 1) dst_pixel++;
2384                     memset(dst_pixel, 0, pad_size);
2385                 }
2386                 dst_start += dst->stride;
2387                 src_start += src->stride / 2;
2388             }
2389         }
2390         else
2391         {
2392             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask);
2393             return FALSE;
2394         }
2395         break;
2396     }
2397
2398     case 8:
2399     {
2400         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2401
2402         for(y = src_rect->top; y < src_rect->bottom; y++)
2403         {
2404             dst_pixel = dst_start;
2405             src_pixel = src_start;
2406             for(x = src_rect->left; x < src_rect->right; x++)
2407             {
2408                 RGBQUAD rgb;
2409                 src_val = *src_pixel++;
2410                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2411                 rgb = src->color_table[src_val];
2412                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2413                 if((x - src_rect->left) & 1)
2414                 {
2415                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2416                     dst_pixel++;
2417                 }
2418                 else
2419                     *dst_pixel = (dst_val << 4) & 0xf0;
2420             }
2421             if(pad_size)
2422             {
2423                 if((x - src_rect->left) & 1) dst_pixel++;
2424                 memset(dst_pixel, 0, pad_size);
2425             }
2426             dst_start += dst->stride;
2427             src_start += src->stride;
2428         }
2429         break;
2430     }
2431
2432     case 4:
2433     {
2434         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2435
2436         if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
2437         {
2438             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2439                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2440             else
2441             {
2442                 for(y = src_rect->top; y < src_rect->bottom; y++)
2443                 {
2444                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
2445                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
2446                     dst_start += dst->stride;
2447                     src_start += src->stride;
2448                 }
2449             }
2450         }
2451         else
2452         {
2453             for(y = src_rect->top; y < src_rect->bottom; y++)
2454             {
2455                 dst_pixel = dst_start;
2456                 src_pixel = src_start;
2457                 for(x = src_rect->left; x < src_rect->right; x++)
2458                 {
2459                     RGBQUAD rgb;
2460                     if(x & 1)
2461                         src_val = *src_pixel++ & 0xf;
2462                     else
2463                         src_val = (*src_pixel >> 4) & 0xf;
2464                     if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2465                     rgb = src->color_table[src_val];
2466                     dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2467                     if((x - src_rect->left) & 1)
2468                     {
2469                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2470                         dst_pixel++;
2471                     }
2472                     else
2473                         *dst_pixel = (dst_val << 4) & 0xf0;
2474                 }
2475                 if(pad_size)
2476                 {
2477                     if((x - src_rect->left) & 1) dst_pixel++;
2478                     memset(dst_pixel, 0, pad_size);
2479                 }
2480                 dst_start += dst->stride;
2481                 src_start += src->stride;
2482             }
2483         }
2484         break;
2485     }
2486
2487     case 1:
2488     {
2489         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2490         for(y = src_rect->top; y < src_rect->bottom; y++)
2491         {
2492             dst_pixel = dst_start;
2493             src_pixel = src_start;
2494             for(x = src_rect->left; x < src_rect->right; x++)
2495             {
2496                 RGBQUAD rgb;
2497                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2498                 if((x % 8) == 7) src_pixel++;
2499                 rgb = src->color_table[src_val];
2500                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2501                 if((x - src_rect->left) & 1)
2502                 {
2503                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2504                     dst_pixel++;
2505                 }
2506                 else
2507                     *dst_pixel = (dst_val << 4) & 0xf0;
2508             }
2509             if(pad_size)
2510             {
2511                 if((x - src_rect->left) & 1) dst_pixel++;
2512                 memset(dst_pixel, 0, pad_size);
2513             }
2514             dst_start += dst->stride;
2515             src_start += src->stride;
2516         }
2517         break;
2518     }
2519
2520     default:
2521         FIXME("Unsupported conversion: %d -> 4\n", src->bit_count);
2522         return FALSE;
2523
2524     }
2525
2526     return TRUE;
2527 }
2528
2529 static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
2530 {
2531     BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
2532     INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
2533     DWORD src_val;
2534     int bit_pos;
2535
2536     /* FIXME: Brushes should be dithered. */
2537
2538     switch(src->bit_count)
2539     {
2540     case 32:
2541     {
2542         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2543
2544         if(src->funcs == &funcs_8888)
2545         {
2546             for(y = src_rect->top; y < src_rect->bottom; y++)
2547             {
2548                 dst_pixel = dst_start;
2549                 src_pixel = src_start;
2550                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2551                 {
2552                     src_val = *src_pixel++;
2553                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
2554                                                                 ( src_val        & 0x00ff00) |
2555                                                                 ((src_val << 16) & 0xff0000) ) ? 0xff : 0;
2556
2557                     if(bit_pos == 0) *dst_pixel = 0;
2558                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2559
2560                     if(++bit_pos == 8)
2561                     {
2562                         dst_pixel++;
2563                         bit_pos = 0;
2564                     }
2565                 }
2566                 if(pad_size)
2567                 {
2568                     if(bit_pos != 0) dst_pixel++;
2569                     memset(dst_pixel, 0, pad_size);
2570                 }
2571                 dst_start += dst->stride;
2572                 src_start += src->stride / 4;
2573             }
2574         }
2575         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2576         {
2577             for(y = src_rect->top; y < src_rect->bottom; y++)
2578             {
2579                 dst_pixel = dst_start;
2580                 src_pixel = src_start;
2581                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2582                 {
2583                     src_val = *src_pixel++;
2584                     dst_val = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift)          & 0x0000ff) |
2585                                                                 (((src_val >> src->green_shift) <<  8) & 0x00ff00) |
2586                                                                 (((src_val >> src->blue_shift)  << 16) & 0xff0000) ) ? 0xff : 0;
2587
2588                    if(bit_pos == 0) *dst_pixel = 0;
2589                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2590
2591                     if(++bit_pos == 8)
2592                     {
2593                         dst_pixel++;
2594                         bit_pos = 0;
2595                     }
2596                 }
2597                 if(pad_size)
2598                 {
2599                     if(bit_pos != 0) dst_pixel++;
2600                     memset(dst_pixel, 0, pad_size);
2601                 }
2602                 dst_start += dst->stride;
2603                 src_start += src->stride / 4;
2604             }
2605         }
2606         else
2607         {
2608             FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask);
2609             return FALSE;
2610         }
2611         break;
2612     }
2613
2614     case 24:
2615     {
2616         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2617
2618         for(y = src_rect->top; y < src_rect->bottom; y++)
2619         {
2620             dst_pixel = dst_start;
2621             src_pixel = src_start;
2622             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2623             {
2624                 RGBQUAD rgb;
2625                 rgb.rgbBlue  = *src_pixel++;
2626                 rgb.rgbGreen = *src_pixel++;
2627                 rgb.rgbRed   = *src_pixel++;
2628
2629                 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
2630                                                             ((rgb.rgbGreen << 8) & 0x00ff00) |
2631                                                             ((rgb.rgbBlue << 16) & 0xff0000)) ? 0xff : 0;
2632
2633                 if(bit_pos == 0) *dst_pixel = 0;
2634                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2635
2636                 if(++bit_pos == 8)
2637                 {
2638                     dst_pixel++;
2639                     bit_pos = 0;
2640                 }
2641             }
2642             if(pad_size)
2643             {
2644                 if(bit_pos != 0) dst_pixel++;
2645                 memset(dst_pixel, 0, pad_size);
2646             }
2647             dst_start += dst->stride;
2648             src_start += src->stride;
2649         }
2650         break;
2651     }
2652
2653     case 16:
2654     {
2655         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2656         if(src->funcs == &funcs_555)
2657         {
2658             for(y = src_rect->top; y < src_rect->bottom; y++)
2659             {
2660                 dst_pixel = dst_start;
2661                 src_pixel = src_start;
2662                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2663                 {
2664                     src_val = *src_pixel++;
2665                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2666                                                                 ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
2667                                                                 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) ) ? 0xff : 0;
2668
2669                     if(bit_pos == 0) *dst_pixel = 0;
2670                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2671
2672                     if(++bit_pos == 8)
2673                     {
2674                         dst_pixel++;
2675                         bit_pos = 0;
2676                     }
2677                 }
2678                 if(pad_size)
2679                 {
2680                     if(bit_pos != 0) dst_pixel++;
2681                     memset(dst_pixel, 0, pad_size);
2682                 }
2683                 dst_start += dst->stride;
2684                 src_start += src->stride / 2;
2685             }
2686         }
2687         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2688         {
2689             for(y = src_rect->top; y < src_rect->bottom; y++)
2690             {
2691                 dst_pixel = dst_start;
2692                 src_pixel = src_start;
2693                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2694                 {
2695                     src_val = *src_pixel++;
2696                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2697                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2698                                                                 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2699                                                                 (((src_val >> src->green_shift) <<  6) & 0x000700) |
2700                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2701                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) ) ? 0xff : 0;
2702                     if(bit_pos == 0) *dst_pixel = 0;
2703                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2704
2705                     if(++bit_pos == 8)
2706                     {
2707                         dst_pixel++;
2708                         bit_pos = 0;
2709                     }
2710                 }
2711                 if(pad_size)
2712                 {
2713                     if(bit_pos != 0) dst_pixel++;
2714                     memset(dst_pixel, 0, pad_size);
2715                 }
2716                 dst_start += dst->stride;
2717                 src_start += src->stride / 2;
2718             }
2719         }
2720         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2721         {
2722             for(y = src_rect->top; y < src_rect->bottom; y++)
2723             {
2724                 dst_pixel = dst_start;
2725                 src_pixel = src_start;
2726                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2727                 {
2728                     src_val = *src_pixel++;
2729                     dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift)   <<  3) & 0x0000f8) |
2730                                                                 (((src_val >> src->red_shift)   >>  2) & 0x000007) |
2731                                                                 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2732                                                                 (((src_val >> src->green_shift) <<  4) & 0x000300) |
2733                                                                 (((src_val >> src->blue_shift)  << 19) & 0xf80000) |
2734                                                                 (((src_val >> src->blue_shift)  << 14) & 0x070000) );
2735                     if(bit_pos == 0) *dst_pixel = 0;
2736                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2737
2738                     if(++bit_pos == 8)
2739                     {
2740                         dst_pixel++;
2741                         bit_pos = 0;
2742                     }
2743                 }
2744                 if(pad_size)
2745                 {
2746                     if(bit_pos != 0) dst_pixel++;
2747                     memset(dst_pixel, 0, pad_size);
2748                 }
2749                 dst_start += dst->stride;
2750                 src_start += src->stride / 2;
2751             }
2752         }
2753         else
2754         {
2755             FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask);
2756             return FALSE;
2757         }
2758         break;
2759     }
2760
2761     case 8:
2762     {
2763         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2764
2765         for(y = src_rect->top; y < src_rect->bottom; y++)
2766         {
2767             dst_pixel = dst_start;
2768             src_pixel = src_start;
2769             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2770             {
2771                 RGBQUAD rgb;
2772                 src_val = *src_pixel++;
2773                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2774                 rgb = src->color_table[src_val];
2775                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2776
2777                 if(bit_pos == 0) *dst_pixel = 0;
2778                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2779
2780                 if(++bit_pos == 8)
2781                 {
2782                     dst_pixel++;
2783                     bit_pos = 0;
2784                 }
2785             }
2786             if(pad_size)
2787             {
2788                 if(bit_pos != 0) dst_pixel++;
2789                 memset(dst_pixel, 0, pad_size);
2790             }
2791             dst_start += dst->stride;
2792             src_start += src->stride;
2793         }
2794         break;
2795     }
2796
2797     case 4:
2798     {
2799         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2800
2801         for(y = src_rect->top; y < src_rect->bottom; y++)
2802         {
2803             dst_pixel = dst_start;
2804             src_pixel = src_start;
2805             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2806             {
2807                 RGBQUAD rgb;
2808                 if(x & 1)
2809                     src_val = *src_pixel++ & 0xf;
2810                 else
2811                     src_val = (*src_pixel >> 4) & 0xf;
2812                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2813                 rgb = src->color_table[src_val];
2814                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2815
2816                 if(bit_pos == 0) *dst_pixel = 0;
2817                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2818
2819                 if(++bit_pos == 8)
2820                 {
2821                     dst_pixel++;
2822                     bit_pos = 0;
2823                 }
2824             }
2825             if(pad_size)
2826             {
2827                 if(bit_pos != 0) dst_pixel++;
2828                 memset(dst_pixel, 0, pad_size);
2829             }
2830             dst_start += dst->stride;
2831             src_start += src->stride;
2832         }
2833         break;
2834     }
2835
2836     /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
2837        uses text/bkgnd colours instead of the dib's colour table, this
2838        doesn't appear to be the case for a dc backed by a
2839        dibsection. */
2840
2841     case 1:
2842     {
2843         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2844         for(y = src_rect->top; y < src_rect->bottom; y++)
2845         {
2846             dst_pixel = dst_start;
2847             src_pixel = src_start;
2848             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2849             {
2850                 RGBQUAD rgb;
2851                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2852                 if((x % 8) == 7) src_pixel++;
2853                 rgb = src->color_table[src_val];
2854                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2855
2856                 if(bit_pos == 0) *dst_pixel = 0;
2857                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2858
2859                 if(++bit_pos == 8)
2860                 {
2861                     dst_pixel++;
2862                     bit_pos = 0;
2863                 }
2864             }
2865             if(pad_size)
2866             {
2867                 if(bit_pos != 0) dst_pixel++;
2868                 memset(dst_pixel, 0, pad_size);
2869             }
2870             dst_start += dst->stride;
2871             src_start += src->stride;
2872         }
2873         break;
2874     }
2875
2876     default:
2877         FIXME("Unsupported conversion: %d -> 1\n", src->bit_count);
2878         return FALSE;
2879
2880     }
2881     return TRUE;
2882 }
2883
2884 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
2885 {
2886     return FALSE;
2887 }
2888
2889 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)
2890 {
2891     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2892     DWORD mask_start = 0, mask_offset;
2893     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
2894     int x, y;
2895
2896     for(y = 0; y < hatch->height; y++)
2897     {
2898         hatch_ptr = hatch_start;
2899         mask_offset = mask_start;
2900         for(x = 0; x < hatch->width; x++)
2901         {
2902             if(*hatch_ptr & pixel_masks_1[x % 8])
2903             {
2904                 and_bits[mask_offset] = fg->and;
2905                 xor_bits[mask_offset] = fg->xor;
2906             }
2907             else
2908             {
2909                 and_bits[mask_offset] = bg->and;
2910                 xor_bits[mask_offset] = bg->xor;
2911             }
2912             if(x % 8 == 7) hatch_ptr++;
2913             mask_offset++;
2914         }
2915         hatch_start += hatch->stride;
2916         mask_start += dib->stride / 4;
2917     }
2918
2919     return TRUE;
2920 }
2921
2922 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)
2923 {
2924     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2925     DWORD mask_start = 0, mask_offset;
2926     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2927     int x, y;
2928
2929     for(y = 0; y < hatch->height; y++)
2930     {
2931         hatch_ptr = hatch_start;
2932         mask_offset = mask_start;
2933         for(x = 0; x < hatch->width; x++)
2934         {
2935             if(*hatch_ptr & pixel_masks_1[x % 8])
2936             {
2937                 and_bits[mask_offset]   =  fg->and        & 0xff;
2938                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
2939                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
2940                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
2941                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
2942                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
2943             }
2944             else
2945             {
2946                 and_bits[mask_offset]   =  bg->and        & 0xff;
2947                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
2948                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
2949                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
2950                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
2951                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
2952             }
2953             if(x % 8 == 7) hatch_ptr++;
2954         }
2955         hatch_start += hatch->stride;
2956         mask_start += dib->stride;
2957     }
2958
2959     return TRUE;
2960 }
2961
2962 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)
2963 {
2964     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2965     DWORD mask_start = 0, mask_offset;
2966     WORD *and_bits = bits->and, *xor_bits = bits->xor;
2967     int x, y;
2968
2969     for(y = 0; y < hatch->height; y++)
2970     {
2971         hatch_ptr = hatch_start;
2972         mask_offset = mask_start;
2973         for(x = 0; x < hatch->width; x++)
2974         {
2975             if(*hatch_ptr & pixel_masks_1[x % 8])
2976             {
2977                 and_bits[mask_offset] = fg->and;
2978                 xor_bits[mask_offset] = fg->xor;
2979             }
2980             else
2981             {
2982                 and_bits[mask_offset] = bg->and;
2983                 xor_bits[mask_offset] = bg->xor;
2984             }
2985             if(x % 8 == 7) hatch_ptr++;
2986             mask_offset++;
2987         }
2988         hatch_start += hatch->stride;
2989         mask_start += dib->stride / 2;
2990     }
2991
2992     return TRUE;
2993 }
2994
2995 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)
2996 {
2997     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2998     DWORD mask_start = 0, mask_offset;
2999     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3000     int x, y;
3001
3002     for(y = 0; y < hatch->height; y++)
3003     {
3004         hatch_ptr = hatch_start;
3005         mask_offset = mask_start;
3006         for(x = 0; x < hatch->width; x++)
3007         {
3008             if(*hatch_ptr & pixel_masks_1[x % 8])
3009             {
3010                 and_bits[mask_offset] = fg->and;
3011                 xor_bits[mask_offset] = fg->xor;
3012             }
3013             else
3014             {
3015                 and_bits[mask_offset] = bg->and;
3016                 xor_bits[mask_offset] = bg->xor;
3017             }
3018             if(x % 8 == 7) hatch_ptr++;
3019             mask_offset++;
3020         }
3021         hatch_start += hatch->stride;
3022         mask_start += dib->stride;
3023     }
3024
3025     return TRUE;
3026 }
3027
3028 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)
3029 {
3030     BYTE *hatch_start = hatch->bits, *hatch_ptr;
3031     DWORD mask_start = 0, mask_offset;
3032     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3033     const rop_mask *rop_mask;
3034     int x, y;
3035
3036     for(y = 0; y < hatch->height; y++)
3037     {
3038         hatch_ptr = hatch_start;
3039         mask_offset = mask_start;
3040         for(x = 0; x < hatch->width; x++)
3041         {
3042             if(*hatch_ptr & pixel_masks_1[x % 8])
3043                 rop_mask = fg;
3044             else
3045                 rop_mask = bg;
3046
3047             if(x & 1)
3048             {
3049                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3050                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3051                 mask_offset++;
3052             }
3053             else
3054             {
3055                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3056                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3057             }
3058
3059             if(x % 8 == 7) hatch_ptr++;
3060         }
3061         hatch_start += hatch->stride;
3062         mask_start += dib->stride;
3063     }
3064
3065     return TRUE;
3066 }
3067
3068 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)
3069 {
3070     BYTE *hatch_start = hatch->bits, *hatch_ptr;
3071     DWORD mask_start = 0, mask_offset;
3072     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3073     rop_mask rop_mask;
3074     int x, y, bit_pos;
3075
3076     for(y = 0; y < hatch->height; y++)
3077     {
3078         hatch_ptr = hatch_start;
3079         mask_offset = mask_start;
3080         for(x = 0, bit_pos = 0; x < hatch->width; x++)
3081         {
3082             if(*hatch_ptr & pixel_masks_1[x % 8])
3083             {
3084                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3085                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3086             }
3087             else
3088             {
3089                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3090                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3091             }
3092
3093             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3094
3095             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3096             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3097
3098             if(++bit_pos == 8)
3099             {
3100                 mask_offset++;
3101                 hatch_ptr++;
3102                 bit_pos = 0;
3103             }
3104         }
3105         hatch_start += hatch->stride;
3106         mask_start += dib->stride;
3107     }
3108
3109     return TRUE;
3110 }
3111
3112 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)
3113 {
3114     return FALSE;
3115 }
3116
3117 const primitive_funcs funcs_8888 =
3118 {
3119     solid_rects_32,
3120     pattern_rects_32,
3121     colorref_to_pixel_888,
3122     convert_to_8888,
3123     create_rop_masks_32
3124 };
3125
3126 const primitive_funcs funcs_32 =
3127 {
3128     solid_rects_32,
3129     pattern_rects_32,
3130     colorref_to_pixel_masks,
3131     convert_to_32,
3132     create_rop_masks_32
3133 };
3134
3135 const primitive_funcs funcs_24 =
3136 {
3137     solid_rects_24,
3138     pattern_rects_24,
3139     colorref_to_pixel_888,
3140     convert_to_24,
3141     create_rop_masks_24
3142 };
3143
3144 const primitive_funcs funcs_555 =
3145 {
3146     solid_rects_16,
3147     pattern_rects_16,
3148     colorref_to_pixel_555,
3149     convert_to_555,
3150     create_rop_masks_16
3151 };
3152
3153 const primitive_funcs funcs_16 =
3154 {
3155     solid_rects_16,
3156     pattern_rects_16,
3157     colorref_to_pixel_masks,
3158     convert_to_16,
3159     create_rop_masks_16
3160 };
3161
3162 const primitive_funcs funcs_8 =
3163 {
3164     solid_rects_8,
3165     pattern_rects_8,
3166     colorref_to_pixel_colortable,
3167     convert_to_8,
3168     create_rop_masks_8
3169 };
3170
3171 const primitive_funcs funcs_4 =
3172 {
3173     solid_rects_4,
3174     pattern_rects_4,
3175     colorref_to_pixel_colortable,
3176     convert_to_4,
3177     create_rop_masks_4
3178 };
3179
3180 const primitive_funcs funcs_1 =
3181 {
3182     solid_rects_1,
3183     pattern_rects_1,
3184     colorref_to_pixel_colortable,
3185     convert_to_1,
3186     create_rop_masks_1
3187 };
3188
3189 const primitive_funcs funcs_null =
3190 {
3191     solid_rects_null,
3192     pattern_rects_null,
3193     colorref_to_pixel_null,
3194     convert_to_null,
3195     create_rop_masks_null
3196 };