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 WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
37 return (WORD *)((BYTE*)dib->bits + y * dib->stride + x * 2);
40 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
42 return (BYTE*)dib->bits + y * dib->stride + x;
45 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
47 return (BYTE*)dib->bits + y * dib->stride + x / 2;
50 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
52 *ptr = (*ptr & and) ^ xor;
55 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
57 *ptr = (*ptr & and) ^ xor;
60 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
62 *ptr = (*ptr & and) ^ xor;
65 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
70 for(i = 0; i < num; i++, rc++)
72 start = get_pixel_ptr_32(dib, rc->left, rc->top);
73 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
74 for(x = rc->left, ptr = start; x < rc->right; x++)
75 do_rop_32(ptr++, and, xor);
79 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
84 for(i = 0; i < num; i++, rc++)
86 start = get_pixel_ptr_16(dib, rc->left, rc->top);
87 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
88 for(x = rc->left, ptr = start; x < rc->right; x++)
89 do_rop_16(ptr++, and, xor);
93 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
98 for(i = 0; i < num; i++, rc++)
100 start = get_pixel_ptr_8(dib, rc->left, rc->top);
101 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
102 for(x = rc->left, ptr = start; x < rc->right; x++)
103 do_rop_8(ptr++, and, xor);
107 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
111 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
112 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
114 for(i = 0; i < num; i++, rc++)
116 if(rc->left >= rc->right) continue;
117 start = get_pixel_ptr_4(dib, rc->left, rc->top);
118 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
121 if(rc->left & 1) /* upper nibble untouched */
122 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
124 for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
125 do_rop_8(ptr++, byte_and, byte_xor);
127 if(rc->right & 1) /* lower nibble untouched */
128 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
133 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
138 static inline INT calc_offset(INT edge, INT size, INT origin)
142 if(edge - origin >= 0)
143 offset = (edge - origin) % size;
146 offset = (origin - edge) % size;
147 if(offset) offset = size - offset;
152 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
156 offset.x = calc_offset(rc->left, brush->width, origin->x);
157 offset.y = calc_offset(rc->top, brush->height, origin->y);
162 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
163 const dib_info *brush, void *and_bits, void *xor_bits)
165 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
169 for(i = 0; i < num; i++, rc++)
171 offset = calc_brush_offset(rc, brush, origin);
173 start = get_pixel_ptr_32(dib, rc->left, rc->top);
174 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
175 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
177 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
179 and_ptr = start_and + offset.x;
180 xor_ptr = start_xor + offset.x;
182 for(x = rc->left, ptr = start; x < rc->right; x++)
184 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
185 if(and_ptr == start_and + brush->width)
193 if(offset.y == brush->height)
195 start_and = and_bits;
196 start_xor = xor_bits;
201 start_and += brush->stride / 4;
202 start_xor += brush->stride / 4;
208 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
209 const dib_info *brush, void *and_bits, void *xor_bits)
211 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
215 for(i = 0; i < num; i++, rc++)
217 offset = calc_brush_offset(rc, brush, origin);
219 start = get_pixel_ptr_16(dib, rc->left, rc->top);
220 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
221 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
223 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
225 and_ptr = start_and + offset.x;
226 xor_ptr = start_xor + offset.x;
228 for(x = rc->left, ptr = start; x < rc->right; x++)
230 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
231 if(and_ptr == start_and + brush->width)
239 if(offset.y == brush->height)
241 start_and = and_bits;
242 start_xor = xor_bits;
247 start_and += brush->stride / 2;
248 start_xor += brush->stride / 2;
254 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
255 const dib_info *brush, void *and_bits, void *xor_bits)
257 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
261 for(i = 0; i < num; i++, rc++)
263 offset = calc_brush_offset(rc, brush, origin);
265 start = get_pixel_ptr_8(dib, rc->left, rc->top);
266 start_and = (BYTE*)and_bits + offset.y * brush->stride;
267 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
269 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
271 and_ptr = start_and + offset.x;
272 xor_ptr = start_xor + offset.x;
274 for(x = rc->left, ptr = start; x < rc->right; x++)
276 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
277 if(and_ptr == start_and + brush->width)
285 if(offset.y == brush->height)
287 start_and = and_bits;
288 start_xor = xor_bits;
293 start_and += brush->stride;
294 start_xor += brush->stride;
300 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
301 const dib_info *brush, void *and_bits, void *xor_bits)
303 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
307 for(i = 0; i < num; i++, rc++)
309 offset = calc_brush_offset(rc, brush, origin);
311 start = get_pixel_ptr_4(dib, rc->left, rc->top);
312 start_and = (BYTE*)and_bits + offset.y * brush->stride;
313 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
315 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
317 INT brush_x = offset.x;
318 BYTE byte_and, byte_xor;
320 and_ptr = start_and + brush_x / 2;
321 xor_ptr = start_xor + brush_x / 2;
323 for(x = rc->left, ptr = start; x < rc->right; x++)
325 /* FIXME: Two pixels at a time */
326 if(x & 1) /* lower dst nibble */
328 if(brush_x & 1) /* lower pat nibble */
330 byte_and = *and_ptr++ | 0xf0;
331 byte_xor = *xor_ptr++ & 0x0f;
333 else /* upper pat nibble */
335 byte_and = (*and_ptr >> 4) | 0xf0;
336 byte_xor = (*xor_ptr >> 4) & 0x0f;
339 else /* upper dst nibble */
341 if(brush_x & 1) /* lower pat nibble */
343 byte_and = (*and_ptr++ << 4) | 0x0f;
344 byte_xor = (*xor_ptr++ << 4) & 0xf0;
346 else /* upper pat nibble */
348 byte_and = *and_ptr | 0x0f;
349 byte_xor = *xor_ptr & 0xf0;
352 do_rop_8(ptr, byte_and, byte_xor);
356 if(++brush_x == brush->width)
365 if(offset.y == brush->height)
367 start_and = and_bits;
368 start_xor = xor_bits;
373 start_and += brush->stride;
374 start_xor += brush->stride;
380 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
381 const dib_info *brush, void *and_bits, void *xor_bits)
386 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
388 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
391 static inline DWORD put_field(DWORD field, int shift, int len)
393 shift = shift - (8 - len);
395 field &= (((1 << len) - 1) << (8 - len));
403 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
407 r = GetRValue(colour);
408 g = GetGValue(colour);
409 b = GetBValue(colour);
411 return put_field(r, dib->red_shift, dib->red_len) |
412 put_field(g, dib->green_shift, dib->green_len) |
413 put_field(b, dib->blue_shift, dib->blue_len);
416 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
418 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
421 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
423 int i, best_index = 0;
425 DWORD diff, best_diff = 0xffffffff;
427 rgb.rgbRed = GetRValue(color);
428 rgb.rgbGreen = GetGValue(color);
429 rgb.rgbBlue = GetBValue(color);
431 for(i = 0; i < dib->color_table_size; i++)
433 RGBQUAD *cur = dib->color_table + i;
434 diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
435 + (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
436 + (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
453 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
458 static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
460 DWORD *dst_start = dst->bits, *dst_pixel, src_val;
463 switch(src->bit_count)
467 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top);
468 if(src->funcs == &funcs_8888)
470 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
471 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
474 for(y = src_rect->top; y < src_rect->bottom; y++)
476 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
477 dst_start += dst->stride / 4;
478 src_start += src->stride / 4;
484 FIXME("Unsupported conversion: 32 -> 8888\n");
492 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
493 if(src->funcs == &funcs_555)
495 for(y = src_rect->top; y < src_rect->bottom; y++)
497 dst_pixel = dst_start;
498 src_pixel = src_start;
499 for(x = src_rect->left; x < src_rect->right; x++)
501 src_val = *src_pixel++;
502 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
503 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
504 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
506 dst_start += dst->stride / 4;
507 src_start += src->stride / 2;
512 FIXME("Unsupported conversion: 16 -> 8888\n");
520 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
521 for(y = src_rect->top; y < src_rect->bottom; y++)
523 dst_pixel = dst_start;
524 src_pixel = src_start;
525 for(x = src_rect->left; x < src_rect->right; x++)
528 src_val = *src_pixel++;
529 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
530 rgb = src->color_table[src_val];
531 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
533 dst_start += dst->stride / 4;
534 src_start += src->stride;
541 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
542 for(y = src_rect->top; y < src_rect->bottom; y++)
544 dst_pixel = dst_start;
545 src_pixel = src_start;
546 for(x = src_rect->left; x < src_rect->right; x++)
550 src_val = *src_pixel++ & 0xf;
552 src_val = (*src_pixel >> 4) & 0xf;
553 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
554 rgb = src->color_table[src_val];
555 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
557 dst_start += dst->stride / 4;
558 src_start += src->stride;
564 FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
571 static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
573 DWORD *dst_start = dst->bits, *dst_pixel, src_val;
576 switch(src->bit_count)
580 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
582 if(src->funcs == &funcs_8888)
584 for(y = src_rect->top; y < src_rect->bottom; y++)
586 dst_pixel = dst_start;
587 src_pixel = src_start;
588 for(x = src_rect->left; x < src_rect->right; x++)
590 src_val = *src_pixel++;
591 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
592 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
593 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
595 dst_start += dst->stride / 4;
596 src_start += src->stride / 4;
601 FIXME("Unsupported conversion: 32 -> 32\n");
609 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
610 if(src->funcs == &funcs_555)
612 for(y = src_rect->top; y < src_rect->bottom; y++)
614 dst_pixel = dst_start;
615 src_pixel = src_start;
616 for(x = src_rect->left; x < src_rect->right; x++)
618 src_val = *src_pixel++;
619 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
620 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
621 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
623 dst_start += dst->stride / 4;
624 src_start += src->stride / 2;
629 FIXME("Unsupported conversion: 16 -> 8888\n");
637 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
638 for(y = src_rect->top; y < src_rect->bottom; y++)
640 dst_pixel = dst_start;
641 src_pixel = src_start;
642 for(x = src_rect->left; x < src_rect->right; x++)
645 src_val = *src_pixel++;
646 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
647 rgb = src->color_table[src_val];
648 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
649 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
650 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
652 dst_start += dst->stride / 4;
653 src_start += src->stride;
660 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
661 for(y = src_rect->top; y < src_rect->bottom; y++)
663 dst_pixel = dst_start;
664 src_pixel = src_start;
665 for(x = src_rect->left; x < src_rect->right; x++)
669 src_val = *src_pixel++ & 0xf;
671 src_val = (*src_pixel >> 4) & 0xf;
672 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
673 rgb = src->color_table[src_val];
674 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
675 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
676 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
678 dst_start += dst->stride / 4;
679 src_start += src->stride;
685 FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
692 static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
694 WORD *dst_start = dst->bits, *dst_pixel;
698 switch(src->bit_count)
702 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
704 if(src->funcs == &funcs_8888)
706 for(y = src_rect->top; y < src_rect->bottom; y++)
708 dst_pixel = dst_start;
709 src_pixel = src_start;
710 for(x = src_rect->left; x < src_rect->right; x++)
712 src_val = *src_pixel++;
713 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
714 ((src_val >> 6) & 0x03e0) |
715 ((src_val >> 3) & 0x001e);
717 dst_start += dst->stride / 2;
718 src_start += src->stride / 4;
723 FIXME("Unsupported conversion: 32 -> 555\n");
731 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top);
732 if(src->funcs == &funcs_555)
734 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
735 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
738 for(y = src_rect->top; y < src_rect->bottom; y++)
740 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
741 dst_start += dst->stride / 2;
742 src_start += src->stride / 2;
748 FIXME("Unsupported conversion: 16 -> 555\n");
756 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
757 for(y = src_rect->top; y < src_rect->bottom; y++)
759 dst_pixel = dst_start;
760 src_pixel = src_start;
761 for(x = src_rect->left; x < src_rect->right; x++)
764 src_val = *src_pixel++;
765 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
766 rgb = src->color_table[src_val];
767 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
768 ((rgb.rgbGreen << 2) & 0x03e0) |
769 ((rgb.rgbBlue >> 3) & 0x001f);
771 dst_start += dst->stride / 2;
772 src_start += src->stride;
779 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
780 for(y = src_rect->top; y < src_rect->bottom; y++)
782 dst_pixel = dst_start;
783 src_pixel = src_start;
784 for(x = src_rect->left; x < src_rect->right; x++)
788 src_val = *src_pixel++ & 0xf;
790 src_val = (*src_pixel >> 4) & 0xf;
791 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
792 rgb = src->color_table[src_val];
793 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
794 ((rgb.rgbGreen << 2) & 0x03e0) |
795 ((rgb.rgbBlue >> 3) & 0x001f);
797 dst_start += dst->stride / 2;
798 src_start += src->stride;
804 FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
811 static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
813 WORD *dst_start = dst->bits, *dst_pixel;
817 switch(src->bit_count)
821 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
823 if(src->funcs == &funcs_8888)
825 for(y = src_rect->top; y < src_rect->bottom; y++)
827 dst_pixel = dst_start;
828 src_pixel = src_start;
829 for(x = src_rect->left; x < src_rect->right; x++)
831 src_val = *src_pixel++;
832 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
833 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
834 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
836 dst_start += dst->stride / 2;
837 src_start += src->stride / 4;
842 FIXME("Unsupported conversion: 32 -> 16\n");
850 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
851 if(src->funcs == &funcs_555)
853 for(y = src_rect->top; y < src_rect->bottom; y++)
855 dst_pixel = dst_start;
856 src_pixel = src_start;
857 for(x = src_rect->left; x < src_rect->right; x++)
859 src_val = *src_pixel++;
860 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
861 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
862 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
864 dst_start += dst->stride / 2;
865 src_start += src->stride / 2;
870 FIXME("Unsupported conversion: 16 -> 16\n");
878 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
879 for(y = src_rect->top; y < src_rect->bottom; y++)
881 dst_pixel = dst_start;
882 src_pixel = src_start;
883 for(x = src_rect->left; x < src_rect->right; x++)
886 src_val = *src_pixel++;
887 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
888 rgb = src->color_table[src_val];
889 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
890 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
891 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
893 dst_start += dst->stride / 2;
894 src_start += src->stride;
901 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
902 for(y = src_rect->top; y < src_rect->bottom; y++)
904 dst_pixel = dst_start;
905 src_pixel = src_start;
906 for(x = src_rect->left; x < src_rect->right; x++)
910 src_val = *src_pixel++ & 0xf;
912 src_val = (*src_pixel >> 4) & 0xf;
913 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
914 rgb = src->color_table[src_val];
915 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
916 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
917 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
919 dst_start += dst->stride / 2;
920 src_start += src->stride;
926 FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
933 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
935 assert(d1->color_table_size && d2->color_table_size);
937 if(d1->color_table_size != d2->color_table_size) return FALSE;
938 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
941 static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
943 BYTE *dst_start = dst->bits, *dst_pixel;
947 switch(src->bit_count)
951 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
953 if(src->funcs == &funcs_8888)
955 for(y = src_rect->top; y < src_rect->bottom; y++)
957 dst_pixel = dst_start;
958 src_pixel = src_start;
959 for(x = src_rect->left; x < src_rect->right; x++)
961 src_val = *src_pixel++;
962 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
963 ( src_val & 0x00ff00) |
964 ((src_val << 16) & 0xff0000) );
966 dst_start += dst->stride;
967 src_start += src->stride / 4;
972 FIXME("Unsupported conversion: 32 -> 8\n");
980 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
981 if(src->funcs == &funcs_555)
983 for(y = src_rect->top; y < src_rect->bottom; y++)
985 dst_pixel = dst_start;
986 src_pixel = src_start;
987 for(x = src_rect->left; x < src_rect->right; x++)
989 src_val = *src_pixel++;
990 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
991 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
992 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
994 dst_start += dst->stride;
995 src_start += src->stride / 2;
1000 FIXME("Unsupported conversion: 16 -> 8\n");
1008 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1010 if(color_tables_match(dst, src))
1012 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1013 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1016 for(y = src_rect->top; y < src_rect->bottom; y++)
1018 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
1019 dst_start += dst->stride;
1020 src_start += src->stride;
1026 for(y = src_rect->top; y < src_rect->bottom; y++)
1028 dst_pixel = dst_start;
1029 src_pixel = src_start;
1030 for(x = src_rect->left; x < src_rect->right; x++)
1033 src_val = *src_pixel++;
1034 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1035 rgb = src->color_table[src_val];
1036 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1038 dst_start += dst->stride;
1039 src_start += src->stride;
1047 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1048 for(y = src_rect->top; y < src_rect->bottom; y++)
1050 dst_pixel = dst_start;
1051 src_pixel = src_start;
1052 for(x = src_rect->left; x < src_rect->right; x++)
1056 src_val = *src_pixel++ & 0xf;
1058 src_val = (*src_pixel >> 4) & 0xf;
1059 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1060 rgb = src->color_table[src_val];
1061 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1063 dst_start += dst->stride;
1064 src_start += src->stride;
1070 FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
1077 static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
1079 BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
1083 switch(src->bit_count)
1087 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1089 if(src->funcs == &funcs_8888)
1091 for(y = src_rect->top; y < src_rect->bottom; y++)
1093 dst_pixel = dst_start;
1094 src_pixel = src_start;
1095 for(x = src_rect->left; x < src_rect->right; x++)
1097 src_val = *src_pixel++;
1098 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1099 ( src_val & 0x00ff00) |
1100 ((src_val << 16) & 0xff0000) );
1101 if((x - src_rect->left) & 1)
1103 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1107 *dst_pixel = (dst_val << 4) & 0xf0;
1109 dst_start += dst->stride;
1110 src_start += src->stride / 4;
1115 FIXME("Unsupported conversion: 32 -> 4\n");
1123 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1124 if(src->funcs == &funcs_555)
1126 for(y = src_rect->top; y < src_rect->bottom; y++)
1128 dst_pixel = dst_start;
1129 src_pixel = src_start;
1130 for(x = src_rect->left; x < src_rect->right; x++)
1132 src_val = *src_pixel++;
1133 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
1134 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1135 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
1136 if((x - src_rect->left) & 1)
1138 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1142 *dst_pixel = (dst_val << 4) & 0xf0;
1144 dst_start += dst->stride;
1145 src_start += src->stride / 2;
1150 FIXME("Unsupported conversion: 16 -> 4\n");
1158 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1160 for(y = src_rect->top; y < src_rect->bottom; y++)
1162 dst_pixel = dst_start;
1163 src_pixel = src_start;
1164 for(x = src_rect->left; x < src_rect->right; x++)
1167 src_val = *src_pixel++;
1168 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1169 rgb = src->color_table[src_val];
1170 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1171 if((x - src_rect->left) & 1)
1173 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1177 *dst_pixel = (dst_val << 4) & 0xf0;
1179 dst_start += dst->stride;
1180 src_start += src->stride;
1187 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1189 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
1191 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1192 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1195 for(y = src_rect->top; y < src_rect->bottom; y++)
1197 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
1198 dst_start += dst->stride;
1199 src_start += src->stride;
1205 for(y = src_rect->top; y < src_rect->bottom; y++)
1207 dst_pixel = dst_start;
1208 src_pixel = src_start;
1209 for(x = src_rect->left; x < src_rect->right; x++)
1213 src_val = *src_pixel++ & 0xf;
1215 src_val = (*src_pixel >> 4) & 0xf;
1216 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1217 rgb = src->color_table[src_val];
1218 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1219 if((x - src_rect->left) & 1)
1221 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1225 *dst_pixel = (dst_val << 4) & 0xf0;
1227 dst_start += dst->stride;
1228 src_start += src->stride;
1235 FIXME("Unsupported conversion: %d -> 4\n", src->bit_count);
1243 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
1248 const primitive_funcs funcs_8888 =
1252 colorref_to_pixel_888,
1256 const primitive_funcs funcs_32 =
1260 colorref_to_pixel_masks,
1264 const primitive_funcs funcs_555 =
1268 colorref_to_pixel_555,
1272 const primitive_funcs funcs_16 =
1276 colorref_to_pixel_masks,
1280 const primitive_funcs funcs_8 =
1284 colorref_to_pixel_colortable,
1288 const primitive_funcs funcs_4 =
1292 colorref_to_pixel_colortable,
1296 const primitive_funcs funcs_null =
1300 colorref_to_pixel_null,