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 get_pixel_32(const dib_info *dib, const POINT *pt)
1030 DWORD *ptr = get_pixel_ptr_32( dib, pt->x, pt->y );
1034 static DWORD get_pixel_24(const dib_info *dib, const POINT *pt)
1036 BYTE *ptr = get_pixel_ptr_24( dib, pt->x, pt->y );
1037 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1040 static DWORD get_pixel_16(const dib_info *dib, const POINT *pt)
1042 WORD *ptr = get_pixel_ptr_16( dib, pt->x, pt->y );
1046 static DWORD get_pixel_8(const dib_info *dib, const POINT *pt)
1048 BYTE *ptr = get_pixel_ptr_8( dib, pt->x, pt->y );
1052 static DWORD get_pixel_4(const dib_info *dib, const POINT *pt)
1054 BYTE *ptr = get_pixel_ptr_4( dib, pt->x, pt->y );
1059 return (*ptr >> 4) & 0x0f;
1062 static DWORD get_pixel_1(const dib_info *dib, const POINT *pt)
1064 BYTE *ptr = get_pixel_ptr_1( dib, pt->x, pt->y );
1065 return (*ptr & pixel_masks_1[pt->x & 0x7]) ? 1 : 0;
1068 static DWORD get_pixel_null(const dib_info *dib, const POINT *pt)
1073 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1075 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1078 static const DWORD field_masks[33] =
1080 0x00, /* should never happen */
1081 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1082 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1083 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1084 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1087 static inline DWORD get_field(DWORD field, int shift, int len)
1089 shift = shift - (8 - len);
1094 field &= field_masks[len];
1095 field |= field >> len;
1099 static inline DWORD put_field(DWORD field, int shift, int len)
1101 shift = shift - (8 - len);
1102 field &= field_masks[len];
1110 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1114 r = GetRValue(colour);
1115 g = GetGValue(colour);
1116 b = GetBValue(colour);
1118 return put_field(r, dib->red_shift, dib->red_len) |
1119 put_field(g, dib->green_shift, dib->green_len) |
1120 put_field(b, dib->blue_shift, dib->blue_len);
1123 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1125 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1128 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1130 int i, best_index = 0;
1131 DWORD diff, best_diff = 0xffffffff;
1133 /* special case for conversion to 1-bpp without a color table:
1134 * we get a 1-entry table containing the background color
1136 if (dib->bit_count == 1 && dib->color_table_size == 1)
1137 return (r == dib->color_table[0].rgbRed &&
1138 g == dib->color_table[0].rgbGreen &&
1139 b == dib->color_table[0].rgbBlue);
1141 for(i = 0; i < dib->color_table_size; i++)
1143 RGBQUAD *cur = dib->color_table + i;
1144 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1145 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1146 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1154 if(diff < best_diff)
1163 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1165 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1168 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1173 static inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1175 static const RGBQUAD default_rgb;
1176 if (index < dib->color_table_size) return dib->color_table[index];
1180 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1182 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1185 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1187 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1188 get_field( pixel, dib->green_shift, dib->green_len ),
1189 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1192 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1194 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1195 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1196 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1199 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1201 RGBQUAD quad = colortable_entry( dib, pixel );
1203 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1206 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1211 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1213 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1215 return d1->red_mask == d2->red_mask &&
1216 d1->green_mask == d2->green_mask &&
1217 d1->blue_mask == d2->blue_mask;
1220 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1222 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1223 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1225 switch(src->bit_count)
1229 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1230 if(src->funcs == &funcs_8888)
1232 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1233 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1236 for(y = src_rect->top; y < src_rect->bottom; y++)
1238 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1239 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1240 dst_start += dst->stride / 4;
1241 src_start += src->stride / 4;
1245 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1247 for(y = src_rect->top; y < src_rect->bottom; y++)
1249 dst_pixel = dst_start;
1250 src_pixel = src_start;
1251 for(x = src_rect->left; x < src_rect->right; x++)
1253 src_val = *src_pixel++;
1254 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1255 (((src_val >> src->green_shift) & 0xff) << 8) |
1256 ((src_val >> src->blue_shift) & 0xff);
1258 if(pad_size) memset(dst_pixel, 0, pad_size);
1259 dst_start += dst->stride / 4;
1260 src_start += src->stride / 4;
1265 for(y = src_rect->top; y < src_rect->bottom; y++)
1267 dst_pixel = dst_start;
1268 src_pixel = src_start;
1269 for(x = src_rect->left; x < src_rect->right; x++)
1271 src_val = *src_pixel++;
1272 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1273 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1274 get_field( src_val, src->blue_shift, src->blue_len ));
1276 if(pad_size) memset(dst_pixel, 0, pad_size);
1277 dst_start += dst->stride / 4;
1278 src_start += src->stride / 4;
1286 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1288 for(y = src_rect->top; y < src_rect->bottom; y++)
1290 dst_pixel = dst_start;
1291 src_pixel = src_start;
1292 for(x = src_rect->left; x < src_rect->right; x++)
1295 rgb.rgbBlue = *src_pixel++;
1296 rgb.rgbGreen = *src_pixel++;
1297 rgb.rgbRed = *src_pixel++;
1299 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1301 if(pad_size) memset(dst_pixel, 0, pad_size);
1302 dst_start += dst->stride / 4;
1303 src_start += src->stride;
1310 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1311 if(src->funcs == &funcs_555)
1313 for(y = src_rect->top; y < src_rect->bottom; y++)
1315 dst_pixel = dst_start;
1316 src_pixel = src_start;
1317 for(x = src_rect->left; x < src_rect->right; x++)
1319 src_val = *src_pixel++;
1320 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1321 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1322 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1324 if(pad_size) memset(dst_pixel, 0, pad_size);
1325 dst_start += dst->stride / 4;
1326 src_start += src->stride / 2;
1329 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1331 for(y = src_rect->top; y < src_rect->bottom; y++)
1333 dst_pixel = dst_start;
1334 src_pixel = src_start;
1335 for(x = src_rect->left; x < src_rect->right; x++)
1337 src_val = *src_pixel++;
1338 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1339 (((src_val >> src->red_shift) << 14) & 0x070000) |
1340 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1341 (((src_val >> src->green_shift) << 6) & 0x000700) |
1342 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1343 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1345 if(pad_size) memset(dst_pixel, 0, pad_size);
1346 dst_start += dst->stride / 4;
1347 src_start += src->stride / 2;
1350 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1352 for(y = src_rect->top; y < src_rect->bottom; y++)
1354 dst_pixel = dst_start;
1355 src_pixel = src_start;
1356 for(x = src_rect->left; x < src_rect->right; x++)
1358 src_val = *src_pixel++;
1359 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1360 (((src_val >> src->red_shift) << 14) & 0x070000) |
1361 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1362 (((src_val >> src->green_shift) << 4) & 0x000300) |
1363 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1364 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1366 if(pad_size) memset(dst_pixel, 0, pad_size);
1367 dst_start += dst->stride / 4;
1368 src_start += src->stride / 2;
1373 for(y = src_rect->top; y < src_rect->bottom; y++)
1375 dst_pixel = dst_start;
1376 src_pixel = src_start;
1377 for(x = src_rect->left; x < src_rect->right; x++)
1379 src_val = *src_pixel++;
1380 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1381 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1382 get_field( src_val, src->blue_shift, src->blue_len ));
1384 if(pad_size) memset(dst_pixel, 0, pad_size);
1385 dst_start += dst->stride / 4;
1386 src_start += src->stride / 2;
1394 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1395 for(y = src_rect->top; y < src_rect->bottom; y++)
1397 dst_pixel = dst_start;
1398 src_pixel = src_start;
1399 for(x = src_rect->left; x < src_rect->right; x++)
1401 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1402 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1404 if(pad_size) memset(dst_pixel, 0, pad_size);
1405 dst_start += dst->stride / 4;
1406 src_start += src->stride;
1413 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1414 for(y = src_rect->top; y < src_rect->bottom; y++)
1416 dst_pixel = dst_start;
1417 src_pixel = src_start;
1418 for(x = src_rect->left; x < src_rect->right; x++)
1422 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1424 rgb = colortable_entry( src, *src_pixel >> 4 );
1425 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1427 if(pad_size) memset(dst_pixel, 0, pad_size);
1428 dst_start += dst->stride / 4;
1429 src_start += src->stride;
1436 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1437 for(y = src_rect->top; y < src_rect->bottom; y++)
1439 dst_pixel = dst_start;
1440 src_pixel = src_start;
1441 for(x = src_rect->left; x < src_rect->right; x++)
1444 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1445 if((x % 8) == 7) src_pixel++;
1446 rgb = src->color_table[src_val];
1447 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1449 if(pad_size) memset(dst_pixel, 0, pad_size);
1450 dst_start += dst->stride / 4;
1451 src_start += src->stride;
1458 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1460 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1461 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1463 switch(src->bit_count)
1467 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1469 if(src->funcs == &funcs_8888)
1471 for(y = src_rect->top; y < src_rect->bottom; y++)
1473 dst_pixel = dst_start;
1474 src_pixel = src_start;
1475 for(x = src_rect->left; x < src_rect->right; x++)
1477 src_val = *src_pixel++;
1478 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1479 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1480 put_field(src_val, dst->blue_shift, dst->blue_len);
1482 if(pad_size) memset(dst_pixel, 0, pad_size);
1483 dst_start += dst->stride / 4;
1484 src_start += src->stride / 4;
1487 else if(bit_fields_match(src, dst))
1489 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1490 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1493 for(y = src_rect->top; y < src_rect->bottom; y++)
1495 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1496 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1497 dst_start += dst->stride / 4;
1498 src_start += src->stride / 4;
1502 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1503 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1505 for(y = src_rect->top; y < src_rect->bottom; y++)
1507 dst_pixel = dst_start;
1508 src_pixel = src_start;
1509 for(x = src_rect->left; x < src_rect->right; x++)
1511 src_val = *src_pixel++;
1512 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1513 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1514 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1516 if(pad_size) memset(dst_pixel, 0, pad_size);
1517 dst_start += dst->stride / 4;
1518 src_start += src->stride / 4;
1523 for(y = src_rect->top; y < src_rect->bottom; y++)
1525 dst_pixel = dst_start;
1526 src_pixel = src_start;
1527 for(x = src_rect->left; x < src_rect->right; x++)
1529 src_val = *src_pixel++;
1530 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1531 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1532 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1534 if(pad_size) memset(dst_pixel, 0, pad_size);
1535 dst_start += dst->stride / 4;
1536 src_start += src->stride / 4;
1544 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1546 for(y = src_rect->top; y < src_rect->bottom; y++)
1548 dst_pixel = dst_start;
1549 src_pixel = src_start;
1550 for(x = src_rect->left; x < src_rect->right; x++)
1553 rgb.rgbBlue = *src_pixel++;
1554 rgb.rgbGreen = *src_pixel++;
1555 rgb.rgbRed = *src_pixel++;
1557 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1558 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1559 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1561 if(pad_size) memset(dst_pixel, 0, pad_size);
1562 dst_start += dst->stride / 4;
1563 src_start += src->stride;
1570 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1571 if(src->funcs == &funcs_555)
1573 for(y = src_rect->top; y < src_rect->bottom; y++)
1575 dst_pixel = dst_start;
1576 src_pixel = src_start;
1577 for(x = src_rect->left; x < src_rect->right; x++)
1579 src_val = *src_pixel++;
1580 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1581 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1582 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1584 if(pad_size) memset(dst_pixel, 0, pad_size);
1585 dst_start += dst->stride / 4;
1586 src_start += src->stride / 2;
1589 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1591 for(y = src_rect->top; y < src_rect->bottom; y++)
1593 dst_pixel = dst_start;
1594 src_pixel = src_start;
1595 for(x = src_rect->left; x < src_rect->right; x++)
1597 src_val = *src_pixel++;
1598 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1599 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1600 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1601 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1602 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1603 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1605 if(pad_size) memset(dst_pixel, 0, pad_size);
1606 dst_start += dst->stride / 4;
1607 src_start += src->stride / 2;
1610 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1612 for(y = src_rect->top; y < src_rect->bottom; y++)
1614 dst_pixel = dst_start;
1615 src_pixel = src_start;
1616 for(x = src_rect->left; x < src_rect->right; x++)
1618 src_val = *src_pixel++;
1619 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1620 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1621 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1622 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1623 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1624 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1626 if(pad_size) memset(dst_pixel, 0, pad_size);
1627 dst_start += dst->stride / 4;
1628 src_start += src->stride / 2;
1633 for(y = src_rect->top; y < src_rect->bottom; y++)
1635 dst_pixel = dst_start;
1636 src_pixel = src_start;
1637 for(x = src_rect->left; x < src_rect->right; x++)
1639 src_val = *src_pixel++;
1640 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1641 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1642 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1644 if(pad_size) memset(dst_pixel, 0, pad_size);
1645 dst_start += dst->stride / 4;
1646 src_start += src->stride / 2;
1654 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1655 for(y = src_rect->top; y < src_rect->bottom; y++)
1657 dst_pixel = dst_start;
1658 src_pixel = src_start;
1659 for(x = src_rect->left; x < src_rect->right; x++)
1661 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1662 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1663 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1664 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1666 if(pad_size) memset(dst_pixel, 0, pad_size);
1667 dst_start += dst->stride / 4;
1668 src_start += src->stride;
1675 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1676 for(y = src_rect->top; y < src_rect->bottom; y++)
1678 dst_pixel = dst_start;
1679 src_pixel = src_start;
1680 for(x = src_rect->left; x < src_rect->right; x++)
1684 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1686 rgb = colortable_entry( src, *src_pixel >> 4 );
1687 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1688 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1689 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1691 if(pad_size) memset(dst_pixel, 0, pad_size);
1692 dst_start += dst->stride / 4;
1693 src_start += src->stride;
1700 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1701 for(y = src_rect->top; y < src_rect->bottom; y++)
1703 dst_pixel = dst_start;
1704 src_pixel = src_start;
1705 for(x = src_rect->left; x < src_rect->right; x++)
1708 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1709 if((x % 8) == 7) src_pixel++;
1710 rgb = src->color_table[src_val];
1711 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1712 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1713 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1715 if(pad_size) memset(dst_pixel, 0, pad_size);
1716 dst_start += dst->stride / 4;
1717 src_start += src->stride;
1724 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1726 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1728 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1730 switch(src->bit_count)
1734 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1735 if(src->funcs == &funcs_8888)
1737 for(y = src_rect->top; y < src_rect->bottom; y++)
1739 dst_pixel = dst_start;
1740 src_pixel = src_start;
1741 for(x = src_rect->left; x < src_rect->right; x++)
1743 src_val = *src_pixel++;
1744 *dst_pixel++ = src_val & 0xff;
1745 *dst_pixel++ = (src_val >> 8) & 0xff;
1746 *dst_pixel++ = (src_val >> 16) & 0xff;
1748 if(pad_size) memset(dst_pixel, 0, pad_size);
1749 dst_start += dst->stride;
1750 src_start += src->stride / 4;
1753 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1755 for(y = src_rect->top; y < src_rect->bottom; y++)
1757 dst_pixel = dst_start;
1758 src_pixel = src_start;
1759 for(x = src_rect->left; x < src_rect->right; x++)
1761 src_val = *src_pixel++;
1762 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
1763 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1764 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
1766 if(pad_size) memset(dst_pixel, 0, pad_size);
1767 dst_start += dst->stride;
1768 src_start += src->stride / 4;
1773 for(y = src_rect->top; y < src_rect->bottom; y++)
1775 dst_pixel = dst_start;
1776 src_pixel = src_start;
1777 for(x = src_rect->left; x < src_rect->right; x++)
1779 src_val = *src_pixel++;
1780 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
1781 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
1782 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
1784 if(pad_size) memset(dst_pixel, 0, pad_size);
1785 dst_start += dst->stride;
1786 src_start += src->stride / 4;
1794 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1796 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1797 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1800 for(y = src_rect->top; y < src_rect->bottom; y++)
1802 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1803 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1804 dst_start += dst->stride;
1805 src_start += src->stride;
1813 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1814 if(src->funcs == &funcs_555)
1816 for(y = src_rect->top; y < src_rect->bottom; y++)
1818 dst_pixel = dst_start;
1819 src_pixel = src_start;
1820 for(x = src_rect->left; x < src_rect->right; x++)
1822 src_val = *src_pixel++;
1823 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
1824 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
1825 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1827 if(pad_size) memset(dst_pixel, 0, pad_size);
1828 dst_start += dst->stride;
1829 src_start += src->stride / 2;
1832 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1834 for(y = src_rect->top; y < src_rect->bottom; y++)
1836 dst_pixel = dst_start;
1837 src_pixel = src_start;
1838 for(x = src_rect->left; x < src_rect->right; x++)
1840 src_val = *src_pixel++;
1841 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1842 (((src_val >> src->blue_shift) >> 2) & 0x07);
1843 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1844 (((src_val >> src->green_shift) >> 2) & 0x07);
1845 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1846 (((src_val >> src->red_shift) >> 2) & 0x07);
1848 if(pad_size) memset(dst_pixel, 0, pad_size);
1849 dst_start += dst->stride;
1850 src_start += src->stride / 2;
1853 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1855 for(y = src_rect->top; y < src_rect->bottom; y++)
1857 dst_pixel = dst_start;
1858 src_pixel = src_start;
1859 for(x = src_rect->left; x < src_rect->right; x++)
1861 src_val = *src_pixel++;
1862 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1863 (((src_val >> src->blue_shift) >> 2) & 0x07);
1864 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1865 (((src_val >> src->green_shift) >> 4) & 0x03);
1866 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1867 (((src_val >> src->red_shift) >> 2) & 0x07);
1869 if(pad_size) memset(dst_pixel, 0, pad_size);
1870 dst_start += dst->stride;
1871 src_start += src->stride / 2;
1876 for(y = src_rect->top; y < src_rect->bottom; y++)
1878 dst_pixel = dst_start;
1879 src_pixel = src_start;
1880 for(x = src_rect->left; x < src_rect->right; x++)
1882 src_val = *src_pixel++;
1883 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
1884 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
1885 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
1887 if(pad_size) memset(dst_pixel, 0, pad_size);
1888 dst_start += dst->stride;
1889 src_start += src->stride / 2;
1897 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1898 for(y = src_rect->top; y < src_rect->bottom; y++)
1900 dst_pixel = dst_start;
1901 src_pixel = src_start;
1902 for(x = src_rect->left; x < src_rect->right; x++)
1904 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1905 *dst_pixel++ = rgb.rgbBlue;
1906 *dst_pixel++ = rgb.rgbGreen;
1907 *dst_pixel++ = rgb.rgbRed;
1909 if(pad_size) memset(dst_pixel, 0, pad_size);
1910 dst_start += dst->stride;
1911 src_start += src->stride;
1918 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1919 for(y = src_rect->top; y < src_rect->bottom; y++)
1921 dst_pixel = dst_start;
1922 src_pixel = src_start;
1923 for(x = src_rect->left; x < src_rect->right; x++)
1927 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1929 rgb = colortable_entry( src, *src_pixel >> 4 );
1930 *dst_pixel++ = rgb.rgbBlue;
1931 *dst_pixel++ = rgb.rgbGreen;
1932 *dst_pixel++ = rgb.rgbRed;
1934 if(pad_size) memset(dst_pixel, 0, pad_size);
1935 dst_start += dst->stride;
1936 src_start += src->stride;
1943 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1944 for(y = src_rect->top; y < src_rect->bottom; y++)
1946 dst_pixel = dst_start;
1947 src_pixel = src_start;
1948 for(x = src_rect->left; x < src_rect->right; x++)
1951 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1952 if((x % 8) == 7) src_pixel++;
1953 rgb = src->color_table[src_val];
1954 *dst_pixel++ = rgb.rgbBlue;
1955 *dst_pixel++ = rgb.rgbGreen;
1956 *dst_pixel++ = rgb.rgbRed;
1958 if(pad_size) memset(dst_pixel, 0, pad_size);
1959 dst_start += dst->stride;
1960 src_start += src->stride;
1967 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1969 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
1970 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1973 switch(src->bit_count)
1977 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1979 if(src->funcs == &funcs_8888)
1981 for(y = src_rect->top; y < src_rect->bottom; y++)
1983 dst_pixel = dst_start;
1984 src_pixel = src_start;
1985 for(x = src_rect->left; x < src_rect->right; x++)
1987 src_val = *src_pixel++;
1988 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1989 ((src_val >> 6) & 0x03e0) |
1990 ((src_val >> 3) & 0x001f);
1992 if(pad_size) memset(dst_pixel, 0, pad_size);
1993 dst_start += dst->stride / 2;
1994 src_start += src->stride / 4;
1997 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1999 for(y = src_rect->top; y < src_rect->bottom; y++)
2001 dst_pixel = dst_start;
2002 src_pixel = src_start;
2003 for(x = src_rect->left; x < src_rect->right; x++)
2005 src_val = *src_pixel++;
2006 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2007 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2008 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2010 if(pad_size) memset(dst_pixel, 0, pad_size);
2011 dst_start += dst->stride / 2;
2012 src_start += src->stride / 4;
2017 for(y = src_rect->top; y < src_rect->bottom; y++)
2019 dst_pixel = dst_start;
2020 src_pixel = src_start;
2021 for(x = src_rect->left; x < src_rect->right; x++)
2023 src_val = *src_pixel++;
2024 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2025 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2026 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2028 if(pad_size) memset(dst_pixel, 0, pad_size);
2029 dst_start += dst->stride / 2;
2030 src_start += src->stride / 4;
2038 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2040 for(y = src_rect->top; y < src_rect->bottom; y++)
2042 dst_pixel = dst_start;
2043 src_pixel = src_start;
2044 for(x = src_rect->left; x < src_rect->right; x++)
2047 rgb.rgbBlue = *src_pixel++;
2048 rgb.rgbGreen = *src_pixel++;
2049 rgb.rgbRed = *src_pixel++;
2051 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2052 ((rgb.rgbGreen << 2) & 0x03e0) |
2053 ((rgb.rgbBlue >> 3) & 0x001f);
2055 if(pad_size) memset(dst_pixel, 0, pad_size);
2056 dst_start += dst->stride / 2;
2057 src_start += src->stride;
2064 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2065 if(src->funcs == &funcs_555)
2067 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2068 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2071 for(y = src_rect->top; y < src_rect->bottom; y++)
2073 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2074 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2075 dst_start += dst->stride / 2;
2076 src_start += src->stride / 2;
2080 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2082 for(y = src_rect->top; y < src_rect->bottom; y++)
2084 dst_pixel = dst_start;
2085 src_pixel = src_start;
2086 for(x = src_rect->left; x < src_rect->right; x++)
2088 src_val = *src_pixel++;
2089 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2090 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2091 ( (src_val >> src->blue_shift) & 0x001f);
2093 if(pad_size) memset(dst_pixel, 0, pad_size);
2094 dst_start += dst->stride / 2;
2095 src_start += src->stride / 2;
2098 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2100 for(y = src_rect->top; y < src_rect->bottom; y++)
2102 dst_pixel = dst_start;
2103 src_pixel = src_start;
2104 for(x = src_rect->left; x < src_rect->right; x++)
2106 src_val = *src_pixel++;
2107 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2108 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2109 ( (src_val >> src->blue_shift) & 0x001f);
2111 if(pad_size) memset(dst_pixel, 0, pad_size);
2112 dst_start += dst->stride / 2;
2113 src_start += src->stride / 2;
2118 for(y = src_rect->top; y < src_rect->bottom; y++)
2120 dst_pixel = dst_start;
2121 src_pixel = src_start;
2122 for(x = src_rect->left; x < src_rect->right; x++)
2124 src_val = *src_pixel++;
2125 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2126 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2127 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2129 if(pad_size) memset(dst_pixel, 0, pad_size);
2130 dst_start += dst->stride / 2;
2131 src_start += src->stride / 2;
2139 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2140 for(y = src_rect->top; y < src_rect->bottom; y++)
2142 dst_pixel = dst_start;
2143 src_pixel = src_start;
2144 for(x = src_rect->left; x < src_rect->right; x++)
2146 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2147 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2148 ((rgb.rgbGreen << 2) & 0x03e0) |
2149 ((rgb.rgbBlue >> 3) & 0x001f);
2151 if(pad_size) memset(dst_pixel, 0, pad_size);
2152 dst_start += dst->stride / 2;
2153 src_start += src->stride;
2160 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2161 for(y = src_rect->top; y < src_rect->bottom; y++)
2163 dst_pixel = dst_start;
2164 src_pixel = src_start;
2165 for(x = src_rect->left; x < src_rect->right; x++)
2169 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2171 rgb = colortable_entry( src, *src_pixel >> 4 );
2172 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2173 ((rgb.rgbGreen << 2) & 0x03e0) |
2174 ((rgb.rgbBlue >> 3) & 0x001f);
2176 if(pad_size) memset(dst_pixel, 0, pad_size);
2177 dst_start += dst->stride / 2;
2178 src_start += src->stride;
2185 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2186 for(y = src_rect->top; y < src_rect->bottom; y++)
2188 dst_pixel = dst_start;
2189 src_pixel = src_start;
2190 for(x = src_rect->left; x < src_rect->right; x++)
2193 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2194 if((x % 8) == 7) src_pixel++;
2195 rgb = src->color_table[src_val];
2196 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2197 ((rgb.rgbGreen << 2) & 0x03e0) |
2198 ((rgb.rgbBlue >> 3) & 0x001f);
2200 if(pad_size) memset(dst_pixel, 0, pad_size);
2201 dst_start += dst->stride / 2;
2202 src_start += src->stride;
2209 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2211 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2212 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2215 switch(src->bit_count)
2219 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2221 if(src->funcs == &funcs_8888)
2223 for(y = src_rect->top; y < src_rect->bottom; y++)
2225 dst_pixel = dst_start;
2226 src_pixel = src_start;
2227 for(x = src_rect->left; x < src_rect->right; x++)
2229 src_val = *src_pixel++;
2230 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2231 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2232 put_field(src_val, dst->blue_shift, dst->blue_len);
2234 if(pad_size) memset(dst_pixel, 0, pad_size);
2235 dst_start += dst->stride / 2;
2236 src_start += src->stride / 4;
2239 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2241 for(y = src_rect->top; y < src_rect->bottom; y++)
2243 dst_pixel = dst_start;
2244 src_pixel = src_start;
2245 for(x = src_rect->left; x < src_rect->right; x++)
2247 src_val = *src_pixel++;
2248 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2249 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2250 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2252 if(pad_size) memset(dst_pixel, 0, pad_size);
2253 dst_start += dst->stride / 2;
2254 src_start += src->stride / 4;
2259 for(y = src_rect->top; y < src_rect->bottom; y++)
2261 dst_pixel = dst_start;
2262 src_pixel = src_start;
2263 for(x = src_rect->left; x < src_rect->right; x++)
2265 src_val = *src_pixel++;
2266 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2267 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2268 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2270 if(pad_size) memset(dst_pixel, 0, pad_size);
2271 dst_start += dst->stride / 2;
2272 src_start += src->stride / 4;
2280 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2282 for(y = src_rect->top; y < src_rect->bottom; y++)
2284 dst_pixel = dst_start;
2285 src_pixel = src_start;
2286 for(x = src_rect->left; x < src_rect->right; x++)
2289 rgb.rgbBlue = *src_pixel++;
2290 rgb.rgbGreen = *src_pixel++;
2291 rgb.rgbRed = *src_pixel++;
2293 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2294 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2295 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2297 if(pad_size) memset(dst_pixel, 0, pad_size);
2298 dst_start += dst->stride / 2;
2299 src_start += src->stride;
2306 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2307 if(src->funcs == &funcs_555)
2309 for(y = src_rect->top; y < src_rect->bottom; y++)
2311 dst_pixel = dst_start;
2312 src_pixel = src_start;
2313 for(x = src_rect->left; x < src_rect->right; x++)
2315 src_val = *src_pixel++;
2316 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2317 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2318 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2320 if(pad_size) memset(dst_pixel, 0, pad_size);
2321 dst_start += dst->stride / 2;
2322 src_start += src->stride / 2;
2325 else if(bit_fields_match(src, dst))
2327 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2328 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2331 for(y = src_rect->top; y < src_rect->bottom; y++)
2333 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2334 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2335 dst_start += dst->stride / 2;
2336 src_start += src->stride / 2;
2340 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2342 for(y = src_rect->top; y < src_rect->bottom; y++)
2344 dst_pixel = dst_start;
2345 src_pixel = src_start;
2346 for(x = src_rect->left; x < src_rect->right; x++)
2348 src_val = *src_pixel++;
2349 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2350 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2351 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2352 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2353 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2354 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2356 if(pad_size) memset(dst_pixel, 0, pad_size);
2357 dst_start += dst->stride / 2;
2358 src_start += src->stride / 2;
2361 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2363 for(y = src_rect->top; y < src_rect->bottom; y++)
2365 dst_pixel = dst_start;
2366 src_pixel = src_start;
2367 for(x = src_rect->left; x < src_rect->right; x++)
2369 src_val = *src_pixel++;
2370 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2371 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2372 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2373 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2374 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2375 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2377 if(pad_size) memset(dst_pixel, 0, pad_size);
2378 dst_start += dst->stride / 2;
2379 src_start += src->stride / 2;
2384 for(y = src_rect->top; y < src_rect->bottom; y++)
2386 dst_pixel = dst_start;
2387 src_pixel = src_start;
2388 for(x = src_rect->left; x < src_rect->right; x++)
2390 src_val = *src_pixel++;
2391 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2392 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2393 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2395 if(pad_size) memset(dst_pixel, 0, pad_size);
2396 dst_start += dst->stride / 2;
2397 src_start += src->stride / 2;
2405 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2406 for(y = src_rect->top; y < src_rect->bottom; y++)
2408 dst_pixel = dst_start;
2409 src_pixel = src_start;
2410 for(x = src_rect->left; x < src_rect->right; x++)
2412 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2413 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2414 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2415 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2417 if(pad_size) memset(dst_pixel, 0, pad_size);
2418 dst_start += dst->stride / 2;
2419 src_start += src->stride;
2426 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2427 for(y = src_rect->top; y < src_rect->bottom; y++)
2429 dst_pixel = dst_start;
2430 src_pixel = src_start;
2431 for(x = src_rect->left; x < src_rect->right; x++)
2435 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2437 rgb = colortable_entry( src, *src_pixel >> 4 );
2438 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2439 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2440 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2442 if(pad_size) memset(dst_pixel, 0, pad_size);
2443 dst_start += dst->stride / 2;
2444 src_start += src->stride;
2451 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2452 for(y = src_rect->top; y < src_rect->bottom; y++)
2454 dst_pixel = dst_start;
2455 src_pixel = src_start;
2456 for(x = src_rect->left; x < src_rect->right; x++)
2459 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2460 if((x % 8) == 7) src_pixel++;
2461 rgb = src->color_table[src_val];
2462 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2463 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2464 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2466 if(pad_size) memset(dst_pixel, 0, pad_size);
2467 dst_start += dst->stride / 2;
2468 src_start += src->stride;
2475 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2477 assert(d1->color_table_size && d2->color_table_size);
2479 if(d1->color_table_size != d2->color_table_size) return FALSE;
2480 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2483 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2485 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2486 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2489 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2491 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2492 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2495 switch(src->bit_count)
2499 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2501 if(src->funcs == &funcs_8888)
2503 for(y = src_rect->top; y < src_rect->bottom; y++)
2505 dst_pixel = dst_start;
2506 src_pixel = src_start;
2507 for(x = src_rect->left; x < src_rect->right; x++)
2509 src_val = *src_pixel++;
2510 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2512 if(pad_size) memset(dst_pixel, 0, pad_size);
2513 dst_start += dst->stride;
2514 src_start += src->stride / 4;
2517 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2519 for(y = src_rect->top; y < src_rect->bottom; y++)
2521 dst_pixel = dst_start;
2522 src_pixel = src_start;
2523 for(x = src_rect->left; x < src_rect->right; x++)
2525 src_val = *src_pixel++;
2526 *dst_pixel++ = rgb_lookup_colortable(dst,
2527 src_val >> src->red_shift,
2528 src_val >> src->green_shift,
2529 src_val >> src->blue_shift );
2531 if(pad_size) memset(dst_pixel, 0, pad_size);
2532 dst_start += dst->stride;
2533 src_start += src->stride / 4;
2538 for(y = src_rect->top; y < src_rect->bottom; y++)
2540 dst_pixel = dst_start;
2541 src_pixel = src_start;
2542 for(x = src_rect->left; x < src_rect->right; x++)
2544 src_val = *src_pixel++;
2545 *dst_pixel++ = rgb_lookup_colortable(dst,
2546 get_field(src_val, src->red_shift, src->red_len),
2547 get_field(src_val, src->green_shift, src->green_len),
2548 get_field(src_val, src->blue_shift, src->blue_len));
2550 if(pad_size) memset(dst_pixel, 0, pad_size);
2551 dst_start += dst->stride;
2552 src_start += src->stride / 4;
2560 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2562 for(y = src_rect->top; y < src_rect->bottom; y++)
2564 dst_pixel = dst_start;
2565 src_pixel = src_start;
2566 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2568 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2570 if(pad_size) memset(dst_pixel, 0, pad_size);
2571 dst_start += dst->stride;
2572 src_start += src->stride;
2579 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2580 if(src->funcs == &funcs_555)
2582 for(y = src_rect->top; y < src_rect->bottom; y++)
2584 dst_pixel = dst_start;
2585 src_pixel = src_start;
2586 for(x = src_rect->left; x < src_rect->right; x++)
2588 src_val = *src_pixel++;
2589 *dst_pixel++ = rgb_lookup_colortable(dst,
2590 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2591 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2592 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2594 if(pad_size) memset(dst_pixel, 0, pad_size);
2595 dst_start += dst->stride;
2596 src_start += src->stride / 2;
2599 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2601 for(y = src_rect->top; y < src_rect->bottom; y++)
2603 dst_pixel = dst_start;
2604 src_pixel = src_start;
2605 for(x = src_rect->left; x < src_rect->right; x++)
2607 src_val = *src_pixel++;
2608 *dst_pixel++ = rgb_lookup_colortable(dst,
2609 (((src_val >> src->red_shift) << 3) & 0xf8) |
2610 (((src_val >> src->red_shift) >> 2) & 0x07),
2611 (((src_val >> src->green_shift) << 3) & 0xf8) |
2612 (((src_val >> src->green_shift) >> 2) & 0x07),
2613 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2614 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2616 if(pad_size) memset(dst_pixel, 0, pad_size);
2617 dst_start += dst->stride;
2618 src_start += src->stride / 2;
2621 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2623 for(y = src_rect->top; y < src_rect->bottom; y++)
2625 dst_pixel = dst_start;
2626 src_pixel = src_start;
2627 for(x = src_rect->left; x < src_rect->right; x++)
2629 src_val = *src_pixel++;
2630 *dst_pixel++ = rgb_lookup_colortable(dst,
2631 (((src_val >> src->red_shift) << 3) & 0xf8) |
2632 (((src_val >> src->red_shift) >> 2) & 0x07),
2633 (((src_val >> src->green_shift) << 2) & 0xfc) |
2634 (((src_val >> src->green_shift) >> 4) & 0x03),
2635 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2636 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2638 if(pad_size) memset(dst_pixel, 0, pad_size);
2639 dst_start += dst->stride;
2640 src_start += src->stride / 2;
2645 for(y = src_rect->top; y < src_rect->bottom; y++)
2647 dst_pixel = dst_start;
2648 src_pixel = src_start;
2649 for(x = src_rect->left; x < src_rect->right; x++)
2651 src_val = *src_pixel++;
2652 *dst_pixel++ = rgb_lookup_colortable(dst,
2653 get_field(src_val, src->red_shift, src->red_len),
2654 get_field(src_val, src->green_shift, src->green_len),
2655 get_field(src_val, src->blue_shift, src->blue_len));
2657 if(pad_size) memset(dst_pixel, 0, pad_size);
2658 dst_start += dst->stride;
2659 src_start += src->stride / 2;
2667 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2669 if(color_tables_match(dst, src))
2671 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2672 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2675 for(y = src_rect->top; y < src_rect->bottom; y++)
2677 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2678 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2679 dst_start += dst->stride;
2680 src_start += src->stride;
2686 for(y = src_rect->top; y < src_rect->bottom; y++)
2688 dst_pixel = dst_start;
2689 src_pixel = src_start;
2690 for(x = src_rect->left; x < src_rect->right; x++)
2692 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2693 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2695 if(pad_size) memset(dst_pixel, 0, pad_size);
2696 dst_start += dst->stride;
2697 src_start += src->stride;
2705 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2706 for(y = src_rect->top; y < src_rect->bottom; y++)
2708 dst_pixel = dst_start;
2709 src_pixel = src_start;
2710 for(x = src_rect->left; x < src_rect->right; x++)
2714 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2716 rgb = colortable_entry( src, *src_pixel >> 4 );
2717 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2719 if(pad_size) memset(dst_pixel, 0, pad_size);
2720 dst_start += dst->stride;
2721 src_start += src->stride;
2728 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2729 for(y = src_rect->top; y < src_rect->bottom; y++)
2731 dst_pixel = dst_start;
2732 src_pixel = src_start;
2733 for(x = src_rect->left; x < src_rect->right; x++)
2736 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2737 if((x % 8) == 7) src_pixel++;
2738 rgb = src->color_table[src_val];
2739 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2741 if(pad_size) memset(dst_pixel, 0, pad_size);
2742 dst_start += dst->stride;
2743 src_start += src->stride;
2750 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2752 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2753 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2756 switch(src->bit_count)
2760 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2762 if(src->funcs == &funcs_8888)
2764 for(y = src_rect->top; y < src_rect->bottom; y++)
2766 dst_pixel = dst_start;
2767 src_pixel = src_start;
2768 for(x = src_rect->left; x < src_rect->right; x++)
2770 src_val = *src_pixel++;
2771 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
2772 if((x - src_rect->left) & 1)
2774 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2778 *dst_pixel = (dst_val << 4) & 0xf0;
2782 if((x - src_rect->left) & 1) dst_pixel++;
2783 memset(dst_pixel, 0, pad_size);
2785 dst_start += dst->stride;
2786 src_start += src->stride / 4;
2789 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2791 for(y = src_rect->top; y < src_rect->bottom; y++)
2793 dst_pixel = dst_start;
2794 src_pixel = src_start;
2795 for(x = src_rect->left; x < src_rect->right; x++)
2797 src_val = *src_pixel++;
2798 dst_val = rgb_to_pixel_colortable(dst,
2799 src_val >> src->red_shift,
2800 src_val >> src->green_shift,
2801 src_val >> src->blue_shift);
2802 if((x - src_rect->left) & 1)
2804 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2808 *dst_pixel = (dst_val << 4) & 0xf0;
2812 if((x - src_rect->left) & 1) dst_pixel++;
2813 memset(dst_pixel, 0, pad_size);
2815 dst_start += dst->stride;
2816 src_start += src->stride / 4;
2821 for(y = src_rect->top; y < src_rect->bottom; y++)
2823 dst_pixel = dst_start;
2824 src_pixel = src_start;
2825 for(x = src_rect->left; x < src_rect->right; x++)
2827 src_val = *src_pixel++;
2828 dst_val = rgb_to_pixel_colortable(dst,
2829 get_field(src_val, src->red_shift, src->red_len),
2830 get_field(src_val, src->green_shift, src->green_len),
2831 get_field(src_val, src->blue_shift, src->blue_len));
2832 if((x - src_rect->left) & 1)
2834 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2838 *dst_pixel = (dst_val << 4) & 0xf0;
2842 if((x - src_rect->left) & 1) dst_pixel++;
2843 memset(dst_pixel, 0, pad_size);
2845 dst_start += dst->stride;
2846 src_start += src->stride / 4;
2854 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2856 for(y = src_rect->top; y < src_rect->bottom; y++)
2858 dst_pixel = dst_start;
2859 src_pixel = src_start;
2860 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2862 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2864 if((x - src_rect->left) & 1)
2866 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2870 *dst_pixel = (dst_val << 4) & 0xf0;
2874 if((x - src_rect->left) & 1) dst_pixel++;
2875 memset(dst_pixel, 0, pad_size);
2877 dst_start += dst->stride;
2878 src_start += src->stride;
2885 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2886 if(src->funcs == &funcs_555)
2888 for(y = src_rect->top; y < src_rect->bottom; y++)
2890 dst_pixel = dst_start;
2891 src_pixel = src_start;
2892 for(x = src_rect->left; x < src_rect->right; x++)
2894 src_val = *src_pixel++;
2895 dst_val = rgb_to_pixel_colortable(dst,
2896 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2897 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2898 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2899 if((x - src_rect->left) & 1)
2901 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2905 *dst_pixel = (dst_val << 4) & 0xf0;
2909 if((x - src_rect->left) & 1) dst_pixel++;
2910 memset(dst_pixel, 0, pad_size);
2912 dst_start += dst->stride;
2913 src_start += src->stride / 2;
2916 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2918 for(y = src_rect->top; y < src_rect->bottom; y++)
2920 dst_pixel = dst_start;
2921 src_pixel = src_start;
2922 for(x = src_rect->left; x < src_rect->right; x++)
2924 src_val = *src_pixel++;
2925 dst_val = rgb_to_pixel_colortable(dst,
2926 (((src_val >> src->red_shift) << 3) & 0xf8) |
2927 (((src_val >> src->red_shift) >> 2) & 0x07),
2928 (((src_val >> src->green_shift) << 3) & 0xf8) |
2929 (((src_val >> src->green_shift) >> 2) & 0x07),
2930 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2931 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2932 if((x - src_rect->left) & 1)
2934 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2938 *dst_pixel = (dst_val << 4) & 0xf0;
2942 if((x - src_rect->left) & 1) dst_pixel++;
2943 memset(dst_pixel, 0, pad_size);
2945 dst_start += dst->stride;
2946 src_start += src->stride / 2;
2949 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2951 for(y = src_rect->top; y < src_rect->bottom; y++)
2953 dst_pixel = dst_start;
2954 src_pixel = src_start;
2955 for(x = src_rect->left; x < src_rect->right; x++)
2957 src_val = *src_pixel++;
2958 dst_val = rgb_to_pixel_colortable(dst,
2959 (((src_val >> src->red_shift) << 3) & 0xf8) |
2960 (((src_val >> src->red_shift) >> 2) & 0x07),
2961 (((src_val >> src->green_shift) << 2) & 0xfc) |
2962 (((src_val >> src->green_shift) >> 4) & 0x03),
2963 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2964 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2965 if((x - src_rect->left) & 1)
2967 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2971 *dst_pixel = (dst_val << 4) & 0xf0;
2975 if((x - src_rect->left) & 1) dst_pixel++;
2976 memset(dst_pixel, 0, pad_size);
2978 dst_start += dst->stride;
2979 src_start += src->stride / 2;
2984 for(y = src_rect->top; y < src_rect->bottom; y++)
2986 dst_pixel = dst_start;
2987 src_pixel = src_start;
2988 for(x = src_rect->left; x < src_rect->right; x++)
2990 src_val = *src_pixel++;
2991 dst_val = rgb_to_pixel_colortable(dst,
2992 get_field(src_val, src->red_shift, src->red_len),
2993 get_field(src_val, src->green_shift, src->green_len),
2994 get_field(src_val, src->blue_shift, src->blue_len));
2995 if((x - src_rect->left) & 1)
2997 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3001 *dst_pixel = (dst_val << 4) & 0xf0;
3005 if((x - src_rect->left) & 1) dst_pixel++;
3006 memset(dst_pixel, 0, pad_size);
3008 dst_start += dst->stride;
3009 src_start += src->stride / 2;
3017 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3019 for(y = src_rect->top; y < src_rect->bottom; y++)
3021 dst_pixel = dst_start;
3022 src_pixel = src_start;
3023 for(x = src_rect->left; x < src_rect->right; x++)
3025 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3026 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3027 if((x - src_rect->left) & 1)
3029 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3033 *dst_pixel = (dst_val << 4) & 0xf0;
3037 if((x - src_rect->left) & 1) dst_pixel++;
3038 memset(dst_pixel, 0, pad_size);
3040 dst_start += dst->stride;
3041 src_start += src->stride;
3048 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3050 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
3052 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
3053 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3056 for(y = src_rect->top; y < src_rect->bottom; y++)
3058 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3059 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3060 dst_start += dst->stride;
3061 src_start += src->stride;
3067 for(y = src_rect->top; y < src_rect->bottom; y++)
3069 dst_pixel = dst_start;
3070 src_pixel = src_start;
3071 for(x = src_rect->left; x < src_rect->right; x++)
3075 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3077 rgb = colortable_entry( src, *src_pixel >> 4 );
3078 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3079 if((x - src_rect->left) & 1)
3081 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3085 *dst_pixel = (dst_val << 4) & 0xf0;
3089 if((x - src_rect->left) & 1) dst_pixel++;
3090 memset(dst_pixel, 0, pad_size);
3092 dst_start += dst->stride;
3093 src_start += src->stride;
3101 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3102 for(y = src_rect->top; y < src_rect->bottom; y++)
3104 dst_pixel = dst_start;
3105 src_pixel = src_start;
3106 for(x = src_rect->left; x < src_rect->right; x++)
3109 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3110 if((x % 8) == 7) src_pixel++;
3111 rgb = src->color_table[src_val];
3112 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3113 if((x - src_rect->left) & 1)
3115 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3119 *dst_pixel = (dst_val << 4) & 0xf0;
3123 if((x - src_rect->left) & 1) dst_pixel++;
3124 memset(dst_pixel, 0, pad_size);
3126 dst_start += dst->stride;
3127 src_start += src->stride;
3134 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3136 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3137 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3141 /* FIXME: Brushes should be dithered. */
3143 switch(src->bit_count)
3147 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3149 if(src->funcs == &funcs_8888)
3151 for(y = src_rect->top; y < src_rect->bottom; y++)
3153 dst_pixel = dst_start;
3154 src_pixel = src_start;
3155 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3157 src_val = *src_pixel++;
3158 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3160 if(bit_pos == 0) *dst_pixel = 0;
3161 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3171 if(bit_pos != 0) dst_pixel++;
3172 memset(dst_pixel, 0, pad_size);
3174 dst_start += dst->stride;
3175 src_start += src->stride / 4;
3178 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3180 for(y = src_rect->top; y < src_rect->bottom; y++)
3182 dst_pixel = dst_start;
3183 src_pixel = src_start;
3184 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3186 src_val = *src_pixel++;
3187 dst_val = rgb_to_pixel_colortable(dst,
3188 src_val >> src->red_shift,
3189 src_val >> src->green_shift,
3190 src_val >> src->blue_shift) ? 0xff : 0;
3192 if(bit_pos == 0) *dst_pixel = 0;
3193 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3203 if(bit_pos != 0) dst_pixel++;
3204 memset(dst_pixel, 0, pad_size);
3206 dst_start += dst->stride;
3207 src_start += src->stride / 4;
3212 for(y = src_rect->top; y < src_rect->bottom; y++)
3214 dst_pixel = dst_start;
3215 src_pixel = src_start;
3216 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3218 src_val = *src_pixel++;
3219 dst_val = rgb_to_pixel_colortable(dst,
3220 get_field(src_val, src->red_shift, src->red_len),
3221 get_field(src_val, src->green_shift, src->green_len),
3222 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3224 if(bit_pos == 0) *dst_pixel = 0;
3225 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3235 if(bit_pos != 0) dst_pixel++;
3236 memset(dst_pixel, 0, pad_size);
3238 dst_start += dst->stride;
3239 src_start += src->stride / 4;
3247 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3249 for(y = src_rect->top; y < src_rect->bottom; y++)
3251 dst_pixel = dst_start;
3252 src_pixel = src_start;
3253 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3255 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3257 if(bit_pos == 0) *dst_pixel = 0;
3258 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3268 if(bit_pos != 0) dst_pixel++;
3269 memset(dst_pixel, 0, pad_size);
3271 dst_start += dst->stride;
3272 src_start += src->stride;
3279 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3280 if(src->funcs == &funcs_555)
3282 for(y = src_rect->top; y < src_rect->bottom; y++)
3284 dst_pixel = dst_start;
3285 src_pixel = src_start;
3286 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3288 src_val = *src_pixel++;
3289 dst_val = rgb_to_pixel_colortable(dst,
3290 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3291 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3292 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3294 if(bit_pos == 0) *dst_pixel = 0;
3295 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3305 if(bit_pos != 0) dst_pixel++;
3306 memset(dst_pixel, 0, pad_size);
3308 dst_start += dst->stride;
3309 src_start += src->stride / 2;
3312 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3314 for(y = src_rect->top; y < src_rect->bottom; y++)
3316 dst_pixel = dst_start;
3317 src_pixel = src_start;
3318 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3320 src_val = *src_pixel++;
3321 dst_val = rgb_to_pixel_colortable(dst,
3322 (((src_val >> src->red_shift) << 3) & 0xf8) |
3323 (((src_val >> src->red_shift) >> 2) & 0x07),
3324 (((src_val >> src->green_shift) << 3) & 0xf8) |
3325 (((src_val >> src->green_shift) >> 2) & 0x07),
3326 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3327 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3328 if(bit_pos == 0) *dst_pixel = 0;
3329 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3339 if(bit_pos != 0) dst_pixel++;
3340 memset(dst_pixel, 0, pad_size);
3342 dst_start += dst->stride;
3343 src_start += src->stride / 2;
3346 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3348 for(y = src_rect->top; y < src_rect->bottom; y++)
3350 dst_pixel = dst_start;
3351 src_pixel = src_start;
3352 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3354 src_val = *src_pixel++;
3355 dst_val = rgb_to_pixel_colortable(dst,
3356 (((src_val >> src->red_shift) << 3) & 0xf8) |
3357 (((src_val >> src->red_shift) >> 2) & 0x07),
3358 (((src_val >> src->green_shift) << 2) & 0xfc) |
3359 (((src_val >> src->green_shift) >> 4) & 0x03),
3360 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3361 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3362 if(bit_pos == 0) *dst_pixel = 0;
3363 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3373 if(bit_pos != 0) dst_pixel++;
3374 memset(dst_pixel, 0, pad_size);
3376 dst_start += dst->stride;
3377 src_start += src->stride / 2;
3382 for(y = src_rect->top; y < src_rect->bottom; y++)
3384 dst_pixel = dst_start;
3385 src_pixel = src_start;
3386 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3388 src_val = *src_pixel++;
3389 dst_val = rgb_to_pixel_colortable(dst,
3390 get_field(src_val, src->red_shift, src->red_len),
3391 get_field(src_val, src->green_shift, src->green_len),
3392 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3393 if(bit_pos == 0) *dst_pixel = 0;
3394 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3404 if(bit_pos != 0) dst_pixel++;
3405 memset(dst_pixel, 0, pad_size);
3407 dst_start += dst->stride;
3408 src_start += src->stride / 2;
3416 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3418 for(y = src_rect->top; y < src_rect->bottom; y++)
3420 dst_pixel = dst_start;
3421 src_pixel = src_start;
3422 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3424 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3425 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3427 if(bit_pos == 0) *dst_pixel = 0;
3428 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3438 if(bit_pos != 0) dst_pixel++;
3439 memset(dst_pixel, 0, pad_size);
3441 dst_start += dst->stride;
3442 src_start += src->stride;
3449 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3451 for(y = src_rect->top; y < src_rect->bottom; y++)
3453 dst_pixel = dst_start;
3454 src_pixel = src_start;
3455 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3459 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3461 rgb = colortable_entry( src, *src_pixel >> 4 );
3462 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3464 if(bit_pos == 0) *dst_pixel = 0;
3465 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3475 if(bit_pos != 0) dst_pixel++;
3476 memset(dst_pixel, 0, pad_size);
3478 dst_start += dst->stride;
3479 src_start += src->stride;
3484 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3485 uses text/bkgnd colours instead of the dib's colour table, this
3486 doesn't appear to be the case for a dc backed by a
3491 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3492 for(y = src_rect->top; y < src_rect->bottom; y++)
3494 dst_pixel = dst_start;
3495 src_pixel = src_start;
3496 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3499 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3500 if((x % 8) == 7) src_pixel++;
3501 rgb = src->color_table[src_val];
3502 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3504 if(bit_pos == 0) *dst_pixel = 0;
3505 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3515 if(bit_pos != 0) dst_pixel++;
3516 memset(dst_pixel, 0, pad_size);
3518 dst_start += dst->stride;
3519 src_start += src->stride;
3526 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3530 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3532 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3535 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3537 return (blend_color( dst, src, alpha ) |
3538 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3539 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3540 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3543 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3545 BYTE b = ((BYTE)src * alpha + 127) / 255;
3546 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3547 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3548 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3549 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3550 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3551 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3552 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3555 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3557 if (blend.AlphaFormat & AC_SRC_ALPHA)
3559 DWORD alpha = blend.SourceConstantAlpha;
3560 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3561 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3562 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3563 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3564 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3565 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3566 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3568 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3569 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3570 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3573 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3574 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3576 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3577 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3580 if (blend.AlphaFormat & AC_SRC_ALPHA)
3581 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3582 for (x = 0; x < rc->right - rc->left; x++)
3583 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3585 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3586 for (x = 0; x < rc->right - rc->left; x++)
3587 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3590 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3591 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3593 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3594 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3597 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3599 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3601 for (x = 0; x < rc->right - rc->left; x++)
3603 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3604 dst_ptr[x] >> dst->green_shift,
3605 dst_ptr[x] >> dst->blue_shift,
3606 src_ptr[x], blend );
3607 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3608 (((val >> 8) & 0xff) << dst->green_shift) |
3609 (((val >> 16) & 0xff) << dst->red_shift));
3615 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3617 for (x = 0; x < rc->right - rc->left; x++)
3619 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3620 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3621 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3622 src_ptr[x], blend );
3623 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3624 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3625 put_field( val, dst->blue_shift, dst->blue_len ));
3631 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3632 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3634 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3635 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3638 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3640 for (x = 0; x < rc->right - rc->left; x++)
3642 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3643 src_ptr[x], blend );
3644 dst_ptr[x * 3] = val;
3645 dst_ptr[x * 3 + 1] = val >> 8;
3646 dst_ptr[x * 3 + 2] = val >> 16;
3651 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3652 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3654 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3655 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3658 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3660 for (x = 0; x < rc->right - rc->left; x++)
3662 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3663 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3664 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3665 src_ptr[x], blend );
3666 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3671 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3672 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3674 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3675 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3678 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3680 for (x = 0; x < rc->right - rc->left; x++)
3682 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3683 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3684 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3685 src_ptr[x], blend );
3686 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3687 put_field((val >> 8), dst->green_shift, dst->green_len) |
3688 put_field( val, dst->blue_shift, dst->blue_len));
3693 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3694 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3696 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3697 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3700 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3702 for (x = 0; x < rc->right - rc->left; x++)
3704 RGBQUAD rgb = colortable_entry( dst, dst_ptr[x] );
3705 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3706 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3711 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3712 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3714 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3715 BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3718 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3720 for (x = rc->left; x < rc->right; x++)
3722 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3723 RGBQUAD rgb = colortable_entry( dst, val );
3724 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3725 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3727 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3729 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3734 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3735 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3737 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3738 BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
3741 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3743 for (x = rc->left; x < rc->right; x++)
3745 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3746 RGBQUAD rgb = dst->color_table[val];
3747 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3748 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
3749 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
3754 static void blend_rect_null(const dib_info *dst, const RECT *rc,
3755 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3759 static BOOL create_rop_masks_32(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3761 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3762 DWORD mask_start = 0, mask_offset;
3763 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
3766 for(y = 0; y < hatch->height; y++)
3768 hatch_ptr = hatch_start;
3769 mask_offset = mask_start;
3770 for(x = 0; x < hatch->width; x++)
3772 if(*hatch_ptr & pixel_masks_1[x % 8])
3774 and_bits[mask_offset] = fg->and;
3775 xor_bits[mask_offset] = fg->xor;
3779 and_bits[mask_offset] = bg->and;
3780 xor_bits[mask_offset] = bg->xor;
3782 if(x % 8 == 7) hatch_ptr++;
3785 hatch_start += hatch->stride;
3786 mask_start += dib->stride / 4;
3792 static BOOL create_rop_masks_24(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3794 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3795 DWORD mask_start = 0, mask_offset;
3796 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3799 for(y = 0; y < hatch->height; y++)
3801 hatch_ptr = hatch_start;
3802 mask_offset = mask_start;
3803 for(x = 0; x < hatch->width; x++)
3805 if(*hatch_ptr & pixel_masks_1[x % 8])
3807 and_bits[mask_offset] = fg->and & 0xff;
3808 xor_bits[mask_offset++] = fg->xor & 0xff;
3809 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
3810 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
3811 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
3812 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
3816 and_bits[mask_offset] = bg->and & 0xff;
3817 xor_bits[mask_offset++] = bg->xor & 0xff;
3818 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
3819 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
3820 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
3821 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
3823 if(x % 8 == 7) hatch_ptr++;
3825 hatch_start += hatch->stride;
3826 mask_start += dib->stride;
3832 static BOOL create_rop_masks_16(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3834 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3835 DWORD mask_start = 0, mask_offset;
3836 WORD *and_bits = bits->and, *xor_bits = bits->xor;
3839 for(y = 0; y < hatch->height; y++)
3841 hatch_ptr = hatch_start;
3842 mask_offset = mask_start;
3843 for(x = 0; x < hatch->width; x++)
3845 if(*hatch_ptr & pixel_masks_1[x % 8])
3847 and_bits[mask_offset] = fg->and;
3848 xor_bits[mask_offset] = fg->xor;
3852 and_bits[mask_offset] = bg->and;
3853 xor_bits[mask_offset] = bg->xor;
3855 if(x % 8 == 7) hatch_ptr++;
3858 hatch_start += hatch->stride;
3859 mask_start += dib->stride / 2;
3865 static BOOL create_rop_masks_8(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3867 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3868 DWORD mask_start = 0, mask_offset;
3869 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3872 for(y = 0; y < hatch->height; y++)
3874 hatch_ptr = hatch_start;
3875 mask_offset = mask_start;
3876 for(x = 0; x < hatch->width; x++)
3878 if(*hatch_ptr & pixel_masks_1[x % 8])
3880 and_bits[mask_offset] = fg->and;
3881 xor_bits[mask_offset] = fg->xor;
3885 and_bits[mask_offset] = bg->and;
3886 xor_bits[mask_offset] = bg->xor;
3888 if(x % 8 == 7) hatch_ptr++;
3891 hatch_start += hatch->stride;
3892 mask_start += dib->stride;
3898 static BOOL create_rop_masks_4(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3900 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3901 DWORD mask_start = 0, mask_offset;
3902 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3903 const rop_mask *rop_mask;
3906 for(y = 0; y < hatch->height; y++)
3908 hatch_ptr = hatch_start;
3909 mask_offset = mask_start;
3910 for(x = 0; x < hatch->width; x++)
3912 if(*hatch_ptr & pixel_masks_1[x % 8])
3919 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3920 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3925 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3926 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3929 if(x % 8 == 7) hatch_ptr++;
3931 hatch_start += hatch->stride;
3932 mask_start += dib->stride;
3938 static BOOL create_rop_masks_1(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3940 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3941 DWORD mask_start = 0, mask_offset;
3942 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3946 for(y = 0; y < hatch->height; y++)
3948 hatch_ptr = hatch_start;
3949 mask_offset = mask_start;
3950 for(x = 0, bit_pos = 0; x < hatch->width; x++)
3952 if(*hatch_ptr & pixel_masks_1[x % 8])
3954 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3955 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3959 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3960 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3963 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3965 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3966 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3975 hatch_start += hatch->stride;
3976 mask_start += dib->stride;
3982 static BOOL create_rop_masks_null(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
3987 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
3992 case STRETCH_DELETESCANS:
3993 get_rop_codes( R2_COPYPEN, codes );
3995 case STRETCH_ORSCANS:
3996 get_rop_codes( R2_MERGEPEN, codes );
3998 case STRETCH_ANDSCANS:
3999 get_rop_codes( R2_MASKPEN, codes );
4005 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
4006 const dib_info *src_dib, const POINT *src_start,
4007 const struct stretch_params *params, int mode,
4010 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4011 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4012 int err = params->err_start;
4014 struct rop_codes codes;
4016 rop_codes_from_stretch_mode( mode, &codes );
4017 for (width = params->length; width; width--)
4019 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4020 dst_ptr += params->dst_inc;
4023 src_ptr += params->src_inc;
4024 err += params->err_add_1;
4026 else err += params->err_add_2;
4030 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
4031 const dib_info *src_dib, const POINT *src_start,
4032 const struct stretch_params *params, int mode,
4035 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4036 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4037 int err = params->err_start;
4039 struct rop_codes codes;
4041 rop_codes_from_stretch_mode( mode, &codes );
4042 for (width = params->length; width; width--)
4044 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4045 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4046 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4047 dst_ptr += 3 * params->dst_inc;
4050 src_ptr += 3 * params->src_inc;
4051 err += params->err_add_1;
4053 else err += params->err_add_2;
4057 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
4058 const dib_info *src_dib, const POINT *src_start,
4059 const struct stretch_params *params, int mode,
4062 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4063 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4064 int err = params->err_start;
4066 struct rop_codes codes;
4068 rop_codes_from_stretch_mode( mode, &codes );
4069 for (width = params->length; width; width--)
4071 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4072 dst_ptr += params->dst_inc;
4075 src_ptr += params->src_inc;
4076 err += params->err_add_1;
4078 else err += params->err_add_2;
4082 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
4083 const dib_info *src_dib, const POINT *src_start,
4084 const struct stretch_params *params, int mode,
4087 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4088 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4089 int err = params->err_start;
4091 struct rop_codes codes;
4093 rop_codes_from_stretch_mode( mode, &codes );
4094 for (width = params->length; width; width--)
4096 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4097 dst_ptr += params->dst_inc;
4100 src_ptr += params->src_inc;
4101 err += params->err_add_1;
4103 else err += params->err_add_2;
4107 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
4108 const dib_info *src_dib, const POINT *src_start,
4109 const struct stretch_params *params, int mode,
4112 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
4113 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
4114 int err = params->err_start;
4115 int width, dst_x = dst_start->x, src_x = src_start->x;
4116 struct rop_codes codes;
4119 rop_codes_from_stretch_mode( mode, &codes );
4120 for (width = params->length; width; width--)
4122 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4123 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4125 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
4127 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4128 dst_ptr += params->dst_inc;
4129 dst_x += params->dst_inc;
4133 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4134 src_ptr += params->src_inc;
4135 src_x += params->src_inc;
4136 err += params->err_add_1;
4138 else err += params->err_add_2;
4142 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
4143 const dib_info *src_dib, const POINT *src_start,
4144 const struct stretch_params *params, int mode,
4147 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4148 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4149 int err = params->err_start;
4150 int width, dst_x = dst_start->x, src_x = src_start->x;
4151 struct rop_codes codes;
4154 rop_codes_from_stretch_mode( mode, &codes );
4155 for (width = params->length; width; width--)
4157 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4158 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4160 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4161 dst_ptr += params->dst_inc;
4162 dst_x += params->dst_inc;
4166 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4167 src_ptr += params->src_inc;
4168 src_x += params->src_inc;
4169 err += params->err_add_1;
4171 else err += params->err_add_2;
4175 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
4176 const dib_info *src_dib, const POINT *src_start,
4177 const struct stretch_params *params, int mode,
4180 FIXME("bit count %d\n", dst_dib->bit_count);
4184 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
4185 const dib_info *src_dib, const POINT *src_start,
4186 const struct stretch_params *params, int mode,
4189 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4190 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4191 int err = params->err_start;
4193 struct rop_codes codes;
4194 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4195 BOOL new_pix = TRUE;
4197 rop_codes_from_stretch_mode( mode, &codes );
4198 for (width = params->length; width; width--)
4200 if (new_pix && !keep_dst) *dst_ptr = init_val;
4201 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4203 src_ptr += params->src_inc;
4206 dst_ptr += params->dst_inc;
4208 err += params->err_add_1;
4210 else err += params->err_add_2;
4214 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
4215 const dib_info *src_dib, const POINT *src_start,
4216 const struct stretch_params *params, int mode,
4219 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4220 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4221 int err = params->err_start;
4223 struct rop_codes codes;
4224 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4225 BOOL new_pix = TRUE;
4227 rop_codes_from_stretch_mode( mode, &codes );
4228 for (width = params->length; width; width--)
4230 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
4231 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4232 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4233 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4235 src_ptr += 3 * params->src_inc;
4238 dst_ptr += 3 * params->dst_inc;
4240 err += params->err_add_1;
4242 else err += params->err_add_2;
4246 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
4247 const dib_info *src_dib, const POINT *src_start,
4248 const struct stretch_params *params, int mode,
4251 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4252 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4253 int err = params->err_start;
4255 struct rop_codes codes;
4256 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4257 BOOL new_pix = TRUE;
4259 rop_codes_from_stretch_mode( mode, &codes );
4260 for (width = params->length; width; width--)
4262 if (new_pix && !keep_dst) *dst_ptr = init_val;
4263 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4265 src_ptr += params->src_inc;
4268 dst_ptr += params->dst_inc;
4270 err += params->err_add_1;
4272 else err += params->err_add_2;
4276 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
4277 const dib_info *src_dib, const POINT *src_start,
4278 const struct stretch_params *params, int mode,
4281 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4282 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4283 int err = params->err_start;
4285 struct rop_codes codes;
4286 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4287 BOOL new_pix = TRUE;
4289 rop_codes_from_stretch_mode( mode, &codes );
4290 for (width = params->length; width; width--)
4292 if (new_pix && !keep_dst) *dst_ptr = init_val;
4293 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4295 src_ptr += params->src_inc;
4298 dst_ptr += params->dst_inc;
4300 err += params->err_add_1;
4302 else err += params->err_add_2;
4306 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
4307 const dib_info *src_dib, const POINT *src_start,
4308 const struct stretch_params *params, int mode,
4311 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4312 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4313 int err = params->err_start;
4314 int width, dst_x = dst_start->x, src_x = src_start->x;
4315 struct rop_codes codes;
4316 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4317 BOOL new_pix = TRUE;
4319 rop_codes_from_stretch_mode( mode, &codes );
4320 for (width = params->length; width; width--)
4322 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4324 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4325 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4327 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4330 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4331 src_ptr += params->src_inc;
4332 src_x += params->src_inc;
4336 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4337 dst_ptr += params->dst_inc;
4338 dst_x += params->dst_inc;
4340 err += params->err_add_1;
4342 else err += params->err_add_2;
4346 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4347 const dib_info *src_dib, const POINT *src_start,
4348 const struct stretch_params *params, int mode,
4351 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4352 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4353 int err = params->err_start;
4354 int width, dst_x = dst_start->x, src_x = src_start->x;
4355 struct rop_codes codes;
4356 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4357 BOOL new_pix = TRUE;
4359 rop_codes_from_stretch_mode( mode, &codes );
4360 for (width = params->length; width; width--)
4362 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4363 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4364 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4367 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4368 src_ptr += params->src_inc;
4369 src_x += params->src_inc;
4373 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4374 dst_ptr += params->dst_inc;
4375 dst_x += params->dst_inc;
4377 err += params->err_add_1;
4379 else err += params->err_add_2;
4383 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4384 const dib_info *src_dib, const POINT *src_start,
4385 const struct stretch_params *params, int mode,
4388 FIXME("bit count %d\n", dst_dib->bit_count);
4392 const primitive_funcs funcs_8888 =
4399 colorref_to_pixel_888,
4400 pixel_to_colorref_888,
4402 create_rop_masks_32,
4407 const primitive_funcs funcs_32 =
4414 colorref_to_pixel_masks,
4415 pixel_to_colorref_masks,
4417 create_rop_masks_32,
4422 const primitive_funcs funcs_24 =
4429 colorref_to_pixel_888,
4430 pixel_to_colorref_888,
4432 create_rop_masks_24,
4437 const primitive_funcs funcs_555 =
4444 colorref_to_pixel_555,
4445 pixel_to_colorref_555,
4447 create_rop_masks_16,
4452 const primitive_funcs funcs_16 =
4459 colorref_to_pixel_masks,
4460 pixel_to_colorref_masks,
4462 create_rop_masks_16,
4467 const primitive_funcs funcs_8 =
4474 colorref_to_pixel_colortable,
4475 pixel_to_colorref_colortable,
4482 const primitive_funcs funcs_4 =
4489 colorref_to_pixel_colortable,
4490 pixel_to_colorref_colortable,
4497 const primitive_funcs funcs_1 =
4504 colorref_to_pixel_colortable,
4505 pixel_to_colorref_colortable,
4512 const primitive_funcs funcs_null =
4519 colorref_to_pixel_null,
4520 pixel_to_colorref_null,
4522 create_rop_masks_null,