2 * DIB driver primitives.
4 * Copyright 2011 Huw Davies
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.
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.
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
23 #include "gdi_private.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dib);
30 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
32 return (DWORD *)((BYTE*)dib->bits.ptr + y * dib->stride + x * 4);
35 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
37 return (DWORD *)((BYTE*)dib->bits.ptr + y * dib->stride) + x * 3 / 4;
40 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
42 return (BYTE*)dib->bits.ptr + y * dib->stride + x * 3;
45 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
47 return (WORD *)((BYTE*)dib->bits.ptr + y * dib->stride + x * 2);
50 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
52 return (BYTE*)dib->bits.ptr + y * dib->stride + x;
55 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
57 return (BYTE*)dib->bits.ptr + y * dib->stride + x / 2;
60 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
62 return (BYTE*)dib->bits.ptr + y * dib->stride + x / 8;
65 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
67 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
69 *ptr = (*ptr & and) ^ xor;
72 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
74 *ptr = (*ptr & and) ^ xor;
77 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
79 *ptr = (*ptr & and) ^ xor;
82 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
84 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
87 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
89 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
92 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
94 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
97 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
99 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
102 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
104 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
107 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
109 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
112 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
114 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
115 do_rop_codes_32( dst, *src, codes );
118 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
120 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
123 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
125 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
126 do_rop_codes_16( dst, *src, codes );
129 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
131 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
134 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
136 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
137 do_rop_codes_8( dst, *src, codes );
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)
145 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
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 );
155 if (src_x & 1) src_val = *src++ << 4;
157 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
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)
169 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
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 );
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 );
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)
191 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
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++;
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)
207 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
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--;
216 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
221 for(i = 0; i < num; i++, rc++)
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);
230 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
233 BYTE *byte_ptr, *byte_start;
235 DWORD and_masks[3], xor_masks[3];
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);
244 for(i = 0; i < num; i++, rc++)
246 if(rc->left >= rc->right) continue;
248 if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
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)
253 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
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);
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)
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]);
276 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
277 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
280 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
284 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
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]);
291 switch(rc->right & 3)
294 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
297 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
298 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
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);
311 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
316 for(i = 0; i < num; i++, rc++)
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);
325 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
330 for(i = 0; i < num; i++, rc++)
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);
339 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
343 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
344 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
346 for(i = 0; i < num; i++, rc++)
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)
353 if(rc->left & 1) /* upper nibble untouched */
354 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
356 for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
357 do_rop_8(ptr++, byte_and, byte_xor);
359 if(rc->right & 1) /* lower nibble untouched */
360 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
365 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
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};
374 for(i = 0; i < num; i++, rc++)
376 if(rc->left >= rc->right) continue;
378 start = get_pixel_ptr_1(dib, rc->left, rc->top);
380 if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
382 mask = masks[rc->left & 7] & ~masks[rc->right & 7];
384 start_and = byte_and | ~mask;
385 start_xor = byte_xor & mask;
386 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
388 do_rop_8(start, start_and, start_xor);
393 mask = masks[rc->left & 7];
394 start_and = byte_and | ~mask;
395 start_xor = byte_xor & mask;
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;
402 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
407 do_rop_8(ptr++, start_and, start_xor);
409 for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
410 do_rop_8(ptr++, byte_and, byte_xor);
413 do_rop_8(ptr, end_and, end_xor);
419 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
424 static inline INT calc_offset(INT edge, INT size, INT origin)
428 if(edge - origin >= 0)
429 offset = (edge - origin) % size;
432 offset = (origin - edge) % size;
433 if(offset) offset = size - offset;
438 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
442 offset.x = calc_offset(rc->left, brush->width, origin->x);
443 offset.y = calc_offset(rc->top, brush->height, origin->y);
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)
451 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
455 for(i = 0; i < num; i++, rc++)
457 offset = calc_brush_offset(rc, brush, origin);
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;
463 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
465 and_ptr = start_and + offset.x;
466 xor_ptr = start_xor + offset.x;
468 for(x = rc->left, ptr = start; x < rc->right; x++)
470 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
471 if(and_ptr == start_and + brush->width)
479 if(offset.y == brush->height)
481 start_and = and_bits;
482 start_xor = xor_bits;
487 start_and += brush->stride / 4;
488 start_xor += brush->stride / 4;
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)
497 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
501 for(i = 0; i < num; i++, rc++)
503 offset = calc_brush_offset(rc, brush, origin);
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;
509 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
511 and_ptr = start_and + offset.x * 3;
512 xor_ptr = start_xor + offset.x * 3;
514 for(x = rc->left, ptr = start; x < rc->right; x++)
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)
527 if(offset.y == brush->height)
529 start_and = and_bits;
530 start_xor = xor_bits;
535 start_and += brush->stride;
536 start_xor += brush->stride;
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)
545 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
549 for(i = 0; i < num; i++, rc++)
551 offset = calc_brush_offset(rc, brush, origin);
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;
557 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
559 and_ptr = start_and + offset.x;
560 xor_ptr = start_xor + offset.x;
562 for(x = rc->left, ptr = start; x < rc->right; x++)
564 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
565 if(and_ptr == start_and + brush->width)
573 if(offset.y == brush->height)
575 start_and = and_bits;
576 start_xor = xor_bits;
581 start_and += brush->stride / 2;
582 start_xor += brush->stride / 2;
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)
591 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
595 for(i = 0; i < num; i++, rc++)
597 offset = calc_brush_offset(rc, brush, origin);
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;
603 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
605 and_ptr = start_and + offset.x;
606 xor_ptr = start_xor + offset.x;
608 for(x = rc->left, ptr = start; x < rc->right; x++)
610 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
611 if(and_ptr == start_and + brush->width)
619 if(offset.y == brush->height)
621 start_and = and_bits;
622 start_xor = xor_bits;
627 start_and += brush->stride;
628 start_xor += brush->stride;
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)
637 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
641 for(i = 0; i < num; i++, rc++)
643 offset = calc_brush_offset(rc, brush, origin);
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;
649 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
651 INT brush_x = offset.x;
652 BYTE byte_and, byte_xor;
654 and_ptr = start_and + brush_x / 2;
655 xor_ptr = start_xor + brush_x / 2;
657 for(x = rc->left, ptr = start; x < rc->right; x++)
659 /* FIXME: Two pixels at a time */
660 if(x & 1) /* lower dst nibble */
662 if(brush_x & 1) /* lower pat nibble */
664 byte_and = *and_ptr++ | 0xf0;
665 byte_xor = *xor_ptr++ & 0x0f;
667 else /* upper pat nibble */
669 byte_and = (*and_ptr >> 4) | 0xf0;
670 byte_xor = (*xor_ptr >> 4) & 0x0f;
673 else /* upper dst nibble */
675 if(brush_x & 1) /* lower pat nibble */
677 byte_and = (*and_ptr++ << 4) | 0x0f;
678 byte_xor = (*xor_ptr++ << 4) & 0xf0;
680 else /* upper pat nibble */
682 byte_and = *and_ptr | 0x0f;
683 byte_xor = *xor_ptr & 0xf0;
686 do_rop_8(ptr, byte_and, byte_xor);
690 if(++brush_x == brush->width)
699 if(offset.y == brush->height)
701 start_and = and_bits;
702 start_xor = xor_bits;
707 start_and += brush->stride;
708 start_xor += brush->stride;
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)
717 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
721 for(i = 0; i < num; i++, rc++)
723 offset = calc_brush_offset(rc, brush, origin);
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;
729 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
731 INT brush_x = offset.x;
732 BYTE byte_and, byte_xor;
734 and_ptr = start_and + brush_x / 8;
735 xor_ptr = start_xor + brush_x / 8;
737 for(x = rc->left, ptr = start; x < rc->right; x++)
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];
744 do_rop_8(ptr, byte_and, byte_xor);
746 if((x & 7) == 7) ptr++;
748 if((brush_x & 7) == 7)
754 if(++brush_x == brush->width)
763 if(offset.y == brush->height)
765 start_and = and_bits;
766 start_xor = xor_bits;
771 start_and += brush->stride;
772 start_xor += brush->stride;
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)
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)
787 DWORD *dst_start, *src_start;
788 DWORD and = 0, xor = 0;
789 struct rop_codes codes;
790 int y, dst_stride, src_stride;
795 case R2_NOT: and = ~0u;
797 case R2_WHITE: xor = ~0u;
800 dst->funcs->solid_rects( dst, 1, rc, and, xor );
804 if (overlap & OVERLAP_BELOW)
806 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
807 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
808 dst_stride = -dst->stride / 4;
809 src_stride = -src->stride / 4;
813 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
814 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
815 dst_stride = dst->stride / 4;
816 src_stride = src->stride / 4;
819 if (rop2 == R2_COPYPEN)
821 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
822 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
826 get_rop_codes( rop2, &codes );
827 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
829 if (overlap & OVERLAP_RIGHT)
830 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
832 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
836 static void copy_rect_24(const dib_info *dst, const RECT *rc,
837 const dib_info *src, const POINT *origin, int rop2, int overlap)
839 BYTE *dst_start, *src_start;
840 DWORD and = 0, xor = 0;
841 int y, dst_stride, src_stride;
842 struct rop_codes codes;
847 case R2_NOT: and = ~0u;
849 case R2_WHITE: xor = ~0u;
852 dst->funcs->solid_rects( dst, 1, rc, and, xor );
856 if (overlap & OVERLAP_BELOW)
858 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
859 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
860 dst_stride = -dst->stride;
861 src_stride = -src->stride;
865 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
866 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
867 dst_stride = dst->stride;
868 src_stride = src->stride;
871 if (rop2 == R2_COPYPEN)
873 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
874 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
878 get_rop_codes( rop2, &codes );
879 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
881 if (overlap & OVERLAP_RIGHT)
882 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
884 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
888 static void copy_rect_16(const dib_info *dst, const RECT *rc,
889 const dib_info *src, const POINT *origin, int rop2, int overlap)
891 WORD *dst_start, *src_start;
892 DWORD and = 0, xor = 0;
893 int y, dst_stride, src_stride;
894 struct rop_codes codes;
899 case R2_NOT: and = ~0u;
901 case R2_WHITE: xor = ~0u;
904 dst->funcs->solid_rects( dst, 1, rc, and, xor );
908 if (overlap & OVERLAP_BELOW)
910 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
911 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
912 dst_stride = -dst->stride / 2;
913 src_stride = -src->stride / 2;
917 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
918 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
919 dst_stride = dst->stride / 2;
920 src_stride = src->stride / 2;
923 if (rop2 == R2_COPYPEN)
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) * 2 );
930 get_rop_codes( rop2, &codes );
931 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
933 if (overlap & OVERLAP_RIGHT)
934 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
936 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
940 static void copy_rect_8(const dib_info *dst, const RECT *rc,
941 const dib_info *src, const POINT *origin, int rop2, int overlap)
943 BYTE *dst_start, *src_start;
944 DWORD and = 0, xor = 0;
945 int y, dst_stride, src_stride;
946 struct rop_codes codes;
951 case R2_NOT: and = ~0u;
953 case R2_WHITE: xor = ~0u;
956 dst->funcs->solid_rects( dst, 1, rc, and, xor );
960 if (overlap & OVERLAP_BELOW)
962 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
963 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
964 dst_stride = -dst->stride;
965 src_stride = -src->stride;
969 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
970 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
971 dst_stride = dst->stride;
972 src_stride = src->stride;
975 if (rop2 == R2_COPYPEN)
977 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
978 memmove( dst_start, src_start, (rc->right - rc->left) );
982 get_rop_codes( rop2, &codes );
983 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
985 if (overlap & OVERLAP_RIGHT)
986 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
988 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
992 static void copy_rect_4(const dib_info *dst, const RECT *rc,
993 const dib_info *src, const POINT *origin, int rop2, int overlap)
995 BYTE *dst_start, *src_start;
996 DWORD and = 0, xor = 0;
997 int y, dst_stride, src_stride;
998 struct rop_codes codes;
1002 case R2_NOP: return;
1003 case R2_NOT: and = ~0u;
1005 case R2_WHITE: xor = ~0u;
1008 dst->funcs->solid_rects( dst, 1, rc, and, xor );
1012 if (overlap & OVERLAP_BELOW)
1014 dst_start = get_pixel_ptr_4(dst, 0, rc->bottom - 1);
1015 src_start = get_pixel_ptr_4(src, 0, origin->y + rc->bottom - rc->top - 1);
1016 dst_stride = -dst->stride;
1017 src_stride = -src->stride;
1021 dst_start = get_pixel_ptr_4(dst, 0, rc->top);
1022 src_start = get_pixel_ptr_4(src, 0, origin->y);
1023 dst_stride = dst->stride;
1024 src_stride = src->stride;
1027 if (rop2 == R2_COPYPEN && (rc->left & 1) == 0 && (origin->x & 1) == 0 && (rc->right & 1) == 0)
1029 dst_start += rc->left / 2;
1030 src_start += origin->x / 2;
1031 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1032 memmove( dst_start, src_start, (rc->right - rc->left) / 2 );
1036 get_rop_codes( rop2, &codes );
1037 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1039 if (overlap & OVERLAP_RIGHT)
1040 do_rop_codes_line_rev_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1042 do_rop_codes_line_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1046 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1047 const dib_info *src, const POINT *origin, int rop2, int overlap)
1049 BYTE *dst_start, *src_start;
1050 DWORD and = 0, xor = 0;
1051 int y, dst_stride, src_stride;
1052 struct rop_codes codes;
1056 case R2_NOP: return;
1057 case R2_NOT: and = ~0u;
1059 case R2_WHITE: xor = ~0u;
1062 dst->funcs->solid_rects( dst, 1, rc, and, xor );
1066 if (overlap & OVERLAP_BELOW)
1068 dst_start = get_pixel_ptr_1(dst, 0, rc->bottom - 1);
1069 src_start = get_pixel_ptr_1(src, 0, origin->y + rc->bottom - rc->top - 1);
1070 dst_stride = -dst->stride;
1071 src_stride = -src->stride;
1075 dst_start = get_pixel_ptr_1(dst, 0, rc->top);
1076 src_start = get_pixel_ptr_1(src, 0, origin->y);
1077 dst_stride = dst->stride;
1078 src_stride = src->stride;
1081 if (rop2 == R2_COPYPEN && (rc->left & 7) == 0 && (origin->x & 7) == 0 && (rc->right & 7) == 0)
1083 dst_start += rc->left / 8;
1084 src_start += origin->x / 8;
1085 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1086 memmove( dst_start, src_start, (rc->right - rc->left) / 8 );
1090 get_rop_codes( rop2, &codes );
1091 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1093 if (overlap & OVERLAP_RIGHT)
1094 do_rop_codes_line_rev_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1096 do_rop_codes_line_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1100 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1101 const dib_info *src, const POINT *origin, int rop2, int overlap)
1106 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1108 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1111 static inline DWORD put_field(DWORD field, int shift, int len)
1113 shift = shift - (8 - len);
1115 field &= (((1 << len) - 1) << (8 - len));
1123 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1127 r = GetRValue(colour);
1128 g = GetGValue(colour);
1129 b = GetBValue(colour);
1131 return put_field(r, dib->red_shift, dib->red_len) |
1132 put_field(g, dib->green_shift, dib->green_len) |
1133 put_field(b, dib->blue_shift, dib->blue_len);
1136 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1138 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1141 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1143 int i, best_index = 0;
1145 DWORD diff, best_diff = 0xffffffff;
1147 rgb.rgbRed = GetRValue(color);
1148 rgb.rgbGreen = GetGValue(color);
1149 rgb.rgbBlue = GetBValue(color);
1151 /* special case for conversion to 1-bpp without a color table:
1152 * we get a 1-entry table containing the background color
1154 if (dib->bit_count == 1 && dib->color_table_size == 1)
1155 return (rgb.rgbRed == dib->color_table[0].rgbRed &&
1156 rgb.rgbGreen == dib->color_table[0].rgbGreen &&
1157 rgb.rgbBlue == dib->color_table[0].rgbBlue);
1159 for(i = 0; i < dib->color_table_size; i++)
1161 RGBQUAD *cur = dib->color_table + i;
1162 diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
1163 + (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
1164 + (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
1172 if(diff < best_diff)
1181 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1186 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1188 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1190 return d1->red_mask == d2->red_mask &&
1191 d1->green_mask == d2->green_mask &&
1192 d1->blue_mask == d2->blue_mask;
1195 static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1197 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1198 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1200 switch(src->bit_count)
1204 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1205 if(src->funcs == &funcs_8888)
1207 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1208 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1211 for(y = src_rect->top; y < src_rect->bottom; y++)
1213 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1214 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1215 dst_start += dst->stride / 4;
1216 src_start += src->stride / 4;
1220 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1222 for(y = src_rect->top; y < src_rect->bottom; y++)
1224 dst_pixel = dst_start;
1225 src_pixel = src_start;
1226 for(x = src_rect->left; x < src_rect->right; x++)
1228 src_val = *src_pixel++;
1229 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1230 (((src_val >> src->green_shift) & 0xff) << 8) |
1231 ((src_val >> src->blue_shift) & 0xff);
1233 if(pad_size) memset(dst_pixel, 0, pad_size);
1234 dst_start += dst->stride / 4;
1235 src_start += src->stride / 4;
1240 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
1248 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1250 for(y = src_rect->top; y < src_rect->bottom; y++)
1252 dst_pixel = dst_start;
1253 src_pixel = src_start;
1254 for(x = src_rect->left; x < src_rect->right; x++)
1257 rgb.rgbBlue = *src_pixel++;
1258 rgb.rgbGreen = *src_pixel++;
1259 rgb.rgbRed = *src_pixel++;
1261 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1263 if(pad_size) memset(dst_pixel, 0, pad_size);
1264 dst_start += dst->stride / 4;
1265 src_start += src->stride;
1272 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1273 if(src->funcs == &funcs_555)
1275 for(y = src_rect->top; y < src_rect->bottom; y++)
1277 dst_pixel = dst_start;
1278 src_pixel = src_start;
1279 for(x = src_rect->left; x < src_rect->right; x++)
1281 src_val = *src_pixel++;
1282 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1283 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1284 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1286 if(pad_size) memset(dst_pixel, 0, pad_size);
1287 dst_start += dst->stride / 4;
1288 src_start += src->stride / 2;
1291 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1293 for(y = src_rect->top; y < src_rect->bottom; y++)
1295 dst_pixel = dst_start;
1296 src_pixel = src_start;
1297 for(x = src_rect->left; x < src_rect->right; x++)
1299 src_val = *src_pixel++;
1300 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1301 (((src_val >> src->red_shift) << 14) & 0x070000) |
1302 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1303 (((src_val >> src->green_shift) << 6) & 0x000700) |
1304 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1305 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1307 if(pad_size) memset(dst_pixel, 0, pad_size);
1308 dst_start += dst->stride / 4;
1309 src_start += src->stride / 2;
1312 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1314 for(y = src_rect->top; y < src_rect->bottom; y++)
1316 dst_pixel = dst_start;
1317 src_pixel = src_start;
1318 for(x = src_rect->left; x < src_rect->right; x++)
1320 src_val = *src_pixel++;
1321 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1322 (((src_val >> src->red_shift) << 14) & 0x070000) |
1323 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1324 (((src_val >> src->green_shift) << 4) & 0x000300) |
1325 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1326 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1328 if(pad_size) memset(dst_pixel, 0, pad_size);
1329 dst_start += dst->stride / 4;
1330 src_start += src->stride / 2;
1335 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
1343 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1344 for(y = src_rect->top; y < src_rect->bottom; y++)
1346 dst_pixel = dst_start;
1347 src_pixel = src_start;
1348 for(x = src_rect->left; x < src_rect->right; x++)
1351 src_val = *src_pixel++;
1352 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1353 rgb = src->color_table[src_val];
1354 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1356 if(pad_size) memset(dst_pixel, 0, pad_size);
1357 dst_start += dst->stride / 4;
1358 src_start += src->stride;
1365 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1366 for(y = src_rect->top; y < src_rect->bottom; y++)
1368 dst_pixel = dst_start;
1369 src_pixel = src_start;
1370 for(x = src_rect->left; x < src_rect->right; x++)
1374 src_val = *src_pixel++ & 0xf;
1376 src_val = (*src_pixel >> 4) & 0xf;
1377 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1378 rgb = src->color_table[src_val];
1379 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1381 if(pad_size) memset(dst_pixel, 0, pad_size);
1382 dst_start += dst->stride / 4;
1383 src_start += src->stride;
1390 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1391 for(y = src_rect->top; y < src_rect->bottom; y++)
1393 dst_pixel = dst_start;
1394 src_pixel = src_start;
1395 for(x = src_rect->left; x < src_rect->right; x++)
1398 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1399 if((x % 8) == 7) src_pixel++;
1400 rgb = src->color_table[src_val];
1401 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1403 if(pad_size) memset(dst_pixel, 0, pad_size);
1404 dst_start += dst->stride / 4;
1405 src_start += src->stride;
1411 FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
1418 static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1420 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1421 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1423 switch(src->bit_count)
1427 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1429 if(src->funcs == &funcs_8888)
1431 for(y = src_rect->top; y < src_rect->bottom; y++)
1433 dst_pixel = dst_start;
1434 src_pixel = src_start;
1435 for(x = src_rect->left; x < src_rect->right; x++)
1437 src_val = *src_pixel++;
1438 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
1439 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
1440 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
1442 if(pad_size) memset(dst_pixel, 0, pad_size);
1443 dst_start += dst->stride / 4;
1444 src_start += src->stride / 4;
1447 else if(bit_fields_match(src, dst))
1449 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1450 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1453 for(y = src_rect->top; y < src_rect->bottom; y++)
1455 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1456 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1457 dst_start += dst->stride / 4;
1458 src_start += src->stride / 4;
1462 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1463 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1465 for(y = src_rect->top; y < src_rect->bottom; y++)
1467 dst_pixel = dst_start;
1468 src_pixel = src_start;
1469 for(x = src_rect->left; x < src_rect->right; x++)
1471 src_val = *src_pixel++;
1472 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1473 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1474 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1476 if(pad_size) memset(dst_pixel, 0, pad_size);
1477 dst_start += dst->stride / 4;
1478 src_start += src->stride / 4;
1483 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 32 (%08x, %08x, %08x)\n",
1484 src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask);
1492 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1494 for(y = src_rect->top; y < src_rect->bottom; y++)
1496 dst_pixel = dst_start;
1497 src_pixel = src_start;
1498 for(x = src_rect->left; x < src_rect->right; x++)
1501 rgb.rgbBlue = *src_pixel++;
1502 rgb.rgbGreen = *src_pixel++;
1503 rgb.rgbRed = *src_pixel++;
1505 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1506 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1507 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1509 if(pad_size) memset(dst_pixel, 0, pad_size);
1510 dst_start += dst->stride / 4;
1511 src_start += src->stride;
1518 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1519 if(src->funcs == &funcs_555)
1521 for(y = src_rect->top; y < src_rect->bottom; y++)
1523 dst_pixel = dst_start;
1524 src_pixel = src_start;
1525 for(x = src_rect->left; x < src_rect->right; x++)
1527 src_val = *src_pixel++;
1528 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1529 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1530 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1532 if(pad_size) memset(dst_pixel, 0, pad_size);
1533 dst_start += dst->stride / 4;
1534 src_start += src->stride / 2;
1537 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1539 for(y = src_rect->top; y < src_rect->bottom; y++)
1541 dst_pixel = dst_start;
1542 src_pixel = src_start;
1543 for(x = src_rect->left; x < src_rect->right; x++)
1545 src_val = *src_pixel++;
1546 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1547 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1548 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1549 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1550 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1551 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1553 if(pad_size) memset(dst_pixel, 0, pad_size);
1554 dst_start += dst->stride / 4;
1555 src_start += src->stride / 2;
1558 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1560 for(y = src_rect->top; y < src_rect->bottom; y++)
1562 dst_pixel = dst_start;
1563 src_pixel = src_start;
1564 for(x = src_rect->left; x < src_rect->right; x++)
1566 src_val = *src_pixel++;
1567 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1568 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1569 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1570 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1571 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1572 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1574 if(pad_size) memset(dst_pixel, 0, pad_size);
1575 dst_start += dst->stride / 4;
1576 src_start += src->stride / 2;
1581 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 32\n", src->red_mask, src->green_mask, src->blue_mask);
1589 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1590 for(y = src_rect->top; y < src_rect->bottom; y++)
1592 dst_pixel = dst_start;
1593 src_pixel = src_start;
1594 for(x = src_rect->left; x < src_rect->right; x++)
1597 src_val = *src_pixel++;
1598 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1599 rgb = src->color_table[src_val];
1600 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1601 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1602 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1604 if(pad_size) memset(dst_pixel, 0, pad_size);
1605 dst_start += dst->stride / 4;
1606 src_start += src->stride;
1613 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1614 for(y = src_rect->top; y < src_rect->bottom; y++)
1616 dst_pixel = dst_start;
1617 src_pixel = src_start;
1618 for(x = src_rect->left; x < src_rect->right; x++)
1622 src_val = *src_pixel++ & 0xf;
1624 src_val = (*src_pixel >> 4) & 0xf;
1625 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1626 rgb = src->color_table[src_val];
1627 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1628 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1629 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1631 if(pad_size) memset(dst_pixel, 0, pad_size);
1632 dst_start += dst->stride / 4;
1633 src_start += src->stride;
1640 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1641 for(y = src_rect->top; y < src_rect->bottom; y++)
1643 dst_pixel = dst_start;
1644 src_pixel = src_start;
1645 for(x = src_rect->left; x < src_rect->right; x++)
1648 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1649 if((x % 8) == 7) src_pixel++;
1650 rgb = src->color_table[src_val];
1651 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1652 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1653 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1655 if(pad_size) memset(dst_pixel, 0, pad_size);
1656 dst_start += dst->stride / 4;
1657 src_start += src->stride;
1663 FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
1670 static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1672 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1674 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1676 switch(src->bit_count)
1680 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1681 if(src->funcs == &funcs_8888)
1683 for(y = src_rect->top; y < src_rect->bottom; y++)
1685 dst_pixel = dst_start;
1686 src_pixel = src_start;
1687 for(x = src_rect->left; x < src_rect->right; x++)
1689 src_val = *src_pixel++;
1690 *dst_pixel++ = src_val & 0xff;
1691 *dst_pixel++ = (src_val >> 8) & 0xff;
1692 *dst_pixel++ = (src_val >> 16) & 0xff;
1694 if(pad_size) memset(dst_pixel, 0, pad_size);
1695 dst_start += dst->stride;
1696 src_start += src->stride / 4;
1699 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1701 for(y = src_rect->top; y < src_rect->bottom; y++)
1703 dst_pixel = dst_start;
1704 src_pixel = src_start;
1705 for(x = src_rect->left; x < src_rect->right; x++)
1707 src_val = *src_pixel++;
1708 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
1709 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1710 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
1712 if(pad_size) memset(dst_pixel, 0, pad_size);
1713 dst_start += dst->stride;
1714 src_start += src->stride / 4;
1719 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask);
1727 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1729 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1730 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1733 for(y = src_rect->top; y < src_rect->bottom; y++)
1735 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1736 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1737 dst_start += dst->stride;
1738 src_start += src->stride;
1746 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1747 if(src->funcs == &funcs_555)
1749 for(y = src_rect->top; y < src_rect->bottom; y++)
1751 dst_pixel = dst_start;
1752 src_pixel = src_start;
1753 for(x = src_rect->left; x < src_rect->right; x++)
1755 src_val = *src_pixel++;
1756 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
1757 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
1758 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1760 if(pad_size) memset(dst_pixel, 0, pad_size);
1761 dst_start += dst->stride;
1762 src_start += src->stride / 2;
1765 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1767 for(y = src_rect->top; y < src_rect->bottom; y++)
1769 dst_pixel = dst_start;
1770 src_pixel = src_start;
1771 for(x = src_rect->left; x < src_rect->right; x++)
1773 src_val = *src_pixel++;
1774 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1775 (((src_val >> src->blue_shift) >> 2) & 0x07);
1776 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1777 (((src_val >> src->green_shift) >> 2) & 0x07);
1778 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1779 (((src_val >> src->red_shift) >> 2) & 0x07);
1781 if(pad_size) memset(dst_pixel, 0, pad_size);
1782 dst_start += dst->stride;
1783 src_start += src->stride / 2;
1786 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1788 for(y = src_rect->top; y < src_rect->bottom; y++)
1790 dst_pixel = dst_start;
1791 src_pixel = src_start;
1792 for(x = src_rect->left; x < src_rect->right; x++)
1794 src_val = *src_pixel++;
1795 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1796 (((src_val >> src->blue_shift) >> 2) & 0x07);
1797 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1798 (((src_val >> src->green_shift) >> 4) & 0x03);
1799 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1800 (((src_val >> src->red_shift) >> 2) & 0x07);
1802 if(pad_size) memset(dst_pixel, 0, pad_size);
1803 dst_start += dst->stride;
1804 src_start += src->stride / 2;
1809 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask);
1817 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1818 for(y = src_rect->top; y < src_rect->bottom; y++)
1820 dst_pixel = dst_start;
1821 src_pixel = src_start;
1822 for(x = src_rect->left; x < src_rect->right; x++)
1825 src_val = *src_pixel++;
1826 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1827 rgb = src->color_table[src_val];
1828 *dst_pixel++ = rgb.rgbBlue;
1829 *dst_pixel++ = rgb.rgbGreen;
1830 *dst_pixel++ = rgb.rgbRed;
1832 if(pad_size) memset(dst_pixel, 0, pad_size);
1833 dst_start += dst->stride;
1834 src_start += src->stride;
1841 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1842 for(y = src_rect->top; y < src_rect->bottom; y++)
1844 dst_pixel = dst_start;
1845 src_pixel = src_start;
1846 for(x = src_rect->left; x < src_rect->right; x++)
1850 src_val = *src_pixel++ & 0xf;
1852 src_val = (*src_pixel >> 4) & 0xf;
1853 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1854 rgb = src->color_table[src_val];
1855 *dst_pixel++ = rgb.rgbBlue;
1856 *dst_pixel++ = rgb.rgbGreen;
1857 *dst_pixel++ = rgb.rgbRed;
1859 if(pad_size) memset(dst_pixel, 0, pad_size);
1860 dst_start += dst->stride;
1861 src_start += src->stride;
1868 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1869 for(y = src_rect->top; y < src_rect->bottom; y++)
1871 dst_pixel = dst_start;
1872 src_pixel = src_start;
1873 for(x = src_rect->left; x < src_rect->right; x++)
1876 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1877 if((x % 8) == 7) src_pixel++;
1878 rgb = src->color_table[src_val];
1879 *dst_pixel++ = rgb.rgbBlue;
1880 *dst_pixel++ = rgb.rgbGreen;
1881 *dst_pixel++ = rgb.rgbRed;
1883 if(pad_size) memset(dst_pixel, 0, pad_size);
1884 dst_start += dst->stride;
1885 src_start += src->stride;
1891 FIXME("Unsupported conversion: %d -> 24\n", src->bit_count);
1898 static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1900 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
1901 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1904 switch(src->bit_count)
1908 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1910 if(src->funcs == &funcs_8888)
1912 for(y = src_rect->top; y < src_rect->bottom; y++)
1914 dst_pixel = dst_start;
1915 src_pixel = src_start;
1916 for(x = src_rect->left; x < src_rect->right; x++)
1918 src_val = *src_pixel++;
1919 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1920 ((src_val >> 6) & 0x03e0) |
1921 ((src_val >> 3) & 0x001f);
1923 if(pad_size) memset(dst_pixel, 0, pad_size);
1924 dst_start += dst->stride / 2;
1925 src_start += src->stride / 4;
1928 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1930 for(y = src_rect->top; y < src_rect->bottom; y++)
1932 dst_pixel = dst_start;
1933 src_pixel = src_start;
1934 for(x = src_rect->left; x < src_rect->right; x++)
1936 src_val = *src_pixel++;
1937 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
1938 (((src_val >> src->green_shift) << 2) & 0x03e0) |
1939 (((src_val >> src->blue_shift) >> 3) & 0x001f);
1941 if(pad_size) memset(dst_pixel, 0, pad_size);
1942 dst_start += dst->stride / 2;
1943 src_start += src->stride / 4;
1948 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask);
1956 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1958 for(y = src_rect->top; y < src_rect->bottom; y++)
1960 dst_pixel = dst_start;
1961 src_pixel = src_start;
1962 for(x = src_rect->left; x < src_rect->right; x++)
1965 rgb.rgbBlue = *src_pixel++;
1966 rgb.rgbGreen = *src_pixel++;
1967 rgb.rgbRed = *src_pixel++;
1969 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1970 ((rgb.rgbGreen << 2) & 0x03e0) |
1971 ((rgb.rgbBlue >> 3) & 0x001f);
1973 if(pad_size) memset(dst_pixel, 0, pad_size);
1974 dst_start += dst->stride / 2;
1975 src_start += src->stride;
1982 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1983 if(src->funcs == &funcs_555)
1985 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1986 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1989 for(y = src_rect->top; y < src_rect->bottom; y++)
1991 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1992 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1993 dst_start += dst->stride / 2;
1994 src_start += src->stride / 2;
1998 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2000 for(y = src_rect->top; y < src_rect->bottom; y++)
2002 dst_pixel = dst_start;
2003 src_pixel = src_start;
2004 for(x = src_rect->left; x < src_rect->right; x++)
2006 src_val = *src_pixel++;
2007 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2008 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2009 ( (src_val >> src->blue_shift) & 0x001f);
2011 if(pad_size) memset(dst_pixel, 0, pad_size);
2012 dst_start += dst->stride / 2;
2013 src_start += src->stride / 2;
2016 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2018 for(y = src_rect->top; y < src_rect->bottom; y++)
2020 dst_pixel = dst_start;
2021 src_pixel = src_start;
2022 for(x = src_rect->left; x < src_rect->right; x++)
2024 src_val = *src_pixel++;
2025 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2026 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2027 ( (src_val >> src->blue_shift) & 0x001f);
2029 if(pad_size) memset(dst_pixel, 0, pad_size);
2030 dst_start += dst->stride / 2;
2031 src_start += src->stride / 2;
2036 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask);
2044 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2045 for(y = src_rect->top; y < src_rect->bottom; y++)
2047 dst_pixel = dst_start;
2048 src_pixel = src_start;
2049 for(x = src_rect->left; x < src_rect->right; x++)
2052 src_val = *src_pixel++;
2053 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2054 rgb = src->color_table[src_val];
2055 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2056 ((rgb.rgbGreen << 2) & 0x03e0) |
2057 ((rgb.rgbBlue >> 3) & 0x001f);
2059 if(pad_size) memset(dst_pixel, 0, pad_size);
2060 dst_start += dst->stride / 2;
2061 src_start += src->stride;
2068 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2069 for(y = src_rect->top; y < src_rect->bottom; y++)
2071 dst_pixel = dst_start;
2072 src_pixel = src_start;
2073 for(x = src_rect->left; x < src_rect->right; x++)
2077 src_val = *src_pixel++ & 0xf;
2079 src_val = (*src_pixel >> 4) & 0xf;
2080 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2081 rgb = src->color_table[src_val];
2082 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2083 ((rgb.rgbGreen << 2) & 0x03e0) |
2084 ((rgb.rgbBlue >> 3) & 0x001f);
2086 if(pad_size) memset(dst_pixel, 0, pad_size);
2087 dst_start += dst->stride / 2;
2088 src_start += src->stride;
2095 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2096 for(y = src_rect->top; y < src_rect->bottom; y++)
2098 dst_pixel = dst_start;
2099 src_pixel = src_start;
2100 for(x = src_rect->left; x < src_rect->right; x++)
2103 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2104 if((x % 8) == 7) src_pixel++;
2105 rgb = src->color_table[src_val];
2106 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2107 ((rgb.rgbGreen << 2) & 0x03e0) |
2108 ((rgb.rgbBlue >> 3) & 0x001f);
2110 if(pad_size) memset(dst_pixel, 0, pad_size);
2111 dst_start += dst->stride / 2;
2112 src_start += src->stride;
2118 FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
2125 static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2127 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2128 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2131 switch(src->bit_count)
2135 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2137 if(src->funcs == &funcs_8888)
2139 for(y = src_rect->top; y < src_rect->bottom; y++)
2141 dst_pixel = dst_start;
2142 src_pixel = src_start;
2143 for(x = src_rect->left; x < src_rect->right; x++)
2145 src_val = *src_pixel++;
2146 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
2147 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
2148 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
2150 if(pad_size) memset(dst_pixel, 0, pad_size);
2151 dst_start += dst->stride / 2;
2152 src_start += src->stride / 4;
2155 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2157 for(y = src_rect->top; y < src_rect->bottom; y++)
2159 dst_pixel = dst_start;
2160 src_pixel = src_start;
2161 for(x = src_rect->left; x < src_rect->right; x++)
2163 src_val = *src_pixel++;
2164 *dst_pixel++ = put_field((src_val >> src->red_shift) & 0xff, dst->red_shift, dst->red_len) |
2165 put_field((src_val >> src->green_shift) & 0xff, dst->green_shift, dst->green_len) |
2166 put_field((src_val >> src->blue_shift) & 0xff, dst->blue_shift, dst->blue_len);
2168 if(pad_size) memset(dst_pixel, 0, pad_size);
2169 dst_start += dst->stride / 2;
2170 src_start += src->stride / 4;
2175 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 16\n", src->red_mask, src->green_mask, src->blue_mask);
2183 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2185 for(y = src_rect->top; y < src_rect->bottom; y++)
2187 dst_pixel = dst_start;
2188 src_pixel = src_start;
2189 for(x = src_rect->left; x < src_rect->right; x++)
2192 rgb.rgbBlue = *src_pixel++;
2193 rgb.rgbGreen = *src_pixel++;
2194 rgb.rgbRed = *src_pixel++;
2196 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2197 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2198 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2200 if(pad_size) memset(dst_pixel, 0, pad_size);
2201 dst_start += dst->stride / 2;
2202 src_start += src->stride;
2209 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2210 if(src->funcs == &funcs_555)
2212 for(y = src_rect->top; y < src_rect->bottom; y++)
2214 dst_pixel = dst_start;
2215 src_pixel = src_start;
2216 for(x = src_rect->left; x < src_rect->right; x++)
2218 src_val = *src_pixel++;
2219 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2220 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2221 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2223 if(pad_size) memset(dst_pixel, 0, pad_size);
2224 dst_start += dst->stride / 2;
2225 src_start += src->stride / 2;
2228 else if(bit_fields_match(src, dst))
2230 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2231 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2234 for(y = src_rect->top; y < src_rect->bottom; y++)
2236 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2237 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2238 dst_start += dst->stride / 2;
2239 src_start += src->stride / 2;
2243 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2245 for(y = src_rect->top; y < src_rect->bottom; y++)
2247 dst_pixel = dst_start;
2248 src_pixel = src_start;
2249 for(x = src_rect->left; x < src_rect->right; x++)
2251 src_val = *src_pixel++;
2252 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2253 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2254 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2255 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2256 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2257 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2259 if(pad_size) memset(dst_pixel, 0, pad_size);
2260 dst_start += dst->stride / 2;
2261 src_start += src->stride / 2;
2264 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2266 for(y = src_rect->top; y < src_rect->bottom; y++)
2268 dst_pixel = dst_start;
2269 src_pixel = src_start;
2270 for(x = src_rect->left; x < src_rect->right; x++)
2272 src_val = *src_pixel++;
2273 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2274 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2275 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2276 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2277 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2278 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2280 if(pad_size) memset(dst_pixel, 0, pad_size);
2281 dst_start += dst->stride / 2;
2282 src_start += src->stride / 2;
2287 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 16 (%08x, %08x, %08x)\n",
2288 src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask);
2296 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2297 for(y = src_rect->top; y < src_rect->bottom; y++)
2299 dst_pixel = dst_start;
2300 src_pixel = src_start;
2301 for(x = src_rect->left; x < src_rect->right; x++)
2304 src_val = *src_pixel++;
2305 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2306 rgb = src->color_table[src_val];
2307 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2308 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2309 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2311 if(pad_size) memset(dst_pixel, 0, pad_size);
2312 dst_start += dst->stride / 2;
2313 src_start += src->stride;
2320 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2321 for(y = src_rect->top; y < src_rect->bottom; y++)
2323 dst_pixel = dst_start;
2324 src_pixel = src_start;
2325 for(x = src_rect->left; x < src_rect->right; x++)
2329 src_val = *src_pixel++ & 0xf;
2331 src_val = (*src_pixel >> 4) & 0xf;
2332 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2333 rgb = src->color_table[src_val];
2334 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2335 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2336 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2338 if(pad_size) memset(dst_pixel, 0, pad_size);
2339 dst_start += dst->stride / 2;
2340 src_start += src->stride;
2347 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2348 for(y = src_rect->top; y < src_rect->bottom; y++)
2350 dst_pixel = dst_start;
2351 src_pixel = src_start;
2352 for(x = src_rect->left; x < src_rect->right; x++)
2355 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2356 if((x % 8) == 7) src_pixel++;
2357 rgb = src->color_table[src_val];
2358 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2359 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2360 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2362 if(pad_size) memset(dst_pixel, 0, pad_size);
2363 dst_start += dst->stride / 2;
2364 src_start += src->stride;
2370 FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
2377 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2379 assert(d1->color_table_size && d2->color_table_size);
2381 if(d1->color_table_size != d2->color_table_size) return FALSE;
2382 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2385 static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2387 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2388 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2391 switch(src->bit_count)
2395 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2397 if(src->funcs == &funcs_8888)
2399 for(y = src_rect->top; y < src_rect->bottom; y++)
2401 dst_pixel = dst_start;
2402 src_pixel = src_start;
2403 for(x = src_rect->left; x < src_rect->right; x++)
2405 src_val = *src_pixel++;
2406 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
2407 ( src_val & 0x00ff00) |
2408 ((src_val << 16) & 0xff0000) );
2410 if(pad_size) memset(dst_pixel, 0, pad_size);
2411 dst_start += dst->stride;
2412 src_start += src->stride / 4;
2415 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2417 for(y = src_rect->top; y < src_rect->bottom; y++)
2419 dst_pixel = dst_start;
2420 src_pixel = src_start;
2421 for(x = src_rect->left; x < src_rect->right; x++)
2423 src_val = *src_pixel++;
2424 *dst_pixel++ = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift) & 0x0000ff) |
2425 (((src_val >> src->green_shift) << 8) & 0x00ff00) |
2426 (((src_val >> src->blue_shift) << 16) & 0xff0000) );
2428 if(pad_size) memset(dst_pixel, 0, pad_size);
2429 dst_start += dst->stride;
2430 src_start += src->stride / 4;
2435 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask);
2443 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2445 for(y = src_rect->top; y < src_rect->bottom; y++)
2447 dst_pixel = dst_start;
2448 src_pixel = src_start;
2449 for(x = src_rect->left; x < src_rect->right; x++)
2452 rgb.rgbBlue = *src_pixel++;
2453 rgb.rgbGreen = *src_pixel++;
2454 rgb.rgbRed = *src_pixel++;
2456 *dst_pixel++ = colorref_to_pixel_colortable(dst, ( rgb.rgbRed & 0x0000ff) |
2457 ((rgb.rgbGreen << 8) & 0x00ff00) |
2458 ((rgb.rgbBlue << 16) & 0xff0000));
2460 if(pad_size) memset(dst_pixel, 0, pad_size);
2461 dst_start += dst->stride;
2462 src_start += src->stride;
2469 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2470 if(src->funcs == &funcs_555)
2472 for(y = src_rect->top; y < src_rect->bottom; y++)
2474 dst_pixel = dst_start;
2475 src_pixel = src_start;
2476 for(x = src_rect->left; x < src_rect->right; x++)
2478 src_val = *src_pixel++;
2479 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2480 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
2481 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
2483 if(pad_size) memset(dst_pixel, 0, pad_size);
2484 dst_start += dst->stride;
2485 src_start += src->stride / 2;
2488 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2490 for(y = src_rect->top; y < src_rect->bottom; y++)
2492 dst_pixel = dst_start;
2493 src_pixel = src_start;
2494 for(x = src_rect->left; x < src_rect->right; x++)
2496 src_val = *src_pixel++;
2497 *dst_pixel++ = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift) << 3) & 0x0000f8) |
2498 (((src_val >> src->red_shift) >> 2) & 0x000007) |
2499 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2500 (((src_val >> src->green_shift) << 6) & 0x000700) |
2501 (((src_val >> src->blue_shift) << 19) & 0xf80000) |
2502 (((src_val >> src->blue_shift) << 14) & 0x070000) );
2504 if(pad_size) memset(dst_pixel, 0, pad_size);
2505 dst_start += dst->stride;
2506 src_start += src->stride / 2;
2509 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2511 for(y = src_rect->top; y < src_rect->bottom; y++)
2513 dst_pixel = dst_start;
2514 src_pixel = src_start;
2515 for(x = src_rect->left; x < src_rect->right; x++)
2517 src_val = *src_pixel++;
2518 *dst_pixel++ = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift) << 3) & 0x0000f8) |
2519 (((src_val >> src->red_shift) >> 2) & 0x000007) |
2520 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2521 (((src_val >> src->green_shift) << 4) & 0x000300) |
2522 (((src_val >> src->blue_shift) << 19) & 0xf80000) |
2523 (((src_val >> src->blue_shift) << 14) & 0x070000) );
2525 if(pad_size) memset(dst_pixel, 0, pad_size);
2526 dst_start += dst->stride;
2527 src_start += src->stride / 2;
2532 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask);
2540 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2542 if(color_tables_match(dst, src))
2544 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2545 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2548 for(y = src_rect->top; y < src_rect->bottom; y++)
2550 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2551 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2552 dst_start += dst->stride;
2553 src_start += src->stride;
2559 for(y = src_rect->top; y < src_rect->bottom; y++)
2561 dst_pixel = dst_start;
2562 src_pixel = src_start;
2563 for(x = src_rect->left; x < src_rect->right; x++)
2566 src_val = *src_pixel++;
2567 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2568 rgb = src->color_table[src_val];
2569 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2571 if(pad_size) memset(dst_pixel, 0, pad_size);
2572 dst_start += dst->stride;
2573 src_start += src->stride;
2581 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2582 for(y = src_rect->top; y < src_rect->bottom; y++)
2584 dst_pixel = dst_start;
2585 src_pixel = src_start;
2586 for(x = src_rect->left; x < src_rect->right; x++)
2590 src_val = *src_pixel++ & 0xf;
2592 src_val = (*src_pixel >> 4) & 0xf;
2593 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2594 rgb = src->color_table[src_val];
2595 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2597 if(pad_size) memset(dst_pixel, 0, pad_size);
2598 dst_start += dst->stride;
2599 src_start += src->stride;
2606 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2607 for(y = src_rect->top; y < src_rect->bottom; y++)
2609 dst_pixel = dst_start;
2610 src_pixel = src_start;
2611 for(x = src_rect->left; x < src_rect->right; x++)
2614 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2615 if((x % 8) == 7) src_pixel++;
2616 rgb = src->color_table[src_val];
2617 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2619 if(pad_size) memset(dst_pixel, 0, pad_size);
2620 dst_start += dst->stride;
2621 src_start += src->stride;
2627 FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
2634 static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2636 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2637 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2640 switch(src->bit_count)
2644 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2646 if(src->funcs == &funcs_8888)
2648 for(y = src_rect->top; y < src_rect->bottom; y++)
2650 dst_pixel = dst_start;
2651 src_pixel = src_start;
2652 for(x = src_rect->left; x < src_rect->right; x++)
2654 src_val = *src_pixel++;
2655 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
2656 ( src_val & 0x00ff00) |
2657 ((src_val << 16) & 0xff0000) );
2658 if((x - src_rect->left) & 1)
2660 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2664 *dst_pixel = (dst_val << 4) & 0xf0;
2668 if((x - src_rect->left) & 1) dst_pixel++;
2669 memset(dst_pixel, 0, pad_size);
2671 dst_start += dst->stride;
2672 src_start += src->stride / 4;
2675 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2677 for(y = src_rect->top; y < src_rect->bottom; y++)
2679 dst_pixel = dst_start;
2680 src_pixel = src_start;
2681 for(x = src_rect->left; x < src_rect->right; x++)
2683 src_val = *src_pixel++;
2684 dst_val = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift) & 0x0000ff) |
2685 (((src_val >> src->green_shift) << 8) & 0x00ff00) |
2686 (((src_val >> src->blue_shift) << 16) & 0xff0000) );
2687 if((x - src_rect->left) & 1)
2689 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2693 *dst_pixel = (dst_val << 4) & 0xf0;
2697 if((x - src_rect->left) & 1) dst_pixel++;
2698 memset(dst_pixel, 0, pad_size);
2700 dst_start += dst->stride;
2701 src_start += src->stride / 4;
2706 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask);
2714 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2716 for(y = src_rect->top; y < src_rect->bottom; y++)
2718 dst_pixel = dst_start;
2719 src_pixel = src_start;
2720 for(x = src_rect->left; x < src_rect->right; x++)
2723 rgb.rgbBlue = *src_pixel++;
2724 rgb.rgbGreen = *src_pixel++;
2725 rgb.rgbRed = *src_pixel++;
2727 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed & 0x0000ff) |
2728 ((rgb.rgbGreen << 8) & 0x00ff00) |
2729 ((rgb.rgbBlue << 16) & 0xff0000));
2731 if((x - src_rect->left) & 1)
2733 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2737 *dst_pixel = (dst_val << 4) & 0xf0;
2741 if((x - src_rect->left) & 1) dst_pixel++;
2742 memset(dst_pixel, 0, pad_size);
2744 dst_start += dst->stride;
2745 src_start += src->stride;
2752 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2753 if(src->funcs == &funcs_555)
2755 for(y = src_rect->top; y < src_rect->bottom; y++)
2757 dst_pixel = dst_start;
2758 src_pixel = src_start;
2759 for(x = src_rect->left; x < src_rect->right; x++)
2761 src_val = *src_pixel++;
2762 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2763 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
2764 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
2765 if((x - src_rect->left) & 1)
2767 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2771 *dst_pixel = (dst_val << 4) & 0xf0;
2775 if((x - src_rect->left) & 1) dst_pixel++;
2776 memset(dst_pixel, 0, pad_size);
2778 dst_start += dst->stride;
2779 src_start += src->stride / 2;
2782 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2784 for(y = src_rect->top; y < src_rect->bottom; y++)
2786 dst_pixel = dst_start;
2787 src_pixel = src_start;
2788 for(x = src_rect->left; x < src_rect->right; x++)
2790 src_val = *src_pixel++;
2791 dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift) << 3) & 0x0000f8) |
2792 (((src_val >> src->red_shift) >> 2) & 0x000007) |
2793 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2794 (((src_val >> src->green_shift) << 6) & 0x000700) |
2795 (((src_val >> src->blue_shift) << 19) & 0xf80000) |
2796 (((src_val >> src->blue_shift) << 14) & 0x070000) );
2797 if((x - src_rect->left) & 1)
2799 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2803 *dst_pixel = (dst_val << 4) & 0xf0;
2807 if((x - src_rect->left) & 1) dst_pixel++;
2808 memset(dst_pixel, 0, pad_size);
2810 dst_start += dst->stride;
2811 src_start += src->stride / 2;
2814 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2816 for(y = src_rect->top; y < src_rect->bottom; y++)
2818 dst_pixel = dst_start;
2819 src_pixel = src_start;
2820 for(x = src_rect->left; x < src_rect->right; x++)
2822 src_val = *src_pixel++;
2823 dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift) << 3) & 0x0000f8) |
2824 (((src_val >> src->red_shift) >> 2) & 0x000007) |
2825 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2826 (((src_val >> src->green_shift) << 4) & 0x000300) |
2827 (((src_val >> src->blue_shift) << 19) & 0xf80000) |
2828 (((src_val >> src->blue_shift) << 14) & 0x070000) );
2829 if((x - src_rect->left) & 1)
2831 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2835 *dst_pixel = (dst_val << 4) & 0xf0;
2839 if((x - src_rect->left) & 1) dst_pixel++;
2840 memset(dst_pixel, 0, pad_size);
2842 dst_start += dst->stride;
2843 src_start += src->stride / 2;
2848 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask);
2856 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2858 for(y = src_rect->top; y < src_rect->bottom; y++)
2860 dst_pixel = dst_start;
2861 src_pixel = src_start;
2862 for(x = src_rect->left; x < src_rect->right; x++)
2865 src_val = *src_pixel++;
2866 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2867 rgb = src->color_table[src_val];
2868 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2869 if((x - src_rect->left) & 1)
2871 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2875 *dst_pixel = (dst_val << 4) & 0xf0;
2879 if((x - src_rect->left) & 1) dst_pixel++;
2880 memset(dst_pixel, 0, pad_size);
2882 dst_start += dst->stride;
2883 src_start += src->stride;
2890 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2892 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
2894 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2895 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2898 for(y = src_rect->top; y < src_rect->bottom; y++)
2900 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
2901 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
2902 dst_start += dst->stride;
2903 src_start += src->stride;
2909 for(y = src_rect->top; y < src_rect->bottom; y++)
2911 dst_pixel = dst_start;
2912 src_pixel = src_start;
2913 for(x = src_rect->left; x < src_rect->right; x++)
2917 src_val = *src_pixel++ & 0xf;
2919 src_val = (*src_pixel >> 4) & 0xf;
2920 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2921 rgb = src->color_table[src_val];
2922 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2923 if((x - src_rect->left) & 1)
2925 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2929 *dst_pixel = (dst_val << 4) & 0xf0;
2933 if((x - src_rect->left) & 1) dst_pixel++;
2934 memset(dst_pixel, 0, pad_size);
2936 dst_start += dst->stride;
2937 src_start += src->stride;
2945 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2946 for(y = src_rect->top; y < src_rect->bottom; y++)
2948 dst_pixel = dst_start;
2949 src_pixel = src_start;
2950 for(x = src_rect->left; x < src_rect->right; x++)
2953 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2954 if((x % 8) == 7) src_pixel++;
2955 rgb = src->color_table[src_val];
2956 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
2957 if((x - src_rect->left) & 1)
2959 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2963 *dst_pixel = (dst_val << 4) & 0xf0;
2967 if((x - src_rect->left) & 1) dst_pixel++;
2968 memset(dst_pixel, 0, pad_size);
2970 dst_start += dst->stride;
2971 src_start += src->stride;
2977 FIXME("Unsupported conversion: %d -> 4\n", src->bit_count);
2985 static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
2987 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
2988 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
2992 /* FIXME: Brushes should be dithered. */
2994 switch(src->bit_count)
2998 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3000 if(src->funcs == &funcs_8888)
3002 for(y = src_rect->top; y < src_rect->bottom; y++)
3004 dst_pixel = dst_start;
3005 src_pixel = src_start;
3006 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3008 src_val = *src_pixel++;
3009 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
3010 ( src_val & 0x00ff00) |
3011 ((src_val << 16) & 0xff0000) ) ? 0xff : 0;
3013 if(bit_pos == 0) *dst_pixel = 0;
3014 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3024 if(bit_pos != 0) dst_pixel++;
3025 memset(dst_pixel, 0, pad_size);
3027 dst_start += dst->stride;
3028 src_start += src->stride / 4;
3031 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3033 for(y = src_rect->top; y < src_rect->bottom; y++)
3035 dst_pixel = dst_start;
3036 src_pixel = src_start;
3037 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3039 src_val = *src_pixel++;
3040 dst_val = colorref_to_pixel_colortable(dst, ( (src_val >> src->red_shift) & 0x0000ff) |
3041 (((src_val >> src->green_shift) << 8) & 0x00ff00) |
3042 (((src_val >> src->blue_shift) << 16) & 0xff0000) ) ? 0xff : 0;
3044 if(bit_pos == 0) *dst_pixel = 0;
3045 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3055 if(bit_pos != 0) dst_pixel++;
3056 memset(dst_pixel, 0, pad_size);
3058 dst_start += dst->stride;
3059 src_start += src->stride / 4;
3064 FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask);
3072 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3074 for(y = src_rect->top; y < src_rect->bottom; y++)
3076 dst_pixel = dst_start;
3077 src_pixel = src_start;
3078 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3081 rgb.rgbBlue = *src_pixel++;
3082 rgb.rgbGreen = *src_pixel++;
3083 rgb.rgbRed = *src_pixel++;
3085 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed & 0x0000ff) |
3086 ((rgb.rgbGreen << 8) & 0x00ff00) |
3087 ((rgb.rgbBlue << 16) & 0xff0000)) ? 0xff : 0;
3089 if(bit_pos == 0) *dst_pixel = 0;
3090 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3100 if(bit_pos != 0) dst_pixel++;
3101 memset(dst_pixel, 0, pad_size);
3103 dst_start += dst->stride;
3104 src_start += src->stride;
3111 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3112 if(src->funcs == &funcs_555)
3114 for(y = src_rect->top; y < src_rect->bottom; y++)
3116 dst_pixel = dst_start;
3117 src_pixel = src_start;
3118 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3120 src_val = *src_pixel++;
3121 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
3122 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
3123 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) ) ? 0xff : 0;
3125 if(bit_pos == 0) *dst_pixel = 0;
3126 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3136 if(bit_pos != 0) dst_pixel++;
3137 memset(dst_pixel, 0, pad_size);
3139 dst_start += dst->stride;
3140 src_start += src->stride / 2;
3143 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3145 for(y = src_rect->top; y < src_rect->bottom; y++)
3147 dst_pixel = dst_start;
3148 src_pixel = src_start;
3149 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3151 src_val = *src_pixel++;
3152 dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift) << 3) & 0x0000f8) |
3153 (((src_val >> src->red_shift) >> 2) & 0x000007) |
3154 (((src_val >> src->green_shift) << 11) & 0x00f800) |
3155 (((src_val >> src->green_shift) << 6) & 0x000700) |
3156 (((src_val >> src->blue_shift) << 19) & 0xf80000) |
3157 (((src_val >> src->blue_shift) << 14) & 0x070000) ) ? 0xff : 0;
3158 if(bit_pos == 0) *dst_pixel = 0;
3159 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3169 if(bit_pos != 0) dst_pixel++;
3170 memset(dst_pixel, 0, pad_size);
3172 dst_start += dst->stride;
3173 src_start += src->stride / 2;
3176 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3178 for(y = src_rect->top; y < src_rect->bottom; y++)
3180 dst_pixel = dst_start;
3181 src_pixel = src_start;
3182 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3184 src_val = *src_pixel++;
3185 dst_val = colorref_to_pixel_colortable(dst, (((src_val >> src->red_shift) << 3) & 0x0000f8) |
3186 (((src_val >> src->red_shift) >> 2) & 0x000007) |
3187 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
3188 (((src_val >> src->green_shift) << 4) & 0x000300) |
3189 (((src_val >> src->blue_shift) << 19) & 0xf80000) |
3190 (((src_val >> src->blue_shift) << 14) & 0x070000) );
3191 if(bit_pos == 0) *dst_pixel = 0;
3192 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3202 if(bit_pos != 0) dst_pixel++;
3203 memset(dst_pixel, 0, pad_size);
3205 dst_start += dst->stride;
3206 src_start += src->stride / 2;
3211 FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask);
3219 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3221 for(y = src_rect->top; y < src_rect->bottom; y++)
3223 dst_pixel = dst_start;
3224 src_pixel = src_start;
3225 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3228 src_val = *src_pixel++;
3229 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
3230 rgb = src->color_table[src_val];
3231 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
3233 if(bit_pos == 0) *dst_pixel = 0;
3234 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3244 if(bit_pos != 0) dst_pixel++;
3245 memset(dst_pixel, 0, pad_size);
3247 dst_start += dst->stride;
3248 src_start += src->stride;
3255 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3257 for(y = src_rect->top; y < src_rect->bottom; y++)
3259 dst_pixel = dst_start;
3260 src_pixel = src_start;
3261 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3265 src_val = *src_pixel++ & 0xf;
3267 src_val = (*src_pixel >> 4) & 0xf;
3268 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
3269 rgb = src->color_table[src_val];
3270 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
3272 if(bit_pos == 0) *dst_pixel = 0;
3273 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3283 if(bit_pos != 0) dst_pixel++;
3284 memset(dst_pixel, 0, pad_size);
3286 dst_start += dst->stride;
3287 src_start += src->stride;
3292 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3293 uses text/bkgnd colours instead of the dib's colour table, this
3294 doesn't appear to be the case for a dc backed by a
3299 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3300 for(y = src_rect->top; y < src_rect->bottom; y++)
3302 dst_pixel = dst_start;
3303 src_pixel = src_start;
3304 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3307 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3308 if((x % 8) == 7) src_pixel++;
3309 rgb = src->color_table[src_val];
3310 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
3312 if(bit_pos == 0) *dst_pixel = 0;
3313 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3323 if(bit_pos != 0) dst_pixel++;
3324 memset(dst_pixel, 0, pad_size);
3326 dst_start += dst->stride;
3327 src_start += src->stride;
3333 FIXME("Unsupported conversion: %d -> 1\n", src->bit_count);
3340 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3345 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)
3347 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3348 DWORD mask_start = 0, mask_offset;
3349 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
3352 for(y = 0; y < hatch->height; y++)
3354 hatch_ptr = hatch_start;
3355 mask_offset = mask_start;
3356 for(x = 0; x < hatch->width; x++)
3358 if(*hatch_ptr & pixel_masks_1[x % 8])
3360 and_bits[mask_offset] = fg->and;
3361 xor_bits[mask_offset] = fg->xor;
3365 and_bits[mask_offset] = bg->and;
3366 xor_bits[mask_offset] = bg->xor;
3368 if(x % 8 == 7) hatch_ptr++;
3371 hatch_start += hatch->stride;
3372 mask_start += dib->stride / 4;
3378 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)
3380 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3381 DWORD mask_start = 0, mask_offset;
3382 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3385 for(y = 0; y < hatch->height; y++)
3387 hatch_ptr = hatch_start;
3388 mask_offset = mask_start;
3389 for(x = 0; x < hatch->width; x++)
3391 if(*hatch_ptr & pixel_masks_1[x % 8])
3393 and_bits[mask_offset] = fg->and & 0xff;
3394 xor_bits[mask_offset++] = fg->xor & 0xff;
3395 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
3396 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
3397 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
3398 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
3402 and_bits[mask_offset] = bg->and & 0xff;
3403 xor_bits[mask_offset++] = bg->xor & 0xff;
3404 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
3405 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
3406 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
3407 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
3409 if(x % 8 == 7) hatch_ptr++;
3411 hatch_start += hatch->stride;
3412 mask_start += dib->stride;
3418 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)
3420 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3421 DWORD mask_start = 0, mask_offset;
3422 WORD *and_bits = bits->and, *xor_bits = bits->xor;
3425 for(y = 0; y < hatch->height; y++)
3427 hatch_ptr = hatch_start;
3428 mask_offset = mask_start;
3429 for(x = 0; x < hatch->width; x++)
3431 if(*hatch_ptr & pixel_masks_1[x % 8])
3433 and_bits[mask_offset] = fg->and;
3434 xor_bits[mask_offset] = fg->xor;
3438 and_bits[mask_offset] = bg->and;
3439 xor_bits[mask_offset] = bg->xor;
3441 if(x % 8 == 7) hatch_ptr++;
3444 hatch_start += hatch->stride;
3445 mask_start += dib->stride / 2;
3451 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)
3453 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3454 DWORD mask_start = 0, mask_offset;
3455 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3458 for(y = 0; y < hatch->height; y++)
3460 hatch_ptr = hatch_start;
3461 mask_offset = mask_start;
3462 for(x = 0; x < hatch->width; x++)
3464 if(*hatch_ptr & pixel_masks_1[x % 8])
3466 and_bits[mask_offset] = fg->and;
3467 xor_bits[mask_offset] = fg->xor;
3471 and_bits[mask_offset] = bg->and;
3472 xor_bits[mask_offset] = bg->xor;
3474 if(x % 8 == 7) hatch_ptr++;
3477 hatch_start += hatch->stride;
3478 mask_start += dib->stride;
3484 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)
3486 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3487 DWORD mask_start = 0, mask_offset;
3488 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3489 const rop_mask *rop_mask;
3492 for(y = 0; y < hatch->height; y++)
3494 hatch_ptr = hatch_start;
3495 mask_offset = mask_start;
3496 for(x = 0; x < hatch->width; x++)
3498 if(*hatch_ptr & pixel_masks_1[x % 8])
3505 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3506 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3511 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3512 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3515 if(x % 8 == 7) hatch_ptr++;
3517 hatch_start += hatch->stride;
3518 mask_start += dib->stride;
3524 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)
3526 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3527 DWORD mask_start = 0, mask_offset;
3528 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3532 for(y = 0; y < hatch->height; y++)
3534 hatch_ptr = hatch_start;
3535 mask_offset = mask_start;
3536 for(x = 0, bit_pos = 0; x < hatch->width; x++)
3538 if(*hatch_ptr & pixel_masks_1[x % 8])
3540 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3541 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3545 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3546 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3549 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3551 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3552 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3561 hatch_start += hatch->stride;
3562 mask_start += dib->stride;
3568 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)
3573 const primitive_funcs funcs_8888 =
3578 colorref_to_pixel_888,
3583 const primitive_funcs funcs_32 =
3588 colorref_to_pixel_masks,
3593 const primitive_funcs funcs_24 =
3598 colorref_to_pixel_888,
3603 const primitive_funcs funcs_555 =
3608 colorref_to_pixel_555,
3613 const primitive_funcs funcs_16 =
3618 colorref_to_pixel_masks,
3623 const primitive_funcs funcs_8 =
3628 colorref_to_pixel_colortable,
3633 const primitive_funcs funcs_4 =
3638 colorref_to_pixel_colortable,
3643 const primitive_funcs funcs_1 =
3648 colorref_to_pixel_colortable,
3653 const primitive_funcs funcs_null =
3658 colorref_to_pixel_null,
3660 create_rop_masks_null