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