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 struct rop_codes codes;
789 int y, dst_stride, src_stride;
791 if (overlap & OVERLAP_BELOW)
793 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
794 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
795 dst_stride = -dst->stride / 4;
796 src_stride = -src->stride / 4;
800 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
801 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
802 dst_stride = dst->stride / 4;
803 src_stride = src->stride / 4;
806 if (rop2 == R2_COPYPEN)
808 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
809 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
813 get_rop_codes( rop2, &codes );
814 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
816 if (overlap & OVERLAP_RIGHT)
817 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
819 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
823 static void copy_rect_24(const dib_info *dst, const RECT *rc,
824 const dib_info *src, const POINT *origin, int rop2, int overlap)
826 BYTE *dst_start, *src_start;
827 int y, dst_stride, src_stride;
828 struct rop_codes codes;
830 if (overlap & OVERLAP_BELOW)
832 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
833 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
834 dst_stride = -dst->stride;
835 src_stride = -src->stride;
839 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
840 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
841 dst_stride = dst->stride;
842 src_stride = src->stride;
845 if (rop2 == R2_COPYPEN)
847 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
848 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
852 get_rop_codes( rop2, &codes );
853 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
855 if (overlap & OVERLAP_RIGHT)
856 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
858 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
862 static void copy_rect_16(const dib_info *dst, const RECT *rc,
863 const dib_info *src, const POINT *origin, int rop2, int overlap)
865 WORD *dst_start, *src_start;
866 int y, dst_stride, src_stride;
867 struct rop_codes codes;
869 if (overlap & OVERLAP_BELOW)
871 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
872 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
873 dst_stride = -dst->stride / 2;
874 src_stride = -src->stride / 2;
878 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
879 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
880 dst_stride = dst->stride / 2;
881 src_stride = src->stride / 2;
884 if (rop2 == R2_COPYPEN)
886 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
887 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
891 get_rop_codes( rop2, &codes );
892 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
894 if (overlap & OVERLAP_RIGHT)
895 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
897 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
901 static void copy_rect_8(const dib_info *dst, const RECT *rc,
902 const dib_info *src, const POINT *origin, int rop2, int overlap)
904 BYTE *dst_start, *src_start;
905 int y, dst_stride, src_stride;
906 struct rop_codes codes;
908 if (overlap & OVERLAP_BELOW)
910 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
911 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
912 dst_stride = -dst->stride;
913 src_stride = -src->stride;
917 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
918 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
919 dst_stride = dst->stride;
920 src_stride = src->stride;
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) );
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_8( dst_start, src_start, &codes, rc->right - rc->left );
936 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
940 static void copy_rect_4(const dib_info *dst, const RECT *rc,
941 const dib_info *src, const POINT *origin, int rop2, int overlap)
943 BYTE *dst_start, *src_start;
944 int y, dst_stride, src_stride;
945 struct rop_codes codes;
947 if (overlap & OVERLAP_BELOW)
949 dst_start = get_pixel_ptr_4(dst, 0, rc->bottom - 1);
950 src_start = get_pixel_ptr_4(src, 0, origin->y + rc->bottom - rc->top - 1);
951 dst_stride = -dst->stride;
952 src_stride = -src->stride;
956 dst_start = get_pixel_ptr_4(dst, 0, rc->top);
957 src_start = get_pixel_ptr_4(src, 0, origin->y);
958 dst_stride = dst->stride;
959 src_stride = src->stride;
962 if (rop2 == R2_COPYPEN && (rc->left & 1) == 0 && (origin->x & 1) == 0 && (rc->right & 1) == 0)
964 dst_start += rc->left / 2;
965 src_start += origin->x / 2;
966 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
967 memmove( dst_start, src_start, (rc->right - rc->left) / 2 );
971 get_rop_codes( rop2, &codes );
972 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
974 if (overlap & OVERLAP_RIGHT)
975 do_rop_codes_line_rev_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
977 do_rop_codes_line_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
981 static void copy_rect_1(const dib_info *dst, const RECT *rc,
982 const dib_info *src, const POINT *origin, int rop2, int overlap)
984 BYTE *dst_start, *src_start;
985 int y, dst_stride, src_stride;
986 struct rop_codes codes;
988 if (overlap & OVERLAP_BELOW)
990 dst_start = get_pixel_ptr_1(dst, 0, rc->bottom - 1);
991 src_start = get_pixel_ptr_1(src, 0, origin->y + rc->bottom - rc->top - 1);
992 dst_stride = -dst->stride;
993 src_stride = -src->stride;
997 dst_start = get_pixel_ptr_1(dst, 0, rc->top);
998 src_start = get_pixel_ptr_1(src, 0, origin->y);
999 dst_stride = dst->stride;
1000 src_stride = src->stride;
1003 if (rop2 == R2_COPYPEN && (rc->left & 7) == 0 && (origin->x & 7) == 0 && (rc->right & 7) == 0)
1005 dst_start += rc->left / 8;
1006 src_start += origin->x / 8;
1007 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1008 memmove( dst_start, src_start, (rc->right - rc->left) / 8 );
1012 get_rop_codes( rop2, &codes );
1013 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1015 if (overlap & OVERLAP_RIGHT)
1016 do_rop_codes_line_rev_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1018 do_rop_codes_line_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1022 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1023 const dib_info *src, const POINT *origin, int rop2, int overlap)
1028 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1030 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1033 static const DWORD field_masks[33] =
1035 0x00, /* should never happen */
1036 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1037 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1038 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1039 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1042 static inline DWORD get_field(DWORD field, int shift, int len)
1044 shift = shift - (8 - len);
1049 field &= field_masks[len];
1050 field |= field >> len;
1054 static inline DWORD put_field(DWORD field, int shift, int len)
1056 shift = shift - (8 - len);
1057 field &= field_masks[len];
1065 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1069 r = GetRValue(colour);
1070 g = GetGValue(colour);
1071 b = GetBValue(colour);
1073 return put_field(r, dib->red_shift, dib->red_len) |
1074 put_field(g, dib->green_shift, dib->green_len) |
1075 put_field(b, dib->blue_shift, dib->blue_len);
1078 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1080 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1083 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1085 int i, best_index = 0;
1086 DWORD diff, best_diff = 0xffffffff;
1088 /* special case for conversion to 1-bpp without a color table:
1089 * we get a 1-entry table containing the background color
1091 if (dib->bit_count == 1 && dib->color_table_size == 1)
1092 return (r == dib->color_table[0].rgbRed &&
1093 g == dib->color_table[0].rgbGreen &&
1094 b == dib->color_table[0].rgbBlue);
1096 for(i = 0; i < dib->color_table_size; i++)
1098 RGBQUAD *cur = dib->color_table + i;
1099 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1100 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1101 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1109 if(diff < best_diff)
1118 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1120 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1123 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1128 static inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1130 static const RGBQUAD default_rgb;
1131 if (index < dib->color_table_size) return dib->color_table[index];
1135 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1137 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1139 return d1->red_mask == d2->red_mask &&
1140 d1->green_mask == d2->green_mask &&
1141 d1->blue_mask == d2->blue_mask;
1144 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1146 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1147 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1149 switch(src->bit_count)
1153 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1154 if(src->funcs == &funcs_8888)
1156 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1157 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1160 for(y = src_rect->top; y < src_rect->bottom; y++)
1162 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1163 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1164 dst_start += dst->stride / 4;
1165 src_start += src->stride / 4;
1169 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1171 for(y = src_rect->top; y < src_rect->bottom; y++)
1173 dst_pixel = dst_start;
1174 src_pixel = src_start;
1175 for(x = src_rect->left; x < src_rect->right; x++)
1177 src_val = *src_pixel++;
1178 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1179 (((src_val >> src->green_shift) & 0xff) << 8) |
1180 ((src_val >> src->blue_shift) & 0xff);
1182 if(pad_size) memset(dst_pixel, 0, pad_size);
1183 dst_start += dst->stride / 4;
1184 src_start += src->stride / 4;
1189 for(y = src_rect->top; y < src_rect->bottom; y++)
1191 dst_pixel = dst_start;
1192 src_pixel = src_start;
1193 for(x = src_rect->left; x < src_rect->right; x++)
1195 src_val = *src_pixel++;
1196 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1197 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1198 get_field( src_val, src->blue_shift, src->blue_len ));
1200 if(pad_size) memset(dst_pixel, 0, pad_size);
1201 dst_start += dst->stride / 4;
1202 src_start += src->stride / 4;
1210 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1212 for(y = src_rect->top; y < src_rect->bottom; y++)
1214 dst_pixel = dst_start;
1215 src_pixel = src_start;
1216 for(x = src_rect->left; x < src_rect->right; x++)
1219 rgb.rgbBlue = *src_pixel++;
1220 rgb.rgbGreen = *src_pixel++;
1221 rgb.rgbRed = *src_pixel++;
1223 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1225 if(pad_size) memset(dst_pixel, 0, pad_size);
1226 dst_start += dst->stride / 4;
1227 src_start += src->stride;
1234 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1235 if(src->funcs == &funcs_555)
1237 for(y = src_rect->top; y < src_rect->bottom; y++)
1239 dst_pixel = dst_start;
1240 src_pixel = src_start;
1241 for(x = src_rect->left; x < src_rect->right; x++)
1243 src_val = *src_pixel++;
1244 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1245 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1246 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1248 if(pad_size) memset(dst_pixel, 0, pad_size);
1249 dst_start += dst->stride / 4;
1250 src_start += src->stride / 2;
1253 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1255 for(y = src_rect->top; y < src_rect->bottom; y++)
1257 dst_pixel = dst_start;
1258 src_pixel = src_start;
1259 for(x = src_rect->left; x < src_rect->right; x++)
1261 src_val = *src_pixel++;
1262 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1263 (((src_val >> src->red_shift) << 14) & 0x070000) |
1264 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1265 (((src_val >> src->green_shift) << 6) & 0x000700) |
1266 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1267 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1269 if(pad_size) memset(dst_pixel, 0, pad_size);
1270 dst_start += dst->stride / 4;
1271 src_start += src->stride / 2;
1274 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1276 for(y = src_rect->top; y < src_rect->bottom; y++)
1278 dst_pixel = dst_start;
1279 src_pixel = src_start;
1280 for(x = src_rect->left; x < src_rect->right; x++)
1282 src_val = *src_pixel++;
1283 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1284 (((src_val >> src->red_shift) << 14) & 0x070000) |
1285 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1286 (((src_val >> src->green_shift) << 4) & 0x000300) |
1287 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1288 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1290 if(pad_size) memset(dst_pixel, 0, pad_size);
1291 dst_start += dst->stride / 4;
1292 src_start += src->stride / 2;
1297 for(y = src_rect->top; y < src_rect->bottom; y++)
1299 dst_pixel = dst_start;
1300 src_pixel = src_start;
1301 for(x = src_rect->left; x < src_rect->right; x++)
1303 src_val = *src_pixel++;
1304 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1305 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1306 get_field( src_val, src->blue_shift, src->blue_len ));
1308 if(pad_size) memset(dst_pixel, 0, pad_size);
1309 dst_start += dst->stride / 4;
1310 src_start += src->stride / 2;
1318 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1319 for(y = src_rect->top; y < src_rect->bottom; y++)
1321 dst_pixel = dst_start;
1322 src_pixel = src_start;
1323 for(x = src_rect->left; x < src_rect->right; x++)
1325 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1326 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1328 if(pad_size) memset(dst_pixel, 0, pad_size);
1329 dst_start += dst->stride / 4;
1330 src_start += src->stride;
1337 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1338 for(y = src_rect->top; y < src_rect->bottom; y++)
1340 dst_pixel = dst_start;
1341 src_pixel = src_start;
1342 for(x = src_rect->left; x < src_rect->right; x++)
1346 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1348 rgb = colortable_entry( src, *src_pixel >> 4 );
1349 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1351 if(pad_size) memset(dst_pixel, 0, pad_size);
1352 dst_start += dst->stride / 4;
1353 src_start += src->stride;
1360 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1361 for(y = src_rect->top; y < src_rect->bottom; y++)
1363 dst_pixel = dst_start;
1364 src_pixel = src_start;
1365 for(x = src_rect->left; x < src_rect->right; x++)
1368 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1369 if((x % 8) == 7) src_pixel++;
1370 rgb = src->color_table[src_val];
1371 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1373 if(pad_size) memset(dst_pixel, 0, pad_size);
1374 dst_start += dst->stride / 4;
1375 src_start += src->stride;
1382 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1384 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1385 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1387 switch(src->bit_count)
1391 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1393 if(src->funcs == &funcs_8888)
1395 for(y = src_rect->top; y < src_rect->bottom; y++)
1397 dst_pixel = dst_start;
1398 src_pixel = src_start;
1399 for(x = src_rect->left; x < src_rect->right; x++)
1401 src_val = *src_pixel++;
1402 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1403 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1404 put_field(src_val, dst->blue_shift, dst->blue_len);
1406 if(pad_size) memset(dst_pixel, 0, pad_size);
1407 dst_start += dst->stride / 4;
1408 src_start += src->stride / 4;
1411 else if(bit_fields_match(src, dst))
1413 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1414 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1417 for(y = src_rect->top; y < src_rect->bottom; y++)
1419 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1420 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1421 dst_start += dst->stride / 4;
1422 src_start += src->stride / 4;
1426 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1427 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1429 for(y = src_rect->top; y < src_rect->bottom; y++)
1431 dst_pixel = dst_start;
1432 src_pixel = src_start;
1433 for(x = src_rect->left; x < src_rect->right; x++)
1435 src_val = *src_pixel++;
1436 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1437 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1438 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1440 if(pad_size) memset(dst_pixel, 0, pad_size);
1441 dst_start += dst->stride / 4;
1442 src_start += src->stride / 4;
1447 for(y = src_rect->top; y < src_rect->bottom; y++)
1449 dst_pixel = dst_start;
1450 src_pixel = src_start;
1451 for(x = src_rect->left; x < src_rect->right; x++)
1453 src_val = *src_pixel++;
1454 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1455 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1456 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1458 if(pad_size) memset(dst_pixel, 0, pad_size);
1459 dst_start += dst->stride / 4;
1460 src_start += src->stride / 4;
1468 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1470 for(y = src_rect->top; y < src_rect->bottom; y++)
1472 dst_pixel = dst_start;
1473 src_pixel = src_start;
1474 for(x = src_rect->left; x < src_rect->right; x++)
1477 rgb.rgbBlue = *src_pixel++;
1478 rgb.rgbGreen = *src_pixel++;
1479 rgb.rgbRed = *src_pixel++;
1481 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1482 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1483 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1485 if(pad_size) memset(dst_pixel, 0, pad_size);
1486 dst_start += dst->stride / 4;
1487 src_start += src->stride;
1494 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1495 if(src->funcs == &funcs_555)
1497 for(y = src_rect->top; y < src_rect->bottom; y++)
1499 dst_pixel = dst_start;
1500 src_pixel = src_start;
1501 for(x = src_rect->left; x < src_rect->right; x++)
1503 src_val = *src_pixel++;
1504 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1505 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1506 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1508 if(pad_size) memset(dst_pixel, 0, pad_size);
1509 dst_start += dst->stride / 4;
1510 src_start += src->stride / 2;
1513 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1515 for(y = src_rect->top; y < src_rect->bottom; y++)
1517 dst_pixel = dst_start;
1518 src_pixel = src_start;
1519 for(x = src_rect->left; x < src_rect->right; x++)
1521 src_val = *src_pixel++;
1522 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1523 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1524 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1525 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1526 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1527 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1529 if(pad_size) memset(dst_pixel, 0, pad_size);
1530 dst_start += dst->stride / 4;
1531 src_start += src->stride / 2;
1534 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1536 for(y = src_rect->top; y < src_rect->bottom; y++)
1538 dst_pixel = dst_start;
1539 src_pixel = src_start;
1540 for(x = src_rect->left; x < src_rect->right; x++)
1542 src_val = *src_pixel++;
1543 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1544 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1545 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1546 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1547 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1548 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1550 if(pad_size) memset(dst_pixel, 0, pad_size);
1551 dst_start += dst->stride / 4;
1552 src_start += src->stride / 2;
1557 for(y = src_rect->top; y < src_rect->bottom; y++)
1559 dst_pixel = dst_start;
1560 src_pixel = src_start;
1561 for(x = src_rect->left; x < src_rect->right; x++)
1563 src_val = *src_pixel++;
1564 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1565 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1566 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1568 if(pad_size) memset(dst_pixel, 0, pad_size);
1569 dst_start += dst->stride / 4;
1570 src_start += src->stride / 2;
1578 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1579 for(y = src_rect->top; y < src_rect->bottom; y++)
1581 dst_pixel = dst_start;
1582 src_pixel = src_start;
1583 for(x = src_rect->left; x < src_rect->right; x++)
1585 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1586 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1587 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1588 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1590 if(pad_size) memset(dst_pixel, 0, pad_size);
1591 dst_start += dst->stride / 4;
1592 src_start += src->stride;
1599 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1600 for(y = src_rect->top; y < src_rect->bottom; y++)
1602 dst_pixel = dst_start;
1603 src_pixel = src_start;
1604 for(x = src_rect->left; x < src_rect->right; x++)
1608 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1610 rgb = colortable_entry( src, *src_pixel >> 4 );
1611 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1612 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1613 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1615 if(pad_size) memset(dst_pixel, 0, pad_size);
1616 dst_start += dst->stride / 4;
1617 src_start += src->stride;
1624 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1625 for(y = src_rect->top; y < src_rect->bottom; y++)
1627 dst_pixel = dst_start;
1628 src_pixel = src_start;
1629 for(x = src_rect->left; x < src_rect->right; x++)
1632 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1633 if((x % 8) == 7) src_pixel++;
1634 rgb = src->color_table[src_val];
1635 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1636 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1637 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1639 if(pad_size) memset(dst_pixel, 0, pad_size);
1640 dst_start += dst->stride / 4;
1641 src_start += src->stride;
1648 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1650 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1652 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1654 switch(src->bit_count)
1658 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1659 if(src->funcs == &funcs_8888)
1661 for(y = src_rect->top; y < src_rect->bottom; y++)
1663 dst_pixel = dst_start;
1664 src_pixel = src_start;
1665 for(x = src_rect->left; x < src_rect->right; x++)
1667 src_val = *src_pixel++;
1668 *dst_pixel++ = src_val & 0xff;
1669 *dst_pixel++ = (src_val >> 8) & 0xff;
1670 *dst_pixel++ = (src_val >> 16) & 0xff;
1672 if(pad_size) memset(dst_pixel, 0, pad_size);
1673 dst_start += dst->stride;
1674 src_start += src->stride / 4;
1677 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1679 for(y = src_rect->top; y < src_rect->bottom; y++)
1681 dst_pixel = dst_start;
1682 src_pixel = src_start;
1683 for(x = src_rect->left; x < src_rect->right; x++)
1685 src_val = *src_pixel++;
1686 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
1687 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1688 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
1690 if(pad_size) memset(dst_pixel, 0, pad_size);
1691 dst_start += dst->stride;
1692 src_start += src->stride / 4;
1697 for(y = src_rect->top; y < src_rect->bottom; y++)
1699 dst_pixel = dst_start;
1700 src_pixel = src_start;
1701 for(x = src_rect->left; x < src_rect->right; x++)
1703 src_val = *src_pixel++;
1704 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
1705 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
1706 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
1708 if(pad_size) memset(dst_pixel, 0, pad_size);
1709 dst_start += dst->stride;
1710 src_start += src->stride / 4;
1718 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1720 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1721 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1724 for(y = src_rect->top; y < src_rect->bottom; y++)
1726 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1727 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1728 dst_start += dst->stride;
1729 src_start += src->stride;
1737 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1738 if(src->funcs == &funcs_555)
1740 for(y = src_rect->top; y < src_rect->bottom; y++)
1742 dst_pixel = dst_start;
1743 src_pixel = src_start;
1744 for(x = src_rect->left; x < src_rect->right; x++)
1746 src_val = *src_pixel++;
1747 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
1748 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
1749 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1751 if(pad_size) memset(dst_pixel, 0, pad_size);
1752 dst_start += dst->stride;
1753 src_start += src->stride / 2;
1756 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1758 for(y = src_rect->top; y < src_rect->bottom; y++)
1760 dst_pixel = dst_start;
1761 src_pixel = src_start;
1762 for(x = src_rect->left; x < src_rect->right; x++)
1764 src_val = *src_pixel++;
1765 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1766 (((src_val >> src->blue_shift) >> 2) & 0x07);
1767 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1768 (((src_val >> src->green_shift) >> 2) & 0x07);
1769 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1770 (((src_val >> src->red_shift) >> 2) & 0x07);
1772 if(pad_size) memset(dst_pixel, 0, pad_size);
1773 dst_start += dst->stride;
1774 src_start += src->stride / 2;
1777 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1779 for(y = src_rect->top; y < src_rect->bottom; y++)
1781 dst_pixel = dst_start;
1782 src_pixel = src_start;
1783 for(x = src_rect->left; x < src_rect->right; x++)
1785 src_val = *src_pixel++;
1786 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1787 (((src_val >> src->blue_shift) >> 2) & 0x07);
1788 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1789 (((src_val >> src->green_shift) >> 4) & 0x03);
1790 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1791 (((src_val >> src->red_shift) >> 2) & 0x07);
1793 if(pad_size) memset(dst_pixel, 0, pad_size);
1794 dst_start += dst->stride;
1795 src_start += src->stride / 2;
1800 for(y = src_rect->top; y < src_rect->bottom; y++)
1802 dst_pixel = dst_start;
1803 src_pixel = src_start;
1804 for(x = src_rect->left; x < src_rect->right; x++)
1806 src_val = *src_pixel++;
1807 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
1808 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
1809 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
1811 if(pad_size) memset(dst_pixel, 0, pad_size);
1812 dst_start += dst->stride;
1813 src_start += src->stride / 2;
1821 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1822 for(y = src_rect->top; y < src_rect->bottom; y++)
1824 dst_pixel = dst_start;
1825 src_pixel = src_start;
1826 for(x = src_rect->left; x < src_rect->right; x++)
1828 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1829 *dst_pixel++ = rgb.rgbBlue;
1830 *dst_pixel++ = rgb.rgbGreen;
1831 *dst_pixel++ = rgb.rgbRed;
1833 if(pad_size) memset(dst_pixel, 0, pad_size);
1834 dst_start += dst->stride;
1835 src_start += src->stride;
1842 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1843 for(y = src_rect->top; y < src_rect->bottom; y++)
1845 dst_pixel = dst_start;
1846 src_pixel = src_start;
1847 for(x = src_rect->left; x < src_rect->right; x++)
1851 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1853 rgb = colortable_entry( src, *src_pixel >> 4 );
1854 *dst_pixel++ = rgb.rgbBlue;
1855 *dst_pixel++ = rgb.rgbGreen;
1856 *dst_pixel++ = rgb.rgbRed;
1858 if(pad_size) memset(dst_pixel, 0, pad_size);
1859 dst_start += dst->stride;
1860 src_start += src->stride;
1867 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1868 for(y = src_rect->top; y < src_rect->bottom; y++)
1870 dst_pixel = dst_start;
1871 src_pixel = src_start;
1872 for(x = src_rect->left; x < src_rect->right; x++)
1875 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1876 if((x % 8) == 7) src_pixel++;
1877 rgb = src->color_table[src_val];
1878 *dst_pixel++ = rgb.rgbBlue;
1879 *dst_pixel++ = rgb.rgbGreen;
1880 *dst_pixel++ = rgb.rgbRed;
1882 if(pad_size) memset(dst_pixel, 0, pad_size);
1883 dst_start += dst->stride;
1884 src_start += src->stride;
1891 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1893 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
1894 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1897 switch(src->bit_count)
1901 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1903 if(src->funcs == &funcs_8888)
1905 for(y = src_rect->top; y < src_rect->bottom; y++)
1907 dst_pixel = dst_start;
1908 src_pixel = src_start;
1909 for(x = src_rect->left; x < src_rect->right; x++)
1911 src_val = *src_pixel++;
1912 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1913 ((src_val >> 6) & 0x03e0) |
1914 ((src_val >> 3) & 0x001f);
1916 if(pad_size) memset(dst_pixel, 0, pad_size);
1917 dst_start += dst->stride / 2;
1918 src_start += src->stride / 4;
1921 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1923 for(y = src_rect->top; y < src_rect->bottom; y++)
1925 dst_pixel = dst_start;
1926 src_pixel = src_start;
1927 for(x = src_rect->left; x < src_rect->right; x++)
1929 src_val = *src_pixel++;
1930 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
1931 (((src_val >> src->green_shift) << 2) & 0x03e0) |
1932 (((src_val >> src->blue_shift) >> 3) & 0x001f);
1934 if(pad_size) memset(dst_pixel, 0, pad_size);
1935 dst_start += dst->stride / 2;
1936 src_start += src->stride / 4;
1941 for(y = src_rect->top; y < src_rect->bottom; y++)
1943 dst_pixel = dst_start;
1944 src_pixel = src_start;
1945 for(x = src_rect->left; x < src_rect->right; x++)
1947 src_val = *src_pixel++;
1948 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
1949 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
1950 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
1952 if(pad_size) memset(dst_pixel, 0, pad_size);
1953 dst_start += dst->stride / 2;
1954 src_start += src->stride / 4;
1962 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1964 for(y = src_rect->top; y < src_rect->bottom; y++)
1966 dst_pixel = dst_start;
1967 src_pixel = src_start;
1968 for(x = src_rect->left; x < src_rect->right; x++)
1971 rgb.rgbBlue = *src_pixel++;
1972 rgb.rgbGreen = *src_pixel++;
1973 rgb.rgbRed = *src_pixel++;
1975 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1976 ((rgb.rgbGreen << 2) & 0x03e0) |
1977 ((rgb.rgbBlue >> 3) & 0x001f);
1979 if(pad_size) memset(dst_pixel, 0, pad_size);
1980 dst_start += dst->stride / 2;
1981 src_start += src->stride;
1988 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1989 if(src->funcs == &funcs_555)
1991 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1992 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1995 for(y = src_rect->top; y < src_rect->bottom; y++)
1997 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1998 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1999 dst_start += dst->stride / 2;
2000 src_start += src->stride / 2;
2004 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2006 for(y = src_rect->top; y < src_rect->bottom; y++)
2008 dst_pixel = dst_start;
2009 src_pixel = src_start;
2010 for(x = src_rect->left; x < src_rect->right; x++)
2012 src_val = *src_pixel++;
2013 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2014 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2015 ( (src_val >> src->blue_shift) & 0x001f);
2017 if(pad_size) memset(dst_pixel, 0, pad_size);
2018 dst_start += dst->stride / 2;
2019 src_start += src->stride / 2;
2022 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2024 for(y = src_rect->top; y < src_rect->bottom; y++)
2026 dst_pixel = dst_start;
2027 src_pixel = src_start;
2028 for(x = src_rect->left; x < src_rect->right; x++)
2030 src_val = *src_pixel++;
2031 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2032 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2033 ( (src_val >> src->blue_shift) & 0x001f);
2035 if(pad_size) memset(dst_pixel, 0, pad_size);
2036 dst_start += dst->stride / 2;
2037 src_start += src->stride / 2;
2042 for(y = src_rect->top; y < src_rect->bottom; y++)
2044 dst_pixel = dst_start;
2045 src_pixel = src_start;
2046 for(x = src_rect->left; x < src_rect->right; x++)
2048 src_val = *src_pixel++;
2049 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2050 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2051 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2053 if(pad_size) memset(dst_pixel, 0, pad_size);
2054 dst_start += dst->stride / 2;
2055 src_start += src->stride / 2;
2063 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2064 for(y = src_rect->top; y < src_rect->bottom; y++)
2066 dst_pixel = dst_start;
2067 src_pixel = src_start;
2068 for(x = src_rect->left; x < src_rect->right; x++)
2070 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2071 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2072 ((rgb.rgbGreen << 2) & 0x03e0) |
2073 ((rgb.rgbBlue >> 3) & 0x001f);
2075 if(pad_size) memset(dst_pixel, 0, pad_size);
2076 dst_start += dst->stride / 2;
2077 src_start += src->stride;
2084 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2085 for(y = src_rect->top; y < src_rect->bottom; y++)
2087 dst_pixel = dst_start;
2088 src_pixel = src_start;
2089 for(x = src_rect->left; x < src_rect->right; x++)
2093 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2095 rgb = colortable_entry( src, *src_pixel >> 4 );
2096 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2097 ((rgb.rgbGreen << 2) & 0x03e0) |
2098 ((rgb.rgbBlue >> 3) & 0x001f);
2100 if(pad_size) memset(dst_pixel, 0, pad_size);
2101 dst_start += dst->stride / 2;
2102 src_start += src->stride;
2109 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2110 for(y = src_rect->top; y < src_rect->bottom; y++)
2112 dst_pixel = dst_start;
2113 src_pixel = src_start;
2114 for(x = src_rect->left; x < src_rect->right; x++)
2117 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2118 if((x % 8) == 7) src_pixel++;
2119 rgb = src->color_table[src_val];
2120 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2121 ((rgb.rgbGreen << 2) & 0x03e0) |
2122 ((rgb.rgbBlue >> 3) & 0x001f);
2124 if(pad_size) memset(dst_pixel, 0, pad_size);
2125 dst_start += dst->stride / 2;
2126 src_start += src->stride;
2133 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2135 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2136 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2139 switch(src->bit_count)
2143 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2145 if(src->funcs == &funcs_8888)
2147 for(y = src_rect->top; y < src_rect->bottom; y++)
2149 dst_pixel = dst_start;
2150 src_pixel = src_start;
2151 for(x = src_rect->left; x < src_rect->right; x++)
2153 src_val = *src_pixel++;
2154 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2155 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2156 put_field(src_val, dst->blue_shift, dst->blue_len);
2158 if(pad_size) memset(dst_pixel, 0, pad_size);
2159 dst_start += dst->stride / 2;
2160 src_start += src->stride / 4;
2163 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2165 for(y = src_rect->top; y < src_rect->bottom; y++)
2167 dst_pixel = dst_start;
2168 src_pixel = src_start;
2169 for(x = src_rect->left; x < src_rect->right; x++)
2171 src_val = *src_pixel++;
2172 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2173 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2174 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2176 if(pad_size) memset(dst_pixel, 0, pad_size);
2177 dst_start += dst->stride / 2;
2178 src_start += src->stride / 4;
2183 for(y = src_rect->top; y < src_rect->bottom; y++)
2185 dst_pixel = dst_start;
2186 src_pixel = src_start;
2187 for(x = src_rect->left; x < src_rect->right; x++)
2189 src_val = *src_pixel++;
2190 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2191 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2192 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2194 if(pad_size) memset(dst_pixel, 0, pad_size);
2195 dst_start += dst->stride / 2;
2196 src_start += src->stride / 4;
2204 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2206 for(y = src_rect->top; y < src_rect->bottom; y++)
2208 dst_pixel = dst_start;
2209 src_pixel = src_start;
2210 for(x = src_rect->left; x < src_rect->right; x++)
2213 rgb.rgbBlue = *src_pixel++;
2214 rgb.rgbGreen = *src_pixel++;
2215 rgb.rgbRed = *src_pixel++;
2217 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2218 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2219 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2221 if(pad_size) memset(dst_pixel, 0, pad_size);
2222 dst_start += dst->stride / 2;
2223 src_start += src->stride;
2230 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2231 if(src->funcs == &funcs_555)
2233 for(y = src_rect->top; y < src_rect->bottom; y++)
2235 dst_pixel = dst_start;
2236 src_pixel = src_start;
2237 for(x = src_rect->left; x < src_rect->right; x++)
2239 src_val = *src_pixel++;
2240 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2241 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2242 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2244 if(pad_size) memset(dst_pixel, 0, pad_size);
2245 dst_start += dst->stride / 2;
2246 src_start += src->stride / 2;
2249 else if(bit_fields_match(src, dst))
2251 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2252 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2255 for(y = src_rect->top; y < src_rect->bottom; y++)
2257 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2258 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2259 dst_start += dst->stride / 2;
2260 src_start += src->stride / 2;
2264 else if(src->red_len == 5 && src->green_len == 5 && 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) << 3) & 0xf8) |
2276 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2277 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2278 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2280 if(pad_size) memset(dst_pixel, 0, pad_size);
2281 dst_start += dst->stride / 2;
2282 src_start += src->stride / 2;
2285 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2287 for(y = src_rect->top; y < src_rect->bottom; y++)
2289 dst_pixel = dst_start;
2290 src_pixel = src_start;
2291 for(x = src_rect->left; x < src_rect->right; x++)
2293 src_val = *src_pixel++;
2294 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2295 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2296 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2297 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2298 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2299 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2301 if(pad_size) memset(dst_pixel, 0, pad_size);
2302 dst_start += dst->stride / 2;
2303 src_start += src->stride / 2;
2308 for(y = src_rect->top; y < src_rect->bottom; y++)
2310 dst_pixel = dst_start;
2311 src_pixel = src_start;
2312 for(x = src_rect->left; x < src_rect->right; x++)
2314 src_val = *src_pixel++;
2315 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2316 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2317 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2319 if(pad_size) memset(dst_pixel, 0, pad_size);
2320 dst_start += dst->stride / 2;
2321 src_start += src->stride / 2;
2329 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2330 for(y = src_rect->top; y < src_rect->bottom; y++)
2332 dst_pixel = dst_start;
2333 src_pixel = src_start;
2334 for(x = src_rect->left; x < src_rect->right; x++)
2336 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2337 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2338 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2339 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2341 if(pad_size) memset(dst_pixel, 0, pad_size);
2342 dst_start += dst->stride / 2;
2343 src_start += src->stride;
2350 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2351 for(y = src_rect->top; y < src_rect->bottom; y++)
2353 dst_pixel = dst_start;
2354 src_pixel = src_start;
2355 for(x = src_rect->left; x < src_rect->right; x++)
2359 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2361 rgb = colortable_entry( src, *src_pixel >> 4 );
2362 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2363 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2364 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2366 if(pad_size) memset(dst_pixel, 0, pad_size);
2367 dst_start += dst->stride / 2;
2368 src_start += src->stride;
2375 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2376 for(y = src_rect->top; y < src_rect->bottom; y++)
2378 dst_pixel = dst_start;
2379 src_pixel = src_start;
2380 for(x = src_rect->left; x < src_rect->right; x++)
2383 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2384 if((x % 8) == 7) src_pixel++;
2385 rgb = src->color_table[src_val];
2386 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2387 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2388 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2390 if(pad_size) memset(dst_pixel, 0, pad_size);
2391 dst_start += dst->stride / 2;
2392 src_start += src->stride;
2399 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2401 assert(d1->color_table_size && d2->color_table_size);
2403 if(d1->color_table_size != d2->color_table_size) return FALSE;
2404 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2407 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2409 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2410 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2413 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2415 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2416 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2419 switch(src->bit_count)
2423 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2425 if(src->funcs == &funcs_8888)
2427 for(y = src_rect->top; y < src_rect->bottom; y++)
2429 dst_pixel = dst_start;
2430 src_pixel = src_start;
2431 for(x = src_rect->left; x < src_rect->right; x++)
2433 src_val = *src_pixel++;
2434 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2436 if(pad_size) memset(dst_pixel, 0, pad_size);
2437 dst_start += dst->stride;
2438 src_start += src->stride / 4;
2441 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2443 for(y = src_rect->top; y < src_rect->bottom; y++)
2445 dst_pixel = dst_start;
2446 src_pixel = src_start;
2447 for(x = src_rect->left; x < src_rect->right; x++)
2449 src_val = *src_pixel++;
2450 *dst_pixel++ = rgb_lookup_colortable(dst,
2451 src_val >> src->red_shift,
2452 src_val >> src->green_shift,
2453 src_val >> src->blue_shift );
2455 if(pad_size) memset(dst_pixel, 0, pad_size);
2456 dst_start += dst->stride;
2457 src_start += src->stride / 4;
2462 for(y = src_rect->top; y < src_rect->bottom; y++)
2464 dst_pixel = dst_start;
2465 src_pixel = src_start;
2466 for(x = src_rect->left; x < src_rect->right; x++)
2468 src_val = *src_pixel++;
2469 *dst_pixel++ = rgb_lookup_colortable(dst,
2470 get_field(src_val, src->red_shift, src->red_len),
2471 get_field(src_val, src->green_shift, src->green_len),
2472 get_field(src_val, src->blue_shift, src->blue_len));
2474 if(pad_size) memset(dst_pixel, 0, pad_size);
2475 dst_start += dst->stride;
2476 src_start += src->stride / 4;
2484 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2486 for(y = src_rect->top; y < src_rect->bottom; y++)
2488 dst_pixel = dst_start;
2489 src_pixel = src_start;
2490 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2492 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2494 if(pad_size) memset(dst_pixel, 0, pad_size);
2495 dst_start += dst->stride;
2496 src_start += src->stride;
2503 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2504 if(src->funcs == &funcs_555)
2506 for(y = src_rect->top; y < src_rect->bottom; y++)
2508 dst_pixel = dst_start;
2509 src_pixel = src_start;
2510 for(x = src_rect->left; x < src_rect->right; x++)
2512 src_val = *src_pixel++;
2513 *dst_pixel++ = rgb_lookup_colortable(dst,
2514 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2515 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2516 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2518 if(pad_size) memset(dst_pixel, 0, pad_size);
2519 dst_start += dst->stride;
2520 src_start += src->stride / 2;
2523 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2525 for(y = src_rect->top; y < src_rect->bottom; y++)
2527 dst_pixel = dst_start;
2528 src_pixel = src_start;
2529 for(x = src_rect->left; x < src_rect->right; x++)
2531 src_val = *src_pixel++;
2532 *dst_pixel++ = rgb_lookup_colortable(dst,
2533 (((src_val >> src->red_shift) << 3) & 0xf8) |
2534 (((src_val >> src->red_shift) >> 2) & 0x07),
2535 (((src_val >> src->green_shift) << 3) & 0xf8) |
2536 (((src_val >> src->green_shift) >> 2) & 0x07),
2537 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2538 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2540 if(pad_size) memset(dst_pixel, 0, pad_size);
2541 dst_start += dst->stride;
2542 src_start += src->stride / 2;
2545 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2547 for(y = src_rect->top; y < src_rect->bottom; y++)
2549 dst_pixel = dst_start;
2550 src_pixel = src_start;
2551 for(x = src_rect->left; x < src_rect->right; x++)
2553 src_val = *src_pixel++;
2554 *dst_pixel++ = rgb_lookup_colortable(dst,
2555 (((src_val >> src->red_shift) << 3) & 0xf8) |
2556 (((src_val >> src->red_shift) >> 2) & 0x07),
2557 (((src_val >> src->green_shift) << 2) & 0xfc) |
2558 (((src_val >> src->green_shift) >> 4) & 0x03),
2559 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2560 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2562 if(pad_size) memset(dst_pixel, 0, pad_size);
2563 dst_start += dst->stride;
2564 src_start += src->stride / 2;
2569 for(y = src_rect->top; y < src_rect->bottom; y++)
2571 dst_pixel = dst_start;
2572 src_pixel = src_start;
2573 for(x = src_rect->left; x < src_rect->right; x++)
2575 src_val = *src_pixel++;
2576 *dst_pixel++ = rgb_lookup_colortable(dst,
2577 get_field(src_val, src->red_shift, src->red_len),
2578 get_field(src_val, src->green_shift, src->green_len),
2579 get_field(src_val, src->blue_shift, src->blue_len));
2581 if(pad_size) memset(dst_pixel, 0, pad_size);
2582 dst_start += dst->stride;
2583 src_start += src->stride / 2;
2591 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2593 if(color_tables_match(dst, src))
2595 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2596 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2599 for(y = src_rect->top; y < src_rect->bottom; y++)
2601 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2602 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2603 dst_start += dst->stride;
2604 src_start += src->stride;
2610 for(y = src_rect->top; y < src_rect->bottom; y++)
2612 dst_pixel = dst_start;
2613 src_pixel = src_start;
2614 for(x = src_rect->left; x < src_rect->right; x++)
2616 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2617 *dst_pixel++ = rgb_to_pixel_colortable(dst, 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;
2629 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2630 for(y = src_rect->top; y < src_rect->bottom; y++)
2632 dst_pixel = dst_start;
2633 src_pixel = src_start;
2634 for(x = src_rect->left; x < src_rect->right; x++)
2638 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2640 rgb = colortable_entry( src, *src_pixel >> 4 );
2641 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2643 if(pad_size) memset(dst_pixel, 0, pad_size);
2644 dst_start += dst->stride;
2645 src_start += src->stride;
2652 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2653 for(y = src_rect->top; y < src_rect->bottom; y++)
2655 dst_pixel = dst_start;
2656 src_pixel = src_start;
2657 for(x = src_rect->left; x < src_rect->right; x++)
2660 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2661 if((x % 8) == 7) src_pixel++;
2662 rgb = src->color_table[src_val];
2663 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2665 if(pad_size) memset(dst_pixel, 0, pad_size);
2666 dst_start += dst->stride;
2667 src_start += src->stride;
2674 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2676 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2677 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2680 switch(src->bit_count)
2684 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2686 if(src->funcs == &funcs_8888)
2688 for(y = src_rect->top; y < src_rect->bottom; y++)
2690 dst_pixel = dst_start;
2691 src_pixel = src_start;
2692 for(x = src_rect->left; x < src_rect->right; x++)
2694 src_val = *src_pixel++;
2695 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
2696 if((x - src_rect->left) & 1)
2698 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2702 *dst_pixel = (dst_val << 4) & 0xf0;
2706 if((x - src_rect->left) & 1) dst_pixel++;
2707 memset(dst_pixel, 0, pad_size);
2709 dst_start += dst->stride;
2710 src_start += src->stride / 4;
2713 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2715 for(y = src_rect->top; y < src_rect->bottom; y++)
2717 dst_pixel = dst_start;
2718 src_pixel = src_start;
2719 for(x = src_rect->left; x < src_rect->right; x++)
2721 src_val = *src_pixel++;
2722 dst_val = rgb_to_pixel_colortable(dst,
2723 src_val >> src->red_shift,
2724 src_val >> src->green_shift,
2725 src_val >> src->blue_shift);
2726 if((x - src_rect->left) & 1)
2728 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2732 *dst_pixel = (dst_val << 4) & 0xf0;
2736 if((x - src_rect->left) & 1) dst_pixel++;
2737 memset(dst_pixel, 0, pad_size);
2739 dst_start += dst->stride;
2740 src_start += src->stride / 4;
2745 for(y = src_rect->top; y < src_rect->bottom; y++)
2747 dst_pixel = dst_start;
2748 src_pixel = src_start;
2749 for(x = src_rect->left; x < src_rect->right; x++)
2751 src_val = *src_pixel++;
2752 dst_val = rgb_to_pixel_colortable(dst,
2753 get_field(src_val, src->red_shift, src->red_len),
2754 get_field(src_val, src->green_shift, src->green_len),
2755 get_field(src_val, src->blue_shift, src->blue_len));
2756 if((x - src_rect->left) & 1)
2758 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2762 *dst_pixel = (dst_val << 4) & 0xf0;
2766 if((x - src_rect->left) & 1) dst_pixel++;
2767 memset(dst_pixel, 0, pad_size);
2769 dst_start += dst->stride;
2770 src_start += src->stride / 4;
2778 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2780 for(y = src_rect->top; y < src_rect->bottom; y++)
2782 dst_pixel = dst_start;
2783 src_pixel = src_start;
2784 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2786 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2788 if((x - src_rect->left) & 1)
2790 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2794 *dst_pixel = (dst_val << 4) & 0xf0;
2798 if((x - src_rect->left) & 1) dst_pixel++;
2799 memset(dst_pixel, 0, pad_size);
2801 dst_start += dst->stride;
2802 src_start += src->stride;
2809 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2810 if(src->funcs == &funcs_555)
2812 for(y = src_rect->top; y < src_rect->bottom; y++)
2814 dst_pixel = dst_start;
2815 src_pixel = src_start;
2816 for(x = src_rect->left; x < src_rect->right; x++)
2818 src_val = *src_pixel++;
2819 dst_val = rgb_to_pixel_colortable(dst,
2820 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2821 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2822 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2823 if((x - src_rect->left) & 1)
2825 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2829 *dst_pixel = (dst_val << 4) & 0xf0;
2833 if((x - src_rect->left) & 1) dst_pixel++;
2834 memset(dst_pixel, 0, pad_size);
2836 dst_start += dst->stride;
2837 src_start += src->stride / 2;
2840 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2842 for(y = src_rect->top; y < src_rect->bottom; y++)
2844 dst_pixel = dst_start;
2845 src_pixel = src_start;
2846 for(x = src_rect->left; x < src_rect->right; x++)
2848 src_val = *src_pixel++;
2849 dst_val = rgb_to_pixel_colortable(dst,
2850 (((src_val >> src->red_shift) << 3) & 0xf8) |
2851 (((src_val >> src->red_shift) >> 2) & 0x07),
2852 (((src_val >> src->green_shift) << 3) & 0xf8) |
2853 (((src_val >> src->green_shift) >> 2) & 0x07),
2854 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2855 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2856 if((x - src_rect->left) & 1)
2858 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2862 *dst_pixel = (dst_val << 4) & 0xf0;
2866 if((x - src_rect->left) & 1) dst_pixel++;
2867 memset(dst_pixel, 0, pad_size);
2869 dst_start += dst->stride;
2870 src_start += src->stride / 2;
2873 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2875 for(y = src_rect->top; y < src_rect->bottom; y++)
2877 dst_pixel = dst_start;
2878 src_pixel = src_start;
2879 for(x = src_rect->left; x < src_rect->right; x++)
2881 src_val = *src_pixel++;
2882 dst_val = rgb_to_pixel_colortable(dst,
2883 (((src_val >> src->red_shift) << 3) & 0xf8) |
2884 (((src_val >> src->red_shift) >> 2) & 0x07),
2885 (((src_val >> src->green_shift) << 2) & 0xfc) |
2886 (((src_val >> src->green_shift) >> 4) & 0x03),
2887 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2888 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2889 if((x - src_rect->left) & 1)
2891 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2895 *dst_pixel = (dst_val << 4) & 0xf0;
2899 if((x - src_rect->left) & 1) dst_pixel++;
2900 memset(dst_pixel, 0, pad_size);
2902 dst_start += dst->stride;
2903 src_start += src->stride / 2;
2908 for(y = src_rect->top; y < src_rect->bottom; y++)
2910 dst_pixel = dst_start;
2911 src_pixel = src_start;
2912 for(x = src_rect->left; x < src_rect->right; x++)
2914 src_val = *src_pixel++;
2915 dst_val = rgb_to_pixel_colortable(dst,
2916 get_field(src_val, src->red_shift, src->red_len),
2917 get_field(src_val, src->green_shift, src->green_len),
2918 get_field(src_val, src->blue_shift, src->blue_len));
2919 if((x - src_rect->left) & 1)
2921 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2925 *dst_pixel = (dst_val << 4) & 0xf0;
2929 if((x - src_rect->left) & 1) dst_pixel++;
2930 memset(dst_pixel, 0, pad_size);
2932 dst_start += dst->stride;
2933 src_start += src->stride / 2;
2941 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2943 for(y = src_rect->top; y < src_rect->bottom; y++)
2945 dst_pixel = dst_start;
2946 src_pixel = src_start;
2947 for(x = src_rect->left; x < src_rect->right; x++)
2949 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2950 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2951 if((x - src_rect->left) & 1)
2953 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2957 *dst_pixel = (dst_val << 4) & 0xf0;
2961 if((x - src_rect->left) & 1) dst_pixel++;
2962 memset(dst_pixel, 0, pad_size);
2964 dst_start += dst->stride;
2965 src_start += src->stride;
2972 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2974 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
2976 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2977 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2980 for(y = src_rect->top; y < src_rect->bottom; y++)
2982 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
2983 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
2984 dst_start += dst->stride;
2985 src_start += src->stride;
2991 for(y = src_rect->top; y < src_rect->bottom; y++)
2993 dst_pixel = dst_start;
2994 src_pixel = src_start;
2995 for(x = src_rect->left; x < src_rect->right; x++)
2999 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3001 rgb = colortable_entry( src, *src_pixel >> 4 );
3002 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3003 if((x - src_rect->left) & 1)
3005 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3009 *dst_pixel = (dst_val << 4) & 0xf0;
3013 if((x - src_rect->left) & 1) dst_pixel++;
3014 memset(dst_pixel, 0, pad_size);
3016 dst_start += dst->stride;
3017 src_start += src->stride;
3025 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3026 for(y = src_rect->top; y < src_rect->bottom; y++)
3028 dst_pixel = dst_start;
3029 src_pixel = src_start;
3030 for(x = src_rect->left; x < src_rect->right; x++)
3033 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3034 if((x % 8) == 7) src_pixel++;
3035 rgb = src->color_table[src_val];
3036 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3037 if((x - src_rect->left) & 1)
3039 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3043 *dst_pixel = (dst_val << 4) & 0xf0;
3047 if((x - src_rect->left) & 1) dst_pixel++;
3048 memset(dst_pixel, 0, pad_size);
3050 dst_start += dst->stride;
3051 src_start += src->stride;
3058 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3060 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3061 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3065 /* FIXME: Brushes should be dithered. */
3067 switch(src->bit_count)
3071 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3073 if(src->funcs == &funcs_8888)
3075 for(y = src_rect->top; y < src_rect->bottom; y++)
3077 dst_pixel = dst_start;
3078 src_pixel = src_start;
3079 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3081 src_val = *src_pixel++;
3082 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3084 if(bit_pos == 0) *dst_pixel = 0;
3085 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3095 if(bit_pos != 0) dst_pixel++;
3096 memset(dst_pixel, 0, pad_size);
3098 dst_start += dst->stride;
3099 src_start += src->stride / 4;
3102 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3104 for(y = src_rect->top; y < src_rect->bottom; y++)
3106 dst_pixel = dst_start;
3107 src_pixel = src_start;
3108 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3110 src_val = *src_pixel++;
3111 dst_val = rgb_to_pixel_colortable(dst,
3112 src_val >> src->red_shift,
3113 src_val >> src->green_shift,
3114 src_val >> src->blue_shift) ? 0xff : 0;
3116 if(bit_pos == 0) *dst_pixel = 0;
3117 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3127 if(bit_pos != 0) dst_pixel++;
3128 memset(dst_pixel, 0, pad_size);
3130 dst_start += dst->stride;
3131 src_start += src->stride / 4;
3136 for(y = src_rect->top; y < src_rect->bottom; y++)
3138 dst_pixel = dst_start;
3139 src_pixel = src_start;
3140 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3142 src_val = *src_pixel++;
3143 dst_val = rgb_to_pixel_colortable(dst,
3144 get_field(src_val, src->red_shift, src->red_len),
3145 get_field(src_val, src->green_shift, src->green_len),
3146 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3148 if(bit_pos == 0) *dst_pixel = 0;
3149 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3159 if(bit_pos != 0) dst_pixel++;
3160 memset(dst_pixel, 0, pad_size);
3162 dst_start += dst->stride;
3163 src_start += src->stride / 4;
3171 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3173 for(y = src_rect->top; y < src_rect->bottom; y++)
3175 dst_pixel = dst_start;
3176 src_pixel = src_start;
3177 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3179 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3181 if(bit_pos == 0) *dst_pixel = 0;
3182 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3192 if(bit_pos != 0) dst_pixel++;
3193 memset(dst_pixel, 0, pad_size);
3195 dst_start += dst->stride;
3196 src_start += src->stride;
3203 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3204 if(src->funcs == &funcs_555)
3206 for(y = src_rect->top; y < src_rect->bottom; y++)
3208 dst_pixel = dst_start;
3209 src_pixel = src_start;
3210 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3212 src_val = *src_pixel++;
3213 dst_val = rgb_to_pixel_colortable(dst,
3214 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3215 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3216 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3218 if(bit_pos == 0) *dst_pixel = 0;
3219 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3229 if(bit_pos != 0) dst_pixel++;
3230 memset(dst_pixel, 0, pad_size);
3232 dst_start += dst->stride;
3233 src_start += src->stride / 2;
3236 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3238 for(y = src_rect->top; y < src_rect->bottom; y++)
3240 dst_pixel = dst_start;
3241 src_pixel = src_start;
3242 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3244 src_val = *src_pixel++;
3245 dst_val = rgb_to_pixel_colortable(dst,
3246 (((src_val >> src->red_shift) << 3) & 0xf8) |
3247 (((src_val >> src->red_shift) >> 2) & 0x07),
3248 (((src_val >> src->green_shift) << 3) & 0xf8) |
3249 (((src_val >> src->green_shift) >> 2) & 0x07),
3250 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3251 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3252 if(bit_pos == 0) *dst_pixel = 0;
3253 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3263 if(bit_pos != 0) dst_pixel++;
3264 memset(dst_pixel, 0, pad_size);
3266 dst_start += dst->stride;
3267 src_start += src->stride / 2;
3270 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3272 for(y = src_rect->top; y < src_rect->bottom; y++)
3274 dst_pixel = dst_start;
3275 src_pixel = src_start;
3276 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3278 src_val = *src_pixel++;
3279 dst_val = rgb_to_pixel_colortable(dst,
3280 (((src_val >> src->red_shift) << 3) & 0xf8) |
3281 (((src_val >> src->red_shift) >> 2) & 0x07),
3282 (((src_val >> src->green_shift) << 2) & 0xfc) |
3283 (((src_val >> src->green_shift) >> 4) & 0x03),
3284 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3285 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3286 if(bit_pos == 0) *dst_pixel = 0;
3287 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3297 if(bit_pos != 0) dst_pixel++;
3298 memset(dst_pixel, 0, pad_size);
3300 dst_start += dst->stride;
3301 src_start += src->stride / 2;
3306 for(y = src_rect->top; y < src_rect->bottom; y++)
3308 dst_pixel = dst_start;
3309 src_pixel = src_start;
3310 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3312 src_val = *src_pixel++;
3313 dst_val = rgb_to_pixel_colortable(dst,
3314 get_field(src_val, src->red_shift, src->red_len),
3315 get_field(src_val, src->green_shift, src->green_len),
3316 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3317 if(bit_pos == 0) *dst_pixel = 0;
3318 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3328 if(bit_pos != 0) dst_pixel++;
3329 memset(dst_pixel, 0, pad_size);
3331 dst_start += dst->stride;
3332 src_start += src->stride / 2;
3340 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3342 for(y = src_rect->top; y < src_rect->bottom; y++)
3344 dst_pixel = dst_start;
3345 src_pixel = src_start;
3346 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3348 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3349 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3351 if(bit_pos == 0) *dst_pixel = 0;
3352 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3362 if(bit_pos != 0) dst_pixel++;
3363 memset(dst_pixel, 0, pad_size);
3365 dst_start += dst->stride;
3366 src_start += src->stride;
3373 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3375 for(y = src_rect->top; y < src_rect->bottom; y++)
3377 dst_pixel = dst_start;
3378 src_pixel = src_start;
3379 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3383 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3385 rgb = colortable_entry( src, *src_pixel >> 4 );
3386 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3388 if(bit_pos == 0) *dst_pixel = 0;
3389 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3399 if(bit_pos != 0) dst_pixel++;
3400 memset(dst_pixel, 0, pad_size);
3402 dst_start += dst->stride;
3403 src_start += src->stride;
3408 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3409 uses text/bkgnd colours instead of the dib's colour table, this
3410 doesn't appear to be the case for a dc backed by a
3415 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3416 for(y = src_rect->top; y < src_rect->bottom; y++)
3418 dst_pixel = dst_start;
3419 src_pixel = src_start;
3420 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3423 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3424 if((x % 8) == 7) src_pixel++;
3425 rgb = src->color_table[src_val];
3426 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3428 if(bit_pos == 0) *dst_pixel = 0;
3429 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3439 if(bit_pos != 0) dst_pixel++;
3440 memset(dst_pixel, 0, pad_size);
3442 dst_start += dst->stride;
3443 src_start += src->stride;
3450 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3454 static BOOL create_rop_masks_32(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3456 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3457 DWORD mask_start = 0, mask_offset;
3458 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
3461 for(y = 0; y < hatch->height; y++)
3463 hatch_ptr = hatch_start;
3464 mask_offset = mask_start;
3465 for(x = 0; x < hatch->width; x++)
3467 if(*hatch_ptr & pixel_masks_1[x % 8])
3469 and_bits[mask_offset] = fg->and;
3470 xor_bits[mask_offset] = fg->xor;
3474 and_bits[mask_offset] = bg->and;
3475 xor_bits[mask_offset] = bg->xor;
3477 if(x % 8 == 7) hatch_ptr++;
3480 hatch_start += hatch->stride;
3481 mask_start += dib->stride / 4;
3487 static BOOL create_rop_masks_24(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3489 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3490 DWORD mask_start = 0, mask_offset;
3491 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3494 for(y = 0; y < hatch->height; y++)
3496 hatch_ptr = hatch_start;
3497 mask_offset = mask_start;
3498 for(x = 0; x < hatch->width; x++)
3500 if(*hatch_ptr & pixel_masks_1[x % 8])
3502 and_bits[mask_offset] = fg->and & 0xff;
3503 xor_bits[mask_offset++] = fg->xor & 0xff;
3504 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
3505 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
3506 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
3507 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
3511 and_bits[mask_offset] = bg->and & 0xff;
3512 xor_bits[mask_offset++] = bg->xor & 0xff;
3513 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
3514 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
3515 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
3516 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
3518 if(x % 8 == 7) hatch_ptr++;
3520 hatch_start += hatch->stride;
3521 mask_start += dib->stride;
3527 static BOOL create_rop_masks_16(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3529 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3530 DWORD mask_start = 0, mask_offset;
3531 WORD *and_bits = bits->and, *xor_bits = bits->xor;
3534 for(y = 0; y < hatch->height; y++)
3536 hatch_ptr = hatch_start;
3537 mask_offset = mask_start;
3538 for(x = 0; x < hatch->width; x++)
3540 if(*hatch_ptr & pixel_masks_1[x % 8])
3542 and_bits[mask_offset] = fg->and;
3543 xor_bits[mask_offset] = fg->xor;
3547 and_bits[mask_offset] = bg->and;
3548 xor_bits[mask_offset] = bg->xor;
3550 if(x % 8 == 7) hatch_ptr++;
3553 hatch_start += hatch->stride;
3554 mask_start += dib->stride / 2;
3560 static BOOL create_rop_masks_8(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3562 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3563 DWORD mask_start = 0, mask_offset;
3564 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3567 for(y = 0; y < hatch->height; y++)
3569 hatch_ptr = hatch_start;
3570 mask_offset = mask_start;
3571 for(x = 0; x < hatch->width; x++)
3573 if(*hatch_ptr & pixel_masks_1[x % 8])
3575 and_bits[mask_offset] = fg->and;
3576 xor_bits[mask_offset] = fg->xor;
3580 and_bits[mask_offset] = bg->and;
3581 xor_bits[mask_offset] = bg->xor;
3583 if(x % 8 == 7) hatch_ptr++;
3586 hatch_start += hatch->stride;
3587 mask_start += dib->stride;
3593 static BOOL create_rop_masks_4(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3595 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3596 DWORD mask_start = 0, mask_offset;
3597 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3598 const rop_mask *rop_mask;
3601 for(y = 0; y < hatch->height; y++)
3603 hatch_ptr = hatch_start;
3604 mask_offset = mask_start;
3605 for(x = 0; x < hatch->width; x++)
3607 if(*hatch_ptr & pixel_masks_1[x % 8])
3614 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3615 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3620 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3621 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3624 if(x % 8 == 7) hatch_ptr++;
3626 hatch_start += hatch->stride;
3627 mask_start += dib->stride;
3633 static BOOL create_rop_masks_1(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3635 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3636 DWORD mask_start = 0, mask_offset;
3637 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3641 for(y = 0; y < hatch->height; y++)
3643 hatch_ptr = hatch_start;
3644 mask_offset = mask_start;
3645 for(x = 0, bit_pos = 0; x < hatch->width; x++)
3647 if(*hatch_ptr & pixel_masks_1[x % 8])
3649 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3650 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3654 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3655 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3658 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3660 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3661 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3670 hatch_start += hatch->stride;
3671 mask_start += dib->stride;
3677 static BOOL create_rop_masks_null(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3682 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
3687 case STRETCH_DELETESCANS:
3688 get_rop_codes( R2_COPYPEN, codes );
3690 case STRETCH_ORSCANS:
3691 get_rop_codes( R2_MERGEPEN, codes );
3693 case STRETCH_ANDSCANS:
3694 get_rop_codes( R2_MASKPEN, codes );
3700 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
3701 const dib_info *src_dib, const POINT *src_start,
3702 const struct stretch_params *params, int mode,
3705 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
3706 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
3707 int err = params->err_start;
3709 struct rop_codes codes;
3711 rop_codes_from_stretch_mode( mode, &codes );
3712 for (width = params->length; width; width--)
3714 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
3715 dst_ptr += params->dst_inc;
3718 src_ptr += params->src_inc;
3719 err += params->err_add_1;
3721 else err += params->err_add_2;
3725 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
3726 const dib_info *src_dib, const POINT *src_start,
3727 const struct stretch_params *params, int mode,
3730 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
3731 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
3732 int err = params->err_start;
3734 struct rop_codes codes;
3736 rop_codes_from_stretch_mode( mode, &codes );
3737 for (width = params->length; width; width--)
3739 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3740 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
3741 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
3742 dst_ptr += 3 * params->dst_inc;
3745 src_ptr += 3 * params->src_inc;
3746 err += params->err_add_1;
3748 else err += params->err_add_2;
3752 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
3753 const dib_info *src_dib, const POINT *src_start,
3754 const struct stretch_params *params, int mode,
3757 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
3758 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
3759 int err = params->err_start;
3761 struct rop_codes codes;
3763 rop_codes_from_stretch_mode( mode, &codes );
3764 for (width = params->length; width; width--)
3766 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
3767 dst_ptr += params->dst_inc;
3770 src_ptr += params->src_inc;
3771 err += params->err_add_1;
3773 else err += params->err_add_2;
3777 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
3778 const dib_info *src_dib, const POINT *src_start,
3779 const struct stretch_params *params, int mode,
3782 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
3783 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
3784 int err = params->err_start;
3786 struct rop_codes codes;
3788 rop_codes_from_stretch_mode( mode, &codes );
3789 for (width = params->length; width; width--)
3791 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3792 dst_ptr += params->dst_inc;
3795 src_ptr += params->src_inc;
3796 err += params->err_add_1;
3798 else err += params->err_add_2;
3802 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
3803 const dib_info *src_dib, const POINT *src_start,
3804 const struct stretch_params *params, int mode,
3807 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
3808 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
3809 int err = params->err_start;
3810 int width, dst_x = dst_start->x, src_x = src_start->x;
3811 struct rop_codes codes;
3814 rop_codes_from_stretch_mode( mode, &codes );
3815 for (width = params->length; width; width--)
3817 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
3818 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
3820 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
3822 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
3823 dst_ptr += params->dst_inc;
3824 dst_x += params->dst_inc;
3828 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
3829 src_ptr += params->src_inc;
3830 src_x += params->src_inc;
3831 err += params->err_add_1;
3833 else err += params->err_add_2;
3837 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
3838 const dib_info *src_dib, const POINT *src_start,
3839 const struct stretch_params *params, int mode,
3842 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
3843 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
3844 int err = params->err_start;
3845 int width, dst_x = dst_start->x, src_x = src_start->x;
3846 struct rop_codes codes;
3849 rop_codes_from_stretch_mode( mode, &codes );
3850 for (width = params->length; width; width--)
3852 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
3853 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
3855 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
3856 dst_ptr += params->dst_inc;
3857 dst_x += params->dst_inc;
3861 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
3862 src_ptr += params->src_inc;
3863 src_x += params->src_inc;
3864 err += params->err_add_1;
3866 else err += params->err_add_2;
3870 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
3871 const dib_info *src_dib, const POINT *src_start,
3872 const struct stretch_params *params, int mode,
3875 FIXME("bit count %d\n", dst_dib->bit_count);
3879 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
3880 const dib_info *src_dib, const POINT *src_start,
3881 const struct stretch_params *params, int mode,
3884 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
3885 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
3886 int err = params->err_start;
3888 struct rop_codes codes;
3889 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3890 BOOL new_pix = TRUE;
3892 rop_codes_from_stretch_mode( mode, &codes );
3893 for (width = params->length; width; width--)
3895 if (new_pix && !keep_dst) *dst_ptr = init_val;
3896 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
3898 src_ptr += params->src_inc;
3901 dst_ptr += params->dst_inc;
3903 err += params->err_add_1;
3905 else err += params->err_add_2;
3909 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
3910 const dib_info *src_dib, const POINT *src_start,
3911 const struct stretch_params *params, int mode,
3914 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
3915 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
3916 int err = params->err_start;
3918 struct rop_codes codes;
3919 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3920 BOOL new_pix = TRUE;
3922 rop_codes_from_stretch_mode( mode, &codes );
3923 for (width = params->length; width; width--)
3925 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
3926 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3927 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
3928 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
3930 src_ptr += 3 * params->src_inc;
3933 dst_ptr += 3 * params->dst_inc;
3935 err += params->err_add_1;
3937 else err += params->err_add_2;
3941 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
3942 const dib_info *src_dib, const POINT *src_start,
3943 const struct stretch_params *params, int mode,
3946 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
3947 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
3948 int err = params->err_start;
3950 struct rop_codes codes;
3951 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3952 BOOL new_pix = TRUE;
3954 rop_codes_from_stretch_mode( mode, &codes );
3955 for (width = params->length; width; width--)
3957 if (new_pix && !keep_dst) *dst_ptr = init_val;
3958 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
3960 src_ptr += params->src_inc;
3963 dst_ptr += params->dst_inc;
3965 err += params->err_add_1;
3967 else err += params->err_add_2;
3971 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
3972 const dib_info *src_dib, const POINT *src_start,
3973 const struct stretch_params *params, int mode,
3976 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
3977 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
3978 int err = params->err_start;
3980 struct rop_codes codes;
3981 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3982 BOOL new_pix = TRUE;
3984 rop_codes_from_stretch_mode( mode, &codes );
3985 for (width = params->length; width; width--)
3987 if (new_pix && !keep_dst) *dst_ptr = init_val;
3988 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3990 src_ptr += params->src_inc;
3993 dst_ptr += params->dst_inc;
3995 err += params->err_add_1;
3997 else err += params->err_add_2;
4001 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
4002 const dib_info *src_dib, const POINT *src_start,
4003 const struct stretch_params *params, int mode,
4006 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4007 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4008 int err = params->err_start;
4009 int width, dst_x = dst_start->x, src_x = src_start->x;
4010 struct rop_codes codes;
4011 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4012 BOOL new_pix = TRUE;
4014 rop_codes_from_stretch_mode( mode, &codes );
4015 for (width = params->length; width; width--)
4017 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4019 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4020 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4022 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4025 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4026 src_ptr += params->src_inc;
4027 src_x += params->src_inc;
4031 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4032 dst_ptr += params->dst_inc;
4033 dst_x += params->dst_inc;
4035 err += params->err_add_1;
4037 else err += params->err_add_2;
4041 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4042 const dib_info *src_dib, const POINT *src_start,
4043 const struct stretch_params *params, int mode,
4046 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4047 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4048 int err = params->err_start;
4049 int width, dst_x = dst_start->x, src_x = src_start->x;
4050 struct rop_codes codes;
4051 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4052 BOOL new_pix = TRUE;
4054 rop_codes_from_stretch_mode( mode, &codes );
4055 for (width = params->length; width; width--)
4057 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4058 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4059 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4062 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4063 src_ptr += params->src_inc;
4064 src_x += params->src_inc;
4068 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4069 dst_ptr += params->dst_inc;
4070 dst_x += params->dst_inc;
4072 err += params->err_add_1;
4074 else err += params->err_add_2;
4078 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4079 const dib_info *src_dib, const POINT *src_start,
4080 const struct stretch_params *params, int mode,
4083 FIXME("bit count %d\n", dst_dib->bit_count);
4087 const primitive_funcs funcs_8888 =
4092 colorref_to_pixel_888,
4094 create_rop_masks_32,
4099 const primitive_funcs funcs_32 =
4104 colorref_to_pixel_masks,
4106 create_rop_masks_32,
4111 const primitive_funcs funcs_24 =
4116 colorref_to_pixel_888,
4118 create_rop_masks_24,
4123 const primitive_funcs funcs_555 =
4128 colorref_to_pixel_555,
4130 create_rop_masks_16,
4135 const primitive_funcs funcs_16 =
4140 colorref_to_pixel_masks,
4142 create_rop_masks_16,
4147 const primitive_funcs funcs_8 =
4152 colorref_to_pixel_colortable,
4159 const primitive_funcs funcs_4 =
4164 colorref_to_pixel_colortable,
4171 const primitive_funcs funcs_1 =
4176 colorref_to_pixel_colortable,
4183 const primitive_funcs funcs_null =
4188 colorref_to_pixel_null,
4190 create_rop_masks_null,