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 + 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 + 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 + 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 + 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 + 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 + y * dib->stride + x / 2;
60 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
62 *ptr = (*ptr & and) ^ xor;
65 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
67 *ptr = (*ptr & and) ^ xor;
70 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
72 *ptr = (*ptr & and) ^ xor;
75 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
80 for(i = 0; i < num; i++, rc++)
82 start = get_pixel_ptr_32(dib, rc->left, rc->top);
83 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
84 for(x = rc->left, ptr = start; x < rc->right; x++)
85 do_rop_32(ptr++, and, xor);
89 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
92 BYTE *byte_ptr, *byte_start;
94 DWORD and_masks[3], xor_masks[3];
96 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
97 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
98 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
99 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
100 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
101 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
103 for(i = 0; i < num; i++, rc++)
105 if(rc->left >= rc->right) continue;
107 if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
109 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
110 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
112 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
114 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
115 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
116 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
122 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
123 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
130 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
131 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
132 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
135 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
136 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
139 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
143 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
145 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
146 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
147 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
150 switch(rc->right & 3)
153 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
156 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
157 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
160 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
161 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
162 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
170 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
175 for(i = 0; i < num; i++, rc++)
177 start = get_pixel_ptr_16(dib, rc->left, rc->top);
178 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
179 for(x = rc->left, ptr = start; x < rc->right; x++)
180 do_rop_16(ptr++, and, xor);
184 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
189 for(i = 0; i < num; i++, rc++)
191 start = get_pixel_ptr_8(dib, rc->left, rc->top);
192 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
193 for(x = rc->left, ptr = start; x < rc->right; x++)
194 do_rop_8(ptr++, and, xor);
198 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
202 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
203 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
205 for(i = 0; i < num; i++, rc++)
207 if(rc->left >= rc->right) continue;
208 start = get_pixel_ptr_4(dib, rc->left, rc->top);
209 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
212 if(rc->left & 1) /* upper nibble untouched */
213 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
215 for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
216 do_rop_8(ptr++, byte_and, byte_xor);
218 if(rc->right & 1) /* lower nibble untouched */
219 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
224 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
229 static inline INT calc_offset(INT edge, INT size, INT origin)
233 if(edge - origin >= 0)
234 offset = (edge - origin) % size;
237 offset = (origin - edge) % size;
238 if(offset) offset = size - offset;
243 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
247 offset.x = calc_offset(rc->left, brush->width, origin->x);
248 offset.y = calc_offset(rc->top, brush->height, origin->y);
253 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
254 const dib_info *brush, void *and_bits, void *xor_bits)
256 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
260 for(i = 0; i < num; i++, rc++)
262 offset = calc_brush_offset(rc, brush, origin);
264 start = get_pixel_ptr_32(dib, rc->left, rc->top);
265 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
266 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
268 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
270 and_ptr = start_and + offset.x;
271 xor_ptr = start_xor + offset.x;
273 for(x = rc->left, ptr = start; x < rc->right; x++)
275 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
276 if(and_ptr == start_and + brush->width)
284 if(offset.y == brush->height)
286 start_and = and_bits;
287 start_xor = xor_bits;
292 start_and += brush->stride / 4;
293 start_xor += brush->stride / 4;
299 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
300 const dib_info *brush, void *and_bits, void *xor_bits)
302 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
306 for(i = 0; i < num; i++, rc++)
308 offset = calc_brush_offset(rc, brush, origin);
310 start = get_pixel_ptr_24(dib, rc->left, rc->top);
311 start_and = (BYTE*)and_bits + offset.y * brush->stride;
312 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
314 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
316 and_ptr = start_and + offset.x * 3;
317 xor_ptr = start_xor + offset.x * 3;
319 for(x = rc->left, ptr = start; x < rc->right; x++)
321 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
322 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
323 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
324 if(and_ptr == start_and + brush->width * 3)
332 if(offset.y == brush->height)
334 start_and = and_bits;
335 start_xor = xor_bits;
340 start_and += brush->stride;
341 start_xor += brush->stride;
347 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
348 const dib_info *brush, void *and_bits, void *xor_bits)
350 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
354 for(i = 0; i < num; i++, rc++)
356 offset = calc_brush_offset(rc, brush, origin);
358 start = get_pixel_ptr_16(dib, rc->left, rc->top);
359 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
360 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
362 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
364 and_ptr = start_and + offset.x;
365 xor_ptr = start_xor + offset.x;
367 for(x = rc->left, ptr = start; x < rc->right; x++)
369 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
370 if(and_ptr == start_and + brush->width)
378 if(offset.y == brush->height)
380 start_and = and_bits;
381 start_xor = xor_bits;
386 start_and += brush->stride / 2;
387 start_xor += brush->stride / 2;
393 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
394 const dib_info *brush, void *and_bits, void *xor_bits)
396 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
400 for(i = 0; i < num; i++, rc++)
402 offset = calc_brush_offset(rc, brush, origin);
404 start = get_pixel_ptr_8(dib, rc->left, rc->top);
405 start_and = (BYTE*)and_bits + offset.y * brush->stride;
406 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
408 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
410 and_ptr = start_and + offset.x;
411 xor_ptr = start_xor + offset.x;
413 for(x = rc->left, ptr = start; x < rc->right; x++)
415 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
416 if(and_ptr == start_and + brush->width)
424 if(offset.y == brush->height)
426 start_and = and_bits;
427 start_xor = xor_bits;
432 start_and += brush->stride;
433 start_xor += brush->stride;
439 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
440 const dib_info *brush, void *and_bits, void *xor_bits)
442 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
446 for(i = 0; i < num; i++, rc++)
448 offset = calc_brush_offset(rc, brush, origin);
450 start = get_pixel_ptr_4(dib, rc->left, rc->top);
451 start_and = (BYTE*)and_bits + offset.y * brush->stride;
452 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
454 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
456 INT brush_x = offset.x;
457 BYTE byte_and, byte_xor;
459 and_ptr = start_and + brush_x / 2;
460 xor_ptr = start_xor + brush_x / 2;
462 for(x = rc->left, ptr = start; x < rc->right; x++)
464 /* FIXME: Two pixels at a time */
465 if(x & 1) /* lower dst nibble */
467 if(brush_x & 1) /* lower pat nibble */
469 byte_and = *and_ptr++ | 0xf0;
470 byte_xor = *xor_ptr++ & 0x0f;
472 else /* upper pat nibble */
474 byte_and = (*and_ptr >> 4) | 0xf0;
475 byte_xor = (*xor_ptr >> 4) & 0x0f;
478 else /* upper dst nibble */
480 if(brush_x & 1) /* lower pat nibble */
482 byte_and = (*and_ptr++ << 4) | 0x0f;
483 byte_xor = (*xor_ptr++ << 4) & 0xf0;
485 else /* upper pat nibble */
487 byte_and = *and_ptr | 0x0f;
488 byte_xor = *xor_ptr & 0xf0;
491 do_rop_8(ptr, byte_and, byte_xor);
495 if(++brush_x == brush->width)
504 if(offset.y == brush->height)
506 start_and = and_bits;
507 start_xor = xor_bits;
512 start_and += brush->stride;
513 start_xor += brush->stride;
519 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
520 const dib_info *brush, void *and_bits, void *xor_bits)
525 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
527 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
530 static inline DWORD put_field(DWORD field, int shift, int len)
532 shift = shift - (8 - len);
534 field &= (((1 << len) - 1) << (8 - len));
542 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
546 r = GetRValue(colour);
547 g = GetGValue(colour);
548 b = GetBValue(colour);
550 return put_field(r, dib->red_shift, dib->red_len) |
551 put_field(g, dib->green_shift, dib->green_len) |
552 put_field(b, dib->blue_shift, dib->blue_len);
555 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
557 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
560 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
562 int i, best_index = 0;
564 DWORD diff, best_diff = 0xffffffff;
566 rgb.rgbRed = GetRValue(color);
567 rgb.rgbGreen = GetGValue(color);
568 rgb.rgbBlue = GetBValue(color);
570 for(i = 0; i < dib->color_table_size; i++)
572 RGBQUAD *cur = dib->color_table + i;
573 diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
574 + (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
575 + (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
592 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
597 static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
599 DWORD *dst_start = dst->bits, *dst_pixel, src_val;
602 switch(src->bit_count)
606 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top);
607 if(src->funcs == &funcs_8888)
609 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
610 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
613 for(y = src_rect->top; y < src_rect->bottom; y++)
615 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
616 dst_start += dst->stride / 4;
617 src_start += src->stride / 4;
623 FIXME("Unsupported conversion: 32 -> 8888\n");
631 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
632 if(src->funcs == &funcs_555)
634 for(y = src_rect->top; y < src_rect->bottom; y++)
636 dst_pixel = dst_start;
637 src_pixel = src_start;
638 for(x = src_rect->left; x < src_rect->right; x++)
640 src_val = *src_pixel++;
641 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
642 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
643 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
645 dst_start += dst->stride / 4;
646 src_start += src->stride / 2;
651 FIXME("Unsupported conversion: 16 -> 8888\n");
659 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
660 for(y = src_rect->top; y < src_rect->bottom; y++)
662 dst_pixel = dst_start;
663 src_pixel = src_start;
664 for(x = src_rect->left; x < src_rect->right; x++)
667 src_val = *src_pixel++;
668 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
669 rgb = src->color_table[src_val];
670 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
672 dst_start += dst->stride / 4;
673 src_start += src->stride;
680 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
681 for(y = src_rect->top; y < src_rect->bottom; y++)
683 dst_pixel = dst_start;
684 src_pixel = src_start;
685 for(x = src_rect->left; x < src_rect->right; x++)
689 src_val = *src_pixel++ & 0xf;
691 src_val = (*src_pixel >> 4) & 0xf;
692 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
693 rgb = src->color_table[src_val];
694 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
696 dst_start += dst->stride / 4;
697 src_start += src->stride;
703 FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
710 static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
712 DWORD *dst_start = dst->bits, *dst_pixel, src_val;
715 switch(src->bit_count)
719 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
721 if(src->funcs == &funcs_8888)
723 for(y = src_rect->top; y < src_rect->bottom; y++)
725 dst_pixel = dst_start;
726 src_pixel = src_start;
727 for(x = src_rect->left; x < src_rect->right; x++)
729 src_val = *src_pixel++;
730 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
731 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
732 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
734 dst_start += dst->stride / 4;
735 src_start += src->stride / 4;
740 FIXME("Unsupported conversion: 32 -> 32\n");
748 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
749 if(src->funcs == &funcs_555)
751 for(y = src_rect->top; y < src_rect->bottom; y++)
753 dst_pixel = dst_start;
754 src_pixel = src_start;
755 for(x = src_rect->left; x < src_rect->right; x++)
757 src_val = *src_pixel++;
758 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
759 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
760 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
762 dst_start += dst->stride / 4;
763 src_start += src->stride / 2;
768 FIXME("Unsupported conversion: 16 -> 8888\n");
776 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
777 for(y = src_rect->top; y < src_rect->bottom; y++)
779 dst_pixel = dst_start;
780 src_pixel = src_start;
781 for(x = src_rect->left; x < src_rect->right; x++)
784 src_val = *src_pixel++;
785 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
786 rgb = src->color_table[src_val];
787 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
788 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
789 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
791 dst_start += dst->stride / 4;
792 src_start += src->stride;
799 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
800 for(y = src_rect->top; y < src_rect->bottom; y++)
802 dst_pixel = dst_start;
803 src_pixel = src_start;
804 for(x = src_rect->left; x < src_rect->right; x++)
808 src_val = *src_pixel++ & 0xf;
810 src_val = (*src_pixel >> 4) & 0xf;
811 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
812 rgb = src->color_table[src_val];
813 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
814 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
815 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
817 dst_start += dst->stride / 4;
818 src_start += src->stride;
824 FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
831 static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
833 BYTE *dst_start = dst->bits, *dst_pixel;
837 switch(src->bit_count)
841 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
842 if(src->funcs == &funcs_8888)
844 for(y = src_rect->top; y < src_rect->bottom; y++)
846 dst_pixel = dst_start;
847 src_pixel = src_start;
848 for(x = src_rect->left; x < src_rect->right; x++)
850 src_val = *src_pixel++;
851 *dst_pixel++ = src_val & 0xff;
852 *dst_pixel++ = (src_val >> 8) & 0xff;
853 *dst_pixel++ = (src_val >> 16) & 0xff;
855 dst_start += dst->stride;
856 src_start += src->stride / 4;
861 FIXME("Unsupported conversion: 32 -> 24\n");
869 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
870 if(src->funcs == &funcs_555)
872 for(y = src_rect->top; y < src_rect->bottom; y++)
874 dst_pixel = dst_start;
875 src_pixel = src_start;
876 for(x = src_rect->left; x < src_rect->right; x++)
878 src_val = *src_pixel++;
879 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
880 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
881 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
883 dst_start += dst->stride;
884 src_start += src->stride / 2;
889 FIXME("Unsupported conversion: 16 -> 24\n");
897 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
898 for(y = src_rect->top; y < src_rect->bottom; y++)
900 dst_pixel = dst_start;
901 src_pixel = src_start;
902 for(x = src_rect->left; x < src_rect->right; x++)
905 src_val = *src_pixel++;
906 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
907 rgb = src->color_table[src_val];
908 *dst_pixel++ = rgb.rgbBlue;
909 *dst_pixel++ = rgb.rgbGreen;
910 *dst_pixel++ = rgb.rgbRed;
912 dst_start += dst->stride;
913 src_start += src->stride;
920 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
921 for(y = src_rect->top; y < src_rect->bottom; y++)
923 dst_pixel = dst_start;
924 src_pixel = src_start;
925 for(x = src_rect->left; x < src_rect->right; x++)
929 src_val = *src_pixel++ & 0xf;
931 src_val = (*src_pixel >> 4) & 0xf;
932 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
933 rgb = src->color_table[src_val];
934 *dst_pixel++ = rgb.rgbBlue;
935 *dst_pixel++ = rgb.rgbGreen;
936 *dst_pixel++ = rgb.rgbRed;
938 dst_start += dst->stride;
939 src_start += src->stride;
945 FIXME("Unsupported conversion: %d -> 24\n", src->bit_count);
952 static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
954 WORD *dst_start = dst->bits, *dst_pixel;
958 switch(src->bit_count)
962 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
964 if(src->funcs == &funcs_8888)
966 for(y = src_rect->top; y < src_rect->bottom; y++)
968 dst_pixel = dst_start;
969 src_pixel = src_start;
970 for(x = src_rect->left; x < src_rect->right; x++)
972 src_val = *src_pixel++;
973 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
974 ((src_val >> 6) & 0x03e0) |
975 ((src_val >> 3) & 0x001e);
977 dst_start += dst->stride / 2;
978 src_start += src->stride / 4;
983 FIXME("Unsupported conversion: 32 -> 555\n");
991 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top);
992 if(src->funcs == &funcs_555)
994 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
995 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
998 for(y = src_rect->top; y < src_rect->bottom; y++)
1000 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1001 dst_start += dst->stride / 2;
1002 src_start += src->stride / 2;
1008 FIXME("Unsupported conversion: 16 -> 555\n");
1016 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1017 for(y = src_rect->top; y < src_rect->bottom; y++)
1019 dst_pixel = dst_start;
1020 src_pixel = src_start;
1021 for(x = src_rect->left; x < src_rect->right; x++)
1024 src_val = *src_pixel++;
1025 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1026 rgb = src->color_table[src_val];
1027 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1028 ((rgb.rgbGreen << 2) & 0x03e0) |
1029 ((rgb.rgbBlue >> 3) & 0x001f);
1031 dst_start += dst->stride / 2;
1032 src_start += src->stride;
1039 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1040 for(y = src_rect->top; y < src_rect->bottom; y++)
1042 dst_pixel = dst_start;
1043 src_pixel = src_start;
1044 for(x = src_rect->left; x < src_rect->right; x++)
1048 src_val = *src_pixel++ & 0xf;
1050 src_val = (*src_pixel >> 4) & 0xf;
1051 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1052 rgb = src->color_table[src_val];
1053 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1054 ((rgb.rgbGreen << 2) & 0x03e0) |
1055 ((rgb.rgbBlue >> 3) & 0x001f);
1057 dst_start += dst->stride / 2;
1058 src_start += src->stride;
1064 FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
1071 static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
1073 WORD *dst_start = dst->bits, *dst_pixel;
1077 switch(src->bit_count)
1081 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1083 if(src->funcs == &funcs_8888)
1085 for(y = src_rect->top; y < src_rect->bottom; y++)
1087 dst_pixel = dst_start;
1088 src_pixel = src_start;
1089 for(x = src_rect->left; x < src_rect->right; x++)
1091 src_val = *src_pixel++;
1092 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
1093 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
1094 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
1096 dst_start += dst->stride / 2;
1097 src_start += src->stride / 4;
1102 FIXME("Unsupported conversion: 32 -> 16\n");
1110 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1111 if(src->funcs == &funcs_555)
1113 for(y = src_rect->top; y < src_rect->bottom; y++)
1115 dst_pixel = dst_start;
1116 src_pixel = src_start;
1117 for(x = src_rect->left; x < src_rect->right; x++)
1119 src_val = *src_pixel++;
1120 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1121 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1122 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1124 dst_start += dst->stride / 2;
1125 src_start += src->stride / 2;
1130 FIXME("Unsupported conversion: 16 -> 16\n");
1138 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1139 for(y = src_rect->top; y < src_rect->bottom; y++)
1141 dst_pixel = dst_start;
1142 src_pixel = src_start;
1143 for(x = src_rect->left; x < src_rect->right; x++)
1146 src_val = *src_pixel++;
1147 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1148 rgb = src->color_table[src_val];
1149 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1150 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1151 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1153 dst_start += dst->stride / 2;
1154 src_start += src->stride;
1161 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1162 for(y = src_rect->top; y < src_rect->bottom; y++)
1164 dst_pixel = dst_start;
1165 src_pixel = src_start;
1166 for(x = src_rect->left; x < src_rect->right; x++)
1170 src_val = *src_pixel++ & 0xf;
1172 src_val = (*src_pixel >> 4) & 0xf;
1173 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1174 rgb = src->color_table[src_val];
1175 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1176 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1177 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1179 dst_start += dst->stride / 2;
1180 src_start += src->stride;
1186 FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
1193 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
1195 assert(d1->color_table_size && d2->color_table_size);
1197 if(d1->color_table_size != d2->color_table_size) return FALSE;
1198 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
1201 static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
1203 BYTE *dst_start = dst->bits, *dst_pixel;
1207 switch(src->bit_count)
1211 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1213 if(src->funcs == &funcs_8888)
1215 for(y = src_rect->top; y < src_rect->bottom; y++)
1217 dst_pixel = dst_start;
1218 src_pixel = src_start;
1219 for(x = src_rect->left; x < src_rect->right; x++)
1221 src_val = *src_pixel++;
1222 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1223 ( src_val & 0x00ff00) |
1224 ((src_val << 16) & 0xff0000) );
1226 dst_start += dst->stride;
1227 src_start += src->stride / 4;
1232 FIXME("Unsupported conversion: 32 -> 8\n");
1240 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1241 if(src->funcs == &funcs_555)
1243 for(y = src_rect->top; y < src_rect->bottom; y++)
1245 dst_pixel = dst_start;
1246 src_pixel = src_start;
1247 for(x = src_rect->left; x < src_rect->right; x++)
1249 src_val = *src_pixel++;
1250 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
1251 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1252 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
1254 dst_start += dst->stride;
1255 src_start += src->stride / 2;
1260 FIXME("Unsupported conversion: 16 -> 8\n");
1268 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1270 if(color_tables_match(dst, src))
1272 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1273 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1276 for(y = src_rect->top; y < src_rect->bottom; y++)
1278 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
1279 dst_start += dst->stride;
1280 src_start += src->stride;
1286 for(y = src_rect->top; y < src_rect->bottom; y++)
1288 dst_pixel = dst_start;
1289 src_pixel = src_start;
1290 for(x = src_rect->left; x < src_rect->right; x++)
1293 src_val = *src_pixel++;
1294 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1295 rgb = src->color_table[src_val];
1296 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1298 dst_start += dst->stride;
1299 src_start += src->stride;
1307 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1308 for(y = src_rect->top; y < src_rect->bottom; y++)
1310 dst_pixel = dst_start;
1311 src_pixel = src_start;
1312 for(x = src_rect->left; x < src_rect->right; x++)
1316 src_val = *src_pixel++ & 0xf;
1318 src_val = (*src_pixel >> 4) & 0xf;
1319 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1320 rgb = src->color_table[src_val];
1321 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1323 dst_start += dst->stride;
1324 src_start += src->stride;
1330 FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
1337 static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
1339 BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
1343 switch(src->bit_count)
1347 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1349 if(src->funcs == &funcs_8888)
1351 for(y = src_rect->top; y < src_rect->bottom; y++)
1353 dst_pixel = dst_start;
1354 src_pixel = src_start;
1355 for(x = src_rect->left; x < src_rect->right; x++)
1357 src_val = *src_pixel++;
1358 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1359 ( src_val & 0x00ff00) |
1360 ((src_val << 16) & 0xff0000) );
1361 if((x - src_rect->left) & 1)
1363 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1367 *dst_pixel = (dst_val << 4) & 0xf0;
1369 dst_start += dst->stride;
1370 src_start += src->stride / 4;
1375 FIXME("Unsupported conversion: 32 -> 4\n");
1383 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1384 if(src->funcs == &funcs_555)
1386 for(y = src_rect->top; y < src_rect->bottom; y++)
1388 dst_pixel = dst_start;
1389 src_pixel = src_start;
1390 for(x = src_rect->left; x < src_rect->right; x++)
1392 src_val = *src_pixel++;
1393 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
1394 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1395 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
1396 if((x - src_rect->left) & 1)
1398 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1402 *dst_pixel = (dst_val << 4) & 0xf0;
1404 dst_start += dst->stride;
1405 src_start += src->stride / 2;
1410 FIXME("Unsupported conversion: 16 -> 4\n");
1418 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1420 for(y = src_rect->top; y < src_rect->bottom; y++)
1422 dst_pixel = dst_start;
1423 src_pixel = src_start;
1424 for(x = src_rect->left; x < src_rect->right; x++)
1427 src_val = *src_pixel++;
1428 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1429 rgb = src->color_table[src_val];
1430 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1431 if((x - src_rect->left) & 1)
1433 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1437 *dst_pixel = (dst_val << 4) & 0xf0;
1439 dst_start += dst->stride;
1440 src_start += src->stride;
1447 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1449 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
1451 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1452 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1455 for(y = src_rect->top; y < src_rect->bottom; y++)
1457 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
1458 dst_start += dst->stride;
1459 src_start += src->stride;
1465 for(y = src_rect->top; y < src_rect->bottom; y++)
1467 dst_pixel = dst_start;
1468 src_pixel = src_start;
1469 for(x = src_rect->left; x < src_rect->right; x++)
1473 src_val = *src_pixel++ & 0xf;
1475 src_val = (*src_pixel >> 4) & 0xf;
1476 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1477 rgb = src->color_table[src_val];
1478 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1479 if((x - src_rect->left) & 1)
1481 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1485 *dst_pixel = (dst_val << 4) & 0xf0;
1487 dst_start += dst->stride;
1488 src_start += src->stride;
1495 FIXME("Unsupported conversion: %d -> 4\n", src->bit_count);
1503 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
1508 const primitive_funcs funcs_8888 =
1512 colorref_to_pixel_888,
1516 const primitive_funcs funcs_32 =
1520 colorref_to_pixel_masks,
1524 const primitive_funcs funcs_24 =
1528 colorref_to_pixel_888,
1532 const primitive_funcs funcs_555 =
1536 colorref_to_pixel_555,
1540 const primitive_funcs funcs_16 =
1544 colorref_to_pixel_masks,
1548 const primitive_funcs funcs_8 =
1552 colorref_to_pixel_colortable,
1556 const primitive_funcs funcs_4 =
1560 colorref_to_pixel_colortable,
1564 const primitive_funcs funcs_null =
1568 colorref_to_pixel_null,