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 /* Bayer matrices for dithering */
32 static const BYTE bayer_4x4[4][4] =
40 static const BYTE bayer_16x16[16][16] =
42 { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170 },
43 { 192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106 },
44 { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154 },
45 { 240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90 },
46 { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166 },
47 { 204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102 },
48 { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150 },
49 { 252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86 },
50 { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169 },
51 { 195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105 },
52 { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153 },
53 { 243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89 },
54 { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165 },
55 { 207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101 },
56 { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149 },
57 { 255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85 },
60 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
62 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 4);
65 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
67 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride) + (dib->rect.left + x) * 3 / 4;
70 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
72 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 3;
75 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
77 return (WORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 2);
80 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
82 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + dib->rect.left + x;
85 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
87 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 2;
90 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
92 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 8;
95 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
96 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
98 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
100 *ptr = (*ptr & and) ^ xor;
103 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
105 *ptr = (*ptr & and) ^ xor;
108 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
110 *ptr = (*ptr & and) ^ xor;
113 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
115 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
118 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
120 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
123 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
125 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
128 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
130 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
133 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
135 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
138 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
140 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
143 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
145 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
146 do_rop_codes_32( dst, *src, codes );
149 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
151 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
154 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
156 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
157 do_rop_codes_16( dst, *src, codes );
160 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
162 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
165 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
167 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
168 do_rop_codes_8( dst, *src, codes );
171 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
172 struct rop_codes *codes, int len)
176 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
180 if (src_x & 1) src_val = *src++;
181 else src_val = *src >> 4;
182 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
186 if (src_x & 1) src_val = *src++ << 4;
188 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
193 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
194 struct rop_codes *codes, int len)
200 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
204 if (src_x & 1) src_val = *src;
205 else src_val = *src-- >> 4;
206 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
210 if (src_x & 1) src_val = *src << 4;
211 else src_val = *src--;
212 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
217 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
218 struct rop_codes *codes, int len)
222 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
224 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
225 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
226 if ((src_x & 7) == 7) src++;
227 if ((dst_x & 7) == 7) dst++;
231 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
232 struct rop_codes *codes, int len)
238 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
240 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
241 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
242 if ((src_x & 7) == 0) src--;
243 if ((dst_x & 7) == 0) dst--;
247 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
252 for(i = 0; i < num; i++, rc++)
254 start = get_pixel_ptr_32(dib, rc->left, rc->top);
255 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
256 for(x = rc->left, ptr = start; x < rc->right; x++)
257 do_rop_32(ptr++, and, xor);
261 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
264 BYTE *byte_ptr, *byte_start;
266 DWORD and_masks[3], xor_masks[3];
268 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
269 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
270 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
271 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
272 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
273 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
275 for(i = 0; i < num; i++, rc++)
277 int left = dib->rect.left + rc->left;
278 int right = dib->rect.left + rc->right;
280 if (left >= right) continue;
282 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
284 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
285 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
287 for(x = left, byte_ptr = byte_start; x < right; x++)
289 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
290 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
291 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
297 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
298 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
305 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
306 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
307 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
310 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
311 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
314 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
318 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
320 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
321 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
322 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
328 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
331 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
332 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
335 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
336 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
337 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
345 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
350 for(i = 0; i < num; i++, rc++)
352 start = get_pixel_ptr_16(dib, rc->left, rc->top);
353 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
354 for(x = rc->left, ptr = start; x < rc->right; x++)
355 do_rop_16(ptr++, and, xor);
359 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
364 for(i = 0; i < num; i++, rc++)
366 start = get_pixel_ptr_8(dib, rc->left, rc->top);
367 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
368 for(x = rc->left, ptr = start; x < rc->right; x++)
369 do_rop_8(ptr++, and, xor);
373 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
377 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
378 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
380 for(i = 0; i < num; i++, rc++)
382 int left = dib->rect.left + rc->left;
383 int right = dib->rect.left + rc->right;
385 if (left >= right) continue;
386 start = get_pixel_ptr_4(dib, rc->left, rc->top);
387 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
390 if(left & 1) /* upper nibble untouched */
391 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
393 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
394 do_rop_8(ptr++, byte_and, byte_xor);
396 if(right & 1) /* lower nibble untouched */
397 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
402 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
406 BYTE byte_and = (and & 1) ? 0xff : 0;
407 BYTE byte_xor = (xor & 1) ? 0xff : 0;
408 BYTE start_and, start_xor, end_and, end_xor, mask;
409 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
411 for(i = 0; i < num; i++, rc++)
413 int left = dib->rect.left + rc->left;
414 int right = dib->rect.left + rc->right;
416 if (left >= right) continue;
418 start = get_pixel_ptr_1(dib, rc->left, rc->top);
420 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
422 mask = masks[left & 7] & ~masks[right & 7];
424 start_and = byte_and | ~mask;
425 start_xor = byte_xor & mask;
426 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
428 do_rop_8(start, start_and, start_xor);
433 mask = masks[left & 7];
434 start_and = byte_and | ~mask;
435 start_xor = byte_xor & mask;
437 mask = masks[right & 7];
438 /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
439 end_and = byte_and | mask;
440 end_xor = byte_xor & ~mask;
442 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
447 do_rop_8(ptr++, start_and, start_xor);
449 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
450 do_rop_8(ptr++, byte_and, byte_xor);
453 do_rop_8(ptr, end_and, end_xor);
459 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
464 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
465 DWORD and, DWORD xor)
467 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
468 int len = params->length, err = params->err_start;
469 int major_inc, minor_inc;
473 major_inc = params->x_inc;
474 minor_inc = (dib->stride * params->y_inc) / 4;
478 major_inc = (dib->stride * params->y_inc) / 4;
479 minor_inc = params->x_inc;
484 do_rop_32( ptr, and, xor );
485 if (err + params->bias > 0)
488 err += params->err_add_1;
490 else err += params->err_add_2;
495 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
496 DWORD and, DWORD xor)
498 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
499 int len = params->length, err = params->err_start;
500 int major_inc, minor_inc;
504 major_inc = params->x_inc * 3;
505 minor_inc = dib->stride * params->y_inc;
509 major_inc = dib->stride * params->y_inc;
510 minor_inc = params->x_inc * 3;
515 do_rop_8( ptr, and, xor );
516 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
517 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
518 if (err + params->bias > 0)
521 err += params->err_add_1;
523 else err += params->err_add_2;
528 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
529 DWORD and, DWORD xor)
531 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
532 int len = params->length, err = params->err_start;
533 int major_inc, minor_inc;
537 major_inc = params->x_inc;
538 minor_inc = (dib->stride * params->y_inc) / 2;
542 major_inc = (dib->stride * params->y_inc) / 2;
543 minor_inc = params->x_inc;
548 do_rop_16( ptr, and, xor );
549 if (err + params->bias > 0)
552 err += params->err_add_1;
554 else err += params->err_add_2;
559 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
560 DWORD and, DWORD xor)
562 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
563 int len = params->length, err = params->err_start;
564 int major_inc, minor_inc;
568 major_inc = params->x_inc;
569 minor_inc = dib->stride * params->y_inc;
573 major_inc = dib->stride * params->y_inc;
574 minor_inc = params->x_inc;
579 do_rop_8( ptr, and, xor );
580 if (err + params->bias > 0)
583 err += params->err_add_1;
585 else err += params->err_add_2;
590 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
591 DWORD and, DWORD xor)
593 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
594 int len = params->length, err = params->err_start;
595 int x = dib->rect.left + start->x;
597 and = (and & 0x0f) | ((and << 4) & 0xf0);
598 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
604 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
605 if (err + params->bias > 0)
607 ptr += dib->stride * params->y_inc;
608 err += params->err_add_1;
610 else err += params->err_add_2;
611 if ((x / 2) != ((x + params->x_inc) / 2))
612 ptr += params->x_inc;
620 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
621 if (err + params->bias > 0)
623 if ((x / 2) != ((x + params->x_inc) / 2))
624 ptr += params->x_inc;
626 err += params->err_add_1;
628 else err += params->err_add_2;
629 ptr += dib->stride * params->y_inc;
634 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
635 DWORD and, DWORD xor)
637 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
638 int len = params->length, err = params->err_start;
639 int x = dib->rect.left + start->x;
641 and = (and & 0x1) ? 0xff : 0;
642 xor = (xor & 0x1) ? 0xff : 0;
648 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
649 if (err + params->bias > 0)
651 ptr += dib->stride * params->y_inc;
652 err += params->err_add_1;
654 else err += params->err_add_2;
655 if ((x / 8) != ((x + params->x_inc) / 8))
656 ptr += params->x_inc;
664 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
665 if (err + params->bias > 0)
667 if ((x / 8) != ((x + params->x_inc) / 8))
668 ptr += params->x_inc;
670 err += params->err_add_1;
672 else err += params->err_add_2;
673 ptr += dib->stride * params->y_inc;
678 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
679 DWORD and, DWORD xor)
684 static inline INT calc_offset(INT edge, INT size, INT origin)
688 if(edge - origin >= 0)
689 offset = (edge - origin) % size;
692 offset = (origin - edge) % size;
693 if(offset) offset = size - offset;
698 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
702 offset.x = calc_offset(rc->left, brush->width, origin->x);
703 offset.y = calc_offset(rc->top, brush->height, origin->y);
708 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
709 const dib_info *brush, void *and_bits, void *xor_bits)
711 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
715 for(i = 0; i < num; i++, rc++)
717 offset = calc_brush_offset(rc, brush, origin);
719 start = get_pixel_ptr_32(dib, rc->left, rc->top);
720 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
721 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
723 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
725 and_ptr = start_and + offset.x;
726 xor_ptr = start_xor + offset.x;
728 for(x = rc->left, ptr = start; x < rc->right; x++)
730 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
731 if(and_ptr == start_and + brush->width)
739 if(offset.y == brush->height)
741 start_and = and_bits;
742 start_xor = xor_bits;
747 start_and += brush->stride / 4;
748 start_xor += brush->stride / 4;
754 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
755 const dib_info *brush, void *and_bits, void *xor_bits)
757 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
761 for(i = 0; i < num; i++, rc++)
763 offset = calc_brush_offset(rc, brush, origin);
765 start = get_pixel_ptr_24(dib, rc->left, rc->top);
766 start_and = (BYTE*)and_bits + offset.y * brush->stride;
767 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
769 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
771 and_ptr = start_and + offset.x * 3;
772 xor_ptr = start_xor + offset.x * 3;
774 for(x = rc->left, ptr = start; x < rc->right; x++)
776 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
777 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
778 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
779 if(and_ptr == start_and + brush->width * 3)
787 if(offset.y == brush->height)
789 start_and = and_bits;
790 start_xor = xor_bits;
795 start_and += brush->stride;
796 start_xor += brush->stride;
802 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
803 const dib_info *brush, void *and_bits, void *xor_bits)
805 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
809 for(i = 0; i < num; i++, rc++)
811 offset = calc_brush_offset(rc, brush, origin);
813 start = get_pixel_ptr_16(dib, rc->left, rc->top);
814 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
815 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
817 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
819 and_ptr = start_and + offset.x;
820 xor_ptr = start_xor + offset.x;
822 for(x = rc->left, ptr = start; x < rc->right; x++)
824 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
825 if(and_ptr == start_and + brush->width)
833 if(offset.y == brush->height)
835 start_and = and_bits;
836 start_xor = xor_bits;
841 start_and += brush->stride / 2;
842 start_xor += brush->stride / 2;
848 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
849 const dib_info *brush, void *and_bits, void *xor_bits)
851 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
855 for(i = 0; i < num; i++, rc++)
857 offset = calc_brush_offset(rc, brush, origin);
859 start = get_pixel_ptr_8(dib, rc->left, rc->top);
860 start_and = (BYTE*)and_bits + offset.y * brush->stride;
861 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
863 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
865 and_ptr = start_and + offset.x;
866 xor_ptr = start_xor + offset.x;
868 for(x = rc->left, ptr = start; x < rc->right; x++)
870 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
871 if(and_ptr == start_and + brush->width)
879 if(offset.y == brush->height)
881 start_and = and_bits;
882 start_xor = xor_bits;
887 start_and += brush->stride;
888 start_xor += brush->stride;
894 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
895 const dib_info *brush, void *and_bits, void *xor_bits)
897 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
898 int x, y, i, left, right;
901 for(i = 0; i < num; i++, rc++)
903 offset = calc_brush_offset(rc, brush, origin);
904 left = dib->rect.left + rc->left;
905 right = dib->rect.left + rc->right;
907 start = get_pixel_ptr_4(dib, rc->left, rc->top);
908 start_and = (BYTE*)and_bits + offset.y * brush->stride;
909 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
911 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
913 INT brush_x = offset.x;
914 BYTE byte_and, byte_xor;
916 and_ptr = start_and + brush_x / 2;
917 xor_ptr = start_xor + brush_x / 2;
919 for(x = left, ptr = start; x < right; x++)
921 /* FIXME: Two pixels at a time */
922 if(x & 1) /* lower dst nibble */
924 if(brush_x & 1) /* lower pat nibble */
926 byte_and = *and_ptr++ | 0xf0;
927 byte_xor = *xor_ptr++ & 0x0f;
929 else /* upper pat nibble */
931 byte_and = (*and_ptr >> 4) | 0xf0;
932 byte_xor = (*xor_ptr >> 4) & 0x0f;
935 else /* upper dst nibble */
937 if(brush_x & 1) /* lower pat nibble */
939 byte_and = (*and_ptr++ << 4) | 0x0f;
940 byte_xor = (*xor_ptr++ << 4) & 0xf0;
942 else /* upper pat nibble */
944 byte_and = *and_ptr | 0x0f;
945 byte_xor = *xor_ptr & 0xf0;
948 do_rop_8(ptr, byte_and, byte_xor);
952 if(++brush_x == brush->width)
961 if(offset.y == brush->height)
963 start_and = and_bits;
964 start_xor = xor_bits;
969 start_and += brush->stride;
970 start_xor += brush->stride;
976 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
977 const dib_info *brush, void *and_bits, void *xor_bits)
979 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
980 int x, y, i, left, right;
983 for(i = 0; i < num; i++, rc++)
985 offset = calc_brush_offset(rc, brush, origin);
986 left = dib->rect.left + rc->left;
987 right = dib->rect.left + rc->right;
989 start = get_pixel_ptr_1(dib, rc->left, rc->top);
990 start_and = (BYTE*)and_bits + offset.y * brush->stride;
991 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
993 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
995 INT brush_x = offset.x;
996 BYTE byte_and, byte_xor;
998 and_ptr = start_and + brush_x / 8;
999 xor_ptr = start_xor + brush_x / 8;
1001 for(x = left, ptr = start; x < right; x++)
1003 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1004 byte_and |= ~pixel_masks_1[x % 8];
1005 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1006 byte_xor &= pixel_masks_1[x % 8];
1008 do_rop_8(ptr, byte_and, byte_xor);
1010 if((x & 7) == 7) ptr++;
1012 if((brush_x & 7) == 7)
1018 if(++brush_x == brush->width)
1021 and_ptr = start_and;
1022 xor_ptr = start_xor;
1027 if(offset.y == brush->height)
1029 start_and = and_bits;
1030 start_xor = xor_bits;
1035 start_and += brush->stride;
1036 start_xor += brush->stride;
1042 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1043 const dib_info *brush, void *and_bits, void *xor_bits)
1048 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1049 const dib_info *src, const POINT *origin, int rop2, int overlap)
1051 DWORD *dst_start, *src_start;
1052 struct rop_codes codes;
1053 int y, dst_stride, src_stride;
1055 if (overlap & OVERLAP_BELOW)
1057 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1058 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1059 dst_stride = -dst->stride / 4;
1060 src_stride = -src->stride / 4;
1064 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1065 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1066 dst_stride = dst->stride / 4;
1067 src_stride = src->stride / 4;
1070 if (rop2 == R2_COPYPEN)
1072 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1073 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1077 get_rop_codes( rop2, &codes );
1078 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1080 if (overlap & OVERLAP_RIGHT)
1081 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1083 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1087 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1088 const dib_info *src, const POINT *origin, int rop2, int overlap)
1090 BYTE *dst_start, *src_start;
1091 int y, dst_stride, src_stride;
1092 struct rop_codes codes;
1094 if (overlap & OVERLAP_BELOW)
1096 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1097 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1098 dst_stride = -dst->stride;
1099 src_stride = -src->stride;
1103 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1104 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1105 dst_stride = dst->stride;
1106 src_stride = src->stride;
1109 if (rop2 == R2_COPYPEN)
1111 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1112 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1116 get_rop_codes( rop2, &codes );
1117 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1119 if (overlap & OVERLAP_RIGHT)
1120 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1122 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1126 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1127 const dib_info *src, const POINT *origin, int rop2, int overlap)
1129 WORD *dst_start, *src_start;
1130 int y, dst_stride, src_stride;
1131 struct rop_codes codes;
1133 if (overlap & OVERLAP_BELOW)
1135 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1136 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1137 dst_stride = -dst->stride / 2;
1138 src_stride = -src->stride / 2;
1142 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1143 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1144 dst_stride = dst->stride / 2;
1145 src_stride = src->stride / 2;
1148 if (rop2 == R2_COPYPEN)
1150 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1151 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1155 get_rop_codes( rop2, &codes );
1156 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1158 if (overlap & OVERLAP_RIGHT)
1159 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1161 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1165 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1166 const dib_info *src, const POINT *origin, int rop2, int overlap)
1168 BYTE *dst_start, *src_start;
1169 int y, dst_stride, src_stride;
1170 struct rop_codes codes;
1172 if (overlap & OVERLAP_BELOW)
1174 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1175 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1176 dst_stride = -dst->stride;
1177 src_stride = -src->stride;
1181 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1182 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1183 dst_stride = dst->stride;
1184 src_stride = src->stride;
1187 if (rop2 == R2_COPYPEN)
1189 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1190 memmove( dst_start, src_start, (rc->right - rc->left) );
1194 get_rop_codes( rop2, &codes );
1195 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1197 if (overlap & OVERLAP_RIGHT)
1198 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1200 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1204 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1205 const dib_info *src, const POINT *origin, int rop2, int overlap)
1207 BYTE *dst_start, *src_start;
1208 int y, dst_stride, src_stride;
1209 struct rop_codes codes;
1210 int left = dst->rect.left + rc->left;
1211 int right = dst->rect.left + rc->right;
1212 int org_x = src->rect.left + origin->x;
1214 if (overlap & OVERLAP_BELOW)
1216 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1217 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1218 dst_stride = -dst->stride;
1219 src_stride = -src->stride;
1223 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1224 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1225 dst_stride = dst->stride;
1226 src_stride = src->stride;
1229 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1231 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1232 memmove( dst_start, src_start, (right - left) / 2 );
1236 get_rop_codes( rop2, &codes );
1237 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1239 if (overlap & OVERLAP_RIGHT)
1240 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1242 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1246 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1247 const dib_info *src, const POINT *origin, int rop2, int overlap)
1249 BYTE *dst_start, *src_start;
1250 int y, dst_stride, src_stride;
1251 struct rop_codes codes;
1252 int left = dst->rect.left + rc->left;
1253 int right = dst->rect.left + rc->right;
1254 int org_x = src->rect.left + origin->x;
1256 if (overlap & OVERLAP_BELOW)
1258 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1259 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1260 dst_stride = -dst->stride;
1261 src_stride = -src->stride;
1265 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1266 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1267 dst_stride = dst->stride;
1268 src_stride = src->stride;
1271 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1273 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1274 memmove( dst_start, src_start, (right - left) / 8 );
1278 get_rop_codes( rop2, &codes );
1279 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1281 if (overlap & OVERLAP_RIGHT)
1282 do_rop_codes_line_rev_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1284 do_rop_codes_line_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1288 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1289 const dib_info *src, const POINT *origin, int rop2, int overlap)
1294 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
1296 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1300 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1302 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1303 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1306 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1308 WORD *ptr = get_pixel_ptr_16( dib, x, y );
1312 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1314 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1318 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1320 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1322 if ((dib->rect.left + x) & 1)
1325 return (*ptr >> 4) & 0x0f;
1328 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1330 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1331 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
1334 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
1339 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1341 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1344 static const DWORD field_masks[33] =
1346 0x00, /* should never happen */
1347 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1348 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1349 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1350 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1353 static inline DWORD get_field(DWORD field, int shift, int len)
1355 shift = shift - (8 - len);
1360 field &= field_masks[len];
1361 field |= field >> len;
1365 static inline DWORD put_field(DWORD field, int shift, int len)
1367 shift = shift - (8 - len);
1368 field &= field_masks[len];
1376 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1380 r = GetRValue(colour);
1381 g = GetGValue(colour);
1382 b = GetBValue(colour);
1384 return put_field(r, dib->red_shift, dib->red_len) |
1385 put_field(g, dib->green_shift, dib->green_len) |
1386 put_field(b, dib->blue_shift, dib->blue_len);
1389 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1391 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1394 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1396 int i, best_index = 0;
1397 DWORD diff, best_diff = 0xffffffff;
1399 /* special case for conversion to 1-bpp without a color table:
1400 * we get a 1-entry table containing the background color
1402 if (dib->bit_count == 1 && dib->color_table_size == 1)
1403 return (r == dib->color_table[0].rgbRed &&
1404 g == dib->color_table[0].rgbGreen &&
1405 b == dib->color_table[0].rgbBlue);
1407 for(i = 0; i < dib->color_table_size; i++)
1409 const RGBQUAD *cur = dib->color_table + i;
1410 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1411 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1412 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1420 if(diff < best_diff)
1429 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1431 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1434 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1439 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1441 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1444 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1446 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1447 get_field( pixel, dib->green_shift, dib->green_len ),
1448 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1451 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1453 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1454 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1455 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1458 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1460 if (pixel < dib->color_table_size)
1462 RGBQUAD quad = dib->color_table[pixel];
1463 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1468 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1473 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1475 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1477 return d1->red_mask == d2->red_mask &&
1478 d1->green_mask == d2->green_mask &&
1479 d1->blue_mask == d2->blue_mask;
1482 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1484 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1485 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1487 switch(src->bit_count)
1491 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1492 if(src->funcs == &funcs_8888)
1494 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1495 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1498 for(y = src_rect->top; y < src_rect->bottom; y++)
1500 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1501 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1502 dst_start += dst->stride / 4;
1503 src_start += src->stride / 4;
1507 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1509 for(y = src_rect->top; y < src_rect->bottom; y++)
1511 dst_pixel = dst_start;
1512 src_pixel = src_start;
1513 for(x = src_rect->left; x < src_rect->right; x++)
1515 src_val = *src_pixel++;
1516 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1517 (((src_val >> src->green_shift) & 0xff) << 8) |
1518 ((src_val >> src->blue_shift) & 0xff);
1520 if(pad_size) memset(dst_pixel, 0, pad_size);
1521 dst_start += dst->stride / 4;
1522 src_start += src->stride / 4;
1527 for(y = src_rect->top; y < src_rect->bottom; y++)
1529 dst_pixel = dst_start;
1530 src_pixel = src_start;
1531 for(x = src_rect->left; x < src_rect->right; x++)
1533 src_val = *src_pixel++;
1534 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1535 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1536 get_field( src_val, src->blue_shift, src->blue_len ));
1538 if(pad_size) memset(dst_pixel, 0, pad_size);
1539 dst_start += dst->stride / 4;
1540 src_start += src->stride / 4;
1548 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1550 for(y = src_rect->top; y < src_rect->bottom; y++)
1552 dst_pixel = dst_start;
1553 src_pixel = src_start;
1554 for(x = src_rect->left; x < src_rect->right; x++)
1557 rgb.rgbBlue = *src_pixel++;
1558 rgb.rgbGreen = *src_pixel++;
1559 rgb.rgbRed = *src_pixel++;
1561 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1563 if(pad_size) memset(dst_pixel, 0, pad_size);
1564 dst_start += dst->stride / 4;
1565 src_start += src->stride;
1572 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1573 if(src->funcs == &funcs_555)
1575 for(y = src_rect->top; y < src_rect->bottom; y++)
1577 dst_pixel = dst_start;
1578 src_pixel = src_start;
1579 for(x = src_rect->left; x < src_rect->right; x++)
1581 src_val = *src_pixel++;
1582 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1583 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1584 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1586 if(pad_size) memset(dst_pixel, 0, pad_size);
1587 dst_start += dst->stride / 4;
1588 src_start += src->stride / 2;
1591 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1593 for(y = src_rect->top; y < src_rect->bottom; y++)
1595 dst_pixel = dst_start;
1596 src_pixel = src_start;
1597 for(x = src_rect->left; x < src_rect->right; x++)
1599 src_val = *src_pixel++;
1600 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1601 (((src_val >> src->red_shift) << 14) & 0x070000) |
1602 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1603 (((src_val >> src->green_shift) << 6) & 0x000700) |
1604 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1605 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1607 if(pad_size) memset(dst_pixel, 0, pad_size);
1608 dst_start += dst->stride / 4;
1609 src_start += src->stride / 2;
1612 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1614 for(y = src_rect->top; y < src_rect->bottom; y++)
1616 dst_pixel = dst_start;
1617 src_pixel = src_start;
1618 for(x = src_rect->left; x < src_rect->right; x++)
1620 src_val = *src_pixel++;
1621 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1622 (((src_val >> src->red_shift) << 14) & 0x070000) |
1623 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1624 (((src_val >> src->green_shift) << 4) & 0x000300) |
1625 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1626 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1628 if(pad_size) memset(dst_pixel, 0, pad_size);
1629 dst_start += dst->stride / 4;
1630 src_start += src->stride / 2;
1635 for(y = src_rect->top; y < src_rect->bottom; y++)
1637 dst_pixel = dst_start;
1638 src_pixel = src_start;
1639 for(x = src_rect->left; x < src_rect->right; x++)
1641 src_val = *src_pixel++;
1642 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1643 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1644 get_field( src_val, src->blue_shift, src->blue_len ));
1646 if(pad_size) memset(dst_pixel, 0, pad_size);
1647 dst_start += dst->stride / 4;
1648 src_start += src->stride / 2;
1656 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1657 for(y = src_rect->top; y < src_rect->bottom; y++)
1659 dst_pixel = dst_start;
1660 src_pixel = src_start;
1661 for(x = src_rect->left; x < src_rect->right; x++)
1663 RGBQUAD rgb = src->color_table[*src_pixel++];
1664 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1666 if(pad_size) memset(dst_pixel, 0, pad_size);
1667 dst_start += dst->stride / 4;
1668 src_start += src->stride;
1675 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1676 for(y = src_rect->top; y < src_rect->bottom; y++)
1678 int pos = (src->rect.left + src_rect->left) & 1;
1679 src_pixel = src_start;
1680 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1684 rgb = src->color_table[*src_pixel++ & 0xf];
1686 rgb = src->color_table[*src_pixel >> 4];
1687 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1689 if(pad_size) memset(dst_start + x, 0, pad_size);
1690 dst_start += dst->stride / 4;
1691 src_start += src->stride;
1698 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1699 for(y = src_rect->top; y < src_rect->bottom; y++)
1701 int pos = (src->rect.left + src_rect->left) & 7;
1702 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1705 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1706 rgb = src->color_table[src_val];
1707 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1709 if(pad_size) memset(dst_start + x, 0, pad_size);
1710 dst_start += dst->stride / 4;
1711 src_start += src->stride;
1718 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1720 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1721 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1723 switch(src->bit_count)
1727 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1729 if(src->funcs == &funcs_8888)
1731 for(y = src_rect->top; y < src_rect->bottom; y++)
1733 dst_pixel = dst_start;
1734 src_pixel = src_start;
1735 for(x = src_rect->left; x < src_rect->right; x++)
1737 src_val = *src_pixel++;
1738 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1739 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1740 put_field(src_val, dst->blue_shift, dst->blue_len);
1742 if(pad_size) memset(dst_pixel, 0, pad_size);
1743 dst_start += dst->stride / 4;
1744 src_start += src->stride / 4;
1747 else if(bit_fields_match(src, dst))
1749 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1750 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1753 for(y = src_rect->top; y < src_rect->bottom; y++)
1755 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1756 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1757 dst_start += dst->stride / 4;
1758 src_start += src->stride / 4;
1762 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1763 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1765 for(y = src_rect->top; y < src_rect->bottom; y++)
1767 dst_pixel = dst_start;
1768 src_pixel = src_start;
1769 for(x = src_rect->left; x < src_rect->right; x++)
1771 src_val = *src_pixel++;
1772 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1773 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1774 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1776 if(pad_size) memset(dst_pixel, 0, pad_size);
1777 dst_start += dst->stride / 4;
1778 src_start += src->stride / 4;
1783 for(y = src_rect->top; y < src_rect->bottom; y++)
1785 dst_pixel = dst_start;
1786 src_pixel = src_start;
1787 for(x = src_rect->left; x < src_rect->right; x++)
1789 src_val = *src_pixel++;
1790 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1791 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1792 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1794 if(pad_size) memset(dst_pixel, 0, pad_size);
1795 dst_start += dst->stride / 4;
1796 src_start += src->stride / 4;
1804 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1806 for(y = src_rect->top; y < src_rect->bottom; y++)
1808 dst_pixel = dst_start;
1809 src_pixel = src_start;
1810 for(x = src_rect->left; x < src_rect->right; x++)
1813 rgb.rgbBlue = *src_pixel++;
1814 rgb.rgbGreen = *src_pixel++;
1815 rgb.rgbRed = *src_pixel++;
1817 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1818 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1819 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1821 if(pad_size) memset(dst_pixel, 0, pad_size);
1822 dst_start += dst->stride / 4;
1823 src_start += src->stride;
1830 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1831 if(src->funcs == &funcs_555)
1833 for(y = src_rect->top; y < src_rect->bottom; y++)
1835 dst_pixel = dst_start;
1836 src_pixel = src_start;
1837 for(x = src_rect->left; x < src_rect->right; x++)
1839 src_val = *src_pixel++;
1840 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1841 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1842 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1844 if(pad_size) memset(dst_pixel, 0, pad_size);
1845 dst_start += dst->stride / 4;
1846 src_start += src->stride / 2;
1849 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1851 for(y = src_rect->top; y < src_rect->bottom; y++)
1853 dst_pixel = dst_start;
1854 src_pixel = src_start;
1855 for(x = src_rect->left; x < src_rect->right; x++)
1857 src_val = *src_pixel++;
1858 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1859 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1860 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1861 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1862 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1863 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1865 if(pad_size) memset(dst_pixel, 0, pad_size);
1866 dst_start += dst->stride / 4;
1867 src_start += src->stride / 2;
1870 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1872 for(y = src_rect->top; y < src_rect->bottom; y++)
1874 dst_pixel = dst_start;
1875 src_pixel = src_start;
1876 for(x = src_rect->left; x < src_rect->right; x++)
1878 src_val = *src_pixel++;
1879 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1880 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1881 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1882 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1883 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1884 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1886 if(pad_size) memset(dst_pixel, 0, pad_size);
1887 dst_start += dst->stride / 4;
1888 src_start += src->stride / 2;
1893 for(y = src_rect->top; y < src_rect->bottom; y++)
1895 dst_pixel = dst_start;
1896 src_pixel = src_start;
1897 for(x = src_rect->left; x < src_rect->right; x++)
1899 src_val = *src_pixel++;
1900 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1901 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1902 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1904 if(pad_size) memset(dst_pixel, 0, pad_size);
1905 dst_start += dst->stride / 4;
1906 src_start += src->stride / 2;
1914 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1915 for(y = src_rect->top; y < src_rect->bottom; y++)
1917 dst_pixel = dst_start;
1918 src_pixel = src_start;
1919 for(x = src_rect->left; x < src_rect->right; x++)
1921 RGBQUAD rgb = src->color_table[*src_pixel++];
1922 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1923 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1924 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1926 if(pad_size) memset(dst_pixel, 0, pad_size);
1927 dst_start += dst->stride / 4;
1928 src_start += src->stride;
1935 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1936 for(y = src_rect->top; y < src_rect->bottom; y++)
1938 int pos = (src->rect.left + src_rect->left) & 1;
1939 src_pixel = src_start;
1940 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1944 rgb = src->color_table[*src_pixel++ & 0xf];
1946 rgb = src->color_table[*src_pixel >> 4];
1947 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1948 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1949 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1951 if(pad_size) memset(dst_start + x, 0, pad_size);
1952 dst_start += dst->stride / 4;
1953 src_start += src->stride;
1960 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1961 for(y = src_rect->top; y < src_rect->bottom; y++)
1963 int pos = (src->rect.left + src_rect->left) & 7;
1964 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1967 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1968 rgb = src->color_table[src_val];
1969 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1970 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1971 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1973 if(pad_size) memset(dst_start + x, 0, pad_size);
1974 dst_start += dst->stride / 4;
1975 src_start += src->stride;
1982 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1984 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1986 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1988 switch(src->bit_count)
1992 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1993 if(src->funcs == &funcs_8888)
1995 for(y = src_rect->top; y < src_rect->bottom; y++)
1997 dst_pixel = dst_start;
1998 src_pixel = src_start;
1999 for(x = src_rect->left; x < src_rect->right; x++)
2001 src_val = *src_pixel++;
2002 *dst_pixel++ = src_val & 0xff;
2003 *dst_pixel++ = (src_val >> 8) & 0xff;
2004 *dst_pixel++ = (src_val >> 16) & 0xff;
2006 if(pad_size) memset(dst_pixel, 0, pad_size);
2007 dst_start += dst->stride;
2008 src_start += src->stride / 4;
2011 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2013 for(y = src_rect->top; y < src_rect->bottom; y++)
2015 dst_pixel = dst_start;
2016 src_pixel = src_start;
2017 for(x = src_rect->left; x < src_rect->right; x++)
2019 src_val = *src_pixel++;
2020 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2021 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2022 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2024 if(pad_size) memset(dst_pixel, 0, pad_size);
2025 dst_start += dst->stride;
2026 src_start += src->stride / 4;
2031 for(y = src_rect->top; y < src_rect->bottom; y++)
2033 dst_pixel = dst_start;
2034 src_pixel = src_start;
2035 for(x = src_rect->left; x < src_rect->right; x++)
2037 src_val = *src_pixel++;
2038 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2039 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2040 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2042 if(pad_size) memset(dst_pixel, 0, pad_size);
2043 dst_start += dst->stride;
2044 src_start += src->stride / 4;
2052 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2054 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2055 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2058 for(y = src_rect->top; y < src_rect->bottom; y++)
2060 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2061 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2062 dst_start += dst->stride;
2063 src_start += src->stride;
2071 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2072 if(src->funcs == &funcs_555)
2074 for(y = src_rect->top; y < src_rect->bottom; y++)
2076 dst_pixel = dst_start;
2077 src_pixel = src_start;
2078 for(x = src_rect->left; x < src_rect->right; x++)
2080 src_val = *src_pixel++;
2081 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2082 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2083 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2085 if(pad_size) memset(dst_pixel, 0, pad_size);
2086 dst_start += dst->stride;
2087 src_start += src->stride / 2;
2090 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2092 for(y = src_rect->top; y < src_rect->bottom; y++)
2094 dst_pixel = dst_start;
2095 src_pixel = src_start;
2096 for(x = src_rect->left; x < src_rect->right; x++)
2098 src_val = *src_pixel++;
2099 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2100 (((src_val >> src->blue_shift) >> 2) & 0x07);
2101 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2102 (((src_val >> src->green_shift) >> 2) & 0x07);
2103 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2104 (((src_val >> src->red_shift) >> 2) & 0x07);
2106 if(pad_size) memset(dst_pixel, 0, pad_size);
2107 dst_start += dst->stride;
2108 src_start += src->stride / 2;
2111 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2113 for(y = src_rect->top; y < src_rect->bottom; y++)
2115 dst_pixel = dst_start;
2116 src_pixel = src_start;
2117 for(x = src_rect->left; x < src_rect->right; x++)
2119 src_val = *src_pixel++;
2120 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2121 (((src_val >> src->blue_shift) >> 2) & 0x07);
2122 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2123 (((src_val >> src->green_shift) >> 4) & 0x03);
2124 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2125 (((src_val >> src->red_shift) >> 2) & 0x07);
2127 if(pad_size) memset(dst_pixel, 0, pad_size);
2128 dst_start += dst->stride;
2129 src_start += src->stride / 2;
2134 for(y = src_rect->top; y < src_rect->bottom; y++)
2136 dst_pixel = dst_start;
2137 src_pixel = src_start;
2138 for(x = src_rect->left; x < src_rect->right; x++)
2140 src_val = *src_pixel++;
2141 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2142 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2143 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2145 if(pad_size) memset(dst_pixel, 0, pad_size);
2146 dst_start += dst->stride;
2147 src_start += src->stride / 2;
2155 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2156 for(y = src_rect->top; y < src_rect->bottom; y++)
2158 dst_pixel = dst_start;
2159 src_pixel = src_start;
2160 for(x = src_rect->left; x < src_rect->right; x++)
2162 RGBQUAD rgb = src->color_table[*src_pixel++];
2163 *dst_pixel++ = rgb.rgbBlue;
2164 *dst_pixel++ = rgb.rgbGreen;
2165 *dst_pixel++ = rgb.rgbRed;
2167 if(pad_size) memset(dst_pixel, 0, pad_size);
2168 dst_start += dst->stride;
2169 src_start += src->stride;
2176 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2177 for(y = src_rect->top; y < src_rect->bottom; y++)
2179 int pos = (src->rect.left + src_rect->left) & 1;
2180 src_pixel = src_start;
2181 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2185 rgb = src->color_table[*src_pixel++ & 0xf];
2187 rgb = src->color_table[*src_pixel >> 4];
2188 dst_start[x * 3] = rgb.rgbBlue;
2189 dst_start[x * 3 + 1] = rgb.rgbGreen;
2190 dst_start[x * 3 + 2] = rgb.rgbRed;
2192 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2193 dst_start += dst->stride;
2194 src_start += src->stride;
2201 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2202 for(y = src_rect->top; y < src_rect->bottom; y++)
2204 int pos = (src->rect.left + src_rect->left) & 7;
2205 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2208 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2209 rgb = src->color_table[src_val];
2210 dst_start[x * 3] = rgb.rgbBlue;
2211 dst_start[x * 3 + 1] = rgb.rgbGreen;
2212 dst_start[x * 3 + 2] = rgb.rgbRed;
2214 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2215 dst_start += dst->stride;
2216 src_start += src->stride;
2223 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
2225 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2226 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2229 switch(src->bit_count)
2233 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2235 if(src->funcs == &funcs_8888)
2237 for(y = src_rect->top; y < src_rect->bottom; y++)
2239 dst_pixel = dst_start;
2240 src_pixel = src_start;
2241 for(x = src_rect->left; x < src_rect->right; x++)
2243 src_val = *src_pixel++;
2244 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2245 ((src_val >> 6) & 0x03e0) |
2246 ((src_val >> 3) & 0x001f);
2248 if(pad_size) memset(dst_pixel, 0, pad_size);
2249 dst_start += dst->stride / 2;
2250 src_start += src->stride / 4;
2253 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2255 for(y = src_rect->top; y < src_rect->bottom; y++)
2257 dst_pixel = dst_start;
2258 src_pixel = src_start;
2259 for(x = src_rect->left; x < src_rect->right; x++)
2261 src_val = *src_pixel++;
2262 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2263 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2264 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2266 if(pad_size) memset(dst_pixel, 0, pad_size);
2267 dst_start += dst->stride / 2;
2268 src_start += src->stride / 4;
2273 for(y = src_rect->top; y < src_rect->bottom; y++)
2275 dst_pixel = dst_start;
2276 src_pixel = src_start;
2277 for(x = src_rect->left; x < src_rect->right; x++)
2279 src_val = *src_pixel++;
2280 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2281 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2282 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2284 if(pad_size) memset(dst_pixel, 0, pad_size);
2285 dst_start += dst->stride / 2;
2286 src_start += src->stride / 4;
2294 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2296 for(y = src_rect->top; y < src_rect->bottom; y++)
2298 dst_pixel = dst_start;
2299 src_pixel = src_start;
2300 for(x = src_rect->left; x < src_rect->right; x++)
2303 rgb.rgbBlue = *src_pixel++;
2304 rgb.rgbGreen = *src_pixel++;
2305 rgb.rgbRed = *src_pixel++;
2307 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2308 ((rgb.rgbGreen << 2) & 0x03e0) |
2309 ((rgb.rgbBlue >> 3) & 0x001f);
2311 if(pad_size) memset(dst_pixel, 0, pad_size);
2312 dst_start += dst->stride / 2;
2313 src_start += src->stride;
2320 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2321 if(src->funcs == &funcs_555)
2323 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2324 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2327 for(y = src_rect->top; y < src_rect->bottom; y++)
2329 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2330 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2331 dst_start += dst->stride / 2;
2332 src_start += src->stride / 2;
2336 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2338 for(y = src_rect->top; y < src_rect->bottom; y++)
2340 dst_pixel = dst_start;
2341 src_pixel = src_start;
2342 for(x = src_rect->left; x < src_rect->right; x++)
2344 src_val = *src_pixel++;
2345 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2346 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2347 ( (src_val >> src->blue_shift) & 0x001f);
2349 if(pad_size) memset(dst_pixel, 0, pad_size);
2350 dst_start += dst->stride / 2;
2351 src_start += src->stride / 2;
2354 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2356 for(y = src_rect->top; y < src_rect->bottom; y++)
2358 dst_pixel = dst_start;
2359 src_pixel = src_start;
2360 for(x = src_rect->left; x < src_rect->right; x++)
2362 src_val = *src_pixel++;
2363 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2364 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2365 ( (src_val >> src->blue_shift) & 0x001f);
2367 if(pad_size) memset(dst_pixel, 0, pad_size);
2368 dst_start += dst->stride / 2;
2369 src_start += src->stride / 2;
2374 for(y = src_rect->top; y < src_rect->bottom; y++)
2376 dst_pixel = dst_start;
2377 src_pixel = src_start;
2378 for(x = src_rect->left; x < src_rect->right; x++)
2380 src_val = *src_pixel++;
2381 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2382 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2383 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2385 if(pad_size) memset(dst_pixel, 0, pad_size);
2386 dst_start += dst->stride / 2;
2387 src_start += src->stride / 2;
2395 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2396 for(y = src_rect->top; y < src_rect->bottom; y++)
2398 dst_pixel = dst_start;
2399 src_pixel = src_start;
2400 for(x = src_rect->left; x < src_rect->right; x++)
2402 RGBQUAD rgb = src->color_table[*src_pixel++];
2403 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2404 ((rgb.rgbGreen << 2) & 0x03e0) |
2405 ((rgb.rgbBlue >> 3) & 0x001f);
2407 if(pad_size) memset(dst_pixel, 0, pad_size);
2408 dst_start += dst->stride / 2;
2409 src_start += src->stride;
2416 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2417 for(y = src_rect->top; y < src_rect->bottom; y++)
2419 int pos = (src->rect.left + src_rect->left) & 1;
2420 src_pixel = src_start;
2421 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2425 rgb = src->color_table[*src_pixel++ & 0xf];
2427 rgb = src->color_table[*src_pixel >> 4];
2428 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2429 ((rgb.rgbGreen << 2) & 0x03e0) |
2430 ((rgb.rgbBlue >> 3) & 0x001f);
2432 if(pad_size) memset(dst_start + x, 0, pad_size);
2433 dst_start += dst->stride / 2;
2434 src_start += src->stride;
2441 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2442 for(y = src_rect->top; y < src_rect->bottom; y++)
2444 int pos = (src->rect.left + src_rect->left) & 7;
2445 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2448 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2449 rgb = src->color_table[src_val];
2450 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2451 ((rgb.rgbGreen << 2) & 0x03e0) |
2452 ((rgb.rgbBlue >> 3) & 0x001f);
2454 if(pad_size) memset(dst_start + x, 0, pad_size);
2455 dst_start += dst->stride / 2;
2456 src_start += src->stride;
2463 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2465 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2466 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2469 switch(src->bit_count)
2473 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2475 if(src->funcs == &funcs_8888)
2477 for(y = src_rect->top; y < src_rect->bottom; y++)
2479 dst_pixel = dst_start;
2480 src_pixel = src_start;
2481 for(x = src_rect->left; x < src_rect->right; x++)
2483 src_val = *src_pixel++;
2484 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2485 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2486 put_field(src_val, dst->blue_shift, dst->blue_len);
2488 if(pad_size) memset(dst_pixel, 0, pad_size);
2489 dst_start += dst->stride / 2;
2490 src_start += src->stride / 4;
2493 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2495 for(y = src_rect->top; y < src_rect->bottom; y++)
2497 dst_pixel = dst_start;
2498 src_pixel = src_start;
2499 for(x = src_rect->left; x < src_rect->right; x++)
2501 src_val = *src_pixel++;
2502 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2503 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2504 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2506 if(pad_size) memset(dst_pixel, 0, pad_size);
2507 dst_start += dst->stride / 2;
2508 src_start += src->stride / 4;
2513 for(y = src_rect->top; y < src_rect->bottom; y++)
2515 dst_pixel = dst_start;
2516 src_pixel = src_start;
2517 for(x = src_rect->left; x < src_rect->right; x++)
2519 src_val = *src_pixel++;
2520 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2521 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2522 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2524 if(pad_size) memset(dst_pixel, 0, pad_size);
2525 dst_start += dst->stride / 2;
2526 src_start += src->stride / 4;
2534 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2536 for(y = src_rect->top; y < src_rect->bottom; y++)
2538 dst_pixel = dst_start;
2539 src_pixel = src_start;
2540 for(x = src_rect->left; x < src_rect->right; x++)
2543 rgb.rgbBlue = *src_pixel++;
2544 rgb.rgbGreen = *src_pixel++;
2545 rgb.rgbRed = *src_pixel++;
2547 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2548 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2549 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2551 if(pad_size) memset(dst_pixel, 0, pad_size);
2552 dst_start += dst->stride / 2;
2553 src_start += src->stride;
2560 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2561 if(src->funcs == &funcs_555)
2563 for(y = src_rect->top; y < src_rect->bottom; y++)
2565 dst_pixel = dst_start;
2566 src_pixel = src_start;
2567 for(x = src_rect->left; x < src_rect->right; x++)
2569 src_val = *src_pixel++;
2570 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2571 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2572 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2574 if(pad_size) memset(dst_pixel, 0, pad_size);
2575 dst_start += dst->stride / 2;
2576 src_start += src->stride / 2;
2579 else if(bit_fields_match(src, dst))
2581 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2582 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2585 for(y = src_rect->top; y < src_rect->bottom; y++)
2587 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2588 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2589 dst_start += dst->stride / 2;
2590 src_start += src->stride / 2;
2594 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2596 for(y = src_rect->top; y < src_rect->bottom; y++)
2598 dst_pixel = dst_start;
2599 src_pixel = src_start;
2600 for(x = src_rect->left; x < src_rect->right; x++)
2602 src_val = *src_pixel++;
2603 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2604 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2605 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2606 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2607 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2608 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2610 if(pad_size) memset(dst_pixel, 0, pad_size);
2611 dst_start += dst->stride / 2;
2612 src_start += src->stride / 2;
2615 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2617 for(y = src_rect->top; y < src_rect->bottom; y++)
2619 dst_pixel = dst_start;
2620 src_pixel = src_start;
2621 for(x = src_rect->left; x < src_rect->right; x++)
2623 src_val = *src_pixel++;
2624 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2625 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2626 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2627 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2628 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2629 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2631 if(pad_size) memset(dst_pixel, 0, pad_size);
2632 dst_start += dst->stride / 2;
2633 src_start += src->stride / 2;
2638 for(y = src_rect->top; y < src_rect->bottom; y++)
2640 dst_pixel = dst_start;
2641 src_pixel = src_start;
2642 for(x = src_rect->left; x < src_rect->right; x++)
2644 src_val = *src_pixel++;
2645 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2646 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2647 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2649 if(pad_size) memset(dst_pixel, 0, pad_size);
2650 dst_start += dst->stride / 2;
2651 src_start += src->stride / 2;
2659 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2660 for(y = src_rect->top; y < src_rect->bottom; y++)
2662 dst_pixel = dst_start;
2663 src_pixel = src_start;
2664 for(x = src_rect->left; x < src_rect->right; x++)
2666 RGBQUAD rgb = src->color_table[*src_pixel++];
2667 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2668 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2669 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2671 if(pad_size) memset(dst_pixel, 0, pad_size);
2672 dst_start += dst->stride / 2;
2673 src_start += src->stride;
2680 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2681 for(y = src_rect->top; y < src_rect->bottom; y++)
2683 int pos = (src->rect.left + src_rect->left) & 1;
2684 src_pixel = src_start;
2685 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2689 rgb = src->color_table[*src_pixel++ & 0xf];
2691 rgb = src->color_table[*src_pixel >> 4];
2692 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2693 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2694 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2696 if(pad_size) memset(dst_start + x, 0, pad_size);
2697 dst_start += dst->stride / 2;
2698 src_start += src->stride;
2705 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2706 for(y = src_rect->top; y < src_rect->bottom; y++)
2708 int pos = (src->rect.left + src_rect->left) & 7;
2709 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2712 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2713 rgb = src->color_table[src_val];
2714 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2715 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2716 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2718 if(pad_size) memset(dst_start + x, 0, pad_size);
2719 dst_start += dst->stride / 2;
2720 src_start += src->stride;
2727 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2729 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
2732 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2734 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2735 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2738 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2740 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2741 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2744 switch(src->bit_count)
2748 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2750 if(src->funcs == &funcs_8888)
2752 for(y = src_rect->top; y < src_rect->bottom; y++)
2754 dst_pixel = dst_start;
2755 src_pixel = src_start;
2756 for(x = src_rect->left; x < src_rect->right; x++)
2758 src_val = *src_pixel++;
2759 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2761 if(pad_size) memset(dst_pixel, 0, pad_size);
2762 dst_start += dst->stride;
2763 src_start += src->stride / 4;
2766 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2768 for(y = src_rect->top; y < src_rect->bottom; y++)
2770 dst_pixel = dst_start;
2771 src_pixel = src_start;
2772 for(x = src_rect->left; x < src_rect->right; x++)
2774 src_val = *src_pixel++;
2775 *dst_pixel++ = rgb_lookup_colortable(dst,
2776 src_val >> src->red_shift,
2777 src_val >> src->green_shift,
2778 src_val >> src->blue_shift );
2780 if(pad_size) memset(dst_pixel, 0, pad_size);
2781 dst_start += dst->stride;
2782 src_start += src->stride / 4;
2787 for(y = src_rect->top; y < src_rect->bottom; y++)
2789 dst_pixel = dst_start;
2790 src_pixel = src_start;
2791 for(x = src_rect->left; x < src_rect->right; x++)
2793 src_val = *src_pixel++;
2794 *dst_pixel++ = rgb_lookup_colortable(dst,
2795 get_field(src_val, src->red_shift, src->red_len),
2796 get_field(src_val, src->green_shift, src->green_len),
2797 get_field(src_val, src->blue_shift, src->blue_len));
2799 if(pad_size) memset(dst_pixel, 0, pad_size);
2800 dst_start += dst->stride;
2801 src_start += src->stride / 4;
2809 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2811 for(y = src_rect->top; y < src_rect->bottom; y++)
2813 dst_pixel = dst_start;
2814 src_pixel = src_start;
2815 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2817 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2819 if(pad_size) memset(dst_pixel, 0, pad_size);
2820 dst_start += dst->stride;
2821 src_start += src->stride;
2828 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2829 if(src->funcs == &funcs_555)
2831 for(y = src_rect->top; y < src_rect->bottom; y++)
2833 dst_pixel = dst_start;
2834 src_pixel = src_start;
2835 for(x = src_rect->left; x < src_rect->right; x++)
2837 src_val = *src_pixel++;
2838 *dst_pixel++ = rgb_lookup_colortable(dst,
2839 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2840 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2841 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2843 if(pad_size) memset(dst_pixel, 0, pad_size);
2844 dst_start += dst->stride;
2845 src_start += src->stride / 2;
2848 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2850 for(y = src_rect->top; y < src_rect->bottom; y++)
2852 dst_pixel = dst_start;
2853 src_pixel = src_start;
2854 for(x = src_rect->left; x < src_rect->right; x++)
2856 src_val = *src_pixel++;
2857 *dst_pixel++ = rgb_lookup_colortable(dst,
2858 (((src_val >> src->red_shift) << 3) & 0xf8) |
2859 (((src_val >> src->red_shift) >> 2) & 0x07),
2860 (((src_val >> src->green_shift) << 3) & 0xf8) |
2861 (((src_val >> src->green_shift) >> 2) & 0x07),
2862 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2863 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2865 if(pad_size) memset(dst_pixel, 0, pad_size);
2866 dst_start += dst->stride;
2867 src_start += src->stride / 2;
2870 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2872 for(y = src_rect->top; y < src_rect->bottom; y++)
2874 dst_pixel = dst_start;
2875 src_pixel = src_start;
2876 for(x = src_rect->left; x < src_rect->right; x++)
2878 src_val = *src_pixel++;
2879 *dst_pixel++ = rgb_lookup_colortable(dst,
2880 (((src_val >> src->red_shift) << 3) & 0xf8) |
2881 (((src_val >> src->red_shift) >> 2) & 0x07),
2882 (((src_val >> src->green_shift) << 2) & 0xfc) |
2883 (((src_val >> src->green_shift) >> 4) & 0x03),
2884 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2885 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2887 if(pad_size) memset(dst_pixel, 0, pad_size);
2888 dst_start += dst->stride;
2889 src_start += src->stride / 2;
2894 for(y = src_rect->top; y < src_rect->bottom; y++)
2896 dst_pixel = dst_start;
2897 src_pixel = src_start;
2898 for(x = src_rect->left; x < src_rect->right; x++)
2900 src_val = *src_pixel++;
2901 *dst_pixel++ = rgb_lookup_colortable(dst,
2902 get_field(src_val, src->red_shift, src->red_len),
2903 get_field(src_val, src->green_shift, src->green_len),
2904 get_field(src_val, src->blue_shift, src->blue_len));
2906 if(pad_size) memset(dst_pixel, 0, pad_size);
2907 dst_start += dst->stride;
2908 src_start += src->stride / 2;
2916 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2918 if(color_tables_match(dst, src))
2920 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2921 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2924 for(y = src_rect->top; y < src_rect->bottom; y++)
2926 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2927 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2928 dst_start += dst->stride;
2929 src_start += src->stride;
2935 for(y = src_rect->top; y < src_rect->bottom; y++)
2937 dst_pixel = dst_start;
2938 src_pixel = src_start;
2939 for(x = src_rect->left; x < src_rect->right; x++)
2941 RGBQUAD rgb = src->color_table[*src_pixel++];
2942 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2944 if(pad_size) memset(dst_pixel, 0, pad_size);
2945 dst_start += dst->stride;
2946 src_start += src->stride;
2954 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2955 for(y = src_rect->top; y < src_rect->bottom; y++)
2957 int pos = (src->rect.left + src_rect->left) & 1;
2958 src_pixel = src_start;
2959 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2963 rgb = src->color_table[*src_pixel++ & 0xf];
2965 rgb = src->color_table[*src_pixel >> 4];
2966 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2968 if(pad_size) memset(dst_start + x, 0, pad_size);
2969 dst_start += dst->stride;
2970 src_start += src->stride;
2977 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2978 for(y = src_rect->top; y < src_rect->bottom; y++)
2980 int pos = (src->rect.left + src_rect->left) & 7;
2981 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2984 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2985 rgb = src->color_table[src_val];
2986 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2988 if(pad_size) memset(dst_start + x, 0, pad_size);
2989 dst_start += dst->stride;
2990 src_start += src->stride;
2997 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2999 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3000 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3003 switch(src->bit_count)
3007 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3009 if(src->funcs == &funcs_8888)
3011 for(y = src_rect->top; y < src_rect->bottom; y++)
3013 dst_pixel = dst_start;
3014 src_pixel = src_start;
3015 for(x = src_rect->left; x < src_rect->right; x++)
3017 src_val = *src_pixel++;
3018 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3019 if((x - src_rect->left) & 1)
3021 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3025 *dst_pixel = (dst_val << 4) & 0xf0;
3029 if((x - src_rect->left) & 1) dst_pixel++;
3030 memset(dst_pixel, 0, pad_size);
3032 dst_start += dst->stride;
3033 src_start += src->stride / 4;
3036 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3038 for(y = src_rect->top; y < src_rect->bottom; y++)
3040 dst_pixel = dst_start;
3041 src_pixel = src_start;
3042 for(x = src_rect->left; x < src_rect->right; x++)
3044 src_val = *src_pixel++;
3045 dst_val = rgb_to_pixel_colortable(dst,
3046 src_val >> src->red_shift,
3047 src_val >> src->green_shift,
3048 src_val >> src->blue_shift);
3049 if((x - src_rect->left) & 1)
3051 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3055 *dst_pixel = (dst_val << 4) & 0xf0;
3059 if((x - src_rect->left) & 1) dst_pixel++;
3060 memset(dst_pixel, 0, pad_size);
3062 dst_start += dst->stride;
3063 src_start += src->stride / 4;
3068 for(y = src_rect->top; y < src_rect->bottom; y++)
3070 dst_pixel = dst_start;
3071 src_pixel = src_start;
3072 for(x = src_rect->left; x < src_rect->right; x++)
3074 src_val = *src_pixel++;
3075 dst_val = rgb_to_pixel_colortable(dst,
3076 get_field(src_val, src->red_shift, src->red_len),
3077 get_field(src_val, src->green_shift, src->green_len),
3078 get_field(src_val, src->blue_shift, src->blue_len));
3079 if((x - src_rect->left) & 1)
3081 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3085 *dst_pixel = (dst_val << 4) & 0xf0;
3089 if((x - src_rect->left) & 1) dst_pixel++;
3090 memset(dst_pixel, 0, pad_size);
3092 dst_start += dst->stride;
3093 src_start += src->stride / 4;
3101 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3103 for(y = src_rect->top; y < src_rect->bottom; y++)
3105 dst_pixel = dst_start;
3106 src_pixel = src_start;
3107 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3109 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3111 if((x - src_rect->left) & 1)
3113 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3117 *dst_pixel = (dst_val << 4) & 0xf0;
3121 if((x - src_rect->left) & 1) dst_pixel++;
3122 memset(dst_pixel, 0, pad_size);
3124 dst_start += dst->stride;
3125 src_start += src->stride;
3132 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3133 if(src->funcs == &funcs_555)
3135 for(y = src_rect->top; y < src_rect->bottom; y++)
3137 dst_pixel = dst_start;
3138 src_pixel = src_start;
3139 for(x = src_rect->left; x < src_rect->right; x++)
3141 src_val = *src_pixel++;
3142 dst_val = rgb_to_pixel_colortable(dst,
3143 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3144 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3145 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3146 if((x - src_rect->left) & 1)
3148 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3152 *dst_pixel = (dst_val << 4) & 0xf0;
3156 if((x - src_rect->left) & 1) dst_pixel++;
3157 memset(dst_pixel, 0, pad_size);
3159 dst_start += dst->stride;
3160 src_start += src->stride / 2;
3163 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3165 for(y = src_rect->top; y < src_rect->bottom; y++)
3167 dst_pixel = dst_start;
3168 src_pixel = src_start;
3169 for(x = src_rect->left; x < src_rect->right; x++)
3171 src_val = *src_pixel++;
3172 dst_val = rgb_to_pixel_colortable(dst,
3173 (((src_val >> src->red_shift) << 3) & 0xf8) |
3174 (((src_val >> src->red_shift) >> 2) & 0x07),
3175 (((src_val >> src->green_shift) << 3) & 0xf8) |
3176 (((src_val >> src->green_shift) >> 2) & 0x07),
3177 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3178 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3179 if((x - src_rect->left) & 1)
3181 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3185 *dst_pixel = (dst_val << 4) & 0xf0;
3189 if((x - src_rect->left) & 1) dst_pixel++;
3190 memset(dst_pixel, 0, pad_size);
3192 dst_start += dst->stride;
3193 src_start += src->stride / 2;
3196 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3198 for(y = src_rect->top; y < src_rect->bottom; y++)
3200 dst_pixel = dst_start;
3201 src_pixel = src_start;
3202 for(x = src_rect->left; x < src_rect->right; x++)
3204 src_val = *src_pixel++;
3205 dst_val = rgb_to_pixel_colortable(dst,
3206 (((src_val >> src->red_shift) << 3) & 0xf8) |
3207 (((src_val >> src->red_shift) >> 2) & 0x07),
3208 (((src_val >> src->green_shift) << 2) & 0xfc) |
3209 (((src_val >> src->green_shift) >> 4) & 0x03),
3210 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3211 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3212 if((x - src_rect->left) & 1)
3214 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3218 *dst_pixel = (dst_val << 4) & 0xf0;
3222 if((x - src_rect->left) & 1) dst_pixel++;
3223 memset(dst_pixel, 0, pad_size);
3225 dst_start += dst->stride;
3226 src_start += src->stride / 2;
3231 for(y = src_rect->top; y < src_rect->bottom; y++)
3233 dst_pixel = dst_start;
3234 src_pixel = src_start;
3235 for(x = src_rect->left; x < src_rect->right; x++)
3237 src_val = *src_pixel++;
3238 dst_val = rgb_to_pixel_colortable(dst,
3239 get_field(src_val, src->red_shift, src->red_len),
3240 get_field(src_val, src->green_shift, src->green_len),
3241 get_field(src_val, src->blue_shift, src->blue_len));
3242 if((x - src_rect->left) & 1)
3244 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3248 *dst_pixel = (dst_val << 4) & 0xf0;
3252 if((x - src_rect->left) & 1) dst_pixel++;
3253 memset(dst_pixel, 0, pad_size);
3255 dst_start += dst->stride;
3256 src_start += src->stride / 2;
3264 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3266 for(y = src_rect->top; y < src_rect->bottom; y++)
3268 dst_pixel = dst_start;
3269 src_pixel = src_start;
3270 for(x = src_rect->left; x < src_rect->right; x++)
3272 RGBQUAD rgb = src->color_table[*src_pixel++];
3273 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3274 if((x - src_rect->left) & 1)
3276 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3280 *dst_pixel = (dst_val << 4) & 0xf0;
3284 if((x - src_rect->left) & 1) dst_pixel++;
3285 memset(dst_pixel, 0, pad_size);
3287 dst_start += dst->stride;
3288 src_start += src->stride;
3295 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3297 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
3299 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3300 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3303 for(y = src_rect->top; y < src_rect->bottom; y++)
3305 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3306 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3307 dst_start += dst->stride;
3308 src_start += src->stride;
3314 for(y = src_rect->top; y < src_rect->bottom; y++)
3316 int pos = (src->rect.left + src_rect->left) & 1;
3317 dst_pixel = dst_start;
3318 src_pixel = src_start;
3319 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3323 rgb = src->color_table[*src_pixel++ & 0xf];
3325 rgb = src->color_table[*src_pixel >> 4];
3326 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3327 if((x - src_rect->left) & 1)
3329 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3333 *dst_pixel = (dst_val << 4) & 0xf0;
3337 if((x - src_rect->left) & 1) dst_pixel++;
3338 memset(dst_pixel, 0, pad_size);
3340 dst_start += dst->stride;
3341 src_start += src->stride;
3349 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3350 for(y = src_rect->top; y < src_rect->bottom; y++)
3352 int pos = (src->rect.left + src_rect->left) & 7;
3353 dst_pixel = dst_start;
3354 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3357 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3358 rgb = src->color_table[src_val];
3359 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3360 if((x - src_rect->left) & 1)
3362 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3366 *dst_pixel = (dst_val << 4) & 0xf0;
3370 if((x - src_rect->left) & 1) dst_pixel++;
3371 memset(dst_pixel, 0, pad_size);
3373 dst_start += dst->stride;
3374 src_start += src->stride;
3381 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3383 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3384 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3388 /* FIXME: Brushes should be dithered. */
3390 switch(src->bit_count)
3394 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3396 if(src->funcs == &funcs_8888)
3398 for(y = src_rect->top; y < src_rect->bottom; y++)
3400 dst_pixel = dst_start;
3401 src_pixel = src_start;
3402 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3404 src_val = *src_pixel++;
3405 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3407 if(bit_pos == 0) *dst_pixel = 0;
3408 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3418 if(bit_pos != 0) dst_pixel++;
3419 memset(dst_pixel, 0, pad_size);
3421 dst_start += dst->stride;
3422 src_start += src->stride / 4;
3425 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3427 for(y = src_rect->top; y < src_rect->bottom; y++)
3429 dst_pixel = dst_start;
3430 src_pixel = src_start;
3431 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3433 src_val = *src_pixel++;
3434 dst_val = rgb_to_pixel_colortable(dst,
3435 src_val >> src->red_shift,
3436 src_val >> src->green_shift,
3437 src_val >> src->blue_shift) ? 0xff : 0;
3439 if(bit_pos == 0) *dst_pixel = 0;
3440 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3450 if(bit_pos != 0) dst_pixel++;
3451 memset(dst_pixel, 0, pad_size);
3453 dst_start += dst->stride;
3454 src_start += src->stride / 4;
3459 for(y = src_rect->top; y < src_rect->bottom; y++)
3461 dst_pixel = dst_start;
3462 src_pixel = src_start;
3463 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3465 src_val = *src_pixel++;
3466 dst_val = rgb_to_pixel_colortable(dst,
3467 get_field(src_val, src->red_shift, src->red_len),
3468 get_field(src_val, src->green_shift, src->green_len),
3469 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3471 if(bit_pos == 0) *dst_pixel = 0;
3472 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3482 if(bit_pos != 0) dst_pixel++;
3483 memset(dst_pixel, 0, pad_size);
3485 dst_start += dst->stride;
3486 src_start += src->stride / 4;
3494 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3496 for(y = src_rect->top; y < src_rect->bottom; y++)
3498 dst_pixel = dst_start;
3499 src_pixel = src_start;
3500 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3502 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3504 if(bit_pos == 0) *dst_pixel = 0;
3505 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3515 if(bit_pos != 0) dst_pixel++;
3516 memset(dst_pixel, 0, pad_size);
3518 dst_start += dst->stride;
3519 src_start += src->stride;
3526 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3527 if(src->funcs == &funcs_555)
3529 for(y = src_rect->top; y < src_rect->bottom; y++)
3531 dst_pixel = dst_start;
3532 src_pixel = src_start;
3533 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3535 src_val = *src_pixel++;
3536 dst_val = rgb_to_pixel_colortable(dst,
3537 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3538 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3539 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3541 if(bit_pos == 0) *dst_pixel = 0;
3542 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3552 if(bit_pos != 0) dst_pixel++;
3553 memset(dst_pixel, 0, pad_size);
3555 dst_start += dst->stride;
3556 src_start += src->stride / 2;
3559 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3561 for(y = src_rect->top; y < src_rect->bottom; y++)
3563 dst_pixel = dst_start;
3564 src_pixel = src_start;
3565 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3567 src_val = *src_pixel++;
3568 dst_val = rgb_to_pixel_colortable(dst,
3569 (((src_val >> src->red_shift) << 3) & 0xf8) |
3570 (((src_val >> src->red_shift) >> 2) & 0x07),
3571 (((src_val >> src->green_shift) << 3) & 0xf8) |
3572 (((src_val >> src->green_shift) >> 2) & 0x07),
3573 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3574 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3575 if(bit_pos == 0) *dst_pixel = 0;
3576 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3586 if(bit_pos != 0) dst_pixel++;
3587 memset(dst_pixel, 0, pad_size);
3589 dst_start += dst->stride;
3590 src_start += src->stride / 2;
3593 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3595 for(y = src_rect->top; y < src_rect->bottom; y++)
3597 dst_pixel = dst_start;
3598 src_pixel = src_start;
3599 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3601 src_val = *src_pixel++;
3602 dst_val = rgb_to_pixel_colortable(dst,
3603 (((src_val >> src->red_shift) << 3) & 0xf8) |
3604 (((src_val >> src->red_shift) >> 2) & 0x07),
3605 (((src_val >> src->green_shift) << 2) & 0xfc) |
3606 (((src_val >> src->green_shift) >> 4) & 0x03),
3607 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3608 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3609 if(bit_pos == 0) *dst_pixel = 0;
3610 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3620 if(bit_pos != 0) dst_pixel++;
3621 memset(dst_pixel, 0, pad_size);
3623 dst_start += dst->stride;
3624 src_start += src->stride / 2;
3629 for(y = src_rect->top; y < src_rect->bottom; y++)
3631 dst_pixel = dst_start;
3632 src_pixel = src_start;
3633 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3635 src_val = *src_pixel++;
3636 dst_val = rgb_to_pixel_colortable(dst,
3637 get_field(src_val, src->red_shift, src->red_len),
3638 get_field(src_val, src->green_shift, src->green_len),
3639 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3640 if(bit_pos == 0) *dst_pixel = 0;
3641 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3651 if(bit_pos != 0) dst_pixel++;
3652 memset(dst_pixel, 0, pad_size);
3654 dst_start += dst->stride;
3655 src_start += src->stride / 2;
3663 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3665 for(y = src_rect->top; y < src_rect->bottom; y++)
3667 dst_pixel = dst_start;
3668 src_pixel = src_start;
3669 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3671 RGBQUAD rgb = src->color_table[*src_pixel++];
3672 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3674 if(bit_pos == 0) *dst_pixel = 0;
3675 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3685 if(bit_pos != 0) dst_pixel++;
3686 memset(dst_pixel, 0, pad_size);
3688 dst_start += dst->stride;
3689 src_start += src->stride;
3696 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3698 for(y = src_rect->top; y < src_rect->bottom; y++)
3700 int pos = (src->rect.left + src_rect->left) & 1;
3701 dst_pixel = dst_start;
3702 src_pixel = src_start;
3703 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3707 rgb = src->color_table[*src_pixel++ & 0xf];
3709 rgb = src->color_table[*src_pixel >> 4];
3710 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3712 if(bit_pos == 0) *dst_pixel = 0;
3713 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3723 if(bit_pos != 0) dst_pixel++;
3724 memset(dst_pixel, 0, pad_size);
3726 dst_start += dst->stride;
3727 src_start += src->stride;
3732 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3733 uses text/bkgnd colours instead of the dib's colour table, this
3734 doesn't appear to be the case for a dc backed by a
3739 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3740 for(y = src_rect->top; y < src_rect->bottom; y++)
3742 int pos = (src->rect.left + src_rect->left) & 7;
3743 dst_pixel = dst_start;
3744 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3747 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3748 rgb = src->color_table[src_val];
3749 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3751 if(bit_pos == 0) *dst_pixel = 0;
3752 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3762 if(bit_pos != 0) dst_pixel++;
3763 memset(dst_pixel, 0, pad_size);
3765 dst_start += dst->stride;
3766 src_start += src->stride;
3773 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3777 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3779 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3782 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
3784 return (blend_color( dst, src, alpha ) |
3785 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3786 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3787 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3790 static inline DWORD blend_argb( DWORD dst, DWORD src )
3793 BYTE g = (BYTE)(src >> 8);
3794 BYTE r = (BYTE)(src >> 16);
3795 DWORD alpha = (BYTE)(src >> 24);
3796 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3797 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3798 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3799 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3802 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3804 BYTE b = ((BYTE)src * alpha + 127) / 255;
3805 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3806 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3807 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3808 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3809 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3810 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3811 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3814 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3816 if (blend.AlphaFormat & AC_SRC_ALPHA)
3818 DWORD alpha = blend.SourceConstantAlpha;
3819 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3820 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3821 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3822 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3823 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3824 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3825 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3827 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3828 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3829 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3832 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3833 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3835 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3836 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3839 if (blend.AlphaFormat & AC_SRC_ALPHA)
3841 if (blend.SourceConstantAlpha == 255)
3842 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3843 for (x = 0; x < rc->right - rc->left; x++)
3844 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
3846 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3847 for (x = 0; x < rc->right - rc->left; x++)
3848 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3851 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3852 for (x = 0; x < rc->right - rc->left; x++)
3853 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3856 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3857 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3859 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3860 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3863 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3865 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3867 for (x = 0; x < rc->right - rc->left; x++)
3869 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3870 dst_ptr[x] >> dst->green_shift,
3871 dst_ptr[x] >> dst->blue_shift,
3872 src_ptr[x], blend );
3873 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3874 (((val >> 8) & 0xff) << dst->green_shift) |
3875 (((val >> 16) & 0xff) << dst->red_shift));
3881 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3883 for (x = 0; x < rc->right - rc->left; x++)
3885 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3886 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3887 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3888 src_ptr[x], blend );
3889 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3890 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3891 put_field( val, dst->blue_shift, dst->blue_len ));
3897 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3898 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3900 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3901 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3904 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3906 for (x = 0; x < rc->right - rc->left; x++)
3908 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3909 src_ptr[x], blend );
3910 dst_ptr[x * 3] = val;
3911 dst_ptr[x * 3 + 1] = val >> 8;
3912 dst_ptr[x * 3 + 2] = val >> 16;
3917 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3918 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3920 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3921 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3924 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3926 for (x = 0; x < rc->right - rc->left; x++)
3928 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3929 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3930 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3931 src_ptr[x], blend );
3932 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3937 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3938 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3940 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3941 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3944 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3946 for (x = 0; x < rc->right - rc->left; x++)
3948 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3949 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3950 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3951 src_ptr[x], blend );
3952 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3953 put_field((val >> 8), dst->green_shift, dst->green_len) |
3954 put_field( val, dst->blue_shift, dst->blue_len));
3959 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3960 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3962 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3963 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3966 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3968 for (x = 0; x < rc->right - rc->left; x++)
3970 RGBQUAD rgb = dst->color_table[dst_ptr[x]];
3971 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3972 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3977 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3978 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3980 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3981 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
3984 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3986 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
3988 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3989 RGBQUAD rgb = dst->color_table[val];
3990 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
3991 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3993 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3995 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4000 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4001 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4003 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4004 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4007 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4009 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4011 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4012 RGBQUAD rgb = dst->color_table[val];
4013 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4014 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4015 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4020 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4021 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4025 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4028 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4029 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4030 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4031 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4032 return a << 24 | r << 16 | g << 8 | b;
4035 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4038 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4039 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4040 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4041 return r << 16 | g << 8 | b;
4044 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4045 unsigned int x, unsigned int y )
4047 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4048 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4049 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4050 r = min( 31, max( 0, r / 16 ));
4051 g = min( 31, max( 0, g / 16 ));
4052 b = min( 31, max( 0, b / 16 ));
4053 return (r << 10) | (g << 5) | b;
4056 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4057 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4059 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4060 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4061 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4062 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4065 /* compute the left/right triangle limit for row y */
4066 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4070 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4071 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4073 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4075 *left = max( rc->left, min( x1, x2 ) );
4076 *right = min( rc->right, max( x1, x2 ) );
4079 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4080 static inline int triangle_det( const TRIVERTEX *v )
4082 return (v[2].y - v[1].y) * (v[2].x - v[0].x) - (v[2].x - v[1].x) * (v[2].y - v[0].y);
4085 /* compute the barycentric weights for a given point inside the triangle */
4086 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4088 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4089 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4092 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4097 triangle_weights( v, x, y, &l1, &l2 );
4098 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4099 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4100 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4101 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4102 return a << 24 | r << 16 | g << 8 | b;
4105 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4110 triangle_weights( v, x, y, &l1, &l2 );
4111 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4112 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4113 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4114 return r << 16 | g << 8 | b;
4117 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4122 triangle_weights( v, x, y, &l1, &l2 );
4123 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4124 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4125 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4126 r = min( 31, max( 0, r / 16 ));
4127 g = min( 31, max( 0, g / 16 ));
4128 b = min( 31, max( 0, b / 16 ));
4129 return (r << 10) | (g << 5) | b;
4132 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4137 triangle_weights( v, x, y, &l1, &l2 );
4138 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4139 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4140 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4141 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4144 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4146 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4147 int x, y, left, right, det;
4151 case GRADIENT_FILL_RECT_H:
4152 for (x = 0; x < rc->right - rc->left; x++)
4153 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4155 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4156 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4159 case GRADIENT_FILL_RECT_V:
4160 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4162 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4163 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4167 case GRADIENT_FILL_TRIANGLE:
4168 if (!(det = triangle_det( v ))) return FALSE;
4169 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4171 triangle_coords( v, rc, y, &left, &right );
4172 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4179 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4181 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4182 int x, y, left, right, det;
4186 case GRADIENT_FILL_RECT_H:
4187 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4189 for (x = 0; x < rc->right - rc->left; x++)
4191 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4192 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4193 (((val >> 8) & 0xff) << dib->green_shift) |
4194 (((val >> 16) & 0xff) << dib->red_shift));
4199 for (x = 0; x < rc->right - rc->left; x++)
4201 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4202 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4203 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4204 put_field( val, dib->blue_shift, dib->blue_len ));
4208 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4209 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4212 case GRADIENT_FILL_RECT_V:
4213 for (y = rc->top; y < rc->bottom; y++)
4215 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4216 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4217 val = ((( val & 0xff) << dib->blue_shift) |
4218 (((val >> 8) & 0xff) << dib->green_shift) |
4219 (((val >> 16) & 0xff) << dib->red_shift));
4221 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4222 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4223 put_field( val, dib->blue_shift, dib->blue_len ));
4225 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4226 ptr += dib->stride / 4;
4230 case GRADIENT_FILL_TRIANGLE:
4231 if (!(det = triangle_det( v ))) return FALSE;
4232 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4234 triangle_coords( v, rc, y, &left, &right );
4236 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4237 for (x = left; x < right; x++)
4239 DWORD val = gradient_triangle_24( v, x, y, det );
4240 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4241 (((val >> 8) & 0xff) << dib->green_shift) |
4242 (((val >> 16) & 0xff) << dib->red_shift));
4245 for (x = left; x < right; x++)
4247 DWORD val = gradient_triangle_24( v, x, y, det );
4248 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4249 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4250 put_field( val, dib->blue_shift, dib->blue_len ));
4258 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4260 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4261 int x, y, left, right, det;
4265 case GRADIENT_FILL_RECT_H:
4266 for (x = 0; x < rc->right - rc->left; x++)
4268 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4270 ptr[x * 3 + 1] = val >> 8;
4271 ptr[x * 3 + 2] = val >> 16;
4274 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4275 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4278 case GRADIENT_FILL_RECT_V:
4279 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4281 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4282 for (x = 0; x < rc->right - rc->left; x++)
4285 ptr[x * 3 + 1] = val >> 8;
4286 ptr[x * 3 + 2] = val >> 16;
4291 case GRADIENT_FILL_TRIANGLE:
4292 if (!(det = triangle_det( v ))) return FALSE;
4293 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4295 triangle_coords( v, rc, y, &left, &right );
4296 for (x = left; x < right; x++)
4298 DWORD val = gradient_triangle_24( v, x, y, det );
4299 ptr[(x - rc->left) * 3] = val;
4300 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4301 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4309 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4311 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4312 int x, y, left, right, det;
4316 case GRADIENT_FILL_RECT_H:
4317 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4318 for (x = rc->left; x < rc->right; x++)
4319 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4320 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4321 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4324 case GRADIENT_FILL_RECT_V:
4325 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4328 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4329 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4333 case GRADIENT_FILL_TRIANGLE:
4334 if (!(det = triangle_det( v ))) return FALSE;
4335 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4337 triangle_coords( v, rc, y, &left, &right );
4338 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4345 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4347 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4348 int x, y, left, right, det;
4352 case GRADIENT_FILL_RECT_H:
4353 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4354 for (x = rc->left; x < rc->right; x++)
4356 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4357 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4358 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4359 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4361 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4362 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4365 case GRADIENT_FILL_RECT_V:
4366 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4369 for (x = 0; x < 4; x++)
4371 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4372 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4373 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4374 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4376 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4380 case GRADIENT_FILL_TRIANGLE:
4381 if (!(det = triangle_det( v ))) return FALSE;
4382 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4384 triangle_coords( v, rc, y, &left, &right );
4385 for (x = left; x < right; x++)
4387 WORD val = gradient_triangle_555( v, x, y, det );
4388 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4389 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4390 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4398 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4400 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4401 int x, y, left, right, det;
4405 case GRADIENT_FILL_RECT_H:
4406 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4407 for (x = rc->left; x < rc->right; x++)
4408 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4409 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4410 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4413 case GRADIENT_FILL_RECT_V:
4414 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4417 for (x = 0; x < 16; x++)
4418 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4419 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4423 case GRADIENT_FILL_TRIANGLE:
4424 if (!(det = triangle_det( v ))) return FALSE;
4425 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4427 triangle_coords( v, rc, y, &left, &right );
4428 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4435 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4437 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4438 int x, y, left, right, det, pos;
4442 case GRADIENT_FILL_RECT_H:
4443 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4445 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4447 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4449 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4451 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4454 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4457 pos = (dib->rect.left + rc->left) & 1;
4460 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4464 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4466 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4470 case GRADIENT_FILL_RECT_V:
4471 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4474 for (x = 0; x < 16; x++)
4475 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4476 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4478 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4480 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4484 case GRADIENT_FILL_TRIANGLE:
4485 if (!(det = triangle_det( v ))) return FALSE;
4486 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4488 triangle_coords( v, rc, y, &left, &right );
4489 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4491 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4493 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4495 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4503 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4505 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4506 int x, y, left, right, det, pos;
4510 case GRADIENT_FILL_RECT_H:
4511 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4513 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4515 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4516 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4519 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4520 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4521 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4522 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4525 case GRADIENT_FILL_RECT_V:
4526 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4529 for (x = 0; x < 16; x++)
4530 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4531 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4532 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4533 (values[x % 16] & pixel_masks_1[pos % 8]);
4537 case GRADIENT_FILL_TRIANGLE:
4538 if (!(det = triangle_det( v ))) return FALSE;
4539 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4541 triangle_coords( v, rc, y, &left, &right );
4542 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4544 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4545 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4553 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4558 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4560 if (dst == text) return dst;
4564 DWORD diff = dst - text;
4565 DWORD range = max_comp - text;
4566 dst = text + (diff * range ) / (0xff - text);
4571 DWORD diff = text - dst;
4572 DWORD range = text - min_comp;
4573 dst = text - (diff * range) / text;
4578 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4580 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4581 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4582 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4585 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4586 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4588 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4589 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4592 for (y = rect->top; y < rect->bottom; y++)
4594 for (x = 0; x < rect->right - rect->left; x++)
4596 if (glyph_ptr[x] <= 1) continue;
4597 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4598 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4600 dst_ptr += dib->stride / 4;
4601 glyph_ptr += glyph->stride;
4605 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4606 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4608 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4609 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4613 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4614 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4615 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4617 for (y = rect->top; y < rect->bottom; y++)
4619 for (x = 0; x < rect->right - rect->left; x++)
4621 if (glyph_ptr[x] <= 1) continue;
4622 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4623 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4624 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4625 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4626 text, ranges + glyph_ptr[x] );
4627 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4628 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4629 put_field( val, dib->blue_shift, dib->blue_len ));
4631 dst_ptr += dib->stride / 4;
4632 glyph_ptr += glyph->stride;
4636 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4637 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4639 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4640 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4644 for (y = rect->top; y < rect->bottom; y++)
4646 for (x = 0; x < rect->right - rect->left; x++)
4648 if (glyph_ptr[x] <= 1) continue;
4649 if (glyph_ptr[x] >= 16)
4652 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4653 text_pixel, ranges + glyph_ptr[x] );
4654 dst_ptr[x * 3] = val;
4655 dst_ptr[x * 3 + 1] = val >> 8;
4656 dst_ptr[x * 3 + 2] = val >> 16;
4658 dst_ptr += dib->stride;
4659 glyph_ptr += glyph->stride;
4663 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4664 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4666 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4667 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4671 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4672 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4673 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4675 for (y = rect->top; y < rect->bottom; y++)
4677 for (x = 0; x < rect->right - rect->left; x++)
4679 if (glyph_ptr[x] <= 1) continue;
4680 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4681 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4682 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4683 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4684 text, ranges + glyph_ptr[x] );
4685 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4687 dst_ptr += dib->stride / 2;
4688 glyph_ptr += glyph->stride;
4692 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4693 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4695 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4696 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4700 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4701 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4702 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4704 for (y = rect->top; y < rect->bottom; y++)
4706 for (x = 0; x < rect->right - rect->left; x++)
4708 if (glyph_ptr[x] <= 1) continue;
4709 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4710 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4711 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4712 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4713 text, ranges + glyph_ptr[x] );
4714 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4715 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4716 put_field( val, dib->blue_shift, dib->blue_len ));
4718 dst_ptr += dib->stride / 2;
4719 glyph_ptr += glyph->stride;
4723 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4724 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4726 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4727 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4730 for (y = rect->top; y < rect->bottom; y++)
4732 for (x = 0; x < rect->right - rect->left; x++)
4734 /* no antialiasing, glyph should only contain 0 or 16. */
4735 if (glyph_ptr[x] >= 16)
4736 dst_ptr[x] = text_pixel;
4738 dst_ptr += dib->stride;
4739 glyph_ptr += glyph->stride;
4743 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4744 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4746 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
4747 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4750 for (y = rect->top; y < rect->bottom; y++)
4752 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
4754 /* no antialiasing, glyph should only contain 0 or 16. */
4755 if (glyph_ptr[x] >= 16)
4758 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
4760 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
4763 dst_ptr += dib->stride;
4764 glyph_ptr += glyph->stride;
4768 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4769 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4771 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
4772 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4774 BYTE text = (text_pixel & 1) ? 0xff : 0;
4776 for (y = rect->top; y < rect->bottom; y++)
4778 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
4780 /* no antialiasing, glyph should only contain 0 or 16. */
4781 if (glyph_ptr[x] >= 16)
4782 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4783 (text & pixel_masks_1[pos % 8]);
4785 dst_ptr += dib->stride;
4786 glyph_ptr += glyph->stride;
4790 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4791 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4796 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)
4798 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4799 DWORD mask_start = 0, mask_offset;
4800 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4803 for(y = 0; y < hatch->height; y++)
4805 hatch_ptr = hatch_start;
4806 mask_offset = mask_start;
4807 for(x = 0; x < hatch->width; x++)
4809 if(*hatch_ptr & pixel_masks_1[x % 8])
4811 and_bits[mask_offset] = fg->and;
4812 xor_bits[mask_offset] = fg->xor;
4816 and_bits[mask_offset] = bg->and;
4817 xor_bits[mask_offset] = bg->xor;
4819 if(x % 8 == 7) hatch_ptr++;
4822 hatch_start += hatch->stride;
4823 mask_start += dib->stride / 4;
4829 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)
4831 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4832 DWORD mask_start = 0, mask_offset;
4833 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4836 for(y = 0; y < hatch->height; y++)
4838 hatch_ptr = hatch_start;
4839 mask_offset = mask_start;
4840 for(x = 0; x < hatch->width; x++)
4842 if(*hatch_ptr & pixel_masks_1[x % 8])
4844 and_bits[mask_offset] = fg->and & 0xff;
4845 xor_bits[mask_offset++] = fg->xor & 0xff;
4846 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4847 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4848 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4849 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4853 and_bits[mask_offset] = bg->and & 0xff;
4854 xor_bits[mask_offset++] = bg->xor & 0xff;
4855 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4856 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4857 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4858 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4860 if(x % 8 == 7) hatch_ptr++;
4862 hatch_start += hatch->stride;
4863 mask_start += dib->stride;
4869 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)
4871 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4872 DWORD mask_start = 0, mask_offset;
4873 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4876 for(y = 0; y < hatch->height; y++)
4878 hatch_ptr = hatch_start;
4879 mask_offset = mask_start;
4880 for(x = 0; x < hatch->width; x++)
4882 if(*hatch_ptr & pixel_masks_1[x % 8])
4884 and_bits[mask_offset] = fg->and;
4885 xor_bits[mask_offset] = fg->xor;
4889 and_bits[mask_offset] = bg->and;
4890 xor_bits[mask_offset] = bg->xor;
4892 if(x % 8 == 7) hatch_ptr++;
4895 hatch_start += hatch->stride;
4896 mask_start += dib->stride / 2;
4902 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)
4904 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4905 DWORD mask_start = 0, mask_offset;
4906 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4909 for(y = 0; y < hatch->height; y++)
4911 hatch_ptr = hatch_start;
4912 mask_offset = mask_start;
4913 for(x = 0; x < hatch->width; x++)
4915 if(*hatch_ptr & pixel_masks_1[x % 8])
4917 and_bits[mask_offset] = fg->and;
4918 xor_bits[mask_offset] = fg->xor;
4922 and_bits[mask_offset] = bg->and;
4923 xor_bits[mask_offset] = bg->xor;
4925 if(x % 8 == 7) hatch_ptr++;
4928 hatch_start += hatch->stride;
4929 mask_start += dib->stride;
4935 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)
4937 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4938 DWORD mask_start = 0, mask_offset;
4939 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4940 const rop_mask *rop_mask;
4943 for(y = 0; y < hatch->height; y++)
4945 hatch_ptr = hatch_start;
4946 mask_offset = mask_start;
4947 for(x = 0; x < hatch->width; x++)
4949 if(*hatch_ptr & pixel_masks_1[x % 8])
4956 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4957 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4962 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4963 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4966 if(x % 8 == 7) hatch_ptr++;
4968 hatch_start += hatch->stride;
4969 mask_start += dib->stride;
4975 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)
4977 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4978 DWORD mask_start = 0, mask_offset;
4979 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4983 for(y = 0; y < hatch->height; y++)
4985 hatch_ptr = hatch_start;
4986 mask_offset = mask_start;
4987 for(x = 0, bit_pos = 0; x < hatch->width; x++)
4989 if(*hatch_ptr & pixel_masks_1[x % 8])
4991 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4992 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4996 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4997 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5000 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
5002 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
5003 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
5012 hatch_start += hatch->stride;
5013 mask_start += dib->stride;
5019 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)
5024 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5029 case STRETCH_DELETESCANS:
5030 get_rop_codes( R2_COPYPEN, codes );
5032 case STRETCH_ORSCANS:
5033 get_rop_codes( R2_MERGEPEN, codes );
5035 case STRETCH_ANDSCANS:
5036 get_rop_codes( R2_MASKPEN, codes );
5042 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5043 const dib_info *src_dib, const POINT *src_start,
5044 const struct stretch_params *params, int mode,
5047 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5048 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5049 int err = params->err_start;
5051 struct rop_codes codes;
5053 rop_codes_from_stretch_mode( mode, &codes );
5054 for (width = params->length; width; width--)
5056 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5057 dst_ptr += params->dst_inc;
5060 src_ptr += params->src_inc;
5061 err += params->err_add_1;
5063 else err += params->err_add_2;
5067 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5068 const dib_info *src_dib, const POINT *src_start,
5069 const struct stretch_params *params, int mode,
5072 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5073 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5074 int err = params->err_start;
5076 struct rop_codes codes;
5078 rop_codes_from_stretch_mode( mode, &codes );
5079 for (width = params->length; width; width--)
5081 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5082 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5083 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5084 dst_ptr += 3 * params->dst_inc;
5087 src_ptr += 3 * params->src_inc;
5088 err += params->err_add_1;
5090 else err += params->err_add_2;
5094 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5095 const dib_info *src_dib, const POINT *src_start,
5096 const struct stretch_params *params, int mode,
5099 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5100 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5101 int err = params->err_start;
5103 struct rop_codes codes;
5105 rop_codes_from_stretch_mode( mode, &codes );
5106 for (width = params->length; width; width--)
5108 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5109 dst_ptr += params->dst_inc;
5112 src_ptr += params->src_inc;
5113 err += params->err_add_1;
5115 else err += params->err_add_2;
5119 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5120 const dib_info *src_dib, const POINT *src_start,
5121 const struct stretch_params *params, int mode,
5124 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5125 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5126 int err = params->err_start;
5128 struct rop_codes codes;
5130 rop_codes_from_stretch_mode( mode, &codes );
5131 for (width = params->length; width; width--)
5133 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5134 dst_ptr += params->dst_inc;
5137 src_ptr += params->src_inc;
5138 err += params->err_add_1;
5140 else err += params->err_add_2;
5144 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5145 const dib_info *src_dib, const POINT *src_start,
5146 const struct stretch_params *params, int mode,
5149 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5150 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5151 int err = params->err_start;
5152 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5153 struct rop_codes codes;
5156 rop_codes_from_stretch_mode( mode, &codes );
5157 for (width = params->length; width; width--)
5159 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5160 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5162 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5164 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5165 dst_ptr += params->dst_inc;
5166 dst_x += params->dst_inc;
5170 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5171 src_ptr += params->src_inc;
5172 src_x += params->src_inc;
5173 err += params->err_add_1;
5175 else err += params->err_add_2;
5179 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5180 const dib_info *src_dib, const POINT *src_start,
5181 const struct stretch_params *params, int mode,
5184 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5185 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5186 int err = params->err_start;
5187 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5188 struct rop_codes codes;
5191 rop_codes_from_stretch_mode( mode, &codes );
5192 for (width = params->length; width; width--)
5194 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5195 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5197 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5198 dst_ptr += params->dst_inc;
5199 dst_x += params->dst_inc;
5203 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5204 src_ptr += params->src_inc;
5205 src_x += params->src_inc;
5206 err += params->err_add_1;
5208 else err += params->err_add_2;
5212 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5213 const dib_info *src_dib, const POINT *src_start,
5214 const struct stretch_params *params, int mode,
5217 FIXME("bit count %d\n", dst_dib->bit_count);
5221 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5222 const dib_info *src_dib, const POINT *src_start,
5223 const struct stretch_params *params, int mode,
5226 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5227 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5228 int err = params->err_start;
5230 struct rop_codes codes;
5231 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5232 BOOL new_pix = TRUE;
5234 rop_codes_from_stretch_mode( mode, &codes );
5235 for (width = params->length; width; width--)
5237 if (new_pix && !keep_dst) *dst_ptr = init_val;
5238 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5240 src_ptr += params->src_inc;
5243 dst_ptr += params->dst_inc;
5245 err += params->err_add_1;
5247 else err += params->err_add_2;
5251 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5252 const dib_info *src_dib, const POINT *src_start,
5253 const struct stretch_params *params, int mode,
5256 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5257 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5258 int err = params->err_start;
5260 struct rop_codes codes;
5261 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5262 BOOL new_pix = TRUE;
5264 rop_codes_from_stretch_mode( mode, &codes );
5265 for (width = params->length; width; width--)
5267 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5268 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5269 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5270 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5272 src_ptr += 3 * params->src_inc;
5275 dst_ptr += 3 * params->dst_inc;
5277 err += params->err_add_1;
5279 else err += params->err_add_2;
5283 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5284 const dib_info *src_dib, const POINT *src_start,
5285 const struct stretch_params *params, int mode,
5288 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5289 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5290 int err = params->err_start;
5292 struct rop_codes codes;
5293 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5294 BOOL new_pix = TRUE;
5296 rop_codes_from_stretch_mode( mode, &codes );
5297 for (width = params->length; width; width--)
5299 if (new_pix && !keep_dst) *dst_ptr = init_val;
5300 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5302 src_ptr += params->src_inc;
5305 dst_ptr += params->dst_inc;
5307 err += params->err_add_1;
5309 else err += params->err_add_2;
5313 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5314 const dib_info *src_dib, const POINT *src_start,
5315 const struct stretch_params *params, int mode,
5318 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5319 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5320 int err = params->err_start;
5322 struct rop_codes codes;
5323 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5324 BOOL new_pix = TRUE;
5326 rop_codes_from_stretch_mode( mode, &codes );
5327 for (width = params->length; width; width--)
5329 if (new_pix && !keep_dst) *dst_ptr = init_val;
5330 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5332 src_ptr += params->src_inc;
5335 dst_ptr += params->dst_inc;
5337 err += params->err_add_1;
5339 else err += params->err_add_2;
5343 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5344 const dib_info *src_dib, const POINT *src_start,
5345 const struct stretch_params *params, int mode,
5348 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5349 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5350 int err = params->err_start;
5351 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5352 struct rop_codes codes;
5353 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5354 BOOL new_pix = TRUE;
5356 rop_codes_from_stretch_mode( mode, &codes );
5357 for (width = params->length; width; width--)
5359 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
5361 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5362 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5364 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5367 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5368 src_ptr += params->src_inc;
5369 src_x += params->src_inc;
5373 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5374 dst_ptr += params->dst_inc;
5375 dst_x += params->dst_inc;
5377 err += params->err_add_1;
5379 else err += params->err_add_2;
5383 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5384 const dib_info *src_dib, const POINT *src_start,
5385 const struct stretch_params *params, int mode,
5388 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5389 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5390 int err = params->err_start;
5391 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5392 struct rop_codes codes;
5393 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5394 BOOL new_pix = TRUE;
5396 rop_codes_from_stretch_mode( mode, &codes );
5397 for (width = params->length; width; width--)
5399 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5400 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5401 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5404 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5405 src_ptr += params->src_inc;
5406 src_x += params->src_inc;
5410 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5411 dst_ptr += params->dst_inc;
5412 dst_x += params->dst_inc;
5414 err += params->err_add_1;
5416 else err += params->err_add_2;
5420 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5421 const dib_info *src_dib, const POINT *src_start,
5422 const struct stretch_params *params, int mode,
5425 FIXME("bit count %d\n", dst_dib->bit_count);
5429 const primitive_funcs funcs_8888 =
5439 colorref_to_pixel_888,
5440 pixel_to_colorref_888,
5442 create_rop_masks_32,
5447 const primitive_funcs funcs_32 =
5457 colorref_to_pixel_masks,
5458 pixel_to_colorref_masks,
5460 create_rop_masks_32,
5465 const primitive_funcs funcs_24 =
5475 colorref_to_pixel_888,
5476 pixel_to_colorref_888,
5478 create_rop_masks_24,
5483 const primitive_funcs funcs_555 =
5493 colorref_to_pixel_555,
5494 pixel_to_colorref_555,
5496 create_rop_masks_16,
5501 const primitive_funcs funcs_16 =
5511 colorref_to_pixel_masks,
5512 pixel_to_colorref_masks,
5514 create_rop_masks_16,
5519 const primitive_funcs funcs_8 =
5529 colorref_to_pixel_colortable,
5530 pixel_to_colorref_colortable,
5537 const primitive_funcs funcs_4 =
5547 colorref_to_pixel_colortable,
5548 pixel_to_colorref_colortable,
5555 const primitive_funcs funcs_1 =
5565 colorref_to_pixel_colortable,
5566 pixel_to_colorref_colortable,
5573 const primitive_funcs funcs_null =
5583 colorref_to_pixel_null,
5584 pixel_to_colorref_null,
5586 create_rop_masks_null,