gdi32: Add support for hatched brushes.
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blob68eb4ae568d7a7f7612a56dca086a878483f82aa
1 /*
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
21 #include <assert.h>
23 #include "gdi_private.h"
24 #include "dibdrv.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 BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
62 return (BYTE*)dib->bits + 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 void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
84 DWORD *ptr, *start;
85 int x, y, i;
87 for(i = 0; i < num; i++, rc++)
89 start = get_pixel_ptr_32(dib, rc->left, rc->top);
90 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
91 for(x = rc->left, ptr = start; x < rc->right; x++)
92 do_rop_32(ptr++, and, xor);
96 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
98 DWORD *ptr, *start;
99 BYTE *byte_ptr, *byte_start;
100 int x, y, i;
101 DWORD and_masks[3], xor_masks[3];
103 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
104 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
105 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
106 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
107 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
108 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
110 for(i = 0; i < num; i++, rc++)
112 if(rc->left >= rc->right) continue;
114 if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
116 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
117 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
119 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
121 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
122 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
123 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
127 else
129 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
130 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
132 ptr = start;
134 switch(rc->left & 3)
136 case 1:
137 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
138 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
139 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
140 break;
141 case 2:
142 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
143 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
144 break;
145 case 3:
146 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
147 break;
150 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
152 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
153 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
154 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
157 switch(rc->right & 3)
159 case 1:
160 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
161 break;
162 case 2:
163 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
164 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
165 break;
166 case 3:
167 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
168 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
169 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
170 break;
177 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
179 WORD *ptr, *start;
180 int x, y, i;
182 for(i = 0; i < num; i++, rc++)
184 start = get_pixel_ptr_16(dib, rc->left, rc->top);
185 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
186 for(x = rc->left, ptr = start; x < rc->right; x++)
187 do_rop_16(ptr++, and, xor);
191 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
193 BYTE *ptr, *start;
194 int x, y, i;
196 for(i = 0; i < num; i++, rc++)
198 start = get_pixel_ptr_8(dib, rc->left, rc->top);
199 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
200 for(x = rc->left, ptr = start; x < rc->right; x++)
201 do_rop_8(ptr++, and, xor);
205 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
207 BYTE *ptr, *start;
208 int x, y, i;
209 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
210 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
212 for(i = 0; i < num; i++, rc++)
214 if(rc->left >= rc->right) continue;
215 start = get_pixel_ptr_4(dib, rc->left, rc->top);
216 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
218 ptr = start;
219 if(rc->left & 1) /* upper nibble untouched */
220 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
222 for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
223 do_rop_8(ptr++, byte_and, byte_xor);
225 if(rc->right & 1) /* lower nibble untouched */
226 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
231 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
233 BYTE *ptr, *start;
234 int x, y, i;
235 BYTE byte_and = (and & 1) ? 0xff : 0;
236 BYTE byte_xor = (xor & 1) ? 0xff : 0;
237 BYTE start_and, start_xor, end_and, end_xor, mask;
238 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
240 for(i = 0; i < num; i++, rc++)
242 if(rc->left >= rc->right) continue;
244 start = get_pixel_ptr_1(dib, rc->left, rc->top);
246 if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
248 mask = masks[rc->left & 7] & ~masks[rc->right & 7];
250 start_and = byte_and | ~mask;
251 start_xor = byte_xor & mask;
252 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
254 do_rop_8(start, start_and, start_xor);
257 else
259 mask = masks[rc->left & 7];
260 start_and = byte_and | ~mask;
261 start_xor = byte_xor & mask;
263 mask = masks[rc->right & 7];
264 /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
265 end_and = byte_and | mask;
266 end_xor = byte_xor & ~mask;
268 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
270 ptr = start;
272 if(rc->left & 7)
273 do_rop_8(ptr++, start_and, start_xor);
275 for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
276 do_rop_8(ptr++, byte_and, byte_xor);
278 if(rc->right & 7)
279 do_rop_8(ptr, end_and, end_xor);
285 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
287 return;
290 static inline INT calc_offset(INT edge, INT size, INT origin)
292 INT offset;
294 if(edge - origin >= 0)
295 offset = (edge - origin) % size;
296 else
298 offset = (origin - edge) % size;
299 if(offset) offset = size - offset;
301 return offset;
304 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
306 POINT offset;
308 offset.x = calc_offset(rc->left, brush->width, origin->x);
309 offset.y = calc_offset(rc->top, brush->height, origin->y);
311 return offset;
314 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
315 const dib_info *brush, void *and_bits, void *xor_bits)
317 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
318 int x, y, i;
319 POINT offset;
321 for(i = 0; i < num; i++, rc++)
323 offset = calc_brush_offset(rc, brush, origin);
325 start = get_pixel_ptr_32(dib, rc->left, rc->top);
326 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
327 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
329 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
331 and_ptr = start_and + offset.x;
332 xor_ptr = start_xor + offset.x;
334 for(x = rc->left, ptr = start; x < rc->right; x++)
336 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
337 if(and_ptr == start_and + brush->width)
339 and_ptr = start_and;
340 xor_ptr = start_xor;
344 offset.y++;
345 if(offset.y == brush->height)
347 start_and = and_bits;
348 start_xor = xor_bits;
349 offset.y = 0;
351 else
353 start_and += brush->stride / 4;
354 start_xor += brush->stride / 4;
360 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
361 const dib_info *brush, void *and_bits, void *xor_bits)
363 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
364 int x, y, i;
365 POINT offset;
367 for(i = 0; i < num; i++, rc++)
369 offset = calc_brush_offset(rc, brush, origin);
371 start = get_pixel_ptr_24(dib, rc->left, rc->top);
372 start_and = (BYTE*)and_bits + offset.y * brush->stride;
373 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
375 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
377 and_ptr = start_and + offset.x * 3;
378 xor_ptr = start_xor + offset.x * 3;
380 for(x = rc->left, ptr = start; x < rc->right; x++)
382 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
383 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
384 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
385 if(and_ptr == start_and + brush->width * 3)
387 and_ptr = start_and;
388 xor_ptr = start_xor;
392 offset.y++;
393 if(offset.y == brush->height)
395 start_and = and_bits;
396 start_xor = xor_bits;
397 offset.y = 0;
399 else
401 start_and += brush->stride;
402 start_xor += brush->stride;
408 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
409 const dib_info *brush, void *and_bits, void *xor_bits)
411 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
412 int x, y, i;
413 POINT offset;
415 for(i = 0; i < num; i++, rc++)
417 offset = calc_brush_offset(rc, brush, origin);
419 start = get_pixel_ptr_16(dib, rc->left, rc->top);
420 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
421 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
423 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
425 and_ptr = start_and + offset.x;
426 xor_ptr = start_xor + offset.x;
428 for(x = rc->left, ptr = start; x < rc->right; x++)
430 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
431 if(and_ptr == start_and + brush->width)
433 and_ptr = start_and;
434 xor_ptr = start_xor;
438 offset.y++;
439 if(offset.y == brush->height)
441 start_and = and_bits;
442 start_xor = xor_bits;
443 offset.y = 0;
445 else
447 start_and += brush->stride / 2;
448 start_xor += brush->stride / 2;
454 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
455 const dib_info *brush, void *and_bits, void *xor_bits)
457 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
458 int x, y, i;
459 POINT offset;
461 for(i = 0; i < num; i++, rc++)
463 offset = calc_brush_offset(rc, brush, origin);
465 start = get_pixel_ptr_8(dib, rc->left, rc->top);
466 start_and = (BYTE*)and_bits + offset.y * brush->stride;
467 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
469 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
471 and_ptr = start_and + offset.x;
472 xor_ptr = start_xor + offset.x;
474 for(x = rc->left, ptr = start; x < rc->right; x++)
476 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
477 if(and_ptr == start_and + brush->width)
479 and_ptr = start_and;
480 xor_ptr = start_xor;
484 offset.y++;
485 if(offset.y == brush->height)
487 start_and = and_bits;
488 start_xor = xor_bits;
489 offset.y = 0;
491 else
493 start_and += brush->stride;
494 start_xor += brush->stride;
500 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
501 const dib_info *brush, void *and_bits, void *xor_bits)
503 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
504 int x, y, i;
505 POINT offset;
507 for(i = 0; i < num; i++, rc++)
509 offset = calc_brush_offset(rc, brush, origin);
511 start = get_pixel_ptr_4(dib, rc->left, rc->top);
512 start_and = (BYTE*)and_bits + offset.y * brush->stride;
513 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
515 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
517 INT brush_x = offset.x;
518 BYTE byte_and, byte_xor;
520 and_ptr = start_and + brush_x / 2;
521 xor_ptr = start_xor + brush_x / 2;
523 for(x = rc->left, ptr = start; x < rc->right; x++)
525 /* FIXME: Two pixels at a time */
526 if(x & 1) /* lower dst nibble */
528 if(brush_x & 1) /* lower pat nibble */
530 byte_and = *and_ptr++ | 0xf0;
531 byte_xor = *xor_ptr++ & 0x0f;
533 else /* upper pat nibble */
535 byte_and = (*and_ptr >> 4) | 0xf0;
536 byte_xor = (*xor_ptr >> 4) & 0x0f;
539 else /* upper dst nibble */
541 if(brush_x & 1) /* lower pat nibble */
543 byte_and = (*and_ptr++ << 4) | 0x0f;
544 byte_xor = (*xor_ptr++ << 4) & 0xf0;
546 else /* upper pat nibble */
548 byte_and = *and_ptr | 0x0f;
549 byte_xor = *xor_ptr & 0xf0;
552 do_rop_8(ptr, byte_and, byte_xor);
554 if(x & 1) ptr++;
556 if(++brush_x == brush->width)
558 brush_x = 0;
559 and_ptr = start_and;
560 xor_ptr = start_xor;
564 offset.y++;
565 if(offset.y == brush->height)
567 start_and = and_bits;
568 start_xor = xor_bits;
569 offset.y = 0;
571 else
573 start_and += brush->stride;
574 start_xor += brush->stride;
580 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
581 const dib_info *brush, void *and_bits, void *xor_bits)
583 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
584 int x, y, i;
585 POINT offset;
587 for(i = 0; i < num; i++, rc++)
589 offset = calc_brush_offset(rc, brush, origin);
591 start = get_pixel_ptr_1(dib, rc->left, rc->top);
592 start_and = (BYTE*)and_bits + offset.y * brush->stride;
593 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
595 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
597 INT brush_x = offset.x;
598 BYTE byte_and, byte_xor;
600 and_ptr = start_and + brush_x / 8;
601 xor_ptr = start_xor + brush_x / 8;
603 for(x = rc->left, ptr = start; x < rc->right; x++)
605 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
606 byte_and |= ~pixel_masks_1[x % 8];
607 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
608 byte_xor &= pixel_masks_1[x % 8];
610 do_rop_8(ptr, byte_and, byte_xor);
612 if((x & 7) == 7) ptr++;
614 if((brush_x & 7) == 7)
616 and_ptr++;
617 xor_ptr++;
620 if(++brush_x == brush->width)
622 brush_x = 0;
623 and_ptr = start_and;
624 xor_ptr = start_xor;
628 offset.y++;
629 if(offset.y == brush->height)
631 start_and = and_bits;
632 start_xor = xor_bits;
633 offset.y = 0;
635 else
637 start_and += brush->stride;
638 start_xor += brush->stride;
644 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
645 const dib_info *brush, void *and_bits, void *xor_bits)
647 return;
650 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
652 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
655 static inline DWORD put_field(DWORD field, int shift, int len)
657 shift = shift - (8 - len);
658 if (len <= 8)
659 field &= (((1 << len) - 1) << (8 - len));
660 if (shift < 0)
661 field >>= -shift;
662 else
663 field <<= shift;
664 return field;
667 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
669 DWORD r,g,b;
671 r = GetRValue(colour);
672 g = GetGValue(colour);
673 b = GetBValue(colour);
675 return put_field(r, dib->red_shift, dib->red_len) |
676 put_field(g, dib->green_shift, dib->green_len) |
677 put_field(b, dib->blue_shift, dib->blue_len);
680 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
682 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
685 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
687 int i, best_index = 0;
688 RGBQUAD rgb;
689 DWORD diff, best_diff = 0xffffffff;
691 rgb.rgbRed = GetRValue(color);
692 rgb.rgbGreen = GetGValue(color);
693 rgb.rgbBlue = GetBValue(color);
695 for(i = 0; i < dib->color_table_size; i++)
697 RGBQUAD *cur = dib->color_table + i;
698 diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
699 + (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
700 + (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
702 if(diff == 0)
704 best_index = i;
705 break;
708 if(diff < best_diff)
710 best_diff = diff;
711 best_index = i;
714 return best_index;
717 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
719 return 0;
722 static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
724 DWORD *dst_start = dst->bits, *dst_pixel, src_val;
725 int x, y;
727 switch(src->bit_count)
729 case 32:
731 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top);
732 if(src->funcs == &funcs_8888)
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);
736 else
738 for(y = src_rect->top; y < src_rect->bottom; y++)
740 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
741 dst_start += dst->stride / 4;
742 src_start += src->stride / 4;
746 else
748 FIXME("Unsupported conversion: 32 -> 8888\n");
749 return FALSE;
751 break;
754 case 24:
756 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
758 for(y = src_rect->top; y < src_rect->bottom; y++)
760 dst_pixel = dst_start;
761 src_pixel = src_start;
762 for(x = src_rect->left; x < src_rect->right; x++)
764 RGBQUAD rgb;
765 rgb.rgbBlue = *src_pixel++;
766 rgb.rgbGreen = *src_pixel++;
767 rgb.rgbRed = *src_pixel++;
769 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
771 dst_start += dst->stride / 4;
772 src_start += src->stride;
774 break;
777 case 16:
779 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
780 if(src->funcs == &funcs_555)
782 for(y = src_rect->top; y < src_rect->bottom; y++)
784 dst_pixel = dst_start;
785 src_pixel = src_start;
786 for(x = src_rect->left; x < src_rect->right; x++)
788 src_val = *src_pixel++;
789 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
790 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
791 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
793 dst_start += dst->stride / 4;
794 src_start += src->stride / 2;
797 else
799 FIXME("Unsupported conversion: 16 -> 8888\n");
800 return FALSE;
802 break;
805 case 8:
807 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
808 for(y = src_rect->top; y < src_rect->bottom; y++)
810 dst_pixel = dst_start;
811 src_pixel = src_start;
812 for(x = src_rect->left; x < src_rect->right; x++)
814 RGBQUAD rgb;
815 src_val = *src_pixel++;
816 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
817 rgb = src->color_table[src_val];
818 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
820 dst_start += dst->stride / 4;
821 src_start += src->stride;
823 break;
826 case 4:
828 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
829 for(y = src_rect->top; y < src_rect->bottom; y++)
831 dst_pixel = dst_start;
832 src_pixel = src_start;
833 for(x = src_rect->left; x < src_rect->right; x++)
835 RGBQUAD rgb;
836 if(x & 1)
837 src_val = *src_pixel++ & 0xf;
838 else
839 src_val = (*src_pixel >> 4) & 0xf;
840 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
841 rgb = src->color_table[src_val];
842 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
844 dst_start += dst->stride / 4;
845 src_start += src->stride;
847 break;
850 case 1:
852 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
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 RGBQUAD rgb;
860 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
861 if((x % 8) == 7) src_pixel++;
862 rgb = src->color_table[src_val];
863 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
865 dst_start += dst->stride / 4;
866 src_start += src->stride;
868 break;
871 default:
872 FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
873 return FALSE;
876 return TRUE;
879 static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
881 DWORD *dst_start = dst->bits, *dst_pixel, src_val;
882 int x, y;
884 switch(src->bit_count)
886 case 32:
888 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
890 if(src->funcs == &funcs_8888)
892 for(y = src_rect->top; y < src_rect->bottom; y++)
894 dst_pixel = dst_start;
895 src_pixel = src_start;
896 for(x = src_rect->left; x < src_rect->right; x++)
898 src_val = *src_pixel++;
899 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
900 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
901 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
903 dst_start += dst->stride / 4;
904 src_start += src->stride / 4;
907 else
909 FIXME("Unsupported conversion: 32 -> 32\n");
910 return FALSE;
912 break;
915 case 24:
917 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
919 for(y = src_rect->top; y < src_rect->bottom; y++)
921 dst_pixel = dst_start;
922 src_pixel = src_start;
923 for(x = src_rect->left; x < src_rect->right; x++)
925 RGBQUAD rgb;
926 rgb.rgbBlue = *src_pixel++;
927 rgb.rgbGreen = *src_pixel++;
928 rgb.rgbRed = *src_pixel++;
930 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
931 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
932 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
934 dst_start += dst->stride / 4;
935 src_start += src->stride;
937 break;
940 case 16:
942 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
943 if(src->funcs == &funcs_555)
945 for(y = src_rect->top; y < src_rect->bottom; y++)
947 dst_pixel = dst_start;
948 src_pixel = src_start;
949 for(x = src_rect->left; x < src_rect->right; x++)
951 src_val = *src_pixel++;
952 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
953 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
954 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
956 dst_start += dst->stride / 4;
957 src_start += src->stride / 2;
960 else
962 FIXME("Unsupported conversion: 16 -> 8888\n");
963 return FALSE;
965 break;
968 case 8:
970 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
971 for(y = src_rect->top; y < src_rect->bottom; y++)
973 dst_pixel = dst_start;
974 src_pixel = src_start;
975 for(x = src_rect->left; x < src_rect->right; x++)
977 RGBQUAD rgb;
978 src_val = *src_pixel++;
979 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
980 rgb = src->color_table[src_val];
981 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
982 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
983 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
985 dst_start += dst->stride / 4;
986 src_start += src->stride;
988 break;
991 case 4:
993 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
994 for(y = src_rect->top; y < src_rect->bottom; y++)
996 dst_pixel = dst_start;
997 src_pixel = src_start;
998 for(x = src_rect->left; x < src_rect->right; x++)
1000 RGBQUAD rgb;
1001 if(x & 1)
1002 src_val = *src_pixel++ & 0xf;
1003 else
1004 src_val = (*src_pixel >> 4) & 0xf;
1005 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1006 rgb = src->color_table[src_val];
1007 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1008 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1009 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1011 dst_start += dst->stride / 4;
1012 src_start += src->stride;
1014 break;
1017 case 1:
1019 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1020 for(y = src_rect->top; y < src_rect->bottom; y++)
1022 dst_pixel = dst_start;
1023 src_pixel = src_start;
1024 for(x = src_rect->left; x < src_rect->right; x++)
1026 RGBQUAD rgb;
1027 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1028 if((x % 8) == 7) src_pixel++;
1029 rgb = src->color_table[src_val];
1030 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1031 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1032 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1034 dst_start += dst->stride / 4;
1035 src_start += src->stride;
1037 break;
1040 default:
1041 FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
1042 return FALSE;
1045 return TRUE;
1048 static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1050 BYTE *dst_start = dst->bits, *dst_pixel;
1051 DWORD src_val;
1052 int x, y;
1054 switch(src->bit_count)
1056 case 32:
1058 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1059 if(src->funcs == &funcs_8888)
1061 for(y = src_rect->top; y < src_rect->bottom; y++)
1063 dst_pixel = dst_start;
1064 src_pixel = src_start;
1065 for(x = src_rect->left; x < src_rect->right; x++)
1067 src_val = *src_pixel++;
1068 *dst_pixel++ = src_val & 0xff;
1069 *dst_pixel++ = (src_val >> 8) & 0xff;
1070 *dst_pixel++ = (src_val >> 16) & 0xff;
1072 dst_start += dst->stride;
1073 src_start += src->stride / 4;
1076 else
1078 FIXME("Unsupported conversion: 32 -> 24\n");
1079 return FALSE;
1081 break;
1084 case 24:
1086 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1088 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1089 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1090 else
1092 for(y = src_rect->top; y < src_rect->bottom; y++)
1094 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1095 dst_start += dst->stride;
1096 src_start += src->stride;
1099 break;
1102 case 16:
1104 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1105 if(src->funcs == &funcs_555)
1107 for(y = src_rect->top; y < src_rect->bottom; y++)
1109 dst_pixel = dst_start;
1110 src_pixel = src_start;
1111 for(x = src_rect->left; x < src_rect->right; x++)
1113 src_val = *src_pixel++;
1114 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
1115 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
1116 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1118 dst_start += dst->stride;
1119 src_start += src->stride / 2;
1122 else
1124 FIXME("Unsupported conversion: 16 -> 24\n");
1125 return FALSE;
1127 break;
1130 case 8:
1132 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1133 for(y = src_rect->top; y < src_rect->bottom; y++)
1135 dst_pixel = dst_start;
1136 src_pixel = src_start;
1137 for(x = src_rect->left; x < src_rect->right; x++)
1139 RGBQUAD rgb;
1140 src_val = *src_pixel++;
1141 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1142 rgb = src->color_table[src_val];
1143 *dst_pixel++ = rgb.rgbBlue;
1144 *dst_pixel++ = rgb.rgbGreen;
1145 *dst_pixel++ = rgb.rgbRed;
1147 dst_start += dst->stride;
1148 src_start += src->stride;
1150 break;
1153 case 4:
1155 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1156 for(y = src_rect->top; y < src_rect->bottom; y++)
1158 dst_pixel = dst_start;
1159 src_pixel = src_start;
1160 for(x = src_rect->left; x < src_rect->right; x++)
1162 RGBQUAD rgb;
1163 if(x & 1)
1164 src_val = *src_pixel++ & 0xf;
1165 else
1166 src_val = (*src_pixel >> 4) & 0xf;
1167 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1168 rgb = src->color_table[src_val];
1169 *dst_pixel++ = rgb.rgbBlue;
1170 *dst_pixel++ = rgb.rgbGreen;
1171 *dst_pixel++ = rgb.rgbRed;
1173 dst_start += dst->stride;
1174 src_start += src->stride;
1176 break;
1179 case 1:
1181 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1182 for(y = src_rect->top; y < src_rect->bottom; y++)
1184 dst_pixel = dst_start;
1185 src_pixel = src_start;
1186 for(x = src_rect->left; x < src_rect->right; x++)
1188 RGBQUAD rgb;
1189 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1190 if((x % 8) == 7) src_pixel++;
1191 rgb = src->color_table[src_val];
1192 *dst_pixel++ = rgb.rgbBlue;
1193 *dst_pixel++ = rgb.rgbGreen;
1194 *dst_pixel++ = rgb.rgbRed;
1196 dst_start += dst->stride;
1197 src_start += src->stride;
1199 break;
1202 default:
1203 FIXME("Unsupported conversion: %d -> 24\n", src->bit_count);
1204 return FALSE;
1207 return TRUE;
1210 static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1212 WORD *dst_start = dst->bits, *dst_pixel;
1213 INT x, y;
1214 DWORD src_val;
1216 switch(src->bit_count)
1218 case 32:
1220 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1222 if(src->funcs == &funcs_8888)
1224 for(y = src_rect->top; y < src_rect->bottom; y++)
1226 dst_pixel = dst_start;
1227 src_pixel = src_start;
1228 for(x = src_rect->left; x < src_rect->right; x++)
1230 src_val = *src_pixel++;
1231 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1232 ((src_val >> 6) & 0x03e0) |
1233 ((src_val >> 3) & 0x001f);
1235 dst_start += dst->stride / 2;
1236 src_start += src->stride / 4;
1239 else
1241 FIXME("Unsupported conversion: 32 -> 555\n");
1242 return FALSE;
1244 break;
1247 case 24:
1249 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1251 for(y = src_rect->top; y < src_rect->bottom; y++)
1253 dst_pixel = dst_start;
1254 src_pixel = src_start;
1255 for(x = src_rect->left; x < src_rect->right; x++)
1257 RGBQUAD rgb;
1258 rgb.rgbBlue = *src_pixel++;
1259 rgb.rgbGreen = *src_pixel++;
1260 rgb.rgbRed = *src_pixel++;
1262 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1263 ((rgb.rgbGreen << 2) & 0x03e0) |
1264 ((rgb.rgbBlue >> 3) & 0x001f);
1266 dst_start += dst->stride / 2;
1267 src_start += src->stride;
1269 break;
1272 case 16:
1274 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top);
1275 if(src->funcs == &funcs_555)
1277 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1278 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1279 else
1281 for(y = src_rect->top; y < src_rect->bottom; y++)
1283 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1284 dst_start += dst->stride / 2;
1285 src_start += src->stride / 2;
1289 else
1291 FIXME("Unsupported conversion: 16 -> 555\n");
1292 return FALSE;
1294 break;
1297 case 8:
1299 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1300 for(y = src_rect->top; y < src_rect->bottom; y++)
1302 dst_pixel = dst_start;
1303 src_pixel = src_start;
1304 for(x = src_rect->left; x < src_rect->right; x++)
1306 RGBQUAD rgb;
1307 src_val = *src_pixel++;
1308 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1309 rgb = src->color_table[src_val];
1310 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1311 ((rgb.rgbGreen << 2) & 0x03e0) |
1312 ((rgb.rgbBlue >> 3) & 0x001f);
1314 dst_start += dst->stride / 2;
1315 src_start += src->stride;
1317 break;
1320 case 4:
1322 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1323 for(y = src_rect->top; y < src_rect->bottom; y++)
1325 dst_pixel = dst_start;
1326 src_pixel = src_start;
1327 for(x = src_rect->left; x < src_rect->right; x++)
1329 RGBQUAD rgb;
1330 if(x & 1)
1331 src_val = *src_pixel++ & 0xf;
1332 else
1333 src_val = (*src_pixel >> 4) & 0xf;
1334 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1335 rgb = src->color_table[src_val];
1336 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1337 ((rgb.rgbGreen << 2) & 0x03e0) |
1338 ((rgb.rgbBlue >> 3) & 0x001f);
1340 dst_start += dst->stride / 2;
1341 src_start += src->stride;
1343 break;
1346 case 1:
1348 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1349 for(y = src_rect->top; y < src_rect->bottom; y++)
1351 dst_pixel = dst_start;
1352 src_pixel = src_start;
1353 for(x = src_rect->left; x < src_rect->right; x++)
1355 RGBQUAD rgb;
1356 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1357 if((x % 8) == 7) src_pixel++;
1358 rgb = src->color_table[src_val];
1359 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1360 ((rgb.rgbGreen << 2) & 0x03e0) |
1361 ((rgb.rgbBlue >> 3) & 0x001f);
1363 dst_start += dst->stride / 2;
1364 src_start += src->stride;
1366 break;
1369 default:
1370 FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
1371 return FALSE;
1374 return TRUE;
1377 static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
1379 WORD *dst_start = dst->bits, *dst_pixel;
1380 INT x, y;
1381 DWORD src_val;
1383 switch(src->bit_count)
1385 case 32:
1387 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1389 if(src->funcs == &funcs_8888)
1391 for(y = src_rect->top; y < src_rect->bottom; y++)
1393 dst_pixel = dst_start;
1394 src_pixel = src_start;
1395 for(x = src_rect->left; x < src_rect->right; x++)
1397 src_val = *src_pixel++;
1398 *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
1399 put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
1400 put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
1402 dst_start += dst->stride / 2;
1403 src_start += src->stride / 4;
1406 else
1408 FIXME("Unsupported conversion: 32 -> 16\n");
1409 return FALSE;
1411 break;
1414 case 24:
1416 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1418 for(y = src_rect->top; y < src_rect->bottom; y++)
1420 dst_pixel = dst_start;
1421 src_pixel = src_start;
1422 for(x = src_rect->left; x < src_rect->right; x++)
1424 RGBQUAD rgb;
1425 rgb.rgbBlue = *src_pixel++;
1426 rgb.rgbGreen = *src_pixel++;
1427 rgb.rgbRed = *src_pixel++;
1429 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1430 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1431 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1433 dst_start += dst->stride / 2;
1434 src_start += src->stride;
1436 break;
1439 case 16:
1441 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1442 if(src->funcs == &funcs_555)
1444 for(y = src_rect->top; y < src_rect->bottom; y++)
1446 dst_pixel = dst_start;
1447 src_pixel = src_start;
1448 for(x = src_rect->left; x < src_rect->right; x++)
1450 src_val = *src_pixel++;
1451 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1452 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1453 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1455 dst_start += dst->stride / 2;
1456 src_start += src->stride / 2;
1459 else
1461 FIXME("Unsupported conversion: 16 -> 16\n");
1462 return FALSE;
1464 break;
1467 case 8:
1469 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1470 for(y = src_rect->top; y < src_rect->bottom; y++)
1472 dst_pixel = dst_start;
1473 src_pixel = src_start;
1474 for(x = src_rect->left; x < src_rect->right; x++)
1476 RGBQUAD rgb;
1477 src_val = *src_pixel++;
1478 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1479 rgb = src->color_table[src_val];
1480 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1481 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1482 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1484 dst_start += dst->stride / 2;
1485 src_start += src->stride;
1487 break;
1490 case 4:
1492 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1493 for(y = src_rect->top; y < src_rect->bottom; y++)
1495 dst_pixel = dst_start;
1496 src_pixel = src_start;
1497 for(x = src_rect->left; x < src_rect->right; x++)
1499 RGBQUAD rgb;
1500 if(x & 1)
1501 src_val = *src_pixel++ & 0xf;
1502 else
1503 src_val = (*src_pixel >> 4) & 0xf;
1504 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1505 rgb = src->color_table[src_val];
1506 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1507 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1508 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1510 dst_start += dst->stride / 2;
1511 src_start += src->stride;
1513 break;
1516 case 1:
1518 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1519 for(y = src_rect->top; y < src_rect->bottom; y++)
1521 dst_pixel = dst_start;
1522 src_pixel = src_start;
1523 for(x = src_rect->left; x < src_rect->right; x++)
1525 RGBQUAD rgb;
1526 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1527 if((x % 8) == 7) src_pixel++;
1528 rgb = src->color_table[src_val];
1529 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1530 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1531 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1533 dst_start += dst->stride / 2;
1534 src_start += src->stride;
1536 break;
1539 default:
1540 FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
1541 return FALSE;
1544 return TRUE;
1547 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
1549 assert(d1->color_table_size && d2->color_table_size);
1551 if(d1->color_table_size != d2->color_table_size) return FALSE;
1552 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
1555 static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
1557 BYTE *dst_start = dst->bits, *dst_pixel;
1558 INT x, y;
1559 DWORD src_val;
1561 switch(src->bit_count)
1563 case 32:
1565 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1567 if(src->funcs == &funcs_8888)
1569 for(y = src_rect->top; y < src_rect->bottom; y++)
1571 dst_pixel = dst_start;
1572 src_pixel = src_start;
1573 for(x = src_rect->left; x < src_rect->right; x++)
1575 src_val = *src_pixel++;
1576 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1577 ( src_val & 0x00ff00) |
1578 ((src_val << 16) & 0xff0000) );
1580 dst_start += dst->stride;
1581 src_start += src->stride / 4;
1584 else
1586 FIXME("Unsupported conversion: 32 -> 8\n");
1587 return FALSE;
1589 break;
1592 case 24:
1594 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1596 for(y = src_rect->top; y < src_rect->bottom; y++)
1598 dst_pixel = dst_start;
1599 src_pixel = src_start;
1600 for(x = src_rect->left; x < src_rect->right; x++)
1602 RGBQUAD rgb;
1603 rgb.rgbBlue = *src_pixel++;
1604 rgb.rgbGreen = *src_pixel++;
1605 rgb.rgbRed = *src_pixel++;
1607 *dst_pixel++ = colorref_to_pixel_colortable(dst, ( rgb.rgbRed & 0x0000ff) |
1608 ((rgb.rgbGreen << 8) & 0x00ff00) |
1609 ((rgb.rgbBlue << 16) & 0xff0000));
1611 dst_start += dst->stride;
1612 src_start += src->stride;
1614 break;
1617 case 16:
1619 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1620 if(src->funcs == &funcs_555)
1622 for(y = src_rect->top; y < src_rect->bottom; y++)
1624 dst_pixel = dst_start;
1625 src_pixel = src_start;
1626 for(x = src_rect->left; x < src_rect->right; x++)
1628 src_val = *src_pixel++;
1629 *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
1630 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1631 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
1633 dst_start += dst->stride;
1634 src_start += src->stride / 2;
1637 else
1639 FIXME("Unsupported conversion: 16 -> 8\n");
1640 return FALSE;
1642 break;
1645 case 8:
1647 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1649 if(color_tables_match(dst, src))
1651 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1652 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1653 else
1655 for(y = src_rect->top; y < src_rect->bottom; y++)
1657 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
1658 dst_start += dst->stride;
1659 src_start += src->stride;
1663 else
1665 for(y = src_rect->top; y < src_rect->bottom; y++)
1667 dst_pixel = dst_start;
1668 src_pixel = src_start;
1669 for(x = src_rect->left; x < src_rect->right; x++)
1671 RGBQUAD rgb;
1672 src_val = *src_pixel++;
1673 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1674 rgb = src->color_table[src_val];
1675 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1677 dst_start += dst->stride;
1678 src_start += src->stride;
1681 break;
1684 case 4:
1686 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1687 for(y = src_rect->top; y < src_rect->bottom; y++)
1689 dst_pixel = dst_start;
1690 src_pixel = src_start;
1691 for(x = src_rect->left; x < src_rect->right; x++)
1693 RGBQUAD rgb;
1694 if(x & 1)
1695 src_val = *src_pixel++ & 0xf;
1696 else
1697 src_val = (*src_pixel >> 4) & 0xf;
1698 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1699 rgb = src->color_table[src_val];
1700 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1702 dst_start += dst->stride;
1703 src_start += src->stride;
1705 break;
1708 case 1:
1710 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1711 for(y = src_rect->top; y < src_rect->bottom; y++)
1713 dst_pixel = dst_start;
1714 src_pixel = src_start;
1715 for(x = src_rect->left; x < src_rect->right; x++)
1717 RGBQUAD rgb;
1718 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1719 if((x % 8) == 7) src_pixel++;
1720 rgb = src->color_table[src_val];
1721 *dst_pixel++ = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1723 dst_start += dst->stride;
1724 src_start += src->stride;
1726 break;
1729 default:
1730 FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
1731 return FALSE;
1734 return TRUE;
1737 static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
1739 BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
1740 INT x, y;
1741 DWORD src_val;
1743 switch(src->bit_count)
1745 case 32:
1747 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1749 if(src->funcs == &funcs_8888)
1751 for(y = src_rect->top; y < src_rect->bottom; y++)
1753 dst_pixel = dst_start;
1754 src_pixel = src_start;
1755 for(x = src_rect->left; x < src_rect->right; x++)
1757 src_val = *src_pixel++;
1758 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1759 ( src_val & 0x00ff00) |
1760 ((src_val << 16) & 0xff0000) );
1761 if((x - src_rect->left) & 1)
1763 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1764 dst_pixel++;
1766 else
1767 *dst_pixel = (dst_val << 4) & 0xf0;
1769 dst_start += dst->stride;
1770 src_start += src->stride / 4;
1773 else
1775 FIXME("Unsupported conversion: 32 -> 4\n");
1776 return FALSE;
1778 break;
1781 case 24:
1783 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1785 for(y = src_rect->top; y < src_rect->bottom; y++)
1787 dst_pixel = dst_start;
1788 src_pixel = src_start;
1789 for(x = src_rect->left; x < src_rect->right; x++)
1791 RGBQUAD rgb;
1792 rgb.rgbBlue = *src_pixel++;
1793 rgb.rgbGreen = *src_pixel++;
1794 rgb.rgbRed = *src_pixel++;
1796 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed & 0x0000ff) |
1797 ((rgb.rgbGreen << 8) & 0x00ff00) |
1798 ((rgb.rgbBlue << 16) & 0xff0000));
1800 if((x - src_rect->left) & 1)
1802 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1803 dst_pixel++;
1805 else
1806 *dst_pixel = (dst_val << 4) & 0xf0;
1808 dst_start += dst->stride;
1809 src_start += src->stride;
1811 break;
1814 case 16:
1816 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1817 if(src->funcs == &funcs_555)
1819 for(y = src_rect->top; y < src_rect->bottom; y++)
1821 dst_pixel = dst_start;
1822 src_pixel = src_start;
1823 for(x = src_rect->left; x < src_rect->right; x++)
1825 src_val = *src_pixel++;
1826 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
1827 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1828 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
1829 if((x - src_rect->left) & 1)
1831 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1832 dst_pixel++;
1834 else
1835 *dst_pixel = (dst_val << 4) & 0xf0;
1837 dst_start += dst->stride;
1838 src_start += src->stride / 2;
1841 else
1843 FIXME("Unsupported conversion: 16 -> 4\n");
1844 return FALSE;
1846 break;
1849 case 8:
1851 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1853 for(y = src_rect->top; y < src_rect->bottom; y++)
1855 dst_pixel = dst_start;
1856 src_pixel = src_start;
1857 for(x = src_rect->left; x < src_rect->right; x++)
1859 RGBQUAD rgb;
1860 src_val = *src_pixel++;
1861 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1862 rgb = src->color_table[src_val];
1863 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1864 if((x - src_rect->left) & 1)
1866 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1867 dst_pixel++;
1869 else
1870 *dst_pixel = (dst_val << 4) & 0xf0;
1872 dst_start += dst->stride;
1873 src_start += src->stride;
1875 break;
1878 case 4:
1880 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1882 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
1884 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1885 memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1886 else
1888 for(y = src_rect->top; y < src_rect->bottom; y++)
1890 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
1891 dst_start += dst->stride;
1892 src_start += src->stride;
1896 else
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;
1905 if(x & 1)
1906 src_val = *src_pixel++ & 0xf;
1907 else
1908 src_val = (*src_pixel >> 4) & 0xf;
1909 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
1910 rgb = src->color_table[src_val];
1911 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1912 if((x - src_rect->left) & 1)
1914 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1915 dst_pixel++;
1917 else
1918 *dst_pixel = (dst_val << 4) & 0xf0;
1920 dst_start += dst->stride;
1921 src_start += src->stride;
1924 break;
1927 case 1:
1929 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1930 for(y = src_rect->top; y < src_rect->bottom; y++)
1932 dst_pixel = dst_start;
1933 src_pixel = src_start;
1934 for(x = src_rect->left; x < src_rect->right; x++)
1936 RGBQUAD rgb;
1937 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1938 if((x % 8) == 7) src_pixel++;
1939 rgb = src->color_table[src_val];
1940 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
1941 if((x - src_rect->left) & 1)
1943 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
1944 dst_pixel++;
1946 else
1947 *dst_pixel = (dst_val << 4) & 0xf0;
1949 dst_start += dst->stride;
1950 src_start += src->stride;
1952 break;
1955 default:
1956 FIXME("Unsupported conversion: %d -> 4\n", src->bit_count);
1957 return FALSE;
1961 return TRUE;
1964 static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
1966 BYTE *dst_start = dst->bits, *dst_pixel, dst_val;
1967 INT x, y;
1968 DWORD src_val;
1969 int bit_pos;
1971 /* FIXME: Brushes should be dithered. */
1973 switch(src->bit_count)
1975 case 32:
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, bit_pos = 0; x < src_rect->right; x++)
1987 src_val = *src_pixel++;
1988 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
1989 ( src_val & 0x00ff00) |
1990 ((src_val << 16) & 0xff0000) ) ? 0xff : 0;
1992 if(bit_pos == 0) *dst_pixel = 0;
1993 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
1995 if(++bit_pos == 8)
1997 dst_pixel++;
1998 bit_pos = 0;
2001 dst_start += dst->stride;
2002 src_start += src->stride / 4;
2005 else
2007 FIXME("Unsupported conversion: 32 -> 1\n");
2008 return FALSE;
2010 break;
2013 case 24:
2015 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
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, bit_pos = 0; x < src_rect->right; x++)
2023 RGBQUAD rgb;
2024 rgb.rgbBlue = *src_pixel++;
2025 rgb.rgbGreen = *src_pixel++;
2026 rgb.rgbRed = *src_pixel++;
2028 dst_val = colorref_to_pixel_colortable(dst, ( rgb.rgbRed & 0x0000ff) |
2029 ((rgb.rgbGreen << 8) & 0x00ff00) |
2030 ((rgb.rgbBlue << 16) & 0xff0000)) ? 0xff : 0;
2032 if(bit_pos == 0) *dst_pixel = 0;
2033 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2035 if(++bit_pos == 8)
2037 dst_pixel++;
2038 bit_pos = 0;
2041 dst_start += dst->stride;
2042 src_start += src->stride;
2044 break;
2047 case 16:
2049 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2050 if(src->funcs == &funcs_555)
2052 for(y = src_rect->top; y < src_rect->bottom; y++)
2054 dst_pixel = dst_start;
2055 src_pixel = src_start;
2056 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2058 src_val = *src_pixel++;
2059 dst_val = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
2060 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
2061 ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) ) ? 0xff : 0;
2063 if(bit_pos == 0) *dst_pixel = 0;
2064 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2066 if(++bit_pos == 8)
2068 dst_pixel++;
2069 bit_pos = 0;
2072 dst_start += dst->stride;
2073 src_start += src->stride / 2;
2076 else
2078 FIXME("Unsupported conversion: 16 -> 1\n");
2079 return FALSE;
2081 break;
2084 case 8:
2086 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2088 for(y = src_rect->top; y < src_rect->bottom; y++)
2090 dst_pixel = dst_start;
2091 src_pixel = src_start;
2092 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2094 RGBQUAD rgb;
2095 src_val = *src_pixel++;
2096 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2097 rgb = src->color_table[src_val];
2098 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2100 if(bit_pos == 0) *dst_pixel = 0;
2101 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2103 if(++bit_pos == 8)
2105 dst_pixel++;
2106 bit_pos = 0;
2109 dst_start += dst->stride;
2110 src_start += src->stride;
2112 break;
2115 case 4:
2117 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2119 for(y = src_rect->top; y < src_rect->bottom; y++)
2121 dst_pixel = dst_start;
2122 src_pixel = src_start;
2123 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2125 RGBQUAD rgb;
2126 if(x & 1)
2127 src_val = *src_pixel++ & 0xf;
2128 else
2129 src_val = (*src_pixel >> 4) & 0xf;
2130 if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
2131 rgb = src->color_table[src_val];
2132 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2134 if(bit_pos == 0) *dst_pixel = 0;
2135 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2137 if(++bit_pos == 8)
2139 dst_pixel++;
2140 bit_pos = 0;
2143 dst_start += dst->stride;
2144 src_start += src->stride;
2146 break;
2149 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
2150 uses text/bkgnd colours instead of the dib's colour table, this
2151 doesn't appear to be the case for a dc backed by a
2152 dibsection. */
2154 case 1:
2156 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2157 for(y = src_rect->top; y < src_rect->bottom; y++)
2159 dst_pixel = dst_start;
2160 src_pixel = src_start;
2161 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
2163 RGBQUAD rgb;
2164 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2165 if((x % 8) == 7) src_pixel++;
2166 rgb = src->color_table[src_val];
2167 dst_val = colorref_to_pixel_colortable(dst, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)) ? 0xff : 0;
2169 if(bit_pos == 0) *dst_pixel = 0;
2170 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
2172 if(++bit_pos == 8)
2174 dst_pixel++;
2175 bit_pos = 0;
2178 dst_start += dst->stride;
2179 src_start += src->stride;
2181 break;
2184 default:
2185 FIXME("Unsupported conversion: %d -> 1\n", src->bit_count);
2186 return FALSE;
2189 return TRUE;
2192 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
2194 return FALSE;
2197 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)
2199 BYTE *hatch_start = hatch->bits, *hatch_ptr;
2200 DWORD mask_start = 0, mask_offset;
2201 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
2202 int x, y;
2204 for(y = 0; y < hatch->height; y++)
2206 hatch_ptr = hatch_start;
2207 mask_offset = mask_start;
2208 for(x = 0; x < hatch->width; x++)
2210 if(*hatch_ptr & pixel_masks_1[x % 8])
2212 and_bits[mask_offset] = fg->and;
2213 xor_bits[mask_offset] = fg->xor;
2215 else
2217 and_bits[mask_offset] = bg->and;
2218 xor_bits[mask_offset] = bg->xor;
2220 if(x % 8 == 7) hatch_ptr++;
2221 mask_offset++;
2223 hatch_start += hatch->stride;
2224 mask_start += dib->stride / 4;
2227 return TRUE;
2230 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)
2232 BYTE *hatch_start = hatch->bits, *hatch_ptr;
2233 DWORD mask_start = 0, mask_offset;
2234 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2235 int x, y;
2237 for(y = 0; y < hatch->height; y++)
2239 hatch_ptr = hatch_start;
2240 mask_offset = mask_start;
2241 for(x = 0; x < hatch->width; x++)
2243 if(*hatch_ptr & pixel_masks_1[x % 8])
2245 and_bits[mask_offset] = fg->and & 0xff;
2246 xor_bits[mask_offset++] = fg->xor & 0xff;
2247 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
2248 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
2249 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
2250 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
2252 else
2254 and_bits[mask_offset] = bg->and & 0xff;
2255 xor_bits[mask_offset++] = bg->xor & 0xff;
2256 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
2257 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
2258 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
2259 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
2261 if(x % 8 == 7) hatch_ptr++;
2263 hatch_start += hatch->stride;
2264 mask_start += dib->stride;
2267 return TRUE;
2270 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)
2272 BYTE *hatch_start = hatch->bits, *hatch_ptr;
2273 DWORD mask_start = 0, mask_offset;
2274 WORD *and_bits = bits->and, *xor_bits = bits->xor;
2275 int x, y;
2277 for(y = 0; y < hatch->height; y++)
2279 hatch_ptr = hatch_start;
2280 mask_offset = mask_start;
2281 for(x = 0; x < hatch->width; x++)
2283 if(*hatch_ptr & pixel_masks_1[x % 8])
2285 and_bits[mask_offset] = fg->and;
2286 xor_bits[mask_offset] = fg->xor;
2288 else
2290 and_bits[mask_offset] = bg->and;
2291 xor_bits[mask_offset] = bg->xor;
2293 if(x % 8 == 7) hatch_ptr++;
2294 mask_offset++;
2296 hatch_start += hatch->stride;
2297 mask_start += dib->stride / 2;
2300 return TRUE;
2303 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)
2305 BYTE *hatch_start = hatch->bits, *hatch_ptr;
2306 DWORD mask_start = 0, mask_offset;
2307 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2308 int x, y;
2310 for(y = 0; y < hatch->height; y++)
2312 hatch_ptr = hatch_start;
2313 mask_offset = mask_start;
2314 for(x = 0; x < hatch->width; x++)
2316 if(*hatch_ptr & pixel_masks_1[x % 8])
2318 and_bits[mask_offset] = fg->and;
2319 xor_bits[mask_offset] = fg->xor;
2321 else
2323 and_bits[mask_offset] = bg->and;
2324 xor_bits[mask_offset] = bg->xor;
2326 if(x % 8 == 7) hatch_ptr++;
2327 mask_offset++;
2329 hatch_start += hatch->stride;
2330 mask_start += dib->stride;
2333 return TRUE;
2336 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)
2338 BYTE *hatch_start = hatch->bits, *hatch_ptr;
2339 DWORD mask_start = 0, mask_offset;
2340 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2341 const rop_mask *rop_mask;
2342 int x, y;
2344 for(y = 0; y < hatch->height; y++)
2346 hatch_ptr = hatch_start;
2347 mask_offset = mask_start;
2348 for(x = 0; x < hatch->width; x++)
2350 if(*hatch_ptr & pixel_masks_1[x % 8])
2351 rop_mask = fg;
2352 else
2353 rop_mask = bg;
2355 if(x & 1)
2357 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
2358 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
2359 mask_offset++;
2361 else
2363 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
2364 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
2367 if(x % 8 == 7) hatch_ptr++;
2369 hatch_start += hatch->stride;
2370 mask_start += dib->stride;
2373 return TRUE;
2376 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)
2378 BYTE *hatch_start = hatch->bits, *hatch_ptr;
2379 DWORD mask_start = 0, mask_offset;
2380 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
2381 rop_mask rop_mask;
2382 int x, y, bit_pos;
2384 for(y = 0; y < hatch->height; y++)
2386 hatch_ptr = hatch_start;
2387 mask_offset = mask_start;
2388 for(x = 0, bit_pos = 0; x < hatch->width; x++)
2390 if(*hatch_ptr & pixel_masks_1[x % 8])
2392 rop_mask.and = (fg->and & 1) ? 0xff : 0;
2393 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
2395 else
2397 rop_mask.and = (bg->and & 1) ? 0xff : 0;
2398 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
2401 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
2403 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
2404 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
2406 if(++bit_pos == 8)
2408 mask_offset++;
2409 hatch_ptr++;
2410 bit_pos = 0;
2413 hatch_start += hatch->stride;
2414 mask_start += dib->stride;
2417 return TRUE;
2420 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)
2422 return FALSE;
2425 const primitive_funcs funcs_8888 =
2427 solid_rects_32,
2428 pattern_rects_32,
2429 colorref_to_pixel_888,
2430 convert_to_8888,
2431 create_rop_masks_32
2434 const primitive_funcs funcs_32 =
2436 solid_rects_32,
2437 pattern_rects_32,
2438 colorref_to_pixel_masks,
2439 convert_to_32,
2440 create_rop_masks_32
2443 const primitive_funcs funcs_24 =
2445 solid_rects_24,
2446 pattern_rects_24,
2447 colorref_to_pixel_888,
2448 convert_to_24,
2449 create_rop_masks_24
2452 const primitive_funcs funcs_555 =
2454 solid_rects_16,
2455 pattern_rects_16,
2456 colorref_to_pixel_555,
2457 convert_to_555,
2458 create_rop_masks_16
2461 const primitive_funcs funcs_16 =
2463 solid_rects_16,
2464 pattern_rects_16,
2465 colorref_to_pixel_masks,
2466 convert_to_16,
2467 create_rop_masks_16
2470 const primitive_funcs funcs_8 =
2472 solid_rects_8,
2473 pattern_rects_8,
2474 colorref_to_pixel_colortable,
2475 convert_to_8,
2476 create_rop_masks_8
2479 const primitive_funcs funcs_4 =
2481 solid_rects_4,
2482 pattern_rects_4,
2483 colorref_to_pixel_colortable,
2484 convert_to_4,
2485 create_rop_masks_4
2488 const primitive_funcs funcs_1 =
2490 solid_rects_1,
2491 pattern_rects_1,
2492 colorref_to_pixel_colortable,
2493 convert_to_1,
2494 create_rop_masks_1
2497 const primitive_funcs funcs_null =
2499 solid_rects_null,
2500 pattern_rects_null,
2501 colorref_to_pixel_null,
2502 convert_to_null,
2503 create_rop_masks_null