mshtml: Wine Gecko 1.4 release.
[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 get_pixel_32(const dib_info *dib, const POINT *pt)
1029 {
1030     DWORD *ptr = get_pixel_ptr_32( dib, pt->x, pt->y );
1031     return *ptr;
1032 }
1033
1034 static DWORD get_pixel_24(const dib_info *dib, const POINT *pt)
1035 {
1036     BYTE *ptr = get_pixel_ptr_24( dib, pt->x, pt->y );
1037     return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1038 }
1039
1040 static DWORD get_pixel_16(const dib_info *dib, const POINT *pt)
1041 {
1042     WORD *ptr = get_pixel_ptr_16( dib, pt->x, pt->y );
1043     return *ptr;
1044 }
1045
1046 static DWORD get_pixel_8(const dib_info *dib, const POINT *pt)
1047 {
1048     BYTE *ptr = get_pixel_ptr_8( dib, pt->x, pt->y );
1049     return *ptr;
1050 }
1051
1052 static DWORD get_pixel_4(const dib_info *dib, const POINT *pt)
1053 {
1054     BYTE *ptr = get_pixel_ptr_4( dib, pt->x, pt->y );
1055
1056     if (pt->x & 1)
1057         return *ptr & 0x0f;
1058     else
1059         return (*ptr >> 4) & 0x0f;
1060 }
1061
1062 static DWORD get_pixel_1(const dib_info *dib, const POINT *pt)
1063 {
1064     BYTE *ptr = get_pixel_ptr_1( dib, pt->x, pt->y );
1065     return (*ptr & pixel_masks_1[pt->x & 0x7]) ? 1 : 0;
1066 }
1067
1068 static DWORD get_pixel_null(const dib_info *dib, const POINT *pt)
1069 {
1070     return 0;
1071 }
1072
1073 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1074 {
1075     return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1076 }
1077
1078 static const DWORD field_masks[33] =
1079 {
1080     0x00,  /* should never happen */
1081     0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1082     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1083     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1084     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1085 };
1086
1087 static inline DWORD get_field(DWORD field, int shift, int len)
1088 {
1089     shift = shift - (8 - len);
1090     if (shift < 0)
1091         field <<= -shift;
1092     else
1093         field >>= shift;
1094     field &= field_masks[len];
1095     field |= field >> len;
1096     return field;
1097 }
1098
1099 static inline DWORD put_field(DWORD field, int shift, int len)
1100 {
1101     shift = shift - (8 - len);
1102     field &= field_masks[len];
1103     if (shift < 0)
1104         field >>= -shift;
1105     else
1106         field <<= shift;
1107     return field;
1108 }
1109
1110 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1111 {
1112     DWORD r,g,b;
1113
1114     r = GetRValue(colour);
1115     g = GetGValue(colour);
1116     b = GetBValue(colour);
1117
1118     return put_field(r, dib->red_shift,   dib->red_len) |
1119            put_field(g, dib->green_shift, dib->green_len) |
1120            put_field(b, dib->blue_shift,  dib->blue_len);
1121 }
1122
1123 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1124 {
1125     return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1126 }
1127
1128 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1129 {
1130     int i, best_index = 0;
1131     DWORD diff, best_diff = 0xffffffff;
1132
1133     /* special case for conversion to 1-bpp without a color table:
1134      * we get a 1-entry table containing the background color
1135      */
1136     if (dib->bit_count == 1 && dib->color_table_size == 1)
1137         return (r == dib->color_table[0].rgbRed &&
1138                 g == dib->color_table[0].rgbGreen &&
1139                 b == dib->color_table[0].rgbBlue);
1140
1141     for(i = 0; i < dib->color_table_size; i++)
1142     {
1143         RGBQUAD *cur = dib->color_table + i;
1144         diff = (r - cur->rgbRed)   * (r - cur->rgbRed)
1145             +  (g - cur->rgbGreen) * (g - cur->rgbGreen)
1146             +  (b - cur->rgbBlue)  * (b - cur->rgbBlue);
1147
1148         if(diff == 0)
1149         {
1150             best_index = i;
1151             break;
1152         }
1153
1154         if(diff < best_diff)
1155         {
1156             best_diff = diff;
1157             best_index = i;
1158         }
1159     }
1160     return best_index;
1161 }
1162
1163 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1164 {
1165     return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1166 }
1167
1168 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1169 {
1170     return 0;
1171 }
1172
1173 static inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1174 {
1175     static const RGBQUAD default_rgb;
1176     if (index < dib->color_table_size) return dib->color_table[index];
1177     return default_rgb;
1178 }
1179
1180 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1181 {
1182     return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1183 }
1184
1185 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1186 {
1187     return RGB( get_field( pixel, dib->red_shift,   dib->red_len ),
1188                 get_field( pixel, dib->green_shift, dib->green_len ),
1189                 get_field( pixel, dib->blue_shift,  dib->blue_len ) );
1190 }
1191
1192 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1193 {
1194     return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1195                 ((pixel >> 2) & 0xf8) | ((pixel >>  7) & 0x07),
1196                 ((pixel << 3) & 0xf8) | ((pixel >>  2) & 0x07) );
1197 }
1198
1199 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1200 {
1201     RGBQUAD quad = colortable_entry( dib, pixel );
1202
1203     return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1204 }
1205
1206 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1207 {
1208     return 0;
1209 }
1210
1211 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1212 {
1213     assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1214
1215     return d1->red_mask   == d2->red_mask &&
1216            d1->green_mask == d2->green_mask &&
1217            d1->blue_mask  == d2->blue_mask;
1218 }
1219
1220 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1221 {
1222     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1223     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1224
1225     switch(src->bit_count)
1226     {
1227     case 32:
1228     {
1229         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1230         if(src->funcs == &funcs_8888)
1231         {
1232             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1233                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1234             else
1235             {
1236                 for(y = src_rect->top; y < src_rect->bottom; y++)
1237                 {
1238                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1239                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1240                     dst_start += dst->stride / 4;
1241                     src_start += src->stride / 4;
1242                 }
1243             }
1244         }
1245         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1246         {
1247             for(y = src_rect->top; y < src_rect->bottom; y++)
1248             {
1249                 dst_pixel = dst_start;
1250                 src_pixel = src_start;
1251                 for(x = src_rect->left; x < src_rect->right; x++)
1252                 {
1253                     src_val = *src_pixel++;
1254                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << 16) |
1255                                    (((src_val >> src->green_shift) & 0xff) <<  8) |
1256                                     ((src_val >> src->blue_shift)  & 0xff);
1257                 }
1258                 if(pad_size) memset(dst_pixel, 0, pad_size);
1259                 dst_start += dst->stride / 4;
1260                 src_start += src->stride / 4;
1261             }
1262         }
1263         else
1264         {
1265             for(y = src_rect->top; y < src_rect->bottom; y++)
1266             {
1267                 dst_pixel = dst_start;
1268                 src_pixel = src_start;
1269                 for(x = src_rect->left; x < src_rect->right; x++)
1270                 {
1271                     src_val = *src_pixel++;
1272                     *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1273                                     get_field( src_val, src->green_shift, src->green_len ) << 8 |
1274                                     get_field( src_val, src->blue_shift, src->blue_len ));
1275                 }
1276                 if(pad_size) memset(dst_pixel, 0, pad_size);
1277                 dst_start += dst->stride / 4;
1278                 src_start += src->stride / 4;
1279             }
1280         }
1281         break;
1282     }
1283
1284     case 24:
1285     {
1286         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1287
1288         for(y = src_rect->top; y < src_rect->bottom; y++)
1289         {
1290             dst_pixel = dst_start;
1291             src_pixel = src_start;
1292             for(x = src_rect->left; x < src_rect->right; x++)
1293             {
1294                 RGBQUAD rgb;
1295                 rgb.rgbBlue  = *src_pixel++;
1296                 rgb.rgbGreen = *src_pixel++;
1297                 rgb.rgbRed   = *src_pixel++;
1298
1299                 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1300             }
1301             if(pad_size) memset(dst_pixel, 0, pad_size);
1302             dst_start += dst->stride / 4;
1303             src_start += src->stride;
1304         }
1305         break;
1306     }
1307
1308     case 16:
1309     {
1310         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1311         if(src->funcs == &funcs_555)
1312         {
1313             for(y = src_rect->top; y < src_rect->bottom; y++)
1314             {
1315                 dst_pixel = dst_start;
1316                 src_pixel = src_start;
1317                 for(x = src_rect->left; x < src_rect->right; x++)
1318                 {
1319                     src_val = *src_pixel++;
1320                     *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1321                                    ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1322                                    ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1323                 }
1324                 if(pad_size) memset(dst_pixel, 0, pad_size);
1325                 dst_start += dst->stride / 4;
1326                 src_start += src->stride / 2;
1327             }
1328         }
1329         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1330         {
1331             for(y = src_rect->top; y < src_rect->bottom; y++)
1332             {
1333                 dst_pixel = dst_start;
1334                 src_pixel = src_start;
1335                 for(x = src_rect->left; x < src_rect->right; x++)
1336                 {
1337                     src_val = *src_pixel++;
1338                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1339                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1340                                    (((src_val >> src->green_shift) << 11) & 0x00f800) |
1341                                    (((src_val >> src->green_shift) <<  6) & 0x000700) |
1342                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1343                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1344                 }
1345                 if(pad_size) memset(dst_pixel, 0, pad_size);
1346                 dst_start += dst->stride / 4;
1347                 src_start += src->stride / 2;
1348             }
1349         }
1350         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1351         {
1352             for(y = src_rect->top; y < src_rect->bottom; y++)
1353             {
1354                 dst_pixel = dst_start;
1355                 src_pixel = src_start;
1356                 for(x = src_rect->left; x < src_rect->right; x++)
1357                 {
1358                     src_val = *src_pixel++;
1359                     *dst_pixel++ = (((src_val >> src->red_shift)   << 19) & 0xf80000) |
1360                                    (((src_val >> src->red_shift)   << 14) & 0x070000) |
1361                                    (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1362                                    (((src_val >> src->green_shift) <<  4) & 0x000300) |
1363                                    (((src_val >> src->blue_shift)  <<  3) & 0x0000f8) |
1364                                    (((src_val >> src->blue_shift)  >>  2) & 0x000007);
1365                 }
1366                 if(pad_size) memset(dst_pixel, 0, pad_size);
1367                 dst_start += dst->stride / 4;
1368                 src_start += src->stride / 2;
1369             }
1370         }
1371         else
1372         {
1373             for(y = src_rect->top; y < src_rect->bottom; y++)
1374             {
1375                 dst_pixel = dst_start;
1376                 src_pixel = src_start;
1377                 for(x = src_rect->left; x < src_rect->right; x++)
1378                 {
1379                     src_val = *src_pixel++;
1380                     *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1381                                     get_field( src_val, src->green_shift, src->green_len ) << 8 |
1382                                     get_field( src_val, src->blue_shift, src->blue_len ));
1383                 }
1384                 if(pad_size) memset(dst_pixel, 0, pad_size);
1385                 dst_start += dst->stride / 4;
1386                 src_start += src->stride / 2;
1387             }
1388         }
1389         break;
1390     }
1391
1392     case 8:
1393     {
1394         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
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                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1402                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1403             }
1404             if(pad_size) memset(dst_pixel, 0, pad_size);
1405             dst_start += dst->stride / 4;
1406             src_start += src->stride;
1407         }
1408         break;
1409     }
1410
1411     case 4:
1412     {
1413         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1414         for(y = src_rect->top; y < src_rect->bottom; y++)
1415         {
1416             dst_pixel = dst_start;
1417             src_pixel = src_start;
1418             for(x = src_rect->left; x < src_rect->right; x++)
1419             {
1420                 RGBQUAD rgb;
1421                 if(x & 1)
1422                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
1423                 else
1424                     rgb = colortable_entry( src, *src_pixel >> 4 );
1425                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1426             }
1427             if(pad_size) memset(dst_pixel, 0, pad_size);
1428             dst_start += dst->stride / 4;
1429             src_start += src->stride;
1430         }
1431         break;
1432     }
1433
1434     case 1:
1435     {
1436         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1437         for(y = src_rect->top; y < src_rect->bottom; y++)
1438         {
1439             dst_pixel = dst_start;
1440             src_pixel = src_start;
1441             for(x = src_rect->left; x < src_rect->right; x++)
1442             {
1443                 RGBQUAD rgb;
1444                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1445                 if((x % 8) == 7) src_pixel++;
1446                 rgb = src->color_table[src_val];
1447                 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1448             }
1449             if(pad_size) memset(dst_pixel, 0, pad_size);
1450             dst_start += dst->stride / 4;
1451             src_start += src->stride;
1452         }
1453         break;
1454     }
1455     }
1456 }
1457
1458 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1459 {
1460     DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1461     int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1462
1463     switch(src->bit_count)
1464     {
1465     case 32:
1466     {
1467         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1468
1469         if(src->funcs == &funcs_8888)
1470         {
1471             for(y = src_rect->top; y < src_rect->bottom; y++)
1472             {
1473                 dst_pixel = dst_start;
1474                 src_pixel = src_start;
1475                 for(x = src_rect->left; x < src_rect->right; x++)
1476                 {
1477                     src_val = *src_pixel++;
1478                     *dst_pixel++ = put_field(src_val >> 16, dst->red_shift,   dst->red_len)   |
1479                                    put_field(src_val >>  8, dst->green_shift, dst->green_len) |
1480                                    put_field(src_val,       dst->blue_shift,  dst->blue_len);
1481                 }
1482                 if(pad_size) memset(dst_pixel, 0, pad_size);
1483                 dst_start += dst->stride / 4;
1484                 src_start += src->stride / 4;
1485             }
1486         }
1487         else if(bit_fields_match(src, dst))
1488         {
1489             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1490                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1491             else
1492             {
1493                 for(y = src_rect->top; y < src_rect->bottom; y++)
1494                 {
1495                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1496                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1497                     dst_start += dst->stride / 4;
1498                     src_start += src->stride / 4;
1499                 }
1500             }
1501         }
1502         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1503                 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1504         {
1505             for(y = src_rect->top; y < src_rect->bottom; y++)
1506             {
1507                 dst_pixel = dst_start;
1508                 src_pixel = src_start;
1509                 for(x = src_rect->left; x < src_rect->right; x++)
1510                 {
1511                     src_val = *src_pixel++;
1512                     *dst_pixel++ = (((src_val >> src->red_shift)   & 0xff) << dst->red_shift)   |
1513                                    (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1514                                    (((src_val >> src->blue_shift)  & 0xff) << dst->blue_shift);
1515                 }
1516                 if(pad_size) memset(dst_pixel, 0, pad_size);
1517                 dst_start += dst->stride / 4;
1518                 src_start += src->stride / 4;
1519             }
1520         }
1521         else
1522         {
1523             for(y = src_rect->top; y < src_rect->bottom; y++)
1524             {
1525                 dst_pixel = dst_start;
1526                 src_pixel = src_start;
1527                 for(x = src_rect->left; x < src_rect->right; x++)
1528                 {
1529                     src_val = *src_pixel++;
1530                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
1531                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1532                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
1533                 }
1534                 if(pad_size) memset(dst_pixel, 0, pad_size);
1535                 dst_start += dst->stride / 4;
1536                 src_start += src->stride / 4;
1537             }
1538         }
1539         break;
1540     }
1541
1542     case 24:
1543     {
1544         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1545
1546         for(y = src_rect->top; y < src_rect->bottom; y++)
1547         {
1548             dst_pixel = dst_start;
1549             src_pixel = src_start;
1550             for(x = src_rect->left; x < src_rect->right; x++)
1551             {
1552                 RGBQUAD rgb;
1553                 rgb.rgbBlue  = *src_pixel++;
1554                 rgb.rgbGreen = *src_pixel++;
1555                 rgb.rgbRed   = *src_pixel++;
1556
1557                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len)   |
1558                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1559                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1560             }
1561             if(pad_size) memset(dst_pixel, 0, pad_size);
1562             dst_start += dst->stride / 4;
1563             src_start += src->stride;
1564         }
1565         break;
1566     }
1567
1568     case 16:
1569     {
1570         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1571         if(src->funcs == &funcs_555)
1572         {
1573             for(y = src_rect->top; y < src_rect->bottom; y++)
1574             {
1575                 dst_pixel = dst_start;
1576                 src_pixel = src_start;
1577                 for(x = src_rect->left; x < src_rect->right; x++)
1578                 {
1579                     src_val = *src_pixel++;
1580                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
1581                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
1582                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
1583                 }
1584                 if(pad_size) memset(dst_pixel, 0, pad_size);
1585                 dst_start += dst->stride / 4;
1586                 src_start += src->stride / 2;
1587             }
1588         }
1589         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1590         {
1591             for(y = src_rect->top; y < src_rect->bottom; y++)
1592             {
1593                 dst_pixel = dst_start;
1594                 src_pixel = src_start;
1595                 for(x = src_rect->left; x < src_rect->right; x++)
1596                 {
1597                     src_val = *src_pixel++;
1598                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1599                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1600                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1601                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1602                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1603                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1604                 }
1605                 if(pad_size) memset(dst_pixel, 0, pad_size);
1606                 dst_start += dst->stride / 4;
1607                 src_start += src->stride / 2;
1608             }
1609         }
1610         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1611         {
1612             for(y = src_rect->top; y < src_rect->bottom; y++)
1613             {
1614                 dst_pixel = dst_start;
1615                 src_pixel = src_start;
1616                 for(x = src_rect->left; x < src_rect->right; x++)
1617                 {
1618                     src_val = *src_pixel++;
1619                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
1620                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1621                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1622                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1623                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1624                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1625                 }
1626                 if(pad_size) memset(dst_pixel, 0, pad_size);
1627                 dst_start += dst->stride / 4;
1628                 src_start += src->stride / 2;
1629             }
1630         }
1631         else
1632         {
1633             for(y = src_rect->top; y < src_rect->bottom; y++)
1634             {
1635                 dst_pixel = dst_start;
1636                 src_pixel = src_start;
1637                 for(x = src_rect->left; x < src_rect->right; x++)
1638                 {
1639                     src_val = *src_pixel++;
1640                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
1641                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1642                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
1643                 }
1644                 if(pad_size) memset(dst_pixel, 0, pad_size);
1645                 dst_start += dst->stride / 4;
1646                 src_start += src->stride / 2;
1647             }
1648         }
1649         break;
1650     }
1651
1652     case 8:
1653     {
1654         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1655         for(y = src_rect->top; y < src_rect->bottom; y++)
1656         {
1657             dst_pixel = dst_start;
1658             src_pixel = src_start;
1659             for(x = src_rect->left; x < src_rect->right; x++)
1660             {
1661                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1662                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1663                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1664                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1665             }
1666             if(pad_size) memset(dst_pixel, 0, pad_size);
1667             dst_start += dst->stride / 4;
1668             src_start += src->stride;
1669         }
1670         break;
1671     }
1672
1673     case 4:
1674     {
1675         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1676         for(y = src_rect->top; y < src_rect->bottom; y++)
1677         {
1678             dst_pixel = dst_start;
1679             src_pixel = src_start;
1680             for(x = src_rect->left; x < src_rect->right; x++)
1681             {
1682                 RGBQUAD rgb;
1683                 if(x & 1)
1684                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
1685                 else
1686                     rgb = colortable_entry( src, *src_pixel >> 4 );
1687                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1688                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1689                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1690             }
1691             if(pad_size) memset(dst_pixel, 0, pad_size);
1692             dst_start += dst->stride / 4;
1693             src_start += src->stride;
1694         }
1695         break;
1696     }
1697
1698     case 1:
1699     {
1700         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1701         for(y = src_rect->top; y < src_rect->bottom; y++)
1702         {
1703             dst_pixel = dst_start;
1704             src_pixel = src_start;
1705             for(x = src_rect->left; x < src_rect->right; x++)
1706             {
1707                 RGBQUAD rgb;
1708                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1709                 if((x % 8) == 7) src_pixel++;
1710                 rgb = src->color_table[src_val];
1711                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
1712                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1713                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
1714             }
1715             if(pad_size) memset(dst_pixel, 0, pad_size);
1716             dst_start += dst->stride / 4;
1717             src_start += src->stride;
1718         }
1719         break;
1720     }
1721     }
1722 }
1723
1724 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1725 {
1726     BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1727     DWORD src_val;
1728     int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1729
1730     switch(src->bit_count)
1731     {
1732     case 32:
1733     {
1734         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1735         if(src->funcs == &funcs_8888)
1736         {
1737             for(y = src_rect->top; y < src_rect->bottom; y++)
1738             {
1739                 dst_pixel = dst_start;
1740                 src_pixel = src_start;
1741                 for(x = src_rect->left; x < src_rect->right; x++)
1742                 {
1743                     src_val = *src_pixel++;
1744                     *dst_pixel++ =  src_val        & 0xff;
1745                     *dst_pixel++ = (src_val >>  8) & 0xff;
1746                     *dst_pixel++ = (src_val >> 16) & 0xff;
1747                 }
1748                 if(pad_size) memset(dst_pixel, 0, pad_size);
1749                 dst_start += dst->stride;
1750                 src_start += src->stride / 4;
1751             }
1752         }
1753         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1754         {
1755             for(y = src_rect->top; y < src_rect->bottom; y++)
1756             {
1757                 dst_pixel = dst_start;
1758                 src_pixel = src_start;
1759                 for(x = src_rect->left; x < src_rect->right; x++)
1760                 {
1761                     src_val = *src_pixel++;
1762                     *dst_pixel++ = (src_val >> src->blue_shift)  & 0xff;
1763                     *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1764                     *dst_pixel++ = (src_val >> src->red_shift)   & 0xff;
1765                 }
1766                 if(pad_size) memset(dst_pixel, 0, pad_size);
1767                 dst_start += dst->stride;
1768                 src_start += src->stride / 4;
1769             }
1770         }
1771         else
1772         {
1773             for(y = src_rect->top; y < src_rect->bottom; y++)
1774             {
1775                 dst_pixel = dst_start;
1776                 src_pixel = src_start;
1777                 for(x = src_rect->left; x < src_rect->right; x++)
1778                 {
1779                     src_val = *src_pixel++;
1780                     *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
1781                     *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
1782                     *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
1783                 }
1784                 if(pad_size) memset(dst_pixel, 0, pad_size);
1785                 dst_start += dst->stride;
1786                 src_start += src->stride / 4;
1787             }
1788         }
1789         break;
1790     }
1791
1792     case 24:
1793     {
1794         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1795
1796         if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1797             memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1798         else
1799         {
1800             for(y = src_rect->top; y < src_rect->bottom; y++)
1801             {
1802                 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1803                 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1804                 dst_start += dst->stride;
1805                 src_start += src->stride;
1806             }
1807         }
1808         break;
1809     }
1810
1811     case 16:
1812     {
1813         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1814         if(src->funcs == &funcs_555)
1815         {
1816             for(y = src_rect->top; y < src_rect->bottom; y++)
1817             {
1818                 dst_pixel = dst_start;
1819                 src_pixel = src_start;
1820                 for(x = src_rect->left; x < src_rect->right; x++)
1821                 {
1822                     src_val = *src_pixel++;
1823                     *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07);
1824                     *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07);
1825                     *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1826                 }
1827                 if(pad_size) memset(dst_pixel, 0, pad_size);
1828                 dst_start += dst->stride;
1829                 src_start += src->stride / 2;
1830             }
1831         }
1832         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1833         {
1834             for(y = src_rect->top; y < src_rect->bottom; y++)
1835             {
1836                 dst_pixel = dst_start;
1837                 src_pixel = src_start;
1838                 for(x = src_rect->left; x < src_rect->right; x++)
1839                 {
1840                     src_val = *src_pixel++;
1841                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1842                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
1843                     *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1844                                    (((src_val >> src->green_shift) >> 2) & 0x07);
1845                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
1846                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
1847                 }
1848                 if(pad_size) memset(dst_pixel, 0, pad_size);
1849                 dst_start += dst->stride;
1850                 src_start += src->stride / 2;
1851             }
1852         }
1853         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1854         {
1855             for(y = src_rect->top; y < src_rect->bottom; y++)
1856             {
1857                 dst_pixel = dst_start;
1858                 src_pixel = src_start;
1859                 for(x = src_rect->left; x < src_rect->right; x++)
1860                 {
1861                     src_val = *src_pixel++;
1862                     *dst_pixel++ = (((src_val >> src->blue_shift)  << 3) & 0xf8) |
1863                                    (((src_val >> src->blue_shift)  >> 2) & 0x07);
1864                     *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1865                                    (((src_val >> src->green_shift) >> 4) & 0x03);
1866                     *dst_pixel++ = (((src_val >> src->red_shift)   << 3) & 0xf8) |
1867                                    (((src_val >> src->red_shift)   >> 2) & 0x07);
1868                 }
1869                 if(pad_size) memset(dst_pixel, 0, pad_size);
1870                 dst_start += dst->stride;
1871                 src_start += src->stride / 2;
1872             }
1873         }
1874         else
1875         {
1876             for(y = src_rect->top; y < src_rect->bottom; y++)
1877             {
1878                 dst_pixel = dst_start;
1879                 src_pixel = src_start;
1880                 for(x = src_rect->left; x < src_rect->right; x++)
1881                 {
1882                     src_val = *src_pixel++;
1883                     *dst_pixel++ = get_field(src_val, src->blue_shift,  src->blue_len );
1884                     *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
1885                     *dst_pixel++ = get_field(src_val, src->red_shift,   src->red_len );
1886                 }
1887                 if(pad_size) memset(dst_pixel, 0, pad_size);
1888                 dst_start += dst->stride;
1889                 src_start += src->stride / 2;
1890             }
1891         }
1892         break;
1893     }
1894
1895     case 8:
1896     {
1897         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1898         for(y = src_rect->top; y < src_rect->bottom; y++)
1899         {
1900             dst_pixel = dst_start;
1901             src_pixel = src_start;
1902             for(x = src_rect->left; x < src_rect->right; x++)
1903             {
1904                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1905                 *dst_pixel++ = rgb.rgbBlue;
1906                 *dst_pixel++ = rgb.rgbGreen;
1907                 *dst_pixel++ = rgb.rgbRed;
1908             }
1909             if(pad_size) memset(dst_pixel, 0, pad_size);
1910             dst_start += dst->stride;
1911             src_start += src->stride;
1912         }
1913         break;
1914     }
1915
1916     case 4:
1917     {
1918         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1919         for(y = src_rect->top; y < src_rect->bottom; y++)
1920         {
1921             dst_pixel = dst_start;
1922             src_pixel = src_start;
1923             for(x = src_rect->left; x < src_rect->right; x++)
1924             {
1925                 RGBQUAD rgb;
1926                 if(x & 1)
1927                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
1928                 else
1929                     rgb = colortable_entry( src, *src_pixel >> 4 );
1930                 *dst_pixel++ = rgb.rgbBlue;
1931                 *dst_pixel++ = rgb.rgbGreen;
1932                 *dst_pixel++ = rgb.rgbRed;
1933             }
1934             if(pad_size) memset(dst_pixel, 0, pad_size);
1935             dst_start += dst->stride;
1936             src_start += src->stride;
1937         }
1938         break;
1939     }
1940
1941     case 1:
1942     {
1943         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1944         for(y = src_rect->top; y < src_rect->bottom; y++)
1945         {
1946             dst_pixel = dst_start;
1947             src_pixel = src_start;
1948             for(x = src_rect->left; x < src_rect->right; x++)
1949             {
1950                 RGBQUAD rgb;
1951                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1952                 if((x % 8) == 7) src_pixel++;
1953                 rgb = src->color_table[src_val];
1954                 *dst_pixel++ = rgb.rgbBlue;
1955                 *dst_pixel++ = rgb.rgbGreen;
1956                 *dst_pixel++ = rgb.rgbRed;
1957             }
1958             if(pad_size) memset(dst_pixel, 0, pad_size);
1959             dst_start += dst->stride;
1960             src_start += src->stride;
1961         }
1962         break;
1963     }
1964     }
1965 }
1966
1967 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1968 {
1969     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
1970     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1971     DWORD src_val;
1972
1973     switch(src->bit_count)
1974     {
1975     case 32:
1976     {
1977         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1978
1979         if(src->funcs == &funcs_8888)
1980         {
1981             for(y = src_rect->top; y < src_rect->bottom; y++)
1982             {
1983                 dst_pixel = dst_start;
1984                 src_pixel = src_start;
1985                 for(x = src_rect->left; x < src_rect->right; x++)
1986                 {
1987                     src_val = *src_pixel++;
1988                     *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1989                                    ((src_val >> 6) & 0x03e0) |
1990                                    ((src_val >> 3) & 0x001f);
1991                 }
1992                 if(pad_size) memset(dst_pixel, 0, pad_size);
1993                 dst_start += dst->stride / 2;
1994                 src_start += src->stride / 4;
1995             }
1996         }
1997         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1998         {
1999             for(y = src_rect->top; y < src_rect->bottom; y++)
2000             {
2001                 dst_pixel = dst_start;
2002                 src_pixel = src_start;
2003                 for(x = src_rect->left; x < src_rect->right; x++)
2004                 {
2005                     src_val = *src_pixel++;
2006                     *dst_pixel++ = (((src_val >> src->red_shift)   << 7) & 0x7c00) |
2007                                    (((src_val >> src->green_shift) << 2) & 0x03e0) |
2008                                    (((src_val >> src->blue_shift)  >> 3) & 0x001f);
2009                 }
2010                 if(pad_size) memset(dst_pixel, 0, pad_size);
2011                 dst_start += dst->stride / 2;
2012                 src_start += src->stride / 4;
2013             }
2014         }
2015         else
2016         {
2017             for(y = src_rect->top; y < src_rect->bottom; y++)
2018             {
2019                 dst_pixel = dst_start;
2020                 src_pixel = src_start;
2021                 for(x = src_rect->left; x < src_rect->right; x++)
2022                 {
2023                     src_val = *src_pixel++;
2024                     *dst_pixel++ = (((get_field(src_val, src->red_shift,   src->red_len )   << 7) & 0x7c00) |
2025                                     ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2026                                     ( get_field(src_val, src->blue_shift,  src->blue_len )  >> 3));
2027                 }
2028                 if(pad_size) memset(dst_pixel, 0, pad_size);
2029                 dst_start += dst->stride / 2;
2030                 src_start += src->stride / 4;
2031             }
2032         }
2033         break;
2034     }
2035
2036     case 24:
2037     {
2038         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2039
2040         for(y = src_rect->top; y < src_rect->bottom; y++)
2041         {
2042             dst_pixel = dst_start;
2043             src_pixel = src_start;
2044             for(x = src_rect->left; x < src_rect->right; x++)
2045             {
2046                 RGBQUAD rgb;
2047                 rgb.rgbBlue  = *src_pixel++;
2048                 rgb.rgbGreen = *src_pixel++;
2049                 rgb.rgbRed   = *src_pixel++;
2050
2051                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2052                                ((rgb.rgbGreen << 2) & 0x03e0) |
2053                                ((rgb.rgbBlue  >> 3) & 0x001f);
2054             }
2055             if(pad_size) memset(dst_pixel, 0, pad_size);
2056             dst_start += dst->stride / 2;
2057             src_start += src->stride;
2058         }
2059         break;
2060     }
2061
2062     case 16:
2063     {
2064         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2065         if(src->funcs == &funcs_555)
2066         {
2067             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2068                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2069             else
2070             {
2071                 for(y = src_rect->top; y < src_rect->bottom; y++)
2072                 {
2073                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2074                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2075                     dst_start += dst->stride / 2;
2076                     src_start += src->stride / 2;
2077                 }
2078             }
2079         }
2080         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2081         {
2082             for(y = src_rect->top; y < src_rect->bottom; y++)
2083             {
2084                 dst_pixel = dst_start;
2085                 src_pixel = src_start;
2086                 for(x = src_rect->left; x < src_rect->right; x++)
2087                 {
2088                     src_val = *src_pixel++;
2089                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2090                                    (((src_val >> src->green_shift) <<  5) & 0x03e0) |
2091                                    ( (src_val >> src->blue_shift)         & 0x001f);
2092                 }
2093                 if(pad_size) memset(dst_pixel, 0, pad_size);
2094                 dst_start += dst->stride / 2;
2095                 src_start += src->stride / 2;
2096             }
2097         }
2098         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2099         {
2100             for(y = src_rect->top; y < src_rect->bottom; y++)
2101             {
2102                 dst_pixel = dst_start;
2103                 src_pixel = src_start;
2104                 for(x = src_rect->left; x < src_rect->right; x++)
2105                 {
2106                     src_val = *src_pixel++;
2107                     *dst_pixel++ = (((src_val >> src->red_shift)   << 10) & 0x7c00) |
2108                                    (((src_val >> src->green_shift) <<  4) & 0x03e0) |
2109                                    ( (src_val >> src->blue_shift)         & 0x001f);
2110                 }
2111                 if(pad_size) memset(dst_pixel, 0, pad_size);
2112                 dst_start += dst->stride / 2;
2113                 src_start += src->stride / 2;
2114             }
2115         }
2116         else
2117         {
2118             for(y = src_rect->top; y < src_rect->bottom; y++)
2119             {
2120                 dst_pixel = dst_start;
2121                 src_pixel = src_start;
2122                 for(x = src_rect->left; x < src_rect->right; x++)
2123                 {
2124                     src_val = *src_pixel++;
2125                     *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len)     << 7) & 0x7c00) |
2126                                     ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2127                                     ( get_field(src_val, src->blue_shift, src->blue_len)   >> 3));
2128                 }
2129                 if(pad_size) memset(dst_pixel, 0, pad_size);
2130                 dst_start += dst->stride / 2;
2131                 src_start += src->stride / 2;
2132             }
2133         }
2134         break;
2135     }
2136
2137     case 8:
2138     {
2139         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2140         for(y = src_rect->top; y < src_rect->bottom; y++)
2141         {
2142             dst_pixel = dst_start;
2143             src_pixel = src_start;
2144             for(x = src_rect->left; x < src_rect->right; x++)
2145             {
2146                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2147                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2148                                ((rgb.rgbGreen << 2) & 0x03e0) |
2149                                ((rgb.rgbBlue  >> 3) & 0x001f);
2150             }
2151             if(pad_size) memset(dst_pixel, 0, pad_size);
2152             dst_start += dst->stride / 2;
2153             src_start += src->stride;
2154         }
2155         break;
2156     }
2157
2158     case 4:
2159     {
2160         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2161         for(y = src_rect->top; y < src_rect->bottom; y++)
2162         {
2163             dst_pixel = dst_start;
2164             src_pixel = src_start;
2165             for(x = src_rect->left; x < src_rect->right; x++)
2166             {
2167                 RGBQUAD rgb;
2168                 if(x & 1)
2169                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
2170                 else
2171                     rgb = colortable_entry( src, *src_pixel >> 4 );
2172                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2173                                ((rgb.rgbGreen << 2) & 0x03e0) |
2174                                ((rgb.rgbBlue  >> 3) & 0x001f);
2175             }
2176             if(pad_size) memset(dst_pixel, 0, pad_size);
2177             dst_start += dst->stride / 2;
2178             src_start += src->stride;
2179         }
2180         break;
2181     }
2182
2183     case 1:
2184     {
2185         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2186         for(y = src_rect->top; y < src_rect->bottom; y++)
2187         {
2188             dst_pixel = dst_start;
2189             src_pixel = src_start;
2190             for(x = src_rect->left; x < src_rect->right; x++)
2191             {
2192                 RGBQUAD rgb;
2193                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2194                 if((x % 8) == 7) src_pixel++;
2195                 rgb = src->color_table[src_val];
2196                 *dst_pixel++ = ((rgb.rgbRed   << 7) & 0x7c00) |
2197                                ((rgb.rgbGreen << 2) & 0x03e0) |
2198                                ((rgb.rgbBlue  >> 3) & 0x001f);
2199             }
2200             if(pad_size) memset(dst_pixel, 0, pad_size);
2201             dst_start += dst->stride / 2;
2202             src_start += src->stride;
2203         }
2204         break;
2205     }
2206     }
2207 }
2208
2209 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2210 {
2211     WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2212     INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2213     DWORD src_val;
2214
2215     switch(src->bit_count)
2216     {
2217     case 32:
2218     {
2219         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2220
2221         if(src->funcs == &funcs_8888)
2222         {
2223             for(y = src_rect->top; y < src_rect->bottom; y++)
2224             {
2225                 dst_pixel = dst_start;
2226                 src_pixel = src_start;
2227                 for(x = src_rect->left; x < src_rect->right; x++)
2228                 {
2229                     src_val = *src_pixel++;
2230                     *dst_pixel++ = put_field(src_val >> 16, dst->red_shift,   dst->red_len)   |
2231                                    put_field(src_val >>  8, dst->green_shift, dst->green_len) |
2232                                    put_field(src_val,       dst->blue_shift,  dst->blue_len);
2233                 }
2234                 if(pad_size) memset(dst_pixel, 0, pad_size);
2235                 dst_start += dst->stride / 2;
2236                 src_start += src->stride / 4;
2237             }
2238         }
2239         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2240         {
2241             for(y = src_rect->top; y < src_rect->bottom; y++)
2242             {
2243                 dst_pixel = dst_start;
2244                 src_pixel = src_start;
2245                 for(x = src_rect->left; x < src_rect->right; x++)
2246                 {
2247                     src_val = *src_pixel++;
2248                     *dst_pixel++ = put_field(src_val >> src->red_shift,   dst->red_shift,   dst->red_len)   |
2249                                    put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2250                                    put_field(src_val >> src->blue_shift,  dst->blue_shift,  dst->blue_len);
2251                 }
2252                 if(pad_size) memset(dst_pixel, 0, pad_size);
2253                 dst_start += dst->stride / 2;
2254                 src_start += src->stride / 4;
2255             }
2256         }
2257         else
2258         {
2259             for(y = src_rect->top; y < src_rect->bottom; y++)
2260             {
2261                 dst_pixel = dst_start;
2262                 src_pixel = src_start;
2263                 for(x = src_rect->left; x < src_rect->right; x++)
2264                 {
2265                     src_val = *src_pixel++;
2266                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
2267                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2268                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
2269                 }
2270                 if(pad_size) memset(dst_pixel, 0, pad_size);
2271                 dst_start += dst->stride / 2;
2272                 src_start += src->stride / 4;
2273             }
2274         }
2275         break;
2276     }
2277
2278     case 24:
2279     {
2280         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2281
2282         for(y = src_rect->top; y < src_rect->bottom; y++)
2283         {
2284             dst_pixel = dst_start;
2285             src_pixel = src_start;
2286             for(x = src_rect->left; x < src_rect->right; x++)
2287             {
2288                 RGBQUAD rgb;
2289                 rgb.rgbBlue  = *src_pixel++;
2290                 rgb.rgbGreen = *src_pixel++;
2291                 rgb.rgbRed   = *src_pixel++;
2292
2293                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2294                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2295                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2296             }
2297             if(pad_size) memset(dst_pixel, 0, pad_size);
2298             dst_start += dst->stride / 2;
2299             src_start += src->stride;
2300         }
2301         break;
2302     }
2303
2304     case 16:
2305     {
2306         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2307         if(src->funcs == &funcs_555)
2308         {
2309             for(y = src_rect->top; y < src_rect->bottom; y++)
2310             {
2311                 dst_pixel = dst_start;
2312                 src_pixel = src_start;
2313                 for(x = src_rect->left; x < src_rect->right; x++)
2314                 {
2315                     src_val = *src_pixel++;
2316                     *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift,   dst->red_len) |
2317                                    put_field(((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07), dst->green_shift, dst->green_len) |
2318                                    put_field(((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07), dst->blue_shift,  dst->blue_len);
2319                 }
2320                 if(pad_size) memset(dst_pixel, 0, pad_size);
2321                 dst_start += dst->stride / 2;
2322                 src_start += src->stride / 2;
2323             }
2324         }
2325         else if(bit_fields_match(src, dst))
2326         {
2327             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2328                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2329             else
2330             {
2331                 for(y = src_rect->top; y < src_rect->bottom; y++)
2332                 {
2333                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2334                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2335                     dst_start += dst->stride / 2;
2336                     src_start += src->stride / 2;
2337                 }
2338             }
2339         }
2340         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2341         {
2342             for(y = src_rect->top; y < src_rect->bottom; y++)
2343             {
2344                 dst_pixel = dst_start;
2345                 src_pixel = src_start;
2346                 for(x = src_rect->left; x < src_rect->right; x++)
2347                 {
2348                     src_val = *src_pixel++;
2349                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2350                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2351                                    put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2352                                               (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2353                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2354                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2355                 }
2356                 if(pad_size) memset(dst_pixel, 0, pad_size);
2357                 dst_start += dst->stride / 2;
2358                 src_start += src->stride / 2;
2359             }
2360         }
2361         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2362         {
2363             for(y = src_rect->top; y < src_rect->bottom; y++)
2364             {
2365                 dst_pixel = dst_start;
2366                 src_pixel = src_start;
2367                 for(x = src_rect->left; x < src_rect->right; x++)
2368                 {
2369                     src_val = *src_pixel++;
2370                     *dst_pixel++ = put_field( (((src_val >> src->red_shift)   << 3) & 0xf8) |
2371                                               (((src_val >> src->red_shift)   >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2372                                    put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2373                                               (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2374                                    put_field( (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2375                                               (((src_val >> src->blue_shift)  >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2376                 }
2377                 if(pad_size) memset(dst_pixel, 0, pad_size);
2378                 dst_start += dst->stride / 2;
2379                 src_start += src->stride / 2;
2380             }
2381         }
2382         else
2383         {
2384             for(y = src_rect->top; y < src_rect->bottom; y++)
2385             {
2386                 dst_pixel = dst_start;
2387                 src_pixel = src_start;
2388                 for(x = src_rect->left; x < src_rect->right; x++)
2389                 {
2390                     src_val = *src_pixel++;
2391                     *dst_pixel++ = put_field(get_field(src_val, src->red_shift,   src->red_len ),   dst->red_shift,   dst->red_len)   |
2392                                    put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2393                                    put_field(get_field(src_val, src->blue_shift,  src->blue_len ),  dst->blue_shift,  dst->blue_len);
2394                 }
2395                 if(pad_size) memset(dst_pixel, 0, pad_size);
2396                 dst_start += dst->stride / 2;
2397                 src_start += src->stride / 2;
2398             }
2399         }
2400         break;
2401     }
2402
2403     case 8:
2404     {
2405         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2406         for(y = src_rect->top; y < src_rect->bottom; y++)
2407         {
2408             dst_pixel = dst_start;
2409             src_pixel = src_start;
2410             for(x = src_rect->left; x < src_rect->right; x++)
2411             {
2412                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2413                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2414                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2415                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2416             }
2417             if(pad_size) memset(dst_pixel, 0, pad_size);
2418             dst_start += dst->stride / 2;
2419             src_start += src->stride;
2420         }
2421         break;
2422     }
2423
2424     case 4:
2425     {
2426         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2427         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                 RGBQUAD rgb;
2434                 if(x & 1)
2435                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
2436                 else
2437                     rgb = colortable_entry( src, *src_pixel >> 4 );
2438                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2439                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2440                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2441             }
2442             if(pad_size) memset(dst_pixel, 0, pad_size);
2443             dst_start += dst->stride / 2;
2444             src_start += src->stride;
2445         }
2446         break;
2447     }
2448
2449     case 1:
2450     {
2451         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2452         for(y = src_rect->top; y < src_rect->bottom; y++)
2453         {
2454             dst_pixel = dst_start;
2455             src_pixel = src_start;
2456             for(x = src_rect->left; x < src_rect->right; x++)
2457             {
2458                 RGBQUAD rgb;
2459                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2460                 if((x % 8) == 7) src_pixel++;
2461                 rgb = src->color_table[src_val];
2462                 *dst_pixel++ = put_field(rgb.rgbRed,   dst->red_shift,   dst->red_len) |
2463                                put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2464                                put_field(rgb.rgbBlue,  dst->blue_shift,  dst->blue_len);
2465             }
2466             if(pad_size) memset(dst_pixel, 0, pad_size);
2467             dst_start += dst->stride / 2;
2468             src_start += src->stride;
2469         }
2470         break;
2471     }
2472     }
2473 }
2474
2475 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2476 {
2477     assert(d1->color_table_size && d2->color_table_size);
2478
2479     if(d1->color_table_size != d2->color_table_size) return FALSE;
2480     return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2481 }
2482
2483 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2484 {
2485     /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2486     return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2487 }
2488
2489 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2490 {
2491     BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2492     INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2493     DWORD src_val;
2494
2495     switch(src->bit_count)
2496     {
2497     case 32:
2498     {
2499         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2500
2501         if(src->funcs == &funcs_8888)
2502         {
2503             for(y = src_rect->top; y < src_rect->bottom; y++)
2504             {
2505                 dst_pixel = dst_start;
2506                 src_pixel = src_start;
2507                 for(x = src_rect->left; x < src_rect->right; x++)
2508                 {
2509                     src_val = *src_pixel++;
2510                     *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2511                 }
2512                 if(pad_size) memset(dst_pixel, 0, pad_size);
2513                 dst_start += dst->stride;
2514                 src_start += src->stride / 4;
2515             }
2516         }
2517         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2518         {
2519             for(y = src_rect->top; y < src_rect->bottom; y++)
2520             {
2521                 dst_pixel = dst_start;
2522                 src_pixel = src_start;
2523                 for(x = src_rect->left; x < src_rect->right; x++)
2524                 {
2525                     src_val = *src_pixel++;
2526                     *dst_pixel++ = rgb_lookup_colortable(dst,
2527                                                          src_val >> src->red_shift,
2528                                                          src_val >> src->green_shift,
2529                                                          src_val >> src->blue_shift );
2530                 }
2531                 if(pad_size) memset(dst_pixel, 0, pad_size);
2532                 dst_start += dst->stride;
2533                 src_start += src->stride / 4;
2534             }
2535         }
2536         else
2537         {
2538             for(y = src_rect->top; y < src_rect->bottom; y++)
2539             {
2540                 dst_pixel = dst_start;
2541                 src_pixel = src_start;
2542                 for(x = src_rect->left; x < src_rect->right; x++)
2543                 {
2544                     src_val = *src_pixel++;
2545                     *dst_pixel++ = rgb_lookup_colortable(dst,
2546                                                          get_field(src_val, src->red_shift, src->red_len),
2547                                                          get_field(src_val, src->green_shift, src->green_len),
2548                                                          get_field(src_val, src->blue_shift, src->blue_len));
2549                 }
2550                 if(pad_size) memset(dst_pixel, 0, pad_size);
2551                 dst_start += dst->stride;
2552                 src_start += src->stride / 4;
2553             }
2554         }
2555         break;
2556     }
2557
2558     case 24:
2559     {
2560         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2561
2562         for(y = src_rect->top; y < src_rect->bottom; y++)
2563         {
2564             dst_pixel = dst_start;
2565             src_pixel = src_start;
2566             for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2567             {
2568                 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2569             }
2570             if(pad_size) memset(dst_pixel, 0, pad_size);
2571             dst_start += dst->stride;
2572             src_start += src->stride;
2573         }
2574         break;
2575     }
2576
2577     case 16:
2578     {
2579         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2580         if(src->funcs == &funcs_555)
2581         {
2582             for(y = src_rect->top; y < src_rect->bottom; y++)
2583             {
2584                 dst_pixel = dst_start;
2585                 src_pixel = src_start;
2586                 for(x = src_rect->left; x < src_rect->right; x++)
2587                 {
2588                     src_val = *src_pixel++;
2589                     *dst_pixel++ = rgb_lookup_colortable(dst,
2590                                                          ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2591                                                          ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2592                                                          ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2593                 }
2594                 if(pad_size) memset(dst_pixel, 0, pad_size);
2595                 dst_start += dst->stride;
2596                 src_start += src->stride / 2;
2597             }
2598         }
2599         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2600         {
2601             for(y = src_rect->top; y < src_rect->bottom; y++)
2602             {
2603                 dst_pixel = dst_start;
2604                 src_pixel = src_start;
2605                 for(x = src_rect->left; x < src_rect->right; x++)
2606                 {
2607                     src_val = *src_pixel++;
2608                     *dst_pixel++ = rgb_lookup_colortable(dst,
2609                                                          (((src_val >> src->red_shift)   << 3) & 0xf8) |
2610                                                          (((src_val >> src->red_shift)   >> 2) & 0x07),
2611                                                          (((src_val >> src->green_shift) << 3) & 0xf8) |
2612                                                          (((src_val >> src->green_shift) >> 2) & 0x07),
2613                                                          (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2614                                                          (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2615                 }
2616                 if(pad_size) memset(dst_pixel, 0, pad_size);
2617                 dst_start += dst->stride;
2618                 src_start += src->stride / 2;
2619             }
2620         }
2621         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2622         {
2623             for(y = src_rect->top; y < src_rect->bottom; y++)
2624             {
2625                 dst_pixel = dst_start;
2626                 src_pixel = src_start;
2627                 for(x = src_rect->left; x < src_rect->right; x++)
2628                 {
2629                     src_val = *src_pixel++;
2630                     *dst_pixel++ = rgb_lookup_colortable(dst,
2631                                                          (((src_val >> src->red_shift)   << 3) & 0xf8) |
2632                                                          (((src_val >> src->red_shift)   >> 2) & 0x07),
2633                                                          (((src_val >> src->green_shift) << 2) & 0xfc) |
2634                                                          (((src_val >> src->green_shift) >> 4) & 0x03),
2635                                                          (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2636                                                          (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2637                 }
2638                 if(pad_size) memset(dst_pixel, 0, pad_size);
2639                 dst_start += dst->stride;
2640                 src_start += src->stride / 2;
2641             }
2642         }
2643         else
2644         {
2645             for(y = src_rect->top; y < src_rect->bottom; y++)
2646             {
2647                 dst_pixel = dst_start;
2648                 src_pixel = src_start;
2649                 for(x = src_rect->left; x < src_rect->right; x++)
2650                 {
2651                     src_val = *src_pixel++;
2652                     *dst_pixel++ = rgb_lookup_colortable(dst,
2653                                                          get_field(src_val, src->red_shift, src->red_len),
2654                                                          get_field(src_val, src->green_shift, src->green_len),
2655                                                          get_field(src_val, src->blue_shift, src->blue_len));
2656                 }
2657                 if(pad_size) memset(dst_pixel, 0, pad_size);
2658                 dst_start += dst->stride;
2659                 src_start += src->stride / 2;
2660             }
2661         }
2662         break;
2663     }
2664
2665     case 8:
2666     {
2667         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2668
2669         if(color_tables_match(dst, src))
2670         {
2671             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2672                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2673             else
2674             {
2675                 for(y = src_rect->top; y < src_rect->bottom; y++)
2676                 {
2677                     memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2678                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2679                     dst_start += dst->stride;
2680                     src_start += src->stride;
2681                 }
2682             }
2683         }
2684         else
2685         {
2686             for(y = src_rect->top; y < src_rect->bottom; y++)
2687             {
2688                 dst_pixel = dst_start;
2689                 src_pixel = src_start;
2690                 for(x = src_rect->left; x < src_rect->right; x++)
2691                 {
2692                     RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2693                     *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2694                 }
2695                 if(pad_size) memset(dst_pixel, 0, pad_size);
2696                 dst_start += dst->stride;
2697                 src_start += src->stride;
2698             }
2699         }
2700         break;
2701     }
2702
2703     case 4:
2704     {
2705         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2706         for(y = src_rect->top; y < src_rect->bottom; y++)
2707         {
2708             dst_pixel = dst_start;
2709             src_pixel = src_start;
2710             for(x = src_rect->left; x < src_rect->right; x++)
2711             {
2712                 RGBQUAD rgb;
2713                 if(x & 1)
2714                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
2715                 else
2716                     rgb = colortable_entry( src, *src_pixel >> 4 );
2717                 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2718             }
2719             if(pad_size) memset(dst_pixel, 0, pad_size);
2720             dst_start += dst->stride;
2721             src_start += src->stride;
2722         }
2723         break;
2724     }
2725
2726     case 1:
2727     {
2728         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2729         for(y = src_rect->top; y < src_rect->bottom; y++)
2730         {
2731             dst_pixel = dst_start;
2732             src_pixel = src_start;
2733             for(x = src_rect->left; x < src_rect->right; x++)
2734             {
2735                 RGBQUAD rgb;
2736                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2737                 if((x % 8) == 7) src_pixel++;
2738                 rgb = src->color_table[src_val];
2739                 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2740             }
2741             if(pad_size) memset(dst_pixel, 0, pad_size);
2742             dst_start += dst->stride;
2743             src_start += src->stride;
2744         }
2745         break;
2746     }
2747     }
2748 }
2749
2750 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2751 {
2752     BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2753     INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2754     DWORD src_val;
2755
2756     switch(src->bit_count)
2757     {
2758     case 32:
2759     {
2760         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2761
2762         if(src->funcs == &funcs_8888)
2763         {
2764             for(y = src_rect->top; y < src_rect->bottom; y++)
2765             {
2766                 dst_pixel = dst_start;
2767                 src_pixel = src_start;
2768                 for(x = src_rect->left; x < src_rect->right; x++)
2769                 {
2770                     src_val = *src_pixel++;
2771                     dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
2772                     if((x - src_rect->left) & 1)
2773                     {
2774                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2775                         dst_pixel++;
2776                     }
2777                     else
2778                         *dst_pixel = (dst_val << 4) & 0xf0;
2779                 }
2780                 if(pad_size)
2781                 {
2782                     if((x - src_rect->left) & 1) dst_pixel++;
2783                     memset(dst_pixel, 0, pad_size);
2784                 }
2785                 dst_start += dst->stride;
2786                 src_start += src->stride / 4;
2787             }
2788         }
2789         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2790         {
2791             for(y = src_rect->top; y < src_rect->bottom; y++)
2792             {
2793                 dst_pixel = dst_start;
2794                 src_pixel = src_start;
2795                 for(x = src_rect->left; x < src_rect->right; x++)
2796                 {
2797                     src_val = *src_pixel++;
2798                     dst_val = rgb_to_pixel_colortable(dst,
2799                                                       src_val >> src->red_shift,
2800                                                       src_val >> src->green_shift,
2801                                                       src_val >> src->blue_shift);
2802                     if((x - src_rect->left) & 1)
2803                     {
2804                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2805                         dst_pixel++;
2806                     }
2807                     else
2808                         *dst_pixel = (dst_val << 4) & 0xf0;
2809                 }
2810                 if(pad_size)
2811                 {
2812                     if((x - src_rect->left) & 1) dst_pixel++;
2813                     memset(dst_pixel, 0, pad_size);
2814                 }
2815                 dst_start += dst->stride;
2816                 src_start += src->stride / 4;
2817             }
2818         }
2819         else
2820         {
2821             for(y = src_rect->top; y < src_rect->bottom; y++)
2822             {
2823                 dst_pixel = dst_start;
2824                 src_pixel = src_start;
2825                 for(x = src_rect->left; x < src_rect->right; x++)
2826                 {
2827                     src_val = *src_pixel++;
2828                     dst_val = rgb_to_pixel_colortable(dst,
2829                                                       get_field(src_val, src->red_shift, src->red_len),
2830                                                       get_field(src_val, src->green_shift, src->green_len),
2831                                                       get_field(src_val, src->blue_shift, src->blue_len));
2832                     if((x - src_rect->left) & 1)
2833                     {
2834                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2835                         dst_pixel++;
2836                     }
2837                     else
2838                         *dst_pixel = (dst_val << 4) & 0xf0;
2839                 }
2840                 if(pad_size)
2841                 {
2842                     if((x - src_rect->left) & 1) dst_pixel++;
2843                     memset(dst_pixel, 0, pad_size);
2844                 }
2845                 dst_start += dst->stride;
2846                 src_start += src->stride / 4;
2847             }
2848         }
2849         break;
2850     }
2851
2852     case 24:
2853     {
2854         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2855
2856         for(y = src_rect->top; y < src_rect->bottom; y++)
2857         {
2858             dst_pixel = dst_start;
2859             src_pixel = src_start;
2860             for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2861             {
2862                 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2863
2864                 if((x - src_rect->left) & 1)
2865                 {
2866                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2867                     dst_pixel++;
2868                 }
2869                 else
2870                     *dst_pixel = (dst_val << 4) & 0xf0;
2871             }
2872             if(pad_size)
2873             {
2874                 if((x - src_rect->left) & 1) dst_pixel++;
2875                 memset(dst_pixel, 0, pad_size);
2876             }
2877             dst_start += dst->stride;
2878             src_start += src->stride;
2879         }
2880         break;
2881     }
2882
2883     case 16:
2884     {
2885         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2886         if(src->funcs == &funcs_555)
2887         {
2888             for(y = src_rect->top; y < src_rect->bottom; y++)
2889             {
2890                 dst_pixel = dst_start;
2891                 src_pixel = src_start;
2892                 for(x = src_rect->left; x < src_rect->right; x++)
2893                 {
2894                     src_val = *src_pixel++;
2895                     dst_val = rgb_to_pixel_colortable(dst,
2896                                                       ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2897                                                       ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07),
2898                                                       ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07) );
2899                     if((x - src_rect->left) & 1)
2900                     {
2901                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2902                         dst_pixel++;
2903                     }
2904                     else
2905                         *dst_pixel = (dst_val << 4) & 0xf0;
2906                 }
2907                 if(pad_size)
2908                 {
2909                     if((x - src_rect->left) & 1) dst_pixel++;
2910                     memset(dst_pixel, 0, pad_size);
2911                 }
2912                 dst_start += dst->stride;
2913                 src_start += src->stride / 2;
2914             }
2915         }
2916         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2917         {
2918             for(y = src_rect->top; y < src_rect->bottom; y++)
2919             {
2920                 dst_pixel = dst_start;
2921                 src_pixel = src_start;
2922                 for(x = src_rect->left; x < src_rect->right; x++)
2923                 {
2924                     src_val = *src_pixel++;
2925                     dst_val = rgb_to_pixel_colortable(dst,
2926                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
2927                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
2928                                                       (((src_val >> src->green_shift) << 3) & 0xf8) |
2929                                                       (((src_val >> src->green_shift) >> 2) & 0x07),
2930                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2931                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2932                     if((x - src_rect->left) & 1)
2933                     {
2934                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2935                         dst_pixel++;
2936                     }
2937                     else
2938                         *dst_pixel = (dst_val << 4) & 0xf0;
2939                 }
2940                 if(pad_size)
2941                 {
2942                     if((x - src_rect->left) & 1) dst_pixel++;
2943                     memset(dst_pixel, 0, pad_size);
2944                 }
2945                 dst_start += dst->stride;
2946                 src_start += src->stride / 2;
2947             }
2948         }
2949         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2950         {
2951             for(y = src_rect->top; y < src_rect->bottom; y++)
2952             {
2953                 dst_pixel = dst_start;
2954                 src_pixel = src_start;
2955                 for(x = src_rect->left; x < src_rect->right; x++)
2956                 {
2957                     src_val = *src_pixel++;
2958                     dst_val = rgb_to_pixel_colortable(dst,
2959                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
2960                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
2961                                                       (((src_val >> src->green_shift) << 2) & 0xfc) |
2962                                                       (((src_val >> src->green_shift) >> 4) & 0x03),
2963                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
2964                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) );
2965                     if((x - src_rect->left) & 1)
2966                     {
2967                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2968                         dst_pixel++;
2969                     }
2970                     else
2971                         *dst_pixel = (dst_val << 4) & 0xf0;
2972                 }
2973                 if(pad_size)
2974                 {
2975                     if((x - src_rect->left) & 1) dst_pixel++;
2976                     memset(dst_pixel, 0, pad_size);
2977                 }
2978                 dst_start += dst->stride;
2979                 src_start += src->stride / 2;
2980             }
2981         }
2982         else
2983         {
2984             for(y = src_rect->top; y < src_rect->bottom; y++)
2985             {
2986                 dst_pixel = dst_start;
2987                 src_pixel = src_start;
2988                 for(x = src_rect->left; x < src_rect->right; x++)
2989                 {
2990                     src_val = *src_pixel++;
2991                     dst_val = rgb_to_pixel_colortable(dst,
2992                                                       get_field(src_val, src->red_shift, src->red_len),
2993                                                       get_field(src_val, src->green_shift, src->green_len),
2994                                                       get_field(src_val, src->blue_shift, src->blue_len));
2995                     if((x - src_rect->left) & 1)
2996                     {
2997                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2998                         dst_pixel++;
2999                     }
3000                     else
3001                         *dst_pixel = (dst_val << 4) & 0xf0;
3002                 }
3003                 if(pad_size)
3004                 {
3005                     if((x - src_rect->left) & 1) dst_pixel++;
3006                     memset(dst_pixel, 0, pad_size);
3007                 }
3008                 dst_start += dst->stride;
3009                 src_start += src->stride / 2;
3010             }
3011         }
3012         break;
3013     }
3014
3015     case 8:
3016     {
3017         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3018
3019         for(y = src_rect->top; y < src_rect->bottom; y++)
3020         {
3021             dst_pixel = dst_start;
3022             src_pixel = src_start;
3023             for(x = src_rect->left; x < src_rect->right; x++)
3024             {
3025                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3026                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3027                 if((x - src_rect->left) & 1)
3028                 {
3029                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3030                     dst_pixel++;
3031                 }
3032                 else
3033                     *dst_pixel = (dst_val << 4) & 0xf0;
3034             }
3035             if(pad_size)
3036             {
3037                 if((x - src_rect->left) & 1) dst_pixel++;
3038                 memset(dst_pixel, 0, pad_size);
3039             }
3040             dst_start += dst->stride;
3041             src_start += src->stride;
3042         }
3043         break;
3044     }
3045
3046     case 4:
3047     {
3048         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3049
3050         if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
3051         {
3052             if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
3053                 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3054             else
3055             {
3056                 for(y = src_rect->top; y < src_rect->bottom; y++)
3057                 {
3058                     memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3059                     if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3060                     dst_start += dst->stride;
3061                     src_start += src->stride;
3062                 }
3063             }
3064         }
3065         else
3066         {
3067             for(y = src_rect->top; y < src_rect->bottom; y++)
3068             {
3069                 dst_pixel = dst_start;
3070                 src_pixel = src_start;
3071                 for(x = src_rect->left; x < src_rect->right; x++)
3072                 {
3073                     RGBQUAD rgb;
3074                     if(x & 1)
3075                         rgb = colortable_entry( src, *src_pixel++ & 0xf );
3076                     else
3077                         rgb = colortable_entry( src, *src_pixel >> 4 );
3078                     dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3079                     if((x - src_rect->left) & 1)
3080                     {
3081                         *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3082                         dst_pixel++;
3083                     }
3084                     else
3085                         *dst_pixel = (dst_val << 4) & 0xf0;
3086                 }
3087                 if(pad_size)
3088                 {
3089                     if((x - src_rect->left) & 1) dst_pixel++;
3090                     memset(dst_pixel, 0, pad_size);
3091                 }
3092                 dst_start += dst->stride;
3093                 src_start += src->stride;
3094             }
3095         }
3096         break;
3097     }
3098
3099     case 1:
3100     {
3101         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3102         for(y = src_rect->top; y < src_rect->bottom; y++)
3103         {
3104             dst_pixel = dst_start;
3105             src_pixel = src_start;
3106             for(x = src_rect->left; x < src_rect->right; x++)
3107             {
3108                 RGBQUAD rgb;
3109                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3110                 if((x % 8) == 7) src_pixel++;
3111                 rgb = src->color_table[src_val];
3112                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3113                 if((x - src_rect->left) & 1)
3114                 {
3115                     *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3116                     dst_pixel++;
3117                 }
3118                 else
3119                     *dst_pixel = (dst_val << 4) & 0xf0;
3120             }
3121             if(pad_size)
3122             {
3123                 if((x - src_rect->left) & 1) dst_pixel++;
3124                 memset(dst_pixel, 0, pad_size);
3125             }
3126             dst_start += dst->stride;
3127             src_start += src->stride;
3128         }
3129         break;
3130     }
3131     }
3132 }
3133
3134 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3135 {
3136     BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3137     INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3138     DWORD src_val;
3139     int bit_pos;
3140
3141     /* FIXME: Brushes should be dithered. */
3142
3143     switch(src->bit_count)
3144     {
3145     case 32:
3146     {
3147         DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3148
3149         if(src->funcs == &funcs_8888)
3150         {
3151             for(y = src_rect->top; y < src_rect->bottom; y++)
3152             {
3153                 dst_pixel = dst_start;
3154                 src_pixel = src_start;
3155                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3156                 {
3157                     src_val = *src_pixel++;
3158                     dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3159
3160                     if(bit_pos == 0) *dst_pixel = 0;
3161                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3162
3163                     if(++bit_pos == 8)
3164                     {
3165                         dst_pixel++;
3166                         bit_pos = 0;
3167                     }
3168                 }
3169                 if(pad_size)
3170                 {
3171                     if(bit_pos != 0) dst_pixel++;
3172                     memset(dst_pixel, 0, pad_size);
3173                 }
3174                 dst_start += dst->stride;
3175                 src_start += src->stride / 4;
3176             }
3177         }
3178         else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3179         {
3180             for(y = src_rect->top; y < src_rect->bottom; y++)
3181             {
3182                 dst_pixel = dst_start;
3183                 src_pixel = src_start;
3184                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3185                 {
3186                     src_val = *src_pixel++;
3187                     dst_val = rgb_to_pixel_colortable(dst,
3188                                                       src_val >> src->red_shift,
3189                                                       src_val >> src->green_shift,
3190                                                       src_val >> src->blue_shift) ? 0xff : 0;
3191
3192                    if(bit_pos == 0) *dst_pixel = 0;
3193                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3194
3195                     if(++bit_pos == 8)
3196                     {
3197                         dst_pixel++;
3198                         bit_pos = 0;
3199                     }
3200                 }
3201                 if(pad_size)
3202                 {
3203                     if(bit_pos != 0) dst_pixel++;
3204                     memset(dst_pixel, 0, pad_size);
3205                 }
3206                 dst_start += dst->stride;
3207                 src_start += src->stride / 4;
3208             }
3209         }
3210         else
3211         {
3212             for(y = src_rect->top; y < src_rect->bottom; y++)
3213             {
3214                 dst_pixel = dst_start;
3215                 src_pixel = src_start;
3216                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3217                 {
3218                     src_val = *src_pixel++;
3219                     dst_val = rgb_to_pixel_colortable(dst,
3220                                                       get_field(src_val, src->red_shift, src->red_len),
3221                                                       get_field(src_val, src->green_shift, src->green_len),
3222                                                       get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3223
3224                    if(bit_pos == 0) *dst_pixel = 0;
3225                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3226
3227                     if(++bit_pos == 8)
3228                     {
3229                         dst_pixel++;
3230                         bit_pos = 0;
3231                     }
3232                 }
3233                 if(pad_size)
3234                 {
3235                     if(bit_pos != 0) dst_pixel++;
3236                     memset(dst_pixel, 0, pad_size);
3237                 }
3238                 dst_start += dst->stride;
3239                 src_start += src->stride / 4;
3240             }
3241         }
3242         break;
3243     }
3244
3245     case 24:
3246     {
3247         BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3248
3249         for(y = src_rect->top; y < src_rect->bottom; y++)
3250         {
3251             dst_pixel = dst_start;
3252             src_pixel = src_start;
3253             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3254             {
3255                 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3256
3257                 if(bit_pos == 0) *dst_pixel = 0;
3258                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3259
3260                 if(++bit_pos == 8)
3261                 {
3262                     dst_pixel++;
3263                     bit_pos = 0;
3264                 }
3265             }
3266             if(pad_size)
3267             {
3268                 if(bit_pos != 0) dst_pixel++;
3269                 memset(dst_pixel, 0, pad_size);
3270             }
3271             dst_start += dst->stride;
3272             src_start += src->stride;
3273         }
3274         break;
3275     }
3276
3277     case 16:
3278     {
3279         WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3280         if(src->funcs == &funcs_555)
3281         {
3282             for(y = src_rect->top; y < src_rect->bottom; y++)
3283             {
3284                 dst_pixel = dst_start;
3285                 src_pixel = src_start;
3286                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3287                 {
3288                     src_val = *src_pixel++;
3289                     dst_val = rgb_to_pixel_colortable(dst,
3290                                                       ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3291                                                       ((src_val >> 2) & 0xf8) | ((src_val >>  7) & 0x07),
3292                                                       ((src_val << 3) & 0xf8) | ((src_val >>  2) & 0x07) ) ? 0xff : 0;
3293
3294                     if(bit_pos == 0) *dst_pixel = 0;
3295                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3296
3297                     if(++bit_pos == 8)
3298                     {
3299                         dst_pixel++;
3300                         bit_pos = 0;
3301                     }
3302                 }
3303                 if(pad_size)
3304                 {
3305                     if(bit_pos != 0) dst_pixel++;
3306                     memset(dst_pixel, 0, pad_size);
3307                 }
3308                 dst_start += dst->stride;
3309                 src_start += src->stride / 2;
3310             }
3311         }
3312         else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3313         {
3314             for(y = src_rect->top; y < src_rect->bottom; y++)
3315             {
3316                 dst_pixel = dst_start;
3317                 src_pixel = src_start;
3318                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3319                 {
3320                     src_val = *src_pixel++;
3321                     dst_val = rgb_to_pixel_colortable(dst,
3322                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3323                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3324                                                       (((src_val >> src->green_shift) << 3) & 0xf8) |
3325                                                       (((src_val >> src->green_shift) >> 2) & 0x07),
3326                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3327                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) ) ? 0xff : 0;
3328                     if(bit_pos == 0) *dst_pixel = 0;
3329                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3330
3331                     if(++bit_pos == 8)
3332                     {
3333                         dst_pixel++;
3334                         bit_pos = 0;
3335                     }
3336                 }
3337                 if(pad_size)
3338                 {
3339                     if(bit_pos != 0) dst_pixel++;
3340                     memset(dst_pixel, 0, pad_size);
3341                 }
3342                 dst_start += dst->stride;
3343                 src_start += src->stride / 2;
3344             }
3345         }
3346         else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3347         {
3348             for(y = src_rect->top; y < src_rect->bottom; y++)
3349             {
3350                 dst_pixel = dst_start;
3351                 src_pixel = src_start;
3352                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3353                 {
3354                     src_val = *src_pixel++;
3355                     dst_val = rgb_to_pixel_colortable(dst,
3356                                                       (((src_val >> src->red_shift)   << 3) & 0xf8) |
3357                                                       (((src_val >> src->red_shift)   >> 2) & 0x07),
3358                                                       (((src_val >> src->green_shift) << 2) & 0xfc) |
3359                                                       (((src_val >> src->green_shift) >> 4) & 0x03),
3360                                                       (((src_val >> src->blue_shift)  << 3) & 0xf8) |
3361                                                       (((src_val >> src->blue_shift)  >> 2) & 0x07) ) ? 0xff : 0;
3362                     if(bit_pos == 0) *dst_pixel = 0;
3363                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3364
3365                     if(++bit_pos == 8)
3366                     {
3367                         dst_pixel++;
3368                         bit_pos = 0;
3369                     }
3370                 }
3371                 if(pad_size)
3372                 {
3373                     if(bit_pos != 0) dst_pixel++;
3374                     memset(dst_pixel, 0, pad_size);
3375                 }
3376                 dst_start += dst->stride;
3377                 src_start += src->stride / 2;
3378             }
3379         }
3380         else
3381         {
3382             for(y = src_rect->top; y < src_rect->bottom; y++)
3383             {
3384                 dst_pixel = dst_start;
3385                 src_pixel = src_start;
3386                 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3387                 {
3388                     src_val = *src_pixel++;
3389                     dst_val = rgb_to_pixel_colortable(dst,
3390                                                       get_field(src_val, src->red_shift, src->red_len),
3391                                                       get_field(src_val, src->green_shift, src->green_len),
3392                                                       get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3393                     if(bit_pos == 0) *dst_pixel = 0;
3394                     *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3395
3396                     if(++bit_pos == 8)
3397                     {
3398                         dst_pixel++;
3399                         bit_pos = 0;
3400                     }
3401                 }
3402                 if(pad_size)
3403                 {
3404                     if(bit_pos != 0) dst_pixel++;
3405                     memset(dst_pixel, 0, pad_size);
3406                 }
3407                 dst_start += dst->stride;
3408                 src_start += src->stride / 2;
3409             }
3410         }
3411         break;
3412     }
3413
3414     case 8:
3415     {
3416         BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3417
3418         for(y = src_rect->top; y < src_rect->bottom; y++)
3419         {
3420             dst_pixel = dst_start;
3421             src_pixel = src_start;
3422             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3423             {
3424                 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3425                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3426
3427                 if(bit_pos == 0) *dst_pixel = 0;
3428                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3429
3430                 if(++bit_pos == 8)
3431                 {
3432                     dst_pixel++;
3433                     bit_pos = 0;
3434                 }
3435             }
3436             if(pad_size)
3437             {
3438                 if(bit_pos != 0) dst_pixel++;
3439                 memset(dst_pixel, 0, pad_size);
3440             }
3441             dst_start += dst->stride;
3442             src_start += src->stride;
3443         }
3444         break;
3445     }
3446
3447     case 4:
3448     {
3449         BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3450
3451         for(y = src_rect->top; y < src_rect->bottom; y++)
3452         {
3453             dst_pixel = dst_start;
3454             src_pixel = src_start;
3455             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3456             {
3457                 RGBQUAD rgb;
3458                 if(x & 1)
3459                     rgb = colortable_entry( src, *src_pixel++ & 0xf );
3460                 else
3461                     rgb = colortable_entry( src, *src_pixel >> 4 );
3462                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3463
3464                 if(bit_pos == 0) *dst_pixel = 0;
3465                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3466
3467                 if(++bit_pos == 8)
3468                 {
3469                     dst_pixel++;
3470                     bit_pos = 0;
3471                 }
3472             }
3473             if(pad_size)
3474             {
3475                 if(bit_pos != 0) dst_pixel++;
3476                 memset(dst_pixel, 0, pad_size);
3477             }
3478             dst_start += dst->stride;
3479             src_start += src->stride;
3480         }
3481         break;
3482     }
3483
3484     /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3485        uses text/bkgnd colours instead of the dib's colour table, this
3486        doesn't appear to be the case for a dc backed by a
3487        dibsection. */
3488
3489     case 1:
3490     {
3491         BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3492         for(y = src_rect->top; y < src_rect->bottom; y++)
3493         {
3494             dst_pixel = dst_start;
3495             src_pixel = src_start;
3496             for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3497             {
3498                 RGBQUAD rgb;
3499                 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3500                 if((x % 8) == 7) src_pixel++;
3501                 rgb = src->color_table[src_val];
3502                 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3503
3504                 if(bit_pos == 0) *dst_pixel = 0;
3505                 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3506
3507                 if(++bit_pos == 8)
3508                 {
3509                     dst_pixel++;
3510                     bit_pos = 0;
3511                 }
3512             }
3513             if(pad_size)
3514             {
3515                 if(bit_pos != 0) dst_pixel++;
3516                 memset(dst_pixel, 0, pad_size);
3517             }
3518             dst_start += dst->stride;
3519             src_start += src->stride;
3520         }
3521         break;
3522     }
3523     }
3524 }
3525
3526 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3527 {
3528 }
3529
3530 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3531 {
3532     return (src * alpha + dst * (255 - alpha) + 127) / 255;
3533 }
3534
3535 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3536 {
3537     return (blend_color( dst, src, alpha ) |
3538             blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3539             blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3540             blend_color( dst >> 24, src >> 24, alpha ) << 24);
3541 }
3542
3543 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3544 {
3545     BYTE b = ((BYTE)src         * alpha + 127) / 255;
3546     BYTE g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3547     BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3548     alpha  = ((BYTE)(src >> 24) * alpha + 127) / 255;
3549     return ((b     + ((BYTE)dst         * (255 - alpha) + 127) / 255) |
3550             (g     + ((BYTE)(dst >> 8)  * (255 - alpha) + 127) / 255) << 8 |
3551             (r     + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3552             (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3553 }
3554
3555 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3556 {
3557     if (blend.AlphaFormat & AC_SRC_ALPHA)
3558     {
3559         DWORD alpha = blend.SourceConstantAlpha;
3560         BYTE src_b = ((BYTE)src         * alpha + 127) / 255;
3561         BYTE src_g = ((BYTE)(src >> 8)  * alpha + 127) / 255;
3562         BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3563         alpha      = ((BYTE)(src >> 24) * alpha + 127) / 255;
3564         return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3565                 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3566                 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3567     }
3568     return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3569             blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3570             blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3571 }
3572
3573 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3574                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3575 {
3576     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3577     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3578     int x, y;
3579
3580     if (blend.AlphaFormat & AC_SRC_ALPHA)
3581         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3582             for (x = 0; x < rc->right - rc->left; x++)
3583                 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3584     else
3585         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3586             for (x = 0; x < rc->right - rc->left; x++)
3587                 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3588 }
3589
3590 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3591                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3592 {
3593     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3594     DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3595     int x, y;
3596
3597     if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3598     {
3599         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3600         {
3601             for (x = 0; x < rc->right - rc->left; x++)
3602             {
3603                 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3604                                        dst_ptr[x] >> dst->green_shift,
3605                                        dst_ptr[x] >> dst->blue_shift,
3606                                        src_ptr[x], blend );
3607                 dst_ptr[x] = ((( val        & 0xff) << dst->blue_shift) |
3608                               (((val >> 8)  & 0xff) << dst->green_shift) |
3609                               (((val >> 16) & 0xff) << dst->red_shift));
3610             }
3611         }
3612     }
3613     else
3614     {
3615         for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3616         {
3617             for (x = 0; x < rc->right - rc->left; x++)
3618             {
3619                 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3620                                        get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3621                                        get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3622                                        src_ptr[x], blend );
3623                 dst_ptr[x] = (put_field( val >> 16, dst->red_shift,   dst->red_len )   |
3624                               put_field( val >> 8,  dst->green_shift, dst->green_len ) |
3625                               put_field( val,       dst->blue_shift,  dst->blue_len ));
3626             }
3627         }
3628     }
3629 }
3630
3631 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3632                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3633 {
3634     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3635     BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3636     int x, y;
3637
3638     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3639     {
3640         for (x = 0; x < rc->right - rc->left; x++)
3641         {
3642             DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3643                                    src_ptr[x], blend );
3644             dst_ptr[x * 3]     = val;
3645             dst_ptr[x * 3 + 1] = val >> 8;
3646             dst_ptr[x * 3 + 2] = val >> 16;
3647         }
3648     }
3649 }
3650
3651 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3652                            const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3653 {
3654     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3655     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3656     int x, y;
3657
3658     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3659     {
3660         for (x = 0; x < rc->right - rc->left; x++)
3661         {
3662             DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3663                                    ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >>  7) & 0x07),
3664                                    ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >>  2) & 0x07),
3665                                    src_ptr[x], blend );
3666             dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3667         }
3668     }
3669 }
3670
3671 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3672                           const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3673 {
3674     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3675     WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3676     int x, y;
3677
3678     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3679     {
3680         for (x = 0; x < rc->right - rc->left; x++)
3681         {
3682             DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3683                                    get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3684                                    get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3685                                    src_ptr[x], blend );
3686             dst_ptr[x] = (put_field((val >> 16), dst->red_shift,   dst->red_len)   |
3687                           put_field((val >>  8), dst->green_shift, dst->green_len) |
3688                           put_field( val,        dst->blue_shift,  dst->blue_len));
3689         }
3690     }
3691 }
3692
3693 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3694                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3695 {
3696     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3697     BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3698     int x, y;
3699
3700     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3701     {
3702         for (x = 0; x < rc->right - rc->left; x++)
3703         {
3704             RGBQUAD rgb = colortable_entry( dst, dst_ptr[x] );
3705             DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3706             dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3707         }
3708     }
3709 }
3710
3711 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3712                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3713 {
3714     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3715     BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3716     int x, y;
3717
3718     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3719     {
3720         for (x = rc->left; x < rc->right; x++)
3721         {
3722             DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3723             RGBQUAD rgb = colortable_entry( dst, val );
3724             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3725             val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3726             if (x & 1)
3727                 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3728             else
3729                 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3730         }
3731     }
3732 }
3733
3734 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3735                          const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3736 {
3737     DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3738     BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
3739     int x, y;
3740
3741     for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3742     {
3743         for (x = rc->left; x < rc->right; x++)
3744         {
3745             DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3746             RGBQUAD rgb = dst->color_table[val];
3747             val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3748             val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
3749             dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
3750         }
3751     }
3752 }
3753
3754 static void blend_rect_null(const dib_info *dst, const RECT *rc,
3755                             const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3756 {
3757 }
3758
3759 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)
3760 {
3761     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3762     DWORD mask_start = 0, mask_offset;
3763     DWORD *and_bits = bits->and, *xor_bits = bits->xor;
3764     int x, y;
3765
3766     for(y = 0; y < hatch->height; y++)
3767     {
3768         hatch_ptr = hatch_start;
3769         mask_offset = mask_start;
3770         for(x = 0; x < hatch->width; x++)
3771         {
3772             if(*hatch_ptr & pixel_masks_1[x % 8])
3773             {
3774                 and_bits[mask_offset] = fg->and;
3775                 xor_bits[mask_offset] = fg->xor;
3776             }
3777             else
3778             {
3779                 and_bits[mask_offset] = bg->and;
3780                 xor_bits[mask_offset] = bg->xor;
3781             }
3782             if(x % 8 == 7) hatch_ptr++;
3783             mask_offset++;
3784         }
3785         hatch_start += hatch->stride;
3786         mask_start += dib->stride / 4;
3787     }
3788
3789     return TRUE;
3790 }
3791
3792 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)
3793 {
3794     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3795     DWORD mask_start = 0, mask_offset;
3796     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3797     int x, y;
3798
3799     for(y = 0; y < hatch->height; y++)
3800     {
3801         hatch_ptr = hatch_start;
3802         mask_offset = mask_start;
3803         for(x = 0; x < hatch->width; x++)
3804         {
3805             if(*hatch_ptr & pixel_masks_1[x % 8])
3806             {
3807                 and_bits[mask_offset]   =  fg->and        & 0xff;
3808                 xor_bits[mask_offset++] =  fg->xor        & 0xff;
3809                 and_bits[mask_offset]   = (fg->and >>  8) & 0xff;
3810                 xor_bits[mask_offset++] = (fg->xor >>  8) & 0xff;
3811                 and_bits[mask_offset]   = (fg->and >> 16) & 0xff;
3812                 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
3813             }
3814             else
3815             {
3816                 and_bits[mask_offset]   =  bg->and        & 0xff;
3817                 xor_bits[mask_offset++] =  bg->xor        & 0xff;
3818                 and_bits[mask_offset]   = (bg->and >>  8) & 0xff;
3819                 xor_bits[mask_offset++] = (bg->xor >>  8) & 0xff;
3820                 and_bits[mask_offset]   = (bg->and >> 16) & 0xff;
3821                 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
3822             }
3823             if(x % 8 == 7) hatch_ptr++;
3824         }
3825         hatch_start += hatch->stride;
3826         mask_start += dib->stride;
3827     }
3828
3829     return TRUE;
3830 }
3831
3832 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)
3833 {
3834     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3835     DWORD mask_start = 0, mask_offset;
3836     WORD *and_bits = bits->and, *xor_bits = bits->xor;
3837     int x, y;
3838
3839     for(y = 0; y < hatch->height; y++)
3840     {
3841         hatch_ptr = hatch_start;
3842         mask_offset = mask_start;
3843         for(x = 0; x < hatch->width; x++)
3844         {
3845             if(*hatch_ptr & pixel_masks_1[x % 8])
3846             {
3847                 and_bits[mask_offset] = fg->and;
3848                 xor_bits[mask_offset] = fg->xor;
3849             }
3850             else
3851             {
3852                 and_bits[mask_offset] = bg->and;
3853                 xor_bits[mask_offset] = bg->xor;
3854             }
3855             if(x % 8 == 7) hatch_ptr++;
3856             mask_offset++;
3857         }
3858         hatch_start += hatch->stride;
3859         mask_start += dib->stride / 2;
3860     }
3861
3862     return TRUE;
3863 }
3864
3865 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)
3866 {
3867     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3868     DWORD mask_start = 0, mask_offset;
3869     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3870     int x, y;
3871
3872     for(y = 0; y < hatch->height; y++)
3873     {
3874         hatch_ptr = hatch_start;
3875         mask_offset = mask_start;
3876         for(x = 0; x < hatch->width; x++)
3877         {
3878             if(*hatch_ptr & pixel_masks_1[x % 8])
3879             {
3880                 and_bits[mask_offset] = fg->and;
3881                 xor_bits[mask_offset] = fg->xor;
3882             }
3883             else
3884             {
3885                 and_bits[mask_offset] = bg->and;
3886                 xor_bits[mask_offset] = bg->xor;
3887             }
3888             if(x % 8 == 7) hatch_ptr++;
3889             mask_offset++;
3890         }
3891         hatch_start += hatch->stride;
3892         mask_start += dib->stride;
3893     }
3894
3895     return TRUE;
3896 }
3897
3898 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)
3899 {
3900     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3901     DWORD mask_start = 0, mask_offset;
3902     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3903     const rop_mask *rop_mask;
3904     int x, y;
3905
3906     for(y = 0; y < hatch->height; y++)
3907     {
3908         hatch_ptr = hatch_start;
3909         mask_offset = mask_start;
3910         for(x = 0; x < hatch->width; x++)
3911         {
3912             if(*hatch_ptr & pixel_masks_1[x % 8])
3913                 rop_mask = fg;
3914             else
3915                 rop_mask = bg;
3916
3917             if(x & 1)
3918             {
3919                 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3920                 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3921                 mask_offset++;
3922             }
3923             else
3924             {
3925                 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3926                 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3927             }
3928
3929             if(x % 8 == 7) hatch_ptr++;
3930         }
3931         hatch_start += hatch->stride;
3932         mask_start += dib->stride;
3933     }
3934
3935     return TRUE;
3936 }
3937
3938 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)
3939 {
3940     BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3941     DWORD mask_start = 0, mask_offset;
3942     BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3943     rop_mask rop_mask;
3944     int x, y, bit_pos;
3945
3946     for(y = 0; y < hatch->height; y++)
3947     {
3948         hatch_ptr = hatch_start;
3949         mask_offset = mask_start;
3950         for(x = 0, bit_pos = 0; x < hatch->width; x++)
3951         {
3952             if(*hatch_ptr & pixel_masks_1[x % 8])
3953             {
3954                 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3955                 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3956             }
3957             else
3958             {
3959                 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3960                 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3961             }
3962
3963             if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3964
3965             and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3966             xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3967
3968             if(++bit_pos == 8)
3969             {
3970                 mask_offset++;
3971                 hatch_ptr++;
3972                 bit_pos = 0;
3973             }
3974         }
3975         hatch_start += hatch->stride;
3976         mask_start += dib->stride;
3977     }
3978
3979     return TRUE;
3980 }
3981
3982 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)
3983 {
3984     return FALSE;
3985 }
3986
3987 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
3988 {
3989     switch (mode)
3990     {
3991     default:
3992     case STRETCH_DELETESCANS:
3993         get_rop_codes( R2_COPYPEN, codes );
3994         break;
3995     case STRETCH_ORSCANS:
3996         get_rop_codes( R2_MERGEPEN, codes );
3997         break;
3998     case STRETCH_ANDSCANS:
3999         get_rop_codes( R2_MASKPEN, codes );
4000         break;
4001     }
4002     return;
4003 }
4004
4005 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
4006                            const dib_info *src_dib, const POINT *src_start,
4007                            const struct stretch_params *params, int mode,
4008                            BOOL keep_dst)
4009 {
4010     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4011     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4012     int err = params->err_start;
4013     int width;
4014     struct rop_codes codes;
4015
4016     rop_codes_from_stretch_mode( mode, &codes );
4017     for (width = params->length; width; width--)
4018     {
4019         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4020         dst_ptr += params->dst_inc;
4021         if (err > 0)
4022         {
4023             src_ptr += params->src_inc;
4024             err += params->err_add_1;
4025         }
4026         else err += params->err_add_2;
4027     }
4028 }
4029
4030 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
4031                            const dib_info *src_dib, const POINT *src_start,
4032                            const struct stretch_params *params, int mode,
4033                            BOOL keep_dst)
4034 {
4035     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4036     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4037     int err = params->err_start;
4038     int width;
4039     struct rop_codes codes;
4040
4041     rop_codes_from_stretch_mode( mode, &codes );
4042     for (width = params->length; width; width--)
4043     {
4044         do_rop_codes_8( dst_ptr,     *src_ptr,       &codes );
4045         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4046         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4047         dst_ptr += 3 * params->dst_inc;
4048         if (err > 0)
4049         {
4050             src_ptr += 3 * params->src_inc;
4051             err += params->err_add_1;
4052         }
4053         else err += params->err_add_2;
4054     }
4055 }
4056
4057 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
4058                            const dib_info *src_dib, const POINT *src_start,
4059                            const struct stretch_params *params, int mode,
4060                            BOOL keep_dst)
4061 {
4062     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4063     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4064     int err = params->err_start;
4065     int width;
4066     struct rop_codes codes;
4067
4068     rop_codes_from_stretch_mode( mode, &codes );
4069     for (width = params->length; width; width--)
4070     {
4071         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4072         dst_ptr += params->dst_inc;
4073         if (err > 0)
4074         {
4075             src_ptr += params->src_inc;
4076             err += params->err_add_1;
4077         }
4078         else err += params->err_add_2;
4079     }
4080 }
4081
4082 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
4083                           const dib_info *src_dib, const POINT *src_start,
4084                           const struct stretch_params *params, int mode,
4085                           BOOL keep_dst)
4086 {
4087     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4088     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4089     int err = params->err_start;
4090     int width;
4091     struct rop_codes codes;
4092
4093     rop_codes_from_stretch_mode( mode, &codes );
4094     for (width = params->length; width; width--)
4095     {
4096         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4097         dst_ptr += params->dst_inc;
4098         if (err > 0)
4099         {
4100             src_ptr += params->src_inc;
4101             err += params->err_add_1;
4102         }
4103         else err += params->err_add_2;
4104     }
4105 }
4106
4107 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
4108                           const dib_info *src_dib, const POINT *src_start,
4109                           const struct stretch_params *params, int mode,
4110                           BOOL keep_dst)
4111 {
4112     BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
4113     BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
4114     int err = params->err_start;
4115     int width, dst_x = dst_start->x, src_x = src_start->x;
4116     struct rop_codes codes;
4117     BYTE src_val;
4118
4119     rop_codes_from_stretch_mode( mode, &codes );
4120     for (width = params->length; width; width--)
4121     {
4122         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4123         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4124
4125         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
4126
4127         if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4128             dst_ptr += params->dst_inc;
4129         dst_x += params->dst_inc;
4130
4131         if (err > 0)
4132         {
4133             if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4134                 src_ptr += params->src_inc;
4135             src_x += params->src_inc;
4136             err += params->err_add_1;
4137         }
4138         else err += params->err_add_2;
4139     }
4140 }
4141
4142 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
4143                           const dib_info *src_dib, const POINT *src_start,
4144                           const struct stretch_params *params, int mode,
4145                           BOOL keep_dst)
4146 {
4147     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4148     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4149     int err = params->err_start;
4150     int width, dst_x = dst_start->x, src_x = src_start->x;
4151     struct rop_codes codes;
4152     BYTE src_val;
4153
4154     rop_codes_from_stretch_mode( mode, &codes );
4155     for (width = params->length; width; width--)
4156     {
4157         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4158         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4159
4160         if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4161             dst_ptr += params->dst_inc;
4162         dst_x += params->dst_inc;
4163
4164         if (err > 0)
4165         {
4166             if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4167                 src_ptr += params->src_inc;
4168             src_x += params->src_inc;
4169             err += params->err_add_1;
4170         }
4171         else err += params->err_add_2;
4172     }
4173 }
4174
4175 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
4176                              const dib_info *src_dib, const POINT *src_start,
4177                              const struct stretch_params *params, int mode,
4178                              BOOL keep_dst)
4179 {
4180     FIXME("bit count %d\n", dst_dib->bit_count);
4181     return;
4182 }
4183
4184 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
4185                           const dib_info *src_dib, const POINT *src_start,
4186                           const struct stretch_params *params, int mode,
4187                           BOOL keep_dst)
4188 {
4189     DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4190     DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4191     int err = params->err_start;
4192     int width;
4193     struct rop_codes codes;
4194     DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4195     BOOL new_pix = TRUE;
4196
4197     rop_codes_from_stretch_mode( mode, &codes );
4198     for (width = params->length; width; width--)
4199     {
4200         if (new_pix && !keep_dst) *dst_ptr = init_val;
4201         do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4202         new_pix = FALSE;
4203         src_ptr += params->src_inc;
4204         if (err > 0)
4205         {
4206             dst_ptr += params->dst_inc;
4207             new_pix = TRUE;
4208             err += params->err_add_1;
4209         }
4210         else err += params->err_add_2;
4211     }
4212 }
4213
4214 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
4215                           const dib_info *src_dib, const POINT *src_start,
4216                           const struct stretch_params *params, int mode,
4217                           BOOL keep_dst)
4218 {
4219     BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4220     BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4221     int err = params->err_start;
4222     int width;
4223     struct rop_codes codes;
4224     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4225     BOOL new_pix = TRUE;
4226
4227     rop_codes_from_stretch_mode( mode, &codes );
4228     for (width = params->length; width; width--)
4229     {
4230         if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
4231         do_rop_codes_8( dst_ptr,      *src_ptr,      &codes );
4232         do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4233         do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4234         new_pix = FALSE;
4235         src_ptr += 3 * params->src_inc;
4236         if (err > 0)
4237         {
4238             dst_ptr += 3 * params->dst_inc;
4239             new_pix = TRUE;
4240             err += params->err_add_1;
4241         }
4242         else err += params->err_add_2;
4243     }
4244 }
4245
4246 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
4247                           const dib_info *src_dib, const POINT *src_start,
4248                           const struct stretch_params *params, int mode,
4249                           BOOL keep_dst)
4250 {
4251     WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4252     WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4253     int err = params->err_start;
4254     int width;
4255     struct rop_codes codes;
4256     WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4257     BOOL new_pix = TRUE;
4258
4259     rop_codes_from_stretch_mode( mode, &codes );
4260     for (width = params->length; width; width--)
4261     {
4262         if (new_pix && !keep_dst) *dst_ptr = init_val;
4263         do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4264         new_pix = FALSE;
4265         src_ptr += params->src_inc;
4266         if (err > 0)
4267         {
4268             dst_ptr += params->dst_inc;
4269             new_pix = TRUE;
4270             err += params->err_add_1;
4271         }
4272         else err += params->err_add_2;
4273     }
4274 }
4275
4276 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
4277                          const dib_info *src_dib, const POINT *src_start,
4278                          const struct stretch_params *params, int mode,
4279                          BOOL keep_dst)
4280 {
4281     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4282     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4283     int err = params->err_start;
4284     int width;
4285     struct rop_codes codes;
4286     BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4287     BOOL new_pix = TRUE;
4288
4289     rop_codes_from_stretch_mode( mode, &codes );
4290     for (width = params->length; width; width--)
4291     {
4292         if (new_pix && !keep_dst) *dst_ptr = init_val;
4293         do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4294         new_pix = FALSE;
4295         src_ptr += params->src_inc;
4296         if (err > 0)
4297         {
4298             dst_ptr += params->dst_inc;
4299             new_pix = TRUE;
4300             err += params->err_add_1;
4301         }
4302         else err += params->err_add_2;
4303     }
4304 }
4305
4306 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
4307                          const dib_info *src_dib, const POINT *src_start,
4308                          const struct stretch_params *params, int mode,
4309                          BOOL keep_dst)
4310 {
4311     BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4312     BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4313     int err = params->err_start;
4314     int width, dst_x = dst_start->x, src_x = src_start->x;
4315     struct rop_codes codes;
4316     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4317     BOOL new_pix = TRUE;
4318
4319     rop_codes_from_stretch_mode( mode, &codes );
4320     for (width = params->length; width; width--)
4321     {
4322         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4323
4324         if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4325         else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4326
4327         do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4328         new_pix = FALSE;
4329
4330         if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4331             src_ptr += params->src_inc;
4332         src_x += params->src_inc;
4333
4334         if (err > 0)
4335         {
4336             if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4337                 dst_ptr += params->dst_inc;
4338             dst_x += params->dst_inc;
4339             new_pix = TRUE;
4340             err += params->err_add_1;
4341         }
4342         else err += params->err_add_2;
4343     }
4344 }
4345
4346 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4347                          const dib_info *src_dib, const POINT *src_start,
4348                          const struct stretch_params *params, int mode,
4349                          BOOL keep_dst)
4350 {
4351     BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4352     BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4353     int err = params->err_start;
4354     int width, dst_x = dst_start->x, src_x = src_start->x;
4355     struct rop_codes codes;
4356     BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4357     BOOL new_pix = TRUE;
4358
4359     rop_codes_from_stretch_mode( mode, &codes );
4360     for (width = params->length; width; width--)
4361     {
4362         if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4363         src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4364         do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4365         new_pix = FALSE;
4366
4367         if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4368             src_ptr += params->src_inc;
4369         src_x += params->src_inc;
4370
4371         if (err > 0)
4372         {
4373             if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4374                 dst_ptr += params->dst_inc;
4375             dst_x += params->dst_inc;
4376             new_pix = TRUE;
4377             err += params->err_add_1;
4378         }
4379         else err += params->err_add_2;
4380     }
4381 }
4382
4383 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4384                             const dib_info *src_dib, const POINT *src_start,
4385                             const struct stretch_params *params, int mode,
4386                             BOOL keep_dst)
4387 {
4388     FIXME("bit count %d\n", dst_dib->bit_count);
4389     return;
4390 }
4391
4392 const primitive_funcs funcs_8888 =
4393 {
4394     solid_rects_32,
4395     pattern_rects_32,
4396     copy_rect_32,
4397     blend_rect_8888,
4398     get_pixel_32,
4399     colorref_to_pixel_888,
4400     pixel_to_colorref_888,
4401     convert_to_8888,
4402     create_rop_masks_32,
4403     stretch_row_32,
4404     shrink_row_32
4405 };
4406
4407 const primitive_funcs funcs_32 =
4408 {
4409     solid_rects_32,
4410     pattern_rects_32,
4411     copy_rect_32,
4412     blend_rect_32,
4413     get_pixel_32,
4414     colorref_to_pixel_masks,
4415     pixel_to_colorref_masks,
4416     convert_to_32,
4417     create_rop_masks_32,
4418     stretch_row_32,
4419     shrink_row_32
4420 };
4421
4422 const primitive_funcs funcs_24 =
4423 {
4424     solid_rects_24,
4425     pattern_rects_24,
4426     copy_rect_24,
4427     blend_rect_24,
4428     get_pixel_24,
4429     colorref_to_pixel_888,
4430     pixel_to_colorref_888,
4431     convert_to_24,
4432     create_rop_masks_24,
4433     stretch_row_24,
4434     shrink_row_24
4435 };
4436
4437 const primitive_funcs funcs_555 =
4438 {
4439     solid_rects_16,
4440     pattern_rects_16,
4441     copy_rect_16,
4442     blend_rect_555,
4443     get_pixel_16,
4444     colorref_to_pixel_555,
4445     pixel_to_colorref_555,
4446     convert_to_555,
4447     create_rop_masks_16,
4448     stretch_row_16,
4449     shrink_row_16
4450 };
4451
4452 const primitive_funcs funcs_16 =
4453 {
4454     solid_rects_16,
4455     pattern_rects_16,
4456     copy_rect_16,
4457     blend_rect_16,
4458     get_pixel_16,
4459     colorref_to_pixel_masks,
4460     pixel_to_colorref_masks,
4461     convert_to_16,
4462     create_rop_masks_16,
4463     stretch_row_16,
4464     shrink_row_16
4465 };
4466
4467 const primitive_funcs funcs_8 =
4468 {
4469     solid_rects_8,
4470     pattern_rects_8,
4471     copy_rect_8,
4472     blend_rect_8,
4473     get_pixel_8,
4474     colorref_to_pixel_colortable,
4475     pixel_to_colorref_colortable,
4476     convert_to_8,
4477     create_rop_masks_8,
4478     stretch_row_8,
4479     shrink_row_8
4480 };
4481
4482 const primitive_funcs funcs_4 =
4483 {
4484     solid_rects_4,
4485     pattern_rects_4,
4486     copy_rect_4,
4487     blend_rect_4,
4488     get_pixel_4,
4489     colorref_to_pixel_colortable,
4490     pixel_to_colorref_colortable,
4491     convert_to_4,
4492     create_rop_masks_4,
4493     stretch_row_4,
4494     shrink_row_4
4495 };
4496
4497 const primitive_funcs funcs_1 =
4498 {
4499     solid_rects_1,
4500     pattern_rects_1,
4501     copy_rect_1,
4502     blend_rect_1,
4503     get_pixel_1,
4504     colorref_to_pixel_colortable,
4505     pixel_to_colorref_colortable,
4506     convert_to_1,
4507     create_rop_masks_1,
4508     stretch_row_1,
4509     shrink_row_1
4510 };
4511
4512 const primitive_funcs funcs_null =
4513 {
4514     solid_rects_null,
4515     pattern_rects_null,
4516     copy_rect_null,
4517     blend_rect_null,
4518     get_pixel_null,
4519     colorref_to_pixel_null,
4520     pixel_to_colorref_null,
4521     convert_to_null,
4522     create_rop_masks_null,
4523     stretch_row_null,
4524     shrink_row_null
4525 };