gdi32: Ask the graphics driver for the function table instead of loading functions...
[wine] / dlls / gdi32 / dibdrv / primitives.c
1 /*
2  * DIB driver primitives.
3  *
4  * Copyright 2011 Huw Davies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22
23 #include "gdi_private.h"
24 #include "dibdrv.h"
25
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(dib);
29
30 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
31 {
32     return (DWORD *)((BYTE*)dib->bits + y * dib->stride + x * 4);
33 }
34
35 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
36 {
37     return (DWORD *)((BYTE*)dib->bits + y * dib->stride) + x * 3 / 4;
38 }
39
40 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
41 {
42     return (BYTE*)dib->bits + y * dib->stride + x * 3;
43 }
44
45 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
46 {
47     return (WORD *)((BYTE*)dib->bits + y * dib->stride + x * 2);
48 }
49
50 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
51 {
52     return (BYTE*)dib->bits + y * dib->stride + x;
53 }
54
55 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
56 {
57     return (BYTE*)dib->bits + y * dib->stride + x / 2;
58 }
59
60 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
61 {
62     return (BYTE*)dib->bits + y * dib->stride + x / 8;
63 }
64
65 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
66
67 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
68 {
69     *ptr = (*ptr & and) ^ xor;
70 }
71
72 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
73 {
74     *ptr = (*ptr & and) ^ xor;
75 }
76
77 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
78 {
79     *ptr = (*ptr & and) ^ xor;
80 }
81
82 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
83 {
84     DWORD *ptr, *start;
85     int x, y, i;
86
87     for(i = 0; i < num; i++, rc++)
88     {
89         start = get_pixel_ptr_32(dib, rc->left, rc->top);
90         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
91             for(x = rc->left, ptr = start; x < rc->right; x++)
92                 do_rop_32(ptr++, and, xor);
93     }
94 }
95
96 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
97 {
98     DWORD *ptr, *start;
99     BYTE *byte_ptr, *byte_start;
100     int x, y, i;
101     DWORD and_masks[3], xor_masks[3];
102
103     and_masks[0] = ( and        & 0x00ffffff) | ((and << 24) & 0xff000000);
104     and_masks[1] = ((and >>  8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
105     and_masks[2] = ((and >> 16) & 0x000000ff) | ((and <<  8) & 0xffffff00);
106     xor_masks[0] = ( xor        & 0x00ffffff) | ((xor << 24) & 0xff000000);
107     xor_masks[1] = ((xor >>  8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
108     xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor <<  8) & 0xffffff00);
109
110     for(i = 0; i < num; i++, rc++)
111     {
112         if(rc->left >= rc->right) continue;
113
114         if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
115         {
116             byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
117             for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
118             {
119                 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
120                 {
121                     do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
122                     do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
123                     do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
124                 }
125             }
126         }
127         else
128         {
129             start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
130             for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
131             {
132                 ptr = start;
133
134                 switch(rc->left & 3)
135                 {
136                 case 1:
137                     do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
138                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
139                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
140                     break;
141                 case 2:
142                     do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
143                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
144                     break;
145                 case 3:
146                     do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
147                     break;
148                 }
149
150                 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
151                 {
152                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
153                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
154                     do_rop_32(ptr++, and_masks[2], xor_masks[2]);
155                 }
156
157                 switch(rc->right & 3)
158                 {
159                 case 1:
160                     do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
161                     break;
162                 case 2:
163                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
164                     do_rop_32(ptr,   and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
165                     break;
166                 case 3:
167                     do_rop_32(ptr++, and_masks[0], xor_masks[0]);
168                     do_rop_32(ptr++, and_masks[1], xor_masks[1]);
169                     do_rop_32(ptr,   and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
170                     break;
171                 }
172             }
173         }
174     }
175 }
176
177 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
178 {
179     WORD *ptr, *start;
180     int x, y, i;
181
182     for(i = 0; i < num; i++, rc++)
183     {
184         start = get_pixel_ptr_16(dib, rc->left, rc->top);
185         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
186             for(x = rc->left, ptr = start; x < rc->right; x++)
187                 do_rop_16(ptr++, and, xor);
188     }
189 }
190
191 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
192 {
193     BYTE *ptr, *start;
194     int x, y, i;
195
196     for(i = 0; i < num; i++, rc++)
197     {
198         start = get_pixel_ptr_8(dib, rc->left, rc->top);
199         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
200             for(x = rc->left, ptr = start; x < rc->right; x++)
201                 do_rop_8(ptr++, and, xor);
202     }
203 }
204
205 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
206 {
207     BYTE *ptr, *start;
208     int x, y, i;
209     BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
210     BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
211
212     for(i = 0; i < num; i++, rc++)
213     {
214         if(rc->left >= rc->right) continue;
215         start = get_pixel_ptr_4(dib, rc->left, rc->top);
216         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
217         {
218             ptr = start;
219             if(rc->left & 1) /* upper nibble untouched */
220                 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
221
222             for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
223                 do_rop_8(ptr++, byte_and, byte_xor);
224
225             if(rc->right & 1) /* lower nibble untouched */
226                 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
227         }
228     }
229 }
230
231 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
232 {
233     BYTE *ptr, *start;
234     int x, y, i;
235     BYTE byte_and = (and & 1) ? 0xff : 0;
236     BYTE byte_xor = (xor & 1) ? 0xff : 0;
237     BYTE start_and, start_xor, end_and, end_xor, mask;
238     static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
239
240     for(i = 0; i < num; i++, rc++)
241     {
242         if(rc->left >= rc->right) continue;
243
244         start = get_pixel_ptr_1(dib, rc->left, rc->top);
245
246         if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
247         {
248             mask = masks[rc->left & 7] & ~masks[rc->right & 7];
249
250             start_and = byte_and | ~mask;
251             start_xor = byte_xor & mask;
252             for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
253             {
254                 do_rop_8(start, start_and, start_xor);
255             }
256         }
257         else
258         {
259             mask = masks[rc->left & 7];
260             start_and = byte_and | ~mask;
261             start_xor = byte_xor & mask;
262
263             mask = masks[rc->right & 7];
264             /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
265             end_and = byte_and | mask;
266             end_xor = byte_xor & ~mask;
267
268             for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
269             {
270                 ptr = start;
271
272                 if(rc->left & 7)
273                     do_rop_8(ptr++, start_and, start_xor);
274
275                 for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
276                     do_rop_8(ptr++, byte_and, byte_xor);
277
278                 if(rc->right & 7)
279                     do_rop_8(ptr, end_and, end_xor);
280             }
281         }
282     }
283 }
284
285 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
286 {
287     return;
288 }
289
290 static inline INT calc_offset(INT edge, INT size, INT origin)
291 {
292     INT offset;
293
294     if(edge - origin >= 0)
295         offset = (edge - origin) % size;
296     else
297     {
298         offset = (origin - edge) % size;
299         if(offset) offset = size - offset;
300     }
301     return offset;
302 }
303
304 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
305 {
306     POINT offset;
307
308     offset.x = calc_offset(rc->left, brush->width,  origin->x);
309     offset.y = calc_offset(rc->top,  brush->height, origin->y);
310
311     return offset;
312 }
313
314 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
315                              const dib_info *brush, void *and_bits, void *xor_bits)
316 {
317     DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
318     int x, y, i;
319     POINT offset;
320
321     for(i = 0; i < num; i++, rc++)
322     {
323         offset = calc_brush_offset(rc, brush, origin);
324
325         start = get_pixel_ptr_32(dib, rc->left, rc->top);
326         start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
327         start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
328
329         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
330         {
331             and_ptr = start_and + offset.x;
332             xor_ptr = start_xor + offset.x;
333
334             for(x = rc->left, ptr = start; x < rc->right; x++)
335             {
336                 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
337                 if(and_ptr == start_and + brush->width)
338                 {
339                     and_ptr = start_and;
340                     xor_ptr = start_xor;
341                 }
342             }
343
344             offset.y++;
345             if(offset.y == brush->height)
346             {
347                 start_and = and_bits;
348                 start_xor = xor_bits;
349                 offset.y = 0;
350             }
351             else
352             {
353                 start_and += brush->stride / 4;
354                 start_xor += brush->stride / 4;
355             }
356         }
357     }
358 }
359
360 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
361                              const dib_info *brush, void *and_bits, void *xor_bits)
362 {
363     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
364     int x, y, i;
365     POINT offset;
366
367     for(i = 0; i < num; i++, rc++)
368     {
369         offset = calc_brush_offset(rc, brush, origin);
370
371         start = get_pixel_ptr_24(dib, rc->left, rc->top);
372         start_and = (BYTE*)and_bits + offset.y * brush->stride;
373         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
374
375         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
376         {
377             and_ptr = start_and + offset.x * 3;
378             xor_ptr = start_xor + offset.x * 3;
379
380             for(x = rc->left, ptr = start; x < rc->right; x++)
381             {
382                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
383                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
384                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
385                 if(and_ptr == start_and + brush->width * 3)
386                 {
387                     and_ptr = start_and;
388                     xor_ptr = start_xor;
389                 }
390             }
391
392             offset.y++;
393             if(offset.y == brush->height)
394             {
395                 start_and = and_bits;
396                 start_xor = xor_bits;
397                 offset.y = 0;
398             }
399             else
400             {
401                 start_and += brush->stride;
402                 start_xor += brush->stride;
403             }
404         }
405     }
406 }
407
408 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
409                              const dib_info *brush, void *and_bits, void *xor_bits)
410 {
411     WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
412     int x, y, i;
413     POINT offset;
414
415     for(i = 0; i < num; i++, rc++)
416     {
417         offset = calc_brush_offset(rc, brush, origin);
418
419         start = get_pixel_ptr_16(dib, rc->left, rc->top);
420         start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
421         start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
422
423         for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
424         {
425             and_ptr = start_and + offset.x;
426             xor_ptr = start_xor + offset.x;
427
428             for(x = rc->left, ptr = start; x < rc->right; x++)
429             {
430                 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
431                 if(and_ptr == start_and + brush->width)
432                 {
433                     and_ptr = start_and;
434                     xor_ptr = start_xor;
435                 }
436             }
437
438             offset.y++;
439             if(offset.y == brush->height)
440             {
441                 start_and = and_bits;
442                 start_xor = xor_bits;
443                 offset.y = 0;
444             }
445             else
446             {
447                 start_and += brush->stride / 2;
448                 start_xor += brush->stride / 2;
449             }
450         }
451     }
452 }
453
454 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
455                             const dib_info *brush, void *and_bits, void *xor_bits)
456 {
457     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
458     int x, y, i;
459     POINT offset;
460
461     for(i = 0; i < num; i++, rc++)
462     {
463         offset = calc_brush_offset(rc, brush, origin);
464
465         start = get_pixel_ptr_8(dib, rc->left, rc->top);
466         start_and = (BYTE*)and_bits + offset.y * brush->stride;
467         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
468
469         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
470         {
471             and_ptr = start_and + offset.x;
472             xor_ptr = start_xor + offset.x;
473
474             for(x = rc->left, ptr = start; x < rc->right; x++)
475             {
476                 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
477                 if(and_ptr == start_and + brush->width)
478                 {
479                     and_ptr = start_and;
480                     xor_ptr = start_xor;
481                 }
482             }
483
484             offset.y++;
485             if(offset.y == brush->height)
486             {
487                 start_and = and_bits;
488                 start_xor = xor_bits;
489                 offset.y = 0;
490             }
491             else
492             {
493                 start_and += brush->stride;
494                 start_xor += brush->stride;
495             }
496         }
497     }
498 }
499
500 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
501                             const dib_info *brush, void *and_bits, void *xor_bits)
502 {
503     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
504     int x, y, i;
505     POINT offset;
506
507     for(i = 0; i < num; i++, rc++)
508     {
509         offset = calc_brush_offset(rc, brush, origin);
510
511         start = get_pixel_ptr_4(dib, rc->left, rc->top);
512         start_and = (BYTE*)and_bits + offset.y * brush->stride;
513         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
514
515         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
516         {
517             INT brush_x = offset.x;
518             BYTE byte_and, byte_xor;
519
520             and_ptr = start_and + brush_x / 2;
521             xor_ptr = start_xor + brush_x / 2;
522
523             for(x = rc->left, ptr = start; x < rc->right; x++)
524             {
525                 /* FIXME: Two pixels at a time */
526                 if(x & 1) /* lower dst nibble */
527                 {
528                     if(brush_x & 1) /* lower pat nibble */
529                     {
530                         byte_and = *and_ptr++ | 0xf0;
531                         byte_xor = *xor_ptr++ & 0x0f;
532                     }
533                     else /* upper pat nibble */
534                     {
535                         byte_and = (*and_ptr >> 4) | 0xf0;
536                         byte_xor = (*xor_ptr >> 4) & 0x0f;
537                     }
538                 }
539                 else /* upper dst nibble */
540                 {
541                     if(brush_x & 1) /* lower pat nibble */
542                     {
543                         byte_and = (*and_ptr++ << 4) | 0x0f;
544                         byte_xor = (*xor_ptr++ << 4) & 0xf0;
545                     }
546                     else /* upper pat nibble */
547                     {
548                         byte_and = *and_ptr | 0x0f;
549                         byte_xor = *xor_ptr & 0xf0;
550                     }
551                 }
552                 do_rop_8(ptr, byte_and, byte_xor);
553
554                 if(x & 1) ptr++;
555
556                 if(++brush_x == brush->width)
557                 {
558                     brush_x = 0;
559                     and_ptr = start_and;
560                     xor_ptr = start_xor;
561                 }
562             }
563
564             offset.y++;
565             if(offset.y == brush->height)
566             {
567                 start_and = and_bits;
568                 start_xor = xor_bits;
569                 offset.y = 0;
570             }
571             else
572             {
573                 start_and += brush->stride;
574                 start_xor += brush->stride;
575             }
576         }
577     }
578 }
579
580 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
581                             const dib_info *brush, void *and_bits, void *xor_bits)
582 {
583     BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
584     int x, y, i;
585     POINT offset;
586
587     for(i = 0; i < num; i++, rc++)
588     {
589         offset = calc_brush_offset(rc, brush, origin);
590
591         start = get_pixel_ptr_1(dib, rc->left, rc->top);
592         start_and = (BYTE*)and_bits + offset.y * brush->stride;
593         start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
594
595         for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
596         {
597             INT brush_x = offset.x;
598             BYTE byte_and, byte_xor;
599
600             and_ptr = start_and + brush_x / 8;
601             xor_ptr = start_xor + brush_x / 8;
602
603             for(x = rc->left, ptr = start; x < rc->right; x++)
604             {
605                 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
606                 byte_and |= ~pixel_masks_1[x % 8];
607                 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
608                 byte_xor &= pixel_masks_1[x % 8];
609
610                 do_rop_8(ptr, byte_and, byte_xor);
611
612                 if((x & 7) == 7) ptr++;
613
614                 if((brush_x & 7) == 7)
615                 {
616                     and_ptr++;
617                     xor_ptr++;
618                 }
619
620                 if(++brush_x == brush->width)
621                 {
622                     brush_x = 0;
623                     and_ptr = start_and;
624                     xor_ptr = start_xor;
625                 }
626             }
627
628             offset.y++;
629             if(offset.y == brush->height)
630             {
631                 start_and = and_bits;
632                 start_xor = xor_bits;
633                 offset.y = 0;
634             }
635             else
636             {
637                 start_and += brush->stride;
638                 start_xor += brush->stride;
639             }
640         }
641     }
642 }
643
644 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
645                                const dib_info *brush, void *and_bits, void *xor_bits)
646 {
647     return;
648 }
649
650 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
651 {
652     return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
653 }
654
655 static inline DWORD put_field(DWORD field, int shift, int len)
656 {
657     shift = shift - (8 - len);
658     if (len <= 8)
659         field &= (((1 << len) - 1) << (8 - len));
660     if (shift < 0)
661         field >>= -shift;
662     else
663         field <<= shift;
664     return field;
665 }
666
667 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
668 {
669     DWORD r,g,b;
670
671     r = GetRValue(colour);
672     g = GetGValue(colour);
673     b = GetBValue(colour);
674
675     return put_field(r, dib->red_shift,   dib->red_len) |
676            put_field(g, dib->green_shift, dib->green_len) |
677            put_field(b, dib->blue_shift,  dib->blue_len);
678 }
679
680 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
681 {
682     return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
683 }
684
685 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
686 {
687     int i, best_index = 0;
688     RGBQUAD rgb;
689     DWORD diff, best_diff = 0xffffffff;
690
691     rgb.rgbRed = GetRValue(color);
692     rgb.rgbGreen = GetGValue(color);
693     rgb.rgbBlue = GetBValue(color);
694
695     for(i = 0; i < dib->color_table_size; i++)
696     {
697         RGBQUAD *cur = dib->color_table + i;
698         diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
699             +  (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
700             +  (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
701
702         if(diff == 0)
703         {
704             best_index = i;
705             break;
706         }
707
708         if(diff < best_diff)
709         {
710             best_diff = diff;
711             best_index = i;
712         }
713     }
714     return best_index;
715 }
716
717 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
718 {
719     return 0;
720 }
721
722 static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
723 {
724     DWORD *dst_start = dst->bits, *dst_pixel, src_val;
725     int x, y;
726
727     switch(src->bit_count)
728     {
729     case 32:
730     {
731         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top);
732         if(src->funcs == &funcs_8888)
733         {
734             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
735                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
736             else
737             {
738                 for(y = src_rect->top; y < src_rect->bottom; y++)
739                 {
740                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
741                     dst_start += dst->stride / 4;
742                     src_start += src->stride / 4;
743                 }
744             }
745         }
746         else
747         {
748             FIXME("Unsupported conversion: 32 -> 8888\n");
749             return FALSE;
750         }
751         break;
752     }
753
754     case 24:
755     {
756         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
757
758         for(y = src_rect->top; y < src_rect->bottom; y++)
759         {
760             dst_pixel = dst_start;
761             src_pixel = src_start;
762             for(x = src_rect->left; x < src_rect->right; x++)
763             {
764                 RGBQUAD rgb;
765                 rgb.rgbBlue  = *src_pixel++;
766                 rgb.rgbGreen = *src_pixel++;
767                 rgb.rgbRed   = *src_pixel++;
768
769                 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
770             }
771             dst_start += dst->stride / 4;
772             src_start += src->stride;
773         }
774         break;
775     }
776
777     case 16:
778     {
779         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
780         if(src->funcs == &funcs_555)
781         {
782             for(y = src_rect->top; y < src_rect->bottom; y++)
783             {
784                 dst_pixel = dst_start;
785                 src_pixel = src_start;
786                 for(x = src_rect->left; x < src_rect->right; x++)
787                 {
788                     src_val = *src_pixel++;
789                     *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
790                                    ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
791                                    ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
792                 }
793                 dst_start += dst->stride / 4;
794                 src_start += src->stride / 2;
795             }
796         }
797         else
798         {
799             FIXME("Unsupported conversion: 16 -> 8888\n");
800             return FALSE;
801         }
802         break;
803     }
804
805     case 8:
806     {
807         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
808         for(y = src_rect->top; y < src_rect->bottom; y++)
809         {
810             dst_pixel = dst_start;
811             src_pixel = src_start;
812             for(x = src_rect->left; x < src_rect->right; x++)
813             {
814                 RGBQUAD rgb;
815                 src_val = *src_pixel++;
816                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
817                 rgb = src->color_table[src_val];
818                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
819             }
820             dst_start += dst->stride / 4;
821             src_start += src->stride;
822         }
823         break;
824     }
825
826     case 4:
827     {
828         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
829         for(y = src_rect->top; y < src_rect->bottom; y++)
830         {
831             dst_pixel = dst_start;
832             src_pixel = src_start;
833             for(x = src_rect->left; x < src_rect->right; x++)
834             {
835                 RGBQUAD rgb;
836                 if(x & 1)
837                     src_val = *src_pixel++ & 0xf;
838                 else
839                     src_val = (*src_pixel >> 4) & 0xf;
840                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
841                 rgb = src->color_table[src_val];
842                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
843             }
844             dst_start += dst->stride / 4;
845             src_start += src->stride;
846         }
847         break;
848     }
849
850     case 1:
851     {
852         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
853         for(y = src_rect->top; y < src_rect->bottom; y++)
854         {
855             dst_pixel = dst_start;
856             src_pixel = src_start;
857             for(x = src_rect->left; x < src_rect->right; x++)
858             {
859                 RGBQUAD rgb;
860                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
861                 if((x % 8) == 7) src_pixel++;
862                 rgb = src->color_table[src_val];
863                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
864             }
865             dst_start += dst->stride / 4;
866             src_start += src->stride;
867         }
868         break;
869     }
870
871     default:
872         FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
873         return FALSE;
874     }
875
876     return TRUE;
877 }
878
879 static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
880 {
881     DWORD *dst_start = dst->bits, *dst_pixel, src_val;
882     int x, y;
883
884     switch(src->bit_count)
885     {
886     case 32:
887     {
888         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
889
890         if(src->funcs == &funcs_8888)
891         {
892             for(y = src_rect->top; y < src_rect->bottom; y++)
893             {
894                 dst_pixel = dst_start;
895                 src_pixel = src_start;
896                 for(x = src_rect->left; x < src_rect->right; x++)
897                 {
898                     src_val = *src_pixel++;
899                     *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift,   dst->red_len)   |
900                                    put_field((src_val >>  8) & 0xff, dst->green_shift, dst->green_len) |
901                                    put_field( src_val        & 0xff, dst->blue_shift,  dst->blue_len);
902                 }
903                 dst_start += dst->stride / 4;
904                 src_start += src->stride / 4;
905             }
906         }
907         else
908         {
909             FIXME("Unsupported conversion: 32 -> 32\n");
910             return FALSE;
911         }
912         break;
913     }
914
915     case 24:
916     {
917         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
918
919         for(y = src_rect->top; y < src_rect->bottom; y++)
920         {
921             dst_pixel = dst_start;
922             src_pixel = src_start;
923             for(x = src_rect->left; x < src_rect->right; x++)
924             {
925                 RGBQUAD rgb;
926                 rgb.rgbBlue  = *src_pixel++;
927                 rgb.rgbGreen = *src_pixel++;
928                 rgb.rgbRed   = *src_pixel++;
929
930                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len)   |
931                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
932                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
933             }
934             dst_start += dst->stride / 4;
935             src_start += src->stride;
936         }
937         break;
938     }
939
940     case 16:
941     {
942         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
943         if(src->funcs == &funcs_555)
944         {
945             for(y = src_rect->top; y < src_rect->bottom; y++)
946             {
947                 dst_pixel = dst_start;
948                 src_pixel = src_start;
949                 for(x = src_rect->left; x < src_rect->right; x++)
950                 {
951                     src_val = *src_pixel++;
952                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
953                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
954                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
955                 }
956                 dst_start += dst->stride / 4;
957                 src_start += src->stride / 2;
958             }
959         }
960         else
961         {
962             FIXME("Unsupported conversion: 16 -> 8888\n");
963             return FALSE;
964         }
965         break;
966     }
967
968     case 8:
969     {
970         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
971         for(y = src_rect->top; y < src_rect->bottom; y++)
972         {
973             dst_pixel = dst_start;
974             src_pixel = src_start;
975             for(x = src_rect->left; x < src_rect->right; x++)
976             {
977                 RGBQUAD rgb;
978                 src_val = *src_pixel++;
979                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
980                 rgb = src->color_table[src_val];
981                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
982                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
983                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
984             }
985             dst_start += dst->stride / 4;
986             src_start += src->stride;
987         }
988         break;
989     }
990
991     case 4:
992     {
993         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
994         for(y = src_rect->top; y < src_rect->bottom; y++)
995         {
996             dst_pixel = dst_start;
997             src_pixel = src_start;
998             for(x = src_rect->left; x < src_rect->right; x++)
999             {
1000                 RGBQUAD rgb;
1001                 if(x & 1)
1002                     src_val = *src_pixel++ & 0xf;
1003                 else
1004                     src_val = (*src_pixel >> 4) & 0xf;
1005                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1006                 rgb = src->color_table[src_val];
1007                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1008                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1009                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1010             }
1011             dst_start += dst->stride / 4;
1012             src_start += src->stride;
1013         }
1014         break;
1015     }
1016
1017     case 1:
1018     {
1019         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1020         for(y = src_rect->top; y < src_rect->bottom; y++)
1021         {
1022             dst_pixel = dst_start;
1023             src_pixel = src_start;
1024             for(x = src_rect->left; x < src_rect->right; x++)
1025             {
1026                 RGBQUAD rgb;
1027                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1028                 if((x % 8) == 7) src_pixel++;
1029                 rgb = src->color_table[src_val];
1030                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1031                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1032                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1033             }
1034             dst_start += dst->stride / 4;
1035             src_start += src->stride;
1036         }
1037         break;
1038     }
1039
1040     default:
1041         FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
1042         return FALSE;
1043     }
1044
1045     return TRUE;
1046 }
1047
1048 static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1049 {
1050     BYTE *dst_start = dst->bits, *dst_pixel;
1051     DWORD src_val;
1052     int x, y;
1053
1054     switch(src->bit_count)
1055     {
1056     case 32:
1057     {
1058         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1059         if(src->funcs == &funcs_8888)
1060         {
1061             for(y = src_rect->top; y < src_rect->bottom; y++)
1062             {
1063                 dst_pixel = dst_start;
1064                 src_pixel = src_start;
1065                 for(x = src_rect->left; x < src_rect->right; x++)
1066                 {
1067                     src_val = *src_pixel++;
1068                     *dst_pixel++ =  src_val        & 0xff;
1069                     *dst_pixel++ = (src_val >>  8) & 0xff;
1070                     *dst_pixel++ = (src_val >> 16) & 0xff;
1071                 }
1072                 dst_start += dst->stride;
1073                 src_start += src->stride / 4;
1074             }
1075         }
1076         else
1077         {
1078             FIXME("Unsupported conversion: 32 -> 24\n");
1079             return FALSE;
1080         }
1081         break;
1082     }
1083
1084     case 24:
1085     {
1086         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1087
1088         if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1089             memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1090         else
1091         {
1092             for(y = src_rect->top; y < src_rect->bottom; y++)
1093             {
1094                 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1095                 dst_start += dst->stride;
1096                 src_start += src->stride;
1097             }
1098         }
1099         break;
1100     }
1101
1102     case 16:
1103     {
1104         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1105         if(src->funcs == &funcs_555)
1106         {
1107             for(y = src_rect->top; y < src_rect->bottom; y++)
1108             {
1109                 dst_pixel = dst_start;
1110                 src_pixel = src_start;
1111                 for(x = src_rect->left; x < src_rect->right; x++)
1112                 {
1113                     src_val = *src_pixel++;
1114                     *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07);
1115                     *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07);
1116                     *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1117                 }
1118                 dst_start += dst->stride;
1119                 src_start += src->stride / 2;
1120             }
1121         }
1122         else
1123         {
1124             FIXME("Unsupported conversion: 16 -> 24\n");
1125             return FALSE;
1126         }
1127         break;
1128     }
1129
1130     case 8:
1131     {
1132         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1133         for(y = src_rect->top; y < src_rect->bottom; y++)
1134         {
1135             dst_pixel = dst_start;
1136             src_pixel = src_start;
1137             for(x = src_rect->left; x < src_rect->right; x++)
1138             {
1139                 RGBQUAD rgb;
1140                 src_val = *src_pixel++;
1141                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1142                 rgb = src->color_table[src_val];
1143                 *dst_pixel++ = rgb.rgbBlue;
1144                 *dst_pixel++ = rgb.rgbGreen;
1145                 *dst_pixel++ = rgb.rgbRed;
1146             }
1147             dst_start += dst->stride;
1148             src_start += src->stride;
1149         }
1150         break;
1151     }
1152
1153     case 4:
1154     {
1155         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1156         for(y = src_rect->top; y < src_rect->bottom; y++)
1157         {
1158             dst_pixel = dst_start;
1159             src_pixel = src_start;
1160             for(x = src_rect->left; x < src_rect->right; x++)
1161             {
1162                 RGBQUAD rgb;
1163                 if(x & 1)
1164                     src_val = *src_pixel++ & 0xf;
1165                 else
1166                     src_val = (*src_pixel >> 4) & 0xf;
1167                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1168                 rgb = src->color_table[src_val];
1169                 *dst_pixel++ = rgb.rgbBlue;
1170                 *dst_pixel++ = rgb.rgbGreen;
1171                 *dst_pixel++ = rgb.rgbRed;
1172             }
1173             dst_start += dst->stride;
1174             src_start += src->stride;
1175         }
1176         break;
1177     }
1178
1179     case 1:
1180     {
1181         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1182         for(y = src_rect->top; y < src_rect->bottom; y++)
1183         {
1184             dst_pixel = dst_start;
1185             src_pixel = src_start;
1186             for(x = src_rect->left; x < src_rect->right; x++)
1187             {
1188                 RGBQUAD rgb;
1189                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1190                 if((x % 8) == 7) src_pixel++;
1191                 rgb = src->color_table[src_val];
1192                 *dst_pixel++ = rgb.rgbBlue;
1193                 *dst_pixel++ = rgb.rgbGreen;
1194                 *dst_pixel++ = rgb.rgbRed;
1195             }
1196             dst_start += dst->stride;
1197             src_start += src->stride;
1198         }
1199         break;
1200     }
1201
1202     default:
1203         FIXME("Unsupported conversion: %d -> 24\n", src->bit_count);
1204         return FALSE;
1205     }
1206
1207     return TRUE;
1208 }
1209
1210 static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1211 {
1212     WORD *dst_start = dst->bits, *dst_pixel;
1213     INT x, y;
1214     DWORD src_val;
1215
1216     switch(src->bit_count)
1217     {
1218     case 32:
1219     {
1220         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1221
1222         if(src->funcs == &funcs_8888)
1223         {
1224             for(y = src_rect->top; y < src_rect->bottom; y++)
1225             {
1226                 dst_pixel = dst_start;
1227                 src_pixel = src_start;
1228                 for(x = src_rect->left; x < src_rect->right; x++)
1229                 {
1230                     src_val = *src_pixel++;
1231                     *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1232                                    ((src_val >> 6) & 0x03e0) |
1233                                    ((src_val >> 3) & 0x001f);
1234                 }
1235                 dst_start += dst->stride / 2;
1236                 src_start += src->stride / 4;
1237             }
1238         }
1239         else
1240         {
1241             FIXME("Unsupported conversion: 32 -> 555\n");
1242             return FALSE;
1243         }
1244         break;
1245     }
1246
1247     case 24:
1248     {
1249         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1250
1251         for(y = src_rect->top; y < src_rect->bottom; y++)
1252         {
1253             dst_pixel = dst_start;
1254             src_pixel = src_start;
1255             for(x = src_rect->left; x < src_rect->right; x++)
1256             {
1257                 RGBQUAD rgb;
1258                 rgb.rgbBlue  = *src_pixel++;
1259                 rgb.rgbGreen = *src_pixel++;
1260                 rgb.rgbRed   = *src_pixel++;
1261
1262                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1263                                ((rgb.rgbGreen << 2) & 0x03e0) |
1264                                ((rgb.rgbBlue  >> 3) & 0x001f);
1265             }
1266             dst_start += dst->stride / 2;
1267             src_start += src->stride;
1268         }
1269         break;
1270     }
1271
1272     case 16:
1273     {
1274         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top);
1275         if(src->funcs == &funcs_555)
1276         {
1277             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1278                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1279             else
1280             {
1281                 for(y = src_rect->top; y < src_rect->bottom; y++)
1282                 {
1283                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1284                     dst_start += dst->stride / 2;
1285                     src_start += src->stride / 2;
1286                 }
1287             }
1288         }
1289         else
1290         {
1291             FIXME("Unsupported conversion: 16 -> 555\n");
1292             return FALSE;
1293         }
1294         break;
1295     }
1296
1297     case 8:
1298     {
1299         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1300         for(y = src_rect->top; y < src_rect->bottom; y++)
1301         {
1302             dst_pixel = dst_start;
1303             src_pixel = src_start;
1304             for(x = src_rect->left; x < src_rect->right; x++)
1305             {
1306                 RGBQUAD rgb;
1307                 src_val = *src_pixel++;
1308                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1309                 rgb = src->color_table[src_val];
1310                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1311                                ((rgb.rgbGreen << 2) & 0x03e0) |
1312                                ((rgb.rgbBlue  >> 3) & 0x001f);
1313             }
1314             dst_start += dst->stride / 2;
1315             src_start += src->stride;
1316         }
1317         break;
1318     }
1319
1320     case 4:
1321     {
1322         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1323         for(y = src_rect->top; y < src_rect->bottom; y++)
1324         {
1325             dst_pixel = dst_start;
1326             src_pixel = src_start;
1327             for(x = src_rect->left; x < src_rect->right; x++)
1328             {
1329                 RGBQUAD rgb;
1330                 if(x & 1)
1331                     src_val = *src_pixel++ & 0xf;
1332                 else
1333                     src_val = (*src_pixel >> 4) & 0xf;
1334                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1335                 rgb = src->color_table[src_val];
1336                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1337                                ((rgb.rgbGreen << 2) & 0x03e0) |
1338                                ((rgb.rgbBlue  >> 3) & 0x001f);
1339             }
1340             dst_start += dst->stride / 2;
1341             src_start += src->stride;
1342         }
1343         break;
1344     }
1345
1346     case 1:
1347     {
1348         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1349         for(y = src_rect->top; y < src_rect->bottom; y++)
1350         {
1351             dst_pixel = dst_start;
1352             src_pixel = src_start;
1353             for(x = src_rect->left; x < src_rect->right; x++)
1354             {
1355                 RGBQUAD rgb;
1356                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1357                 if((x % 8) == 7) src_pixel++;
1358                 rgb = src->color_table[src_val];
1359                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
1360                                ((rgb.rgbGreen << 2) & 0x03e0) |
1361                                ((rgb.rgbBlue  >> 3) & 0x001f);
1362             }
1363             dst_start += dst->stride / 2;
1364             src_start += src->stride;
1365         }
1366         break;
1367     }
1368
1369     default:
1370         FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
1371         return FALSE;
1372
1373     }
1374     return TRUE;
1375 }
1376
1377 static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
1378 {
1379     WORD *dst_start = dst->bits, *dst_pixel;
1380     INT x, y;
1381     DWORD src_val;
1382
1383     switch(src->bit_count)
1384     {
1385     case 32:
1386     {
1387         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1388
1389         if(src->funcs == &funcs_8888)
1390         {
1391             for(y = src_rect->top; y < src_rect->bottom; y++)
1392             {
1393                 dst_pixel = dst_start;
1394                 src_pixel = src_start;
1395                 for(x = src_rect->left; x < src_rect->right; x++)
1396                 {
1397                     src_val = *src_pixel++;
1398                     *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift,   dst->red_len)   |
1399                                    put_field((src_val >>  8) & 0xff, dst->green_shift, dst->green_len) |
1400                                    put_field( src_val        & 0xff, dst->blue_shift,  dst->blue_len);
1401                 }
1402                 dst_start += dst->stride / 2;
1403                 src_start += src->stride / 4;
1404             }
1405         }
1406         else
1407         {
1408             FIXME("Unsupported conversion: 32 -> 16\n");
1409             return FALSE;
1410         }
1411         break;
1412     }
1413
1414     case 24:
1415     {
1416         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1417
1418         for(y = src_rect->top; y < src_rect->bottom; y++)
1419         {
1420             dst_pixel = dst_start;
1421             src_pixel = src_start;
1422             for(x = src_rect->left; x < src_rect->right; x++)
1423             {
1424                 RGBQUAD rgb;
1425                 rgb.rgbBlue  = *src_pixel++;
1426                 rgb.rgbGreen = *src_pixel++;
1427                 rgb.rgbRed   = *src_pixel++;
1428
1429                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1430                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1431                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1432             }
1433             dst_start += dst->stride / 2;
1434             src_start += src->stride;
1435         }
1436         break;
1437     }
1438
1439     case 16:
1440     {
1441         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1442         if(src->funcs == &funcs_555)
1443         {
1444             for(y = src_rect->top; y < src_rect->bottom; y++)
1445             {
1446                 dst_pixel = dst_start;
1447                 src_pixel = src_start;
1448                 for(x = src_rect->left; x < src_rect->right; x++)
1449                 {
1450                     src_val = *src_pixel++;
1451                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
1452                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
1453                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
1454                 }
1455                 dst_start += dst->stride / 2;
1456                 src_start += src->stride / 2;
1457             }
1458         }
1459         else
1460         {
1461             FIXME("Unsupported conversion: 16 -> 16\n");
1462             return FALSE;
1463         }
1464         break;
1465     }
1466
1467     case 8:
1468     {
1469         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1470         for(y = src_rect->top; y < src_rect->bottom; y++)
1471         {
1472             dst_pixel = dst_start;
1473             src_pixel = src_start;
1474             for(x = src_rect->left; x < src_rect->right; x++)
1475             {
1476                 RGBQUAD rgb;
1477                 src_val = *src_pixel++;
1478                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1479                 rgb = src->color_table[src_val];
1480                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1481                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1482                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1483             }
1484             dst_start += dst->stride / 2;
1485             src_start += src->stride;
1486         }
1487         break;
1488     }
1489
1490     case 4:
1491     {
1492         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1493         for(y = src_rect->top; y < src_rect->bottom; y++)
1494         {
1495             dst_pixel = dst_start;
1496             src_pixel = src_start;
1497             for(x = src_rect->left; x < src_rect->right; x++)
1498             {
1499                 RGBQUAD rgb;
1500                 if(x & 1)
1501                     src_val = *src_pixel++ & 0xf;
1502                 else
1503                     src_val = (*src_pixel >> 4) & 0xf;
1504                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1505                 rgb = src->color_table[src_val];
1506                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1507                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1508                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1509             }
1510             dst_start += dst->stride / 2;
1511             src_start += src->stride;
1512         }
1513         break;
1514     }
1515
1516     case 1:
1517     {
1518         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1519         for(y = src_rect->top; y < src_rect->bottom; y++)
1520         {
1521             dst_pixel = dst_start;
1522             src_pixel = src_start;
1523             for(x = src_rect->left; x < src_rect->right; x++)
1524             {
1525                 RGBQUAD rgb;
1526                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1527                 if((x % 8) == 7) src_pixel++;
1528                 rgb = src->color_table[src_val];
1529                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1530                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1531                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1532             }
1533             dst_start += dst->stride / 2;
1534             src_start += src->stride;
1535         }
1536         break;
1537     }
1538
1539     default:
1540         FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
1541         return FALSE;
1542
1543     }
1544     return TRUE;
1545 }
1546
1547 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
1548 {
1549     assert(d1->color_table_size && d2->color_table_size);
1550
1551     if(d1->color_table_size != d2->color_table_size) return FALSE;
1552     return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
1553 }
1554
1555 static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
1556 {
1557     BYTE *dst_start = dst->bits, *dst_pixel;
1558     INT x, y;
1559     DWORD src_val;
1560
1561     switch(src->bit_count)
1562     {
1563     case 32:
1564     {
1565         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1566
1567         if(src->funcs == &funcs_8888)
1568         {
1569             for(y = src_rect->top; y < src_rect->bottom; y++)
1570             {
1571                 dst_pixel = dst_start;
1572                 src_pixel = src_start;
1573                 for(x = src_rect->left; x < src_rect->right; x++)
1574                 {
1575                     src_val = *src_pixel++;
1576                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1577                                                                      ( src_val        & 0x00ff00) |
1578                                                                      ((src_val << 16) & 0xff0000) );
1579                 }
1580                 dst_start += dst->stride;
1581                 src_start += src->stride / 4;
1582             }
1583         }
1584         else
1585         {
1586             FIXME("Unsupported conversion: 32 -> 8\n");
1587             return FALSE;
1588         }
1589         break;
1590     }
1591
1592     case 24:
1593     {
1594         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1595
1596         for(y = src_rect->top; y < src_rect->bottom; y++)
1597         {
1598             dst_pixel = dst_start;
1599             src_pixel = src_start;
1600             for(x = src_rect->left; x < src_rect->right; x++)
1601             {
1602                 RGBQUAD rgb;
1603                 rgb.rgbBlue  = *src_pixel++;
1604                 rgb.rgbGreen = *src_pixel++;
1605                 rgb.rgbRed   = *src_pixel++;
1606
1607                 *dst_pixel++ = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
1608                                                                  ((rgb.rgbGreen << 8) & 0x00ff00) |
1609                                                                  ((rgb.rgbBlue << 16) & 0xff0000));
1610             }
1611             dst_start += dst->stride;
1612             src_start += src->stride;
1613         }
1614         break;
1615     }
1616
1617     case 16:
1618     {
1619         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1620         if(src->funcs == &funcs_555)
1621         {
1622             for(y = src_rect->top; y < src_rect->bottom; y++)
1623             {
1624                 dst_pixel = dst_start;
1625                 src_pixel = src_start;
1626                 for(x = src_rect->left; x < src_rect->right; x++)
1627                 {
1628                     src_val = *src_pixel++;
1629                     *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
1630                                                                      ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
1631                                                                      ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
1632                 }
1633                 dst_start += dst->stride;
1634                 src_start += src->stride / 2;
1635             }
1636         }
1637         else
1638         {
1639             FIXME("Unsupported conversion: 16 -> 8\n");
1640             return FALSE;
1641         }
1642         break;
1643     }
1644
1645     case 8:
1646     {
1647         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1648
1649         if(color_tables_match(dst, src))
1650         {
1651             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1652                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1653             else
1654             {
1655                 for(y = src_rect->top; y < src_rect->bottom; y++)
1656                 {
1657                     memcpy(dst_start, src_start, src_rect->right - src_rect->left);
1658                     dst_start += dst->stride;
1659                     src_start += src->stride;
1660                 }
1661             }
1662         }
1663         else
1664         {
1665             for(y = src_rect->top; y < src_rect->bottom; y++)
1666             {
1667                 dst_pixel = dst_start;
1668                 src_pixel = src_start;
1669                 for(x = src_rect->left; x < src_rect->right; x++)
1670                 {
1671                     RGBQUAD rgb;
1672                     src_val = *src_pixel++;
1673                     if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1674                     rgb = src->color_table[src_val];
1675                     *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1676                 }
1677                 dst_start += dst->stride;
1678                 src_start += src->stride;
1679             }
1680         }
1681         break;
1682     }
1683
1684     case 4:
1685     {
1686         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1687         for(y = src_rect->top; y < src_rect->bottom; y++)
1688         {
1689             dst_pixel = dst_start;
1690             src_pixel = src_start;
1691             for(x = src_rect->left; x < src_rect->right; x++)
1692             {
1693                 RGBQUAD rgb;
1694                 if(x & 1)
1695                     src_val = *src_pixel++ & 0xf;
1696                 else
1697                     src_val = (*src_pixel >> 4) & 0xf;
1698                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1699                 rgb = src->color_table[src_val];
1700                 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1701             }
1702             dst_start += dst->stride;
1703             src_start += src->stride;
1704         }
1705         break;
1706     }
1707
1708     case 1:
1709     {
1710         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1711         for(y = src_rect->top; y < src_rect->bottom; y++)
1712         {
1713             dst_pixel = dst_start;
1714             src_pixel = src_start;
1715             for(x = src_rect->left; x < src_rect->right; x++)
1716             {
1717                 RGBQUAD rgb;
1718                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1719                 if((x % 8) == 7) src_pixel++;
1720                 rgb = src->color_table[src_val];
1721                 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1722             }
1723             dst_start += dst->stride;
1724             src_start += src->stride;
1725         }
1726         break;
1727     }
1728
1729     default:
1730         FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
1731         return FALSE;
1732
1733     }
1734     return TRUE;
1735 }
1736
1737 static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
1738 {
1739     BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
1740     INT x, y;
1741     DWORD src_val;
1742
1743     switch(src->bit_count)
1744     {
1745     case 32:
1746     {
1747         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1748
1749         if(src->funcs == &funcs_8888)
1750         {
1751             for(y = src_rect->top; y < src_rect->bottom; y++)
1752             {
1753                 dst_pixel = dst_start;
1754                 src_pixel = src_start;
1755                 for(x = src_rect->left; x < src_rect->right; x++)
1756                 {
1757                     src_val = *src_pixel++;
1758                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1759                                                                 ( src_val        & 0x00ff00) |
1760                                                                 ((src_val << 16) & 0xff0000) );
1761                     if((x - src_rect->left) & 1)
1762                     {
1763                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1764                         dst_pixel++;
1765                     }
1766                     else
1767                         *dst_pixel = (dst_val << 4) & 0xf0;
1768                 }
1769                 dst_start += dst->stride;
1770                 src_start += src->stride / 4;
1771             }
1772         }
1773         else
1774         {
1775             FIXME("Unsupported conversion: 32 -> 4\n");
1776             return FALSE;
1777         }
1778         break;
1779     }
1780
1781     case 24:
1782     {
1783         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1784
1785         for(y = src_rect->top; y < src_rect->bottom; y++)
1786         {
1787             dst_pixel = dst_start;
1788             src_pixel = src_start;
1789             for(x = src_rect->left; x < src_rect->right; x++)
1790             {
1791                 RGBQUAD rgb;
1792                 rgb.rgbBlue  = *src_pixel++;
1793                 rgb.rgbGreen = *src_pixel++;
1794                 rgb.rgbRed   = *src_pixel++;
1795
1796                 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
1797                                                             ((rgb.rgbGreen << 8) & 0x00ff00) |
1798                                                             ((rgb.rgbBlue << 16) & 0xff0000));
1799
1800                 if((x - src_rect->left) & 1)
1801                 {
1802                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1803                     dst_pixel++;
1804                 }
1805                 else
1806                     *dst_pixel = (dst_val << 4) & 0xf0;
1807             }
1808             dst_start += dst->stride;
1809             src_start += src->stride;
1810         }
1811         break;
1812     }
1813
1814     case 16:
1815     {
1816         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1817         if(src->funcs == &funcs_555)
1818         {
1819             for(y = src_rect->top; y < src_rect->bottom; y++)
1820             {
1821                 dst_pixel = dst_start;
1822                 src_pixel = src_start;
1823                 for(x = src_rect->left; x < src_rect->right; x++)
1824                 {
1825                     src_val = *src_pixel++;
1826                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
1827                                                                 ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
1828                                                                 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
1829                     if((x - src_rect->left) & 1)
1830                     {
1831                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1832                         dst_pixel++;
1833                     }
1834                     else
1835                         *dst_pixel = (dst_val << 4) & 0xf0;
1836                 }
1837                 dst_start += dst->stride;
1838                 src_start += src->stride / 2;
1839             }
1840         }
1841         else
1842         {
1843             FIXME("Unsupported conversion: 16 -> 4\n");
1844             return FALSE;
1845         }
1846         break;
1847     }
1848
1849     case 8:
1850     {
1851         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1852
1853         for(y = src_rect->top; y < src_rect->bottom; y++)
1854         {
1855             dst_pixel = dst_start;
1856             src_pixel = src_start;
1857             for(x = src_rect->left; x < src_rect->right; x++)
1858             {
1859                 RGBQUAD rgb;
1860                 src_val = *src_pixel++;
1861                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1862                 rgb = src->color_table[src_val];
1863                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1864                 if((x - src_rect->left) & 1)
1865                 {
1866                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1867                     dst_pixel++;
1868                 }
1869                 else
1870                     *dst_pixel = (dst_val << 4) & 0xf0;
1871             }
1872             dst_start += dst->stride;
1873             src_start += src->stride;
1874         }
1875         break;
1876     }
1877
1878     case 4:
1879     {
1880         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1881
1882         if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
1883         {
1884             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1885                 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1886             else
1887             {
1888                 for(y = src_rect->top; y < src_rect->bottom; y++)
1889                 {
1890                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
1891                     dst_start += dst->stride;
1892                     src_start += src->stride;
1893                 }
1894             }
1895         }
1896         else
1897         {
1898             for(y = src_rect->top; y < src_rect->bottom; y++)
1899             {
1900                 dst_pixel = dst_start;
1901                 src_pixel = src_start;
1902                 for(x = src_rect->left; x < src_rect->right; x++)
1903                 {
1904                     RGBQUAD rgb;
1905                     if(x & 1)
1906                         src_val = *src_pixel++ & 0xf;
1907                     else
1908                         src_val = (*src_pixel >> 4) & 0xf;
1909                     if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1910                     rgb = src->color_table[src_val];
1911                     dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1912                     if((x - src_rect->left) & 1)
1913                     {
1914                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1915                         dst_pixel++;
1916                     }
1917                     else
1918                         *dst_pixel = (dst_val << 4) & 0xf0;
1919                 }
1920                 dst_start += dst->stride;
1921                 src_start += src->stride;
1922             }
1923         }
1924         break;
1925     }
1926
1927     case 1:
1928     {
1929         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1930         for(y = src_rect->top; y < src_rect->bottom; y++)
1931         {
1932             dst_pixel = dst_start;
1933             src_pixel = src_start;
1934             for(x = src_rect->left; x < src_rect->right; x++)
1935             {
1936                 RGBQUAD rgb;
1937                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1938                 if((x % 8) == 7) src_pixel++;
1939                 rgb = src->color_table[src_val];
1940                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1941                 if((x - src_rect->left) & 1)
1942                 {
1943                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1944                     dst_pixel++;
1945                 }
1946                 else
1947                     *dst_pixel = (dst_val << 4) & 0xf0;
1948             }
1949             dst_start += dst->stride;
1950             src_start += src->stride;
1951         }
1952         break;
1953     }
1954
1955     default:
1956         FIXME("Unsupported conversion: %d -> 4\n", src->bit_count);
1957         return FALSE;
1958
1959     }
1960
1961     return TRUE;
1962 }
1963
1964 static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
1965 {
1966     BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
1967     INT x, y;
1968     DWORD src_val;
1969     int bit_pos;
1970
1971     /* FIXME: Brushes should be dithered. */
1972
1973     switch(src->bit_count)
1974     {
1975     case 32:
1976     {
1977         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1978
1979         if(src->funcs == &funcs_8888)
1980         {
1981             for(y = src_rect->top; y < src_rect->bottom; y++)
1982             {
1983                 dst_pixel = dst_start;
1984                 src_pixel = src_start;
1985                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
1986                 {
1987                     src_val = *src_pixel++;
1988                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1989                                                                 ( src_val        & 0x00ff00) |
1990                                                                 ((src_val << 16) & 0xff0000) ) ? 0xff : 0;
1991
1992                     if(bit_pos == 0) *dst_pixel = 0;
1993                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
1994
1995                     if(++bit_pos == 8)
1996                     {
1997                         dst_pixel++;
1998                         bit_pos = 0;
1999                     }
2000                 }
2001                 dst_start += dst->stride;
2002                 src_start += src->stride / 4;
2003             }
2004         }
2005         else
2006         {
2007             FIXME("Unsupported conversion: 32 -> 1\n");
2008             return FALSE;
2009         }
2010         break;
2011     }
2012
2013     case 24:
2014     {
2015         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2016
2017         for(y = src_rect->top; y < src_rect->bottom; y++)
2018         {
2019             dst_pixel = dst_start;
2020             src_pixel = src_start;
2021             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2022             {
2023                 RGBQUAD rgb;
2024                 rgb.rgbBlue  = *src_pixel++;
2025                 rgb.rgbGreen = *src_pixel++;
2026                 rgb.rgbRed   = *src_pixel++;
2027
2028                 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed         & 0x0000ff) |
2029                                                             ((rgb.rgbGreen << 8) & 0x00ff00) |
2030                                                             ((rgb.rgbBlue << 16) & 0xff0000)) ? 0xff : 0;
2031
2032                 if(bit_pos == 0) *dst_pixel = 0;
2033                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2034
2035                 if(++bit_pos == 8)
2036                 {
2037                     dst_pixel++;
2038                     bit_pos = 0;
2039                 }
2040             }
2041             dst_start += dst->stride;
2042             src_start += src->stride;
2043         }
2044         break;
2045     }
2046
2047     case 16:
2048     {
2049         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2050         if(src->funcs == &funcs_555)
2051         {
2052             for(y = src_rect->top; y < src_rect->bottom; y++)
2053             {
2054                 dst_pixel = dst_start;
2055                 src_pixel = src_start;
2056                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2057                 {
2058                     src_val = *src_pixel++;
2059                     dst_val = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2060                                                                 ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
2061                                                                 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) ) ? 0xff : 0;
2062
2063                     if(bit_pos == 0) *dst_pixel = 0;
2064                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2065
2066                     if(++bit_pos == 8)
2067                     {
2068                         dst_pixel++;
2069                         bit_pos = 0;
2070                     }
2071                 }
2072                 dst_start += dst->stride;
2073                 src_start += src->stride / 2;
2074             }
2075         }
2076         else
2077         {
2078             FIXME("Unsupported conversion: 16 -> 1\n");
2079             return FALSE;
2080         }
2081         break;
2082     }
2083
2084     case 8:
2085     {
2086         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2087
2088         for(y = src_rect->top; y < src_rect->bottom; y++)
2089         {
2090             dst_pixel = dst_start;
2091             src_pixel = src_start;
2092             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2093             {
2094                 RGBQUAD rgb;
2095                 src_val = *src_pixel++;
2096                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2097                 rgb = src->color_table[src_val];
2098                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2099
2100                 if(bit_pos == 0) *dst_pixel = 0;
2101                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2102
2103                 if(++bit_pos == 8)
2104                 {
2105                     dst_pixel++;
2106                     bit_pos = 0;
2107                 }
2108             }
2109             dst_start += dst->stride;
2110             src_start += src->stride;
2111         }
2112         break;
2113     }
2114
2115     case 4:
2116     {
2117         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2118
2119         for(y = src_rect->top; y < src_rect->bottom; y++)
2120         {
2121             dst_pixel = dst_start;
2122             src_pixel = src_start;
2123             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2124             {
2125                 RGBQUAD rgb;
2126                 if(x & 1)
2127                     src_val = *src_pixel++ & 0xf;
2128                 else
2129                     src_val = (*src_pixel >> 4) & 0xf;
2130                 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2131                 rgb = src->color_table[src_val];
2132                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2133
2134                 if(bit_pos == 0) *dst_pixel = 0;
2135                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2136
2137                 if(++bit_pos == 8)
2138                 {
2139                     dst_pixel++;
2140                     bit_pos = 0;
2141                 }
2142             }
2143             dst_start += dst->stride;
2144             src_start += src->stride;
2145         }
2146         break;
2147     }
2148
2149     /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
2150        uses text/bkgnd colours instead of the dib's colour table, this
2151        doesn't appear to be the case for a dc backed by a
2152        dibsection. */
2153
2154     case 1:
2155     {
2156         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2157         for(y = src_rect->top; y < src_rect->bottom; y++)
2158         {
2159             dst_pixel = dst_start;
2160             src_pixel = src_start;
2161             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2162             {
2163                 RGBQUAD rgb;
2164                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2165                 if((x % 8) == 7) src_pixel++;
2166                 rgb = src->color_table[src_val];
2167                 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2168
2169                 if(bit_pos == 0) *dst_pixel = 0;
2170                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2171
2172                 if(++bit_pos == 8)
2173                 {
2174                     dst_pixel++;
2175                     bit_pos = 0;
2176                 }
2177             }
2178             dst_start += dst->stride;
2179             src_start += src->stride;
2180         }
2181         break;
2182     }
2183
2184     default:
2185         FIXME("Unsupported conversion: %d -> 1\n", src->bit_count);
2186         return FALSE;
2187
2188     }
2189     return TRUE;
2190 }
2191
2192 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
2193 {
2194     return FALSE;
2195 }
2196
2197 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)
2198 {
2199     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2200     DWORD mask_start = 0, mask_offset;
2201     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
2202     int x, y;
2203
2204     for(y = 0; y < hatch->height; y++)
2205     {
2206         hatch_ptr = hatch_start;
2207         mask_offset = mask_start;
2208         for(x = 0; x < hatch->width; x++)
2209         {
2210             if(*hatch_ptr & pixel_masks_1[x % 8])
2211             {
2212                 and_bits[mask_offset] = fg->and;
2213                 xor_bits[mask_offset] = fg->xor;
2214             }
2215             else
2216             {
2217                 and_bits[mask_offset] = bg->and;
2218                 xor_bits[mask_offset] = bg->xor;
2219             }
2220             if(x % 8 == 7) hatch_ptr++;
2221             mask_offset++;
2222         }
2223         hatch_start += hatch->stride;
2224         mask_start += dib->stride / 4;
2225     }
2226
2227     return TRUE;
2228 }
2229
2230 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)
2231 {
2232     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2233     DWORD mask_start = 0, mask_offset;
2234     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2235     int x, y;
2236
2237     for(y = 0; y < hatch->height; y++)
2238     {
2239         hatch_ptr = hatch_start;
2240         mask_offset = mask_start;
2241         for(x = 0; x < hatch->width; x++)
2242         {
2243             if(*hatch_ptr & pixel_masks_1[x % 8])
2244             {
2245                 and_bits[mask_offset]   =  fg->and        & 0xff;
2246                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
2247                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
2248                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
2249                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
2250                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
2251             }
2252             else
2253             {
2254                 and_bits[mask_offset]   =  bg->and        & 0xff;
2255                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
2256                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
2257                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
2258                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
2259                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
2260             }
2261             if(x % 8 == 7) hatch_ptr++;
2262         }
2263         hatch_start += hatch->stride;
2264         mask_start += dib->stride;
2265     }
2266
2267     return TRUE;
2268 }
2269
2270 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)
2271 {
2272     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2273     DWORD mask_start = 0, mask_offset;
2274     WORD *and_bits = bits->and, *xor_bits = bits->xor;
2275     int x, y;
2276
2277     for(y = 0; y < hatch->height; y++)
2278     {
2279         hatch_ptr = hatch_start;
2280         mask_offset = mask_start;
2281         for(x = 0; x < hatch->width; x++)
2282         {
2283             if(*hatch_ptr & pixel_masks_1[x % 8])
2284             {
2285                 and_bits[mask_offset] = fg->and;
2286                 xor_bits[mask_offset] = fg->xor;
2287             }
2288             else
2289             {
2290                 and_bits[mask_offset] = bg->and;
2291                 xor_bits[mask_offset] = bg->xor;
2292             }
2293             if(x % 8 == 7) hatch_ptr++;
2294             mask_offset++;
2295         }
2296         hatch_start += hatch->stride;
2297         mask_start += dib->stride / 2;
2298     }
2299
2300     return TRUE;
2301 }
2302
2303 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)
2304 {
2305     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2306     DWORD mask_start = 0, mask_offset;
2307     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2308     int x, y;
2309
2310     for(y = 0; y < hatch->height; y++)
2311     {
2312         hatch_ptr = hatch_start;
2313         mask_offset = mask_start;
2314         for(x = 0; x < hatch->width; x++)
2315         {
2316             if(*hatch_ptr & pixel_masks_1[x % 8])
2317             {
2318                 and_bits[mask_offset] = fg->and;
2319                 xor_bits[mask_offset] = fg->xor;
2320             }
2321             else
2322             {
2323                 and_bits[mask_offset] = bg->and;
2324                 xor_bits[mask_offset] = bg->xor;
2325             }
2326             if(x % 8 == 7) hatch_ptr++;
2327             mask_offset++;
2328         }
2329         hatch_start += hatch->stride;
2330         mask_start += dib->stride;
2331     }
2332
2333     return TRUE;
2334 }
2335
2336 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)
2337 {
2338     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2339     DWORD mask_start = 0, mask_offset;
2340     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2341     const rop_mask *rop_mask;
2342     int x, y;
2343
2344     for(y = 0; y < hatch->height; y++)
2345     {
2346         hatch_ptr = hatch_start;
2347         mask_offset = mask_start;
2348         for(x = 0; x < hatch->width; x++)
2349         {
2350             if(*hatch_ptr & pixel_masks_1[x % 8])
2351                 rop_mask = fg;
2352             else
2353                 rop_mask = bg;
2354
2355             if(x & 1)
2356             {
2357                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
2358                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
2359                 mask_offset++;
2360             }
2361             else
2362             {
2363                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
2364                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
2365             }
2366
2367             if(x % 8 == 7) hatch_ptr++;
2368         }
2369         hatch_start += hatch->stride;
2370         mask_start += dib->stride;
2371     }
2372
2373     return TRUE;
2374 }
2375
2376 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)
2377 {
2378     BYTE *hatch_start = hatch->bits, *hatch_ptr;
2379     DWORD mask_start = 0, mask_offset;
2380     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2381     rop_mask rop_mask;
2382     int x, y, bit_pos;
2383
2384     for(y = 0; y < hatch->height; y++)
2385     {
2386         hatch_ptr = hatch_start;
2387         mask_offset = mask_start;
2388         for(x = 0, bit_pos = 0; x < hatch->width; x++)
2389         {
2390             if(*hatch_ptr & pixel_masks_1[x % 8])
2391             {
2392                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
2393                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
2394             }
2395             else
2396             {
2397                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
2398                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
2399             }
2400
2401             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
2402
2403             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
2404             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
2405
2406             if(++bit_pos == 8)
2407             {
2408                 mask_offset++;
2409                 hatch_ptr++;
2410                 bit_pos = 0;
2411             }
2412         }
2413         hatch_start += hatch->stride;
2414         mask_start += dib->stride;
2415     }
2416
2417     return TRUE;
2418 }
2419
2420 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)
2421 {
2422     return FALSE;
2423 }
2424
2425 const primitive_funcs funcs_8888 =
2426 {
2427     solid_rects_32,
2428     pattern_rects_32,
2429     colorref_to_pixel_888,
2430     convert_to_8888,
2431     create_rop_masks_32
2432 };
2433
2434 const primitive_funcs funcs_32 =
2435 {
2436     solid_rects_32,
2437     pattern_rects_32,
2438     colorref_to_pixel_masks,
2439     convert_to_32,
2440     create_rop_masks_32
2441 };
2442
2443 const primitive_funcs funcs_24 =
2444 {
2445     solid_rects_24,
2446     pattern_rects_24,
2447     colorref_to_pixel_888,
2448     convert_to_24,
2449     create_rop_masks_24
2450 };
2451
2452 const primitive_funcs funcs_555 =
2453 {
2454     solid_rects_16,
2455     pattern_rects_16,
2456     colorref_to_pixel_555,
2457     convert_to_555,
2458     create_rop_masks_16
2459 };
2460
2461 const primitive_funcs funcs_16 =
2462 {
2463     solid_rects_16,
2464     pattern_rects_16,
2465     colorref_to_pixel_masks,
2466     convert_to_16,
2467     create_rop_masks_16
2468 };
2469
2470 const primitive_funcs funcs_8 =
2471 {
2472     solid_rects_8,
2473     pattern_rects_8,
2474     colorref_to_pixel_colortable,
2475     convert_to_8,
2476     create_rop_masks_8
2477 };
2478
2479 const primitive_funcs funcs_4 =
2480 {
2481     solid_rects_4,
2482     pattern_rects_4,
2483     colorref_to_pixel_colortable,
2484     convert_to_4,
2485     create_rop_masks_4
2486 };
2487
2488 const primitive_funcs funcs_1 =
2489 {
2490     solid_rects_1,
2491     pattern_rects_1,
2492     colorref_to_pixel_colortable,
2493     convert_to_1,
2494     create_rop_masks_1
2495 };
2496
2497 const primitive_funcs funcs_null =
2498 {
2499     solid_rects_null,
2500     pattern_rects_null,
2501     colorref_to_pixel_null,
2502     convert_to_null,
2503     create_rop_masks_null
2504 };