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_8x8[8][8] =
42 { 0, 32, 8, 40, 2, 34, 10, 42 },
43 { 48, 16, 56, 24, 50, 18, 58, 26 },
44 { 12, 44, 4, 36, 14, 46, 6, 38 },
45 { 60, 28, 52, 20, 62, 30, 54, 22 },
46 { 3, 35, 11, 43, 1, 33, 9, 41 },
47 { 51, 19, 59, 27, 49, 17, 57, 25 },
48 { 15, 47, 7, 39, 13, 45, 5, 37 },
49 { 63, 31, 55, 23, 61, 29, 53, 21 }
52 static const BYTE bayer_16x16[16][16] =
54 { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170 },
55 { 192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106 },
56 { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154 },
57 { 240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90 },
58 { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166 },
59 { 204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102 },
60 { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150 },
61 { 252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86 },
62 { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169 },
63 { 195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105 },
64 { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153 },
65 { 243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89 },
66 { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165 },
67 { 207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101 },
68 { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149 },
69 { 255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85 },
72 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
74 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 4);
77 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
79 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride) + (dib->rect.left + x) * 3 / 4;
82 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
84 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 3;
87 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
89 return (WORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 2);
92 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
94 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + dib->rect.left + x;
97 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
99 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 2;
102 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
104 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 8;
107 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
108 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
110 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
112 *ptr = (*ptr & and) ^ xor;
115 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
117 *ptr = (*ptr & and) ^ xor;
120 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
122 *ptr = (*ptr & and) ^ xor;
125 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
127 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
130 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
132 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
135 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
137 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
140 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
142 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
145 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
147 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
150 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
152 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
155 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
157 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
158 do_rop_codes_32( dst, *src, codes );
161 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
163 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
166 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
168 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
169 do_rop_codes_16( dst, *src, codes );
172 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
174 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
177 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
179 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
180 do_rop_codes_8( dst, *src, codes );
183 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
184 struct rop_codes *codes, int len)
188 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
192 if (src_x & 1) src_val = *src++;
193 else src_val = *src >> 4;
194 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
198 if (src_x & 1) src_val = *src++ << 4;
200 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
205 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
206 struct rop_codes *codes, int len)
212 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
216 if (src_x & 1) src_val = *src;
217 else src_val = *src-- >> 4;
218 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
222 if (src_x & 1) src_val = *src << 4;
223 else src_val = *src--;
224 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
229 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
230 struct rop_codes *codes, int len)
234 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
236 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
237 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
238 if ((src_x & 7) == 7) src++;
239 if ((dst_x & 7) == 7) dst++;
243 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
244 struct rop_codes *codes, int len)
250 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
252 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
253 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
254 if ((src_x & 7) == 0) src--;
255 if ((dst_x & 7) == 0) dst--;
259 static inline void memset_32( DWORD *start, DWORD val, DWORD size )
261 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
263 __asm__ __volatile__( "cld; rep; stosl"
264 : "=c" (dummy), "=D" (dummy)
265 : "a" (val), "0" (size), "1" (start) );
267 while (size--) *start++ = val;
271 static inline void memset_16( WORD *start, WORD val, DWORD size )
273 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
275 __asm__ __volatile__( "cld; rep; stosw"
276 : "=c" (dummy), "=D" (dummy)
277 : "a" (val), "0" (size), "1" (start) );
279 while (size--) *start++ = val;
283 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
288 for(i = 0; i < num; i++, rc++)
290 assert( !is_rect_empty( rc ));
292 start = get_pixel_ptr_32(dib, rc->left, rc->top);
294 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
295 for(x = rc->left, ptr = start; x < rc->right; x++)
296 do_rop_32(ptr++, and, xor);
298 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
299 memset_32( start, xor, rc->right - rc->left );
303 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
306 BYTE *byte_ptr, *byte_start;
308 DWORD and_masks[3], xor_masks[3];
310 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
311 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
312 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
313 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
314 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
315 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
317 for(i = 0; i < num; i++, rc++)
319 int left = dib->rect.left + rc->left;
320 int right = dib->rect.left + rc->right;
322 assert( !is_rect_empty( rc ));
324 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
326 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
327 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
329 for(x = left, byte_ptr = byte_start; x < right; x++)
331 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
332 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
333 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
339 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
340 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
347 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
348 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
349 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
352 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
353 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
356 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
360 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
362 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
363 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
364 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
370 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
373 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
374 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
377 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
378 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
379 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
386 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
387 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
394 do_rop_32(ptr++, 0x00ffffff, xor_masks[0] & 0xff000000);
395 *ptr++ = xor_masks[1];
396 *ptr++ = xor_masks[2];
399 do_rop_32(ptr++, 0x0000ffff, xor_masks[1] & 0xffff0000);
400 *ptr++ = xor_masks[2];
403 do_rop_32(ptr++, 0x000000ff, xor_masks[2] & 0xffffff00);
407 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
409 *ptr++ = xor_masks[0];
410 *ptr++ = xor_masks[1];
411 *ptr++ = xor_masks[2];
417 do_rop_32(ptr, 0xff000000, xor_masks[0] & 0x00ffffff);
420 *ptr++ = xor_masks[0];
421 do_rop_32(ptr, 0xffff0000, xor_masks[1] & 0x0000ffff);
424 *ptr++ = xor_masks[0];
425 *ptr++ = xor_masks[1];
426 do_rop_32(ptr, 0xffffff00, xor_masks[2] & 0x000000ff);
434 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
439 for(i = 0; i < num; i++, rc++)
441 assert( !is_rect_empty( rc ));
443 start = get_pixel_ptr_16(dib, rc->left, rc->top);
445 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
446 for(x = rc->left, ptr = start; x < rc->right; x++)
447 do_rop_16(ptr++, and, xor);
449 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
450 memset_16( start, xor, rc->right - rc->left );
454 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
459 for(i = 0; i < num; i++, rc++)
461 assert( !is_rect_empty( rc ));
463 start = get_pixel_ptr_8(dib, rc->left, rc->top);
465 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
466 for(x = rc->left, ptr = start; x < rc->right; x++)
467 do_rop_8(ptr++, and, xor);
469 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
470 memset( start, xor, rc->right - rc->left );
474 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
478 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
479 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
481 for(i = 0; i < num; i++, rc++)
483 int left = dib->rect.left + rc->left;
484 int right = dib->rect.left + rc->right;
486 assert( !is_rect_empty( rc ));
488 start = get_pixel_ptr_4(dib, rc->left, rc->top);
491 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
494 if(left & 1) /* upper nibble untouched */
495 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
497 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
498 do_rop_8(ptr++, byte_and, byte_xor);
500 if(right & 1) /* lower nibble untouched */
501 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
506 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
508 unsigned int byte_len = (right - ((left + 1) & ~1)) / 2;
511 if(left & 1) /* upper nibble untouched */
512 do_rop_8(ptr++, 0xf0, byte_xor & 0x0f);
514 memset( ptr, byte_xor, byte_len );
516 if(right & 1) /* lower nibble untouched */
517 do_rop_8(ptr + byte_len, 0x0f, byte_xor & 0xf0);
523 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
527 BYTE byte_and = (and & 1) ? 0xff : 0;
528 BYTE byte_xor = (xor & 1) ? 0xff : 0;
529 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
531 for(i = 0; i < num; i++, rc++)
533 int left = dib->rect.left + rc->left;
534 int right = dib->rect.left + rc->right;
536 assert( !is_rect_empty( rc ));
538 start = get_pixel_ptr_1(dib, rc->left, rc->top);
540 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
542 BYTE mask = masks[left & 7] & ~masks[right & 7];
544 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
546 do_rop_8(start, byte_and | ~mask, byte_xor & mask);
551 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
556 do_rop_8(ptr++, byte_and | ~masks[left & 7], byte_xor & masks[left & 7]);
558 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
559 do_rop_8(ptr++, byte_and, byte_xor);
562 /* this is inverted wrt start mask */
563 do_rop_8(ptr, byte_and | masks[right & 7], byte_xor & ~masks[right & 7]);
568 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
570 unsigned int byte_len = (right - ((left + 7) & ~7)) / 8;
575 do_rop_8(ptr++, ~masks[left & 7], byte_xor & masks[left & 7]);
577 memset( ptr, byte_xor, byte_len );
580 do_rop_8(ptr + byte_len, masks[right & 7], byte_xor & ~masks[right & 7]);
586 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
591 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
592 DWORD and, DWORD xor)
594 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
595 int len = params->length, err = params->err_start;
596 int major_inc, minor_inc;
600 major_inc = params->x_inc;
601 minor_inc = (dib->stride * params->y_inc) / 4;
605 major_inc = (dib->stride * params->y_inc) / 4;
606 minor_inc = params->x_inc;
611 do_rop_32( ptr, and, xor );
612 if (err + params->bias > 0)
615 err += params->err_add_1;
617 else err += params->err_add_2;
622 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
623 DWORD and, DWORD xor)
625 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
626 int len = params->length, err = params->err_start;
627 int major_inc, minor_inc;
631 major_inc = params->x_inc * 3;
632 minor_inc = dib->stride * params->y_inc;
636 major_inc = dib->stride * params->y_inc;
637 minor_inc = params->x_inc * 3;
642 do_rop_8( ptr, and, xor );
643 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
644 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
645 if (err + params->bias > 0)
648 err += params->err_add_1;
650 else err += params->err_add_2;
655 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
656 DWORD and, DWORD xor)
658 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
659 int len = params->length, err = params->err_start;
660 int major_inc, minor_inc;
664 major_inc = params->x_inc;
665 minor_inc = (dib->stride * params->y_inc) / 2;
669 major_inc = (dib->stride * params->y_inc) / 2;
670 minor_inc = params->x_inc;
675 do_rop_16( ptr, and, xor );
676 if (err + params->bias > 0)
679 err += params->err_add_1;
681 else err += params->err_add_2;
686 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
687 DWORD and, DWORD xor)
689 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
690 int len = params->length, err = params->err_start;
691 int major_inc, minor_inc;
695 major_inc = params->x_inc;
696 minor_inc = dib->stride * params->y_inc;
700 major_inc = dib->stride * params->y_inc;
701 minor_inc = params->x_inc;
706 do_rop_8( ptr, and, xor );
707 if (err + params->bias > 0)
710 err += params->err_add_1;
712 else err += params->err_add_2;
717 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
718 DWORD and, DWORD xor)
720 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
721 int len = params->length, err = params->err_start;
722 int x = dib->rect.left + start->x;
724 and = (and & 0x0f) | ((and << 4) & 0xf0);
725 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
731 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
732 if (err + params->bias > 0)
734 ptr += dib->stride * params->y_inc;
735 err += params->err_add_1;
737 else err += params->err_add_2;
738 if ((x / 2) != ((x + params->x_inc) / 2))
739 ptr += params->x_inc;
747 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
748 if (err + params->bias > 0)
750 if ((x / 2) != ((x + params->x_inc) / 2))
751 ptr += params->x_inc;
753 err += params->err_add_1;
755 else err += params->err_add_2;
756 ptr += dib->stride * params->y_inc;
761 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
762 DWORD and, DWORD xor)
764 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
765 int len = params->length, err = params->err_start;
766 int x = dib->rect.left + start->x;
768 and = (and & 0x1) ? 0xff : 0;
769 xor = (xor & 0x1) ? 0xff : 0;
775 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
776 if (err + params->bias > 0)
778 ptr += dib->stride * params->y_inc;
779 err += params->err_add_1;
781 else err += params->err_add_2;
782 if ((x / 8) != ((x + params->x_inc) / 8))
783 ptr += params->x_inc;
791 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
792 if (err + params->bias > 0)
794 if ((x / 8) != ((x + params->x_inc) / 8))
795 ptr += params->x_inc;
797 err += params->err_add_1;
799 else err += params->err_add_2;
800 ptr += dib->stride * params->y_inc;
805 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
806 DWORD and, DWORD xor)
811 static inline INT calc_offset(INT edge, INT size, INT origin)
815 if(edge - origin >= 0)
816 offset = (edge - origin) % size;
819 offset = (origin - edge) % size;
820 if(offset) offset = size - offset;
825 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
829 offset.x = calc_offset(rc->left, brush->width, origin->x);
830 offset.y = calc_offset(rc->top, brush->height, origin->y);
835 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
836 const dib_info *brush, const rop_mask_bits *bits)
838 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
839 int x, y, i, len, brush_x;
842 for(i = 0; i < num; i++, rc++)
844 offset = calc_brush_offset(rc, brush, origin);
845 start = get_pixel_ptr_32(dib, rc->left, rc->top);
846 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
850 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
852 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
854 and_ptr = start_and + offset.x;
855 xor_ptr = start_xor + offset.x;
857 for(x = rc->left, ptr = start; x < rc->right; x++)
859 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
860 if(and_ptr == start_and + brush->width)
868 if(offset.y == brush->height)
870 start_and = bits->and;
871 start_xor = bits->xor;
876 start_and += brush->stride / 4;
877 start_xor += brush->stride / 4;
883 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
885 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
887 len = min( rc->right - x, brush->width - brush_x );
888 memcpy( start + x - rc->left, start_xor + brush_x, len * 4 );
892 start_xor += brush->stride / 4;
894 if(offset.y == brush->height)
896 start_xor = bits->xor;
904 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
905 const dib_info *brush, const rop_mask_bits *bits)
907 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
908 int x, y, i, len, brush_x;
911 for(i = 0; i < num; i++, rc++)
913 offset = calc_brush_offset(rc, brush, origin);
915 start = get_pixel_ptr_24(dib, rc->left, rc->top);
916 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
920 start_and = (BYTE*)bits->and + offset.y * brush->stride;
921 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
923 and_ptr = start_and + offset.x * 3;
924 xor_ptr = start_xor + offset.x * 3;
926 for(x = rc->left, ptr = start; x < rc->right; x++)
928 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
929 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
930 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
931 if(and_ptr == start_and + brush->width * 3)
939 if(offset.y == brush->height)
941 start_and = bits->and;
942 start_xor = bits->xor;
947 start_and += brush->stride;
948 start_xor += brush->stride;
954 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
956 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
958 len = min( rc->right - x, brush->width - brush_x );
959 memcpy( start + (x - rc->left) * 3, start_xor + brush_x * 3, len * 3 );
963 start_xor += brush->stride;
965 if(offset.y == brush->height)
967 start_xor = bits->xor;
975 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
976 const dib_info *brush, const rop_mask_bits *bits)
978 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
979 int x, y, i, len, brush_x;
982 for(i = 0; i < num; i++, rc++)
984 offset = calc_brush_offset(rc, brush, origin);
986 start = get_pixel_ptr_16(dib, rc->left, rc->top);
987 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
991 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
992 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
994 and_ptr = start_and + offset.x;
995 xor_ptr = start_xor + offset.x;
997 for(x = rc->left, ptr = start; x < rc->right; x++)
999 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
1000 if(and_ptr == start_and + brush->width)
1002 and_ptr = start_and;
1003 xor_ptr = start_xor;
1008 if(offset.y == brush->height)
1010 start_and = bits->and;
1011 start_xor = bits->xor;
1016 start_and += brush->stride / 2;
1017 start_xor += brush->stride / 2;
1023 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
1025 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1027 len = min( rc->right - x, brush->width - brush_x );
1028 memcpy( start + x - rc->left, start_xor + brush_x, len * 2 );
1032 start_xor += brush->stride / 2;
1034 if(offset.y == brush->height)
1036 start_xor = bits->xor;
1044 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1045 const dib_info *brush, const rop_mask_bits *bits)
1047 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1048 int x, y, i, len, brush_x;
1051 for(i = 0; i < num; i++, rc++)
1053 offset = calc_brush_offset(rc, brush, origin);
1055 start = get_pixel_ptr_8(dib, rc->left, rc->top);
1056 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1060 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1061 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1063 and_ptr = start_and + offset.x;
1064 xor_ptr = start_xor + offset.x;
1066 for(x = rc->left, ptr = start; x < rc->right; x++)
1068 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1069 if(and_ptr == start_and + brush->width)
1071 and_ptr = start_and;
1072 xor_ptr = start_xor;
1077 if(offset.y == brush->height)
1079 start_and = bits->and;
1080 start_xor = bits->xor;
1085 start_and += brush->stride;
1086 start_xor += brush->stride;
1092 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1094 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1096 len = min( rc->right - x, brush->width - brush_x );
1097 memcpy( start + x - rc->left, start_xor + brush_x, len );
1101 start_xor += brush->stride;
1103 if(offset.y == brush->height)
1105 start_xor = bits->xor;
1113 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1114 const dib_info *brush, const rop_mask_bits *bits)
1116 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1117 int x, y, i, left, right;
1120 for(i = 0; i < num; i++, rc++)
1122 offset = calc_brush_offset(rc, brush, origin);
1123 left = dib->rect.left + rc->left;
1124 right = dib->rect.left + rc->right;
1126 start = get_pixel_ptr_4(dib, rc->left, rc->top);
1127 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1131 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1132 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1134 INT brush_x = offset.x;
1135 BYTE byte_and, byte_xor;
1137 and_ptr = start_and + brush_x / 2;
1138 xor_ptr = start_xor + brush_x / 2;
1140 for(x = left, ptr = start; x < right; x++)
1142 /* FIXME: Two pixels at a time */
1143 if(x & 1) /* lower dst nibble */
1145 if(brush_x & 1) /* lower pat nibble */
1147 byte_and = *and_ptr++ | 0xf0;
1148 byte_xor = *xor_ptr++ & 0x0f;
1150 else /* upper pat nibble */
1152 byte_and = (*and_ptr >> 4) | 0xf0;
1153 byte_xor = (*xor_ptr >> 4) & 0x0f;
1156 else /* upper dst nibble */
1158 if(brush_x & 1) /* lower pat nibble */
1160 byte_and = (*and_ptr++ << 4) | 0x0f;
1161 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1163 else /* upper pat nibble */
1165 byte_and = *and_ptr | 0x0f;
1166 byte_xor = *xor_ptr & 0xf0;
1169 do_rop_8(ptr, byte_and, byte_xor);
1173 if(++brush_x == brush->width)
1176 and_ptr = start_and;
1177 xor_ptr = start_xor;
1182 if(offset.y == brush->height)
1184 start_and = bits->and;
1185 start_xor = bits->xor;
1190 start_and += brush->stride;
1191 start_xor += brush->stride;
1197 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1199 INT brush_x = offset.x;
1202 xor_ptr = start_xor + brush_x / 2;
1204 for(x = left, ptr = start; x < right; x++)
1206 /* FIXME: Two pixels at a time */
1207 if(x & 1) /* lower dst nibble */
1209 if(brush_x & 1) /* lower pat nibble */
1210 byte_xor = *xor_ptr++ & 0x0f;
1211 else /* upper pat nibble */
1212 byte_xor = (*xor_ptr >> 4) & 0x0f;
1213 do_rop_8(ptr, 0xf0, byte_xor);
1215 else /* upper dst nibble */
1217 if(brush_x & 1) /* lower pat nibble */
1218 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1219 else /* upper pat nibble */
1220 byte_xor = *xor_ptr & 0xf0;
1221 do_rop_8(ptr, 0x0f, byte_xor);
1226 if(++brush_x == brush->width)
1229 xor_ptr = start_xor;
1233 start_xor += brush->stride;
1235 if(offset.y == brush->height)
1237 start_xor = bits->xor;
1245 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1246 const dib_info *brush, const rop_mask_bits *bits)
1248 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1249 int x, y, i, left, right;
1252 for(i = 0; i < num; i++, rc++)
1254 offset = calc_brush_offset(rc, brush, origin);
1255 left = dib->rect.left + rc->left;
1256 right = dib->rect.left + rc->right;
1258 start = get_pixel_ptr_1(dib, rc->left, rc->top);
1259 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1263 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1264 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1266 INT brush_x = offset.x;
1267 BYTE byte_and, byte_xor;
1269 and_ptr = start_and + brush_x / 8;
1270 xor_ptr = start_xor + brush_x / 8;
1272 for(x = left, ptr = start; x < right; x++)
1274 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1275 byte_and |= ~pixel_masks_1[x % 8];
1276 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1277 byte_xor &= pixel_masks_1[x % 8];
1279 do_rop_8(ptr, byte_and, byte_xor);
1281 if((x & 7) == 7) ptr++;
1283 if((brush_x & 7) == 7)
1289 if(++brush_x == brush->width)
1292 and_ptr = start_and;
1293 xor_ptr = start_xor;
1298 if(offset.y == brush->height)
1300 start_and = bits->and;
1301 start_xor = bits->xor;
1306 start_and += brush->stride;
1307 start_xor += brush->stride;
1313 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1315 INT brush_x = offset.x;
1317 xor_ptr = start_xor + brush_x / 8;
1319 for(x = left, ptr = start; x < right; x++)
1321 BYTE byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1322 byte_xor &= pixel_masks_1[x % 8];
1324 do_rop_8(ptr, ~pixel_masks_1[x % 8], byte_xor);
1326 if((x & 7) == 7) ptr++;
1327 if((brush_x & 7) == 7) xor_ptr++;
1329 if(++brush_x == brush->width)
1332 xor_ptr = start_xor;
1336 start_xor += brush->stride;
1338 if(offset.y == brush->height)
1340 start_xor = bits->xor;
1348 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1349 const dib_info *brush, const rop_mask_bits *bits)
1354 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1355 const dib_info *src, const POINT *origin, int rop2, int overlap)
1357 DWORD *dst_start, *src_start;
1358 struct rop_codes codes;
1359 int y, dst_stride, src_stride;
1361 if (overlap & OVERLAP_BELOW)
1363 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1364 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1365 dst_stride = -dst->stride / 4;
1366 src_stride = -src->stride / 4;
1370 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1371 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1372 dst_stride = dst->stride / 4;
1373 src_stride = src->stride / 4;
1376 if (rop2 == R2_COPYPEN)
1378 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1379 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1383 get_rop_codes( rop2, &codes );
1384 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1386 if (overlap & OVERLAP_RIGHT)
1387 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1389 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1393 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1394 const dib_info *src, const POINT *origin, int rop2, int overlap)
1396 BYTE *dst_start, *src_start;
1397 int y, dst_stride, src_stride;
1398 struct rop_codes codes;
1400 if (overlap & OVERLAP_BELOW)
1402 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1403 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1404 dst_stride = -dst->stride;
1405 src_stride = -src->stride;
1409 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1410 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1411 dst_stride = dst->stride;
1412 src_stride = src->stride;
1415 if (rop2 == R2_COPYPEN)
1417 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1418 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1422 get_rop_codes( rop2, &codes );
1423 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1425 if (overlap & OVERLAP_RIGHT)
1426 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1428 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1432 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1433 const dib_info *src, const POINT *origin, int rop2, int overlap)
1435 WORD *dst_start, *src_start;
1436 int y, dst_stride, src_stride;
1437 struct rop_codes codes;
1439 if (overlap & OVERLAP_BELOW)
1441 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1442 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1443 dst_stride = -dst->stride / 2;
1444 src_stride = -src->stride / 2;
1448 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1449 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1450 dst_stride = dst->stride / 2;
1451 src_stride = src->stride / 2;
1454 if (rop2 == R2_COPYPEN)
1456 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1457 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1461 get_rop_codes( rop2, &codes );
1462 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1464 if (overlap & OVERLAP_RIGHT)
1465 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1467 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1471 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1472 const dib_info *src, const POINT *origin, int rop2, int overlap)
1474 BYTE *dst_start, *src_start;
1475 int y, dst_stride, src_stride;
1476 struct rop_codes codes;
1478 if (overlap & OVERLAP_BELOW)
1480 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1481 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1482 dst_stride = -dst->stride;
1483 src_stride = -src->stride;
1487 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1488 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1489 dst_stride = dst->stride;
1490 src_stride = src->stride;
1493 if (rop2 == R2_COPYPEN)
1495 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1496 memmove( dst_start, src_start, (rc->right - rc->left) );
1500 get_rop_codes( rop2, &codes );
1501 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1503 if (overlap & OVERLAP_RIGHT)
1504 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1506 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1510 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1511 const dib_info *src, const POINT *origin, int rop2, int overlap)
1513 BYTE *dst_start, *src_start;
1514 int y, dst_stride, src_stride;
1515 struct rop_codes codes;
1516 int left = dst->rect.left + rc->left;
1517 int right = dst->rect.left + rc->right;
1518 int org_x = src->rect.left + origin->x;
1520 if (overlap & OVERLAP_BELOW)
1522 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1523 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1524 dst_stride = -dst->stride;
1525 src_stride = -src->stride;
1529 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1530 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1531 dst_stride = dst->stride;
1532 src_stride = src->stride;
1535 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1537 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1538 memmove( dst_start, src_start, (right - left) / 2 );
1542 get_rop_codes( rop2, &codes );
1543 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1545 if (overlap & OVERLAP_RIGHT)
1546 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1548 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1552 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1553 const dib_info *src, const POINT *origin, int rop2, int overlap)
1555 BYTE *dst_start, *src_start;
1556 int y, dst_stride, src_stride;
1557 struct rop_codes codes;
1558 int left = dst->rect.left + rc->left;
1559 int right = dst->rect.left + rc->right;
1560 int org_x = src->rect.left + origin->x;
1562 if (overlap & OVERLAP_BELOW)
1564 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1565 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1566 dst_stride = -dst->stride;
1567 src_stride = -src->stride;
1571 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1572 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1573 dst_stride = dst->stride;
1574 src_stride = src->stride;
1577 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1579 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1580 memmove( dst_start, src_start, (right - left) / 8 );
1584 get_rop_codes( rop2, &codes );
1585 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1587 if (overlap & OVERLAP_RIGHT)
1588 do_rop_codes_line_rev_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1590 do_rop_codes_line_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1594 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1595 const dib_info *src, const POINT *origin, int rop2, int overlap)
1600 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
1602 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1606 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1608 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1609 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1612 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1614 WORD *ptr = get_pixel_ptr_16( dib, x, y );
1618 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1620 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1624 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1626 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1628 if ((dib->rect.left + x) & 1)
1631 return (*ptr >> 4) & 0x0f;
1634 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1636 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1637 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
1640 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
1645 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1647 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1650 static const DWORD field_masks[33] =
1652 0x00, /* should never happen */
1653 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1654 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1655 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1656 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1659 static inline DWORD get_field(DWORD field, int shift, int len)
1661 shift = shift - (8 - len);
1666 field &= field_masks[len];
1667 field |= field >> len;
1671 static inline DWORD put_field(DWORD field, int shift, int len)
1673 shift = shift - (8 - len);
1674 field &= field_masks[len];
1682 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1686 r = GetRValue(colour);
1687 g = GetGValue(colour);
1688 b = GetBValue(colour);
1690 return put_field(r, dib->red_shift, dib->red_len) |
1691 put_field(g, dib->green_shift, dib->green_len) |
1692 put_field(b, dib->blue_shift, dib->blue_len);
1695 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1697 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1700 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1702 const RGBQUAD *color_table = get_dib_color_table( dib );
1703 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
1704 int i, best_index = 0;
1705 DWORD diff, best_diff = 0xffffffff;
1707 /* special case for conversion to 1-bpp without a color table:
1708 * we get a 1-entry table containing the background color
1710 if (dib->bit_count == 1 && size == 1)
1711 return (r == color_table[0].rgbRed &&
1712 g == color_table[0].rgbGreen &&
1713 b == color_table[0].rgbBlue);
1715 for(i = 0; i < size; i++)
1717 const RGBQUAD *cur = color_table + i;
1718 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1719 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1720 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1728 if(diff < best_diff)
1737 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, BYTE r, BYTE g, BYTE b)
1742 ret = rgb_to_pixel_colortable( dib, r, g, b );
1744 ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255;
1746 return ret ? 0xff : 0;
1749 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1751 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1754 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1759 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1761 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1764 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1766 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1767 get_field( pixel, dib->green_shift, dib->green_len ),
1768 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1771 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1773 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1774 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1775 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1778 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1780 const RGBQUAD *color_table = get_dib_color_table( dib );
1782 if (!dib->color_table || pixel < dib->color_table_size)
1784 RGBQUAD quad = color_table[pixel];
1785 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1790 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1795 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1797 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1799 return d1->red_mask == d2->red_mask &&
1800 d1->green_mask == d2->green_mask &&
1801 d1->blue_mask == d2->blue_mask;
1804 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1806 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1807 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1809 switch(src->bit_count)
1813 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1814 if(src->funcs == &funcs_8888)
1816 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1817 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1820 for(y = src_rect->top; y < src_rect->bottom; y++)
1822 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1823 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1824 dst_start += dst->stride / 4;
1825 src_start += src->stride / 4;
1829 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1831 for(y = src_rect->top; y < src_rect->bottom; y++)
1833 dst_pixel = dst_start;
1834 src_pixel = src_start;
1835 for(x = src_rect->left; x < src_rect->right; x++)
1837 src_val = *src_pixel++;
1838 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1839 (((src_val >> src->green_shift) & 0xff) << 8) |
1840 ((src_val >> src->blue_shift) & 0xff);
1842 if(pad_size) memset(dst_pixel, 0, pad_size);
1843 dst_start += dst->stride / 4;
1844 src_start += src->stride / 4;
1849 for(y = src_rect->top; y < src_rect->bottom; y++)
1851 dst_pixel = dst_start;
1852 src_pixel = src_start;
1853 for(x = src_rect->left; x < src_rect->right; x++)
1855 src_val = *src_pixel++;
1856 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1857 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1858 get_field( src_val, src->blue_shift, src->blue_len ));
1860 if(pad_size) memset(dst_pixel, 0, pad_size);
1861 dst_start += dst->stride / 4;
1862 src_start += src->stride / 4;
1870 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
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++)
1879 rgb.rgbBlue = *src_pixel++;
1880 rgb.rgbGreen = *src_pixel++;
1881 rgb.rgbRed = *src_pixel++;
1883 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1885 if(pad_size) memset(dst_pixel, 0, pad_size);
1886 dst_start += dst->stride / 4;
1887 src_start += src->stride;
1894 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1895 if(src->funcs == &funcs_555)
1897 for(y = src_rect->top; y < src_rect->bottom; y++)
1899 dst_pixel = dst_start;
1900 src_pixel = src_start;
1901 for(x = src_rect->left; x < src_rect->right; x++)
1903 src_val = *src_pixel++;
1904 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1905 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1906 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1908 if(pad_size) memset(dst_pixel, 0, pad_size);
1909 dst_start += dst->stride / 4;
1910 src_start += src->stride / 2;
1913 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
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 src_val = *src_pixel++;
1922 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1923 (((src_val >> src->red_shift) << 14) & 0x070000) |
1924 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1925 (((src_val >> src->green_shift) << 6) & 0x000700) |
1926 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1927 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1929 if(pad_size) memset(dst_pixel, 0, pad_size);
1930 dst_start += dst->stride / 4;
1931 src_start += src->stride / 2;
1934 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1936 for(y = src_rect->top; y < src_rect->bottom; y++)
1938 dst_pixel = dst_start;
1939 src_pixel = src_start;
1940 for(x = src_rect->left; x < src_rect->right; x++)
1942 src_val = *src_pixel++;
1943 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1944 (((src_val >> src->red_shift) << 14) & 0x070000) |
1945 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1946 (((src_val >> src->green_shift) << 4) & 0x000300) |
1947 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1948 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1950 if(pad_size) memset(dst_pixel, 0, pad_size);
1951 dst_start += dst->stride / 4;
1952 src_start += src->stride / 2;
1957 for(y = src_rect->top; y < src_rect->bottom; y++)
1959 dst_pixel = dst_start;
1960 src_pixel = src_start;
1961 for(x = src_rect->left; x < src_rect->right; x++)
1963 src_val = *src_pixel++;
1964 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1965 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1966 get_field( src_val, src->blue_shift, src->blue_len ));
1968 if(pad_size) memset(dst_pixel, 0, pad_size);
1969 dst_start += dst->stride / 4;
1970 src_start += src->stride / 2;
1978 const RGBQUAD *color_table = get_dib_color_table( src );
1979 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1980 for(y = src_rect->top; y < src_rect->bottom; y++)
1982 dst_pixel = dst_start;
1983 src_pixel = src_start;
1984 for(x = src_rect->left; x < src_rect->right; x++)
1986 RGBQUAD rgb = color_table[*src_pixel++];
1987 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1989 if(pad_size) memset(dst_pixel, 0, pad_size);
1990 dst_start += dst->stride / 4;
1991 src_start += src->stride;
1998 const RGBQUAD *color_table = get_dib_color_table( src );
1999 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2000 for(y = src_rect->top; y < src_rect->bottom; y++)
2002 int pos = (src->rect.left + src_rect->left) & 1;
2003 src_pixel = src_start;
2004 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2008 rgb = color_table[*src_pixel++ & 0xf];
2010 rgb = color_table[*src_pixel >> 4];
2011 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
2013 if(pad_size) memset(dst_start + x, 0, pad_size);
2014 dst_start += dst->stride / 4;
2015 src_start += src->stride;
2022 const RGBQUAD *color_table = get_dib_color_table( src );
2023 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2024 for(y = src_rect->top; y < src_rect->bottom; y++)
2026 int pos = (src->rect.left + src_rect->left) & 7;
2027 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2030 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2031 rgb = color_table[src_val];
2032 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
2034 if(pad_size) memset(dst_start + x, 0, pad_size);
2035 dst_start += dst->stride / 4;
2036 src_start += src->stride;
2043 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2045 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2046 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2048 switch(src->bit_count)
2052 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2054 if(src->funcs == &funcs_8888)
2056 for(y = src_rect->top; y < src_rect->bottom; y++)
2058 dst_pixel = dst_start;
2059 src_pixel = src_start;
2060 for(x = src_rect->left; x < src_rect->right; x++)
2062 src_val = *src_pixel++;
2063 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2064 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2065 put_field(src_val, dst->blue_shift, dst->blue_len);
2067 if(pad_size) memset(dst_pixel, 0, pad_size);
2068 dst_start += dst->stride / 4;
2069 src_start += src->stride / 4;
2072 else if(bit_fields_match(src, dst))
2074 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2075 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2078 for(y = src_rect->top; y < src_rect->bottom; y++)
2080 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2081 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2082 dst_start += dst->stride / 4;
2083 src_start += src->stride / 4;
2087 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
2088 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
2090 for(y = src_rect->top; y < src_rect->bottom; y++)
2092 dst_pixel = dst_start;
2093 src_pixel = src_start;
2094 for(x = src_rect->left; x < src_rect->right; x++)
2096 src_val = *src_pixel++;
2097 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
2098 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
2099 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
2101 if(pad_size) memset(dst_pixel, 0, pad_size);
2102 dst_start += dst->stride / 4;
2103 src_start += src->stride / 4;
2108 for(y = src_rect->top; y < src_rect->bottom; y++)
2110 dst_pixel = dst_start;
2111 src_pixel = src_start;
2112 for(x = src_rect->left; x < src_rect->right; x++)
2114 src_val = *src_pixel++;
2115 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2116 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2117 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2119 if(pad_size) memset(dst_pixel, 0, pad_size);
2120 dst_start += dst->stride / 4;
2121 src_start += src->stride / 4;
2129 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2131 for(y = src_rect->top; y < src_rect->bottom; y++)
2133 dst_pixel = dst_start;
2134 src_pixel = src_start;
2135 for(x = src_rect->left; x < src_rect->right; x++)
2138 rgb.rgbBlue = *src_pixel++;
2139 rgb.rgbGreen = *src_pixel++;
2140 rgb.rgbRed = *src_pixel++;
2142 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2143 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2144 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2146 if(pad_size) memset(dst_pixel, 0, pad_size);
2147 dst_start += dst->stride / 4;
2148 src_start += src->stride;
2155 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2156 if(src->funcs == &funcs_555)
2158 for(y = src_rect->top; y < src_rect->bottom; y++)
2160 dst_pixel = dst_start;
2161 src_pixel = src_start;
2162 for(x = src_rect->left; x < src_rect->right; x++)
2164 src_val = *src_pixel++;
2165 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2166 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2167 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2169 if(pad_size) memset(dst_pixel, 0, pad_size);
2170 dst_start += dst->stride / 4;
2171 src_start += src->stride / 2;
2174 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2176 for(y = src_rect->top; y < src_rect->bottom; y++)
2178 dst_pixel = dst_start;
2179 src_pixel = src_start;
2180 for(x = src_rect->left; x < src_rect->right; x++)
2182 src_val = *src_pixel++;
2183 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2184 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2185 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2186 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2187 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2188 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2190 if(pad_size) memset(dst_pixel, 0, pad_size);
2191 dst_start += dst->stride / 4;
2192 src_start += src->stride / 2;
2195 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2197 for(y = src_rect->top; y < src_rect->bottom; y++)
2199 dst_pixel = dst_start;
2200 src_pixel = src_start;
2201 for(x = src_rect->left; x < src_rect->right; x++)
2203 src_val = *src_pixel++;
2204 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2205 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2206 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2207 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2208 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2209 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2211 if(pad_size) memset(dst_pixel, 0, pad_size);
2212 dst_start += dst->stride / 4;
2213 src_start += src->stride / 2;
2218 for(y = src_rect->top; y < src_rect->bottom; y++)
2220 dst_pixel = dst_start;
2221 src_pixel = src_start;
2222 for(x = src_rect->left; x < src_rect->right; x++)
2224 src_val = *src_pixel++;
2225 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2226 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2227 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2229 if(pad_size) memset(dst_pixel, 0, pad_size);
2230 dst_start += dst->stride / 4;
2231 src_start += src->stride / 2;
2239 const RGBQUAD *color_table = get_dib_color_table( src );
2240 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2241 for(y = src_rect->top; y < src_rect->bottom; y++)
2243 dst_pixel = dst_start;
2244 src_pixel = src_start;
2245 for(x = src_rect->left; x < src_rect->right; x++)
2247 RGBQUAD rgb = color_table[*src_pixel++];
2248 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2249 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2250 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2252 if(pad_size) memset(dst_pixel, 0, pad_size);
2253 dst_start += dst->stride / 4;
2254 src_start += src->stride;
2261 const RGBQUAD *color_table = get_dib_color_table( src );
2262 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2263 for(y = src_rect->top; y < src_rect->bottom; y++)
2265 int pos = (src->rect.left + src_rect->left) & 1;
2266 src_pixel = src_start;
2267 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2271 rgb = color_table[*src_pixel++ & 0xf];
2273 rgb = color_table[*src_pixel >> 4];
2274 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2275 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2276 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2278 if(pad_size) memset(dst_start + x, 0, pad_size);
2279 dst_start += dst->stride / 4;
2280 src_start += src->stride;
2287 const RGBQUAD *color_table = get_dib_color_table( src );
2288 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2289 for(y = src_rect->top; y < src_rect->bottom; y++)
2291 int pos = (src->rect.left + src_rect->left) & 7;
2292 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2295 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2296 rgb = color_table[src_val];
2297 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2298 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2299 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2301 if(pad_size) memset(dst_start + x, 0, pad_size);
2302 dst_start += dst->stride / 4;
2303 src_start += src->stride;
2310 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2312 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2314 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2316 switch(src->bit_count)
2320 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2321 if(src->funcs == &funcs_8888)
2323 for(y = src_rect->top; y < src_rect->bottom; y++)
2325 dst_pixel = dst_start;
2326 src_pixel = src_start;
2327 for(x = src_rect->left; x < src_rect->right; x++)
2329 src_val = *src_pixel++;
2330 *dst_pixel++ = src_val & 0xff;
2331 *dst_pixel++ = (src_val >> 8) & 0xff;
2332 *dst_pixel++ = (src_val >> 16) & 0xff;
2334 if(pad_size) memset(dst_pixel, 0, pad_size);
2335 dst_start += dst->stride;
2336 src_start += src->stride / 4;
2339 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2341 for(y = src_rect->top; y < src_rect->bottom; y++)
2343 dst_pixel = dst_start;
2344 src_pixel = src_start;
2345 for(x = src_rect->left; x < src_rect->right; x++)
2347 src_val = *src_pixel++;
2348 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2349 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2350 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2352 if(pad_size) memset(dst_pixel, 0, pad_size);
2353 dst_start += dst->stride;
2354 src_start += src->stride / 4;
2359 for(y = src_rect->top; y < src_rect->bottom; y++)
2361 dst_pixel = dst_start;
2362 src_pixel = src_start;
2363 for(x = src_rect->left; x < src_rect->right; x++)
2365 src_val = *src_pixel++;
2366 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2367 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2368 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2370 if(pad_size) memset(dst_pixel, 0, pad_size);
2371 dst_start += dst->stride;
2372 src_start += src->stride / 4;
2380 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2382 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2383 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2386 for(y = src_rect->top; y < src_rect->bottom; y++)
2388 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2389 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2390 dst_start += dst->stride;
2391 src_start += src->stride;
2399 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2400 if(src->funcs == &funcs_555)
2402 for(y = src_rect->top; y < src_rect->bottom; y++)
2404 dst_pixel = dst_start;
2405 src_pixel = src_start;
2406 for(x = src_rect->left; x < src_rect->right; x++)
2408 src_val = *src_pixel++;
2409 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2410 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2411 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2413 if(pad_size) memset(dst_pixel, 0, pad_size);
2414 dst_start += dst->stride;
2415 src_start += src->stride / 2;
2418 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2420 for(y = src_rect->top; y < src_rect->bottom; y++)
2422 dst_pixel = dst_start;
2423 src_pixel = src_start;
2424 for(x = src_rect->left; x < src_rect->right; x++)
2426 src_val = *src_pixel++;
2427 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2428 (((src_val >> src->blue_shift) >> 2) & 0x07);
2429 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2430 (((src_val >> src->green_shift) >> 2) & 0x07);
2431 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2432 (((src_val >> src->red_shift) >> 2) & 0x07);
2434 if(pad_size) memset(dst_pixel, 0, pad_size);
2435 dst_start += dst->stride;
2436 src_start += src->stride / 2;
2439 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2441 for(y = src_rect->top; y < src_rect->bottom; y++)
2443 dst_pixel = dst_start;
2444 src_pixel = src_start;
2445 for(x = src_rect->left; x < src_rect->right; x++)
2447 src_val = *src_pixel++;
2448 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2449 (((src_val >> src->blue_shift) >> 2) & 0x07);
2450 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2451 (((src_val >> src->green_shift) >> 4) & 0x03);
2452 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2453 (((src_val >> src->red_shift) >> 2) & 0x07);
2455 if(pad_size) memset(dst_pixel, 0, pad_size);
2456 dst_start += dst->stride;
2457 src_start += src->stride / 2;
2462 for(y = src_rect->top; y < src_rect->bottom; y++)
2464 dst_pixel = dst_start;
2465 src_pixel = src_start;
2466 for(x = src_rect->left; x < src_rect->right; x++)
2468 src_val = *src_pixel++;
2469 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2470 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2471 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2473 if(pad_size) memset(dst_pixel, 0, pad_size);
2474 dst_start += dst->stride;
2475 src_start += src->stride / 2;
2483 const RGBQUAD *color_table = get_dib_color_table( src );
2484 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2485 for(y = src_rect->top; y < src_rect->bottom; y++)
2487 dst_pixel = dst_start;
2488 src_pixel = src_start;
2489 for(x = src_rect->left; x < src_rect->right; x++)
2491 RGBQUAD rgb = color_table[*src_pixel++];
2492 *dst_pixel++ = rgb.rgbBlue;
2493 *dst_pixel++ = rgb.rgbGreen;
2494 *dst_pixel++ = rgb.rgbRed;
2496 if(pad_size) memset(dst_pixel, 0, pad_size);
2497 dst_start += dst->stride;
2498 src_start += src->stride;
2505 const RGBQUAD *color_table = get_dib_color_table( src );
2506 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2507 for(y = src_rect->top; y < src_rect->bottom; y++)
2509 int pos = (src->rect.left + src_rect->left) & 1;
2510 src_pixel = src_start;
2511 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2515 rgb = color_table[*src_pixel++ & 0xf];
2517 rgb = color_table[*src_pixel >> 4];
2518 dst_start[x * 3] = rgb.rgbBlue;
2519 dst_start[x * 3 + 1] = rgb.rgbGreen;
2520 dst_start[x * 3 + 2] = rgb.rgbRed;
2522 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2523 dst_start += dst->stride;
2524 src_start += src->stride;
2531 const RGBQUAD *color_table = get_dib_color_table( src );
2532 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2533 for(y = src_rect->top; y < src_rect->bottom; y++)
2535 int pos = (src->rect.left + src_rect->left) & 7;
2536 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2539 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2540 rgb = color_table[src_val];
2541 dst_start[x * 3] = rgb.rgbBlue;
2542 dst_start[x * 3 + 1] = rgb.rgbGreen;
2543 dst_start[x * 3 + 2] = rgb.rgbRed;
2545 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2546 dst_start += dst->stride;
2547 src_start += src->stride;
2554 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2556 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2557 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2560 switch(src->bit_count)
2564 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2566 if(src->funcs == &funcs_8888)
2568 for(y = src_rect->top; y < src_rect->bottom; y++)
2570 dst_pixel = dst_start;
2571 src_pixel = src_start;
2572 for(x = src_rect->left; x < src_rect->right; x++)
2574 src_val = *src_pixel++;
2575 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2576 ((src_val >> 6) & 0x03e0) |
2577 ((src_val >> 3) & 0x001f);
2579 if(pad_size) memset(dst_pixel, 0, pad_size);
2580 dst_start += dst->stride / 2;
2581 src_start += src->stride / 4;
2584 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2586 for(y = src_rect->top; y < src_rect->bottom; y++)
2588 dst_pixel = dst_start;
2589 src_pixel = src_start;
2590 for(x = src_rect->left; x < src_rect->right; x++)
2592 src_val = *src_pixel++;
2593 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2594 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2595 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2597 if(pad_size) memset(dst_pixel, 0, pad_size);
2598 dst_start += dst->stride / 2;
2599 src_start += src->stride / 4;
2604 for(y = src_rect->top; y < src_rect->bottom; y++)
2606 dst_pixel = dst_start;
2607 src_pixel = src_start;
2608 for(x = src_rect->left; x < src_rect->right; x++)
2610 src_val = *src_pixel++;
2611 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2612 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2613 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2615 if(pad_size) memset(dst_pixel, 0, pad_size);
2616 dst_start += dst->stride / 2;
2617 src_start += src->stride / 4;
2625 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2627 for(y = src_rect->top; y < src_rect->bottom; y++)
2629 dst_pixel = dst_start;
2630 src_pixel = src_start;
2631 for(x = src_rect->left; x < src_rect->right; x++)
2634 rgb.rgbBlue = *src_pixel++;
2635 rgb.rgbGreen = *src_pixel++;
2636 rgb.rgbRed = *src_pixel++;
2638 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2639 ((rgb.rgbGreen << 2) & 0x03e0) |
2640 ((rgb.rgbBlue >> 3) & 0x001f);
2642 if(pad_size) memset(dst_pixel, 0, pad_size);
2643 dst_start += dst->stride / 2;
2644 src_start += src->stride;
2651 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2652 if(src->funcs == &funcs_555)
2654 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2655 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2658 for(y = src_rect->top; y < src_rect->bottom; y++)
2660 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2661 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2662 dst_start += dst->stride / 2;
2663 src_start += src->stride / 2;
2667 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2669 for(y = src_rect->top; y < src_rect->bottom; y++)
2671 dst_pixel = dst_start;
2672 src_pixel = src_start;
2673 for(x = src_rect->left; x < src_rect->right; x++)
2675 src_val = *src_pixel++;
2676 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2677 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2678 ( (src_val >> src->blue_shift) & 0x001f);
2680 if(pad_size) memset(dst_pixel, 0, pad_size);
2681 dst_start += dst->stride / 2;
2682 src_start += src->stride / 2;
2685 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2687 for(y = src_rect->top; y < src_rect->bottom; y++)
2689 dst_pixel = dst_start;
2690 src_pixel = src_start;
2691 for(x = src_rect->left; x < src_rect->right; x++)
2693 src_val = *src_pixel++;
2694 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2695 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2696 ( (src_val >> src->blue_shift) & 0x001f);
2698 if(pad_size) memset(dst_pixel, 0, pad_size);
2699 dst_start += dst->stride / 2;
2700 src_start += src->stride / 2;
2705 for(y = src_rect->top; y < src_rect->bottom; y++)
2707 dst_pixel = dst_start;
2708 src_pixel = src_start;
2709 for(x = src_rect->left; x < src_rect->right; x++)
2711 src_val = *src_pixel++;
2712 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2713 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2714 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2716 if(pad_size) memset(dst_pixel, 0, pad_size);
2717 dst_start += dst->stride / 2;
2718 src_start += src->stride / 2;
2726 const RGBQUAD *color_table = get_dib_color_table( src );
2727 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2728 for(y = src_rect->top; y < src_rect->bottom; y++)
2730 dst_pixel = dst_start;
2731 src_pixel = src_start;
2732 for(x = src_rect->left; x < src_rect->right; x++)
2734 RGBQUAD rgb = color_table[*src_pixel++];
2735 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2736 ((rgb.rgbGreen << 2) & 0x03e0) |
2737 ((rgb.rgbBlue >> 3) & 0x001f);
2739 if(pad_size) memset(dst_pixel, 0, pad_size);
2740 dst_start += dst->stride / 2;
2741 src_start += src->stride;
2748 const RGBQUAD *color_table = get_dib_color_table( src );
2749 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2750 for(y = src_rect->top; y < src_rect->bottom; y++)
2752 int pos = (src->rect.left + src_rect->left) & 1;
2753 src_pixel = src_start;
2754 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2758 rgb = color_table[*src_pixel++ & 0xf];
2760 rgb = color_table[*src_pixel >> 4];
2761 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2762 ((rgb.rgbGreen << 2) & 0x03e0) |
2763 ((rgb.rgbBlue >> 3) & 0x001f);
2765 if(pad_size) memset(dst_start + x, 0, pad_size);
2766 dst_start += dst->stride / 2;
2767 src_start += src->stride;
2774 const RGBQUAD *color_table = get_dib_color_table( src );
2775 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2776 for(y = src_rect->top; y < src_rect->bottom; y++)
2778 int pos = (src->rect.left + src_rect->left) & 7;
2779 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2782 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2783 rgb = color_table[src_val];
2784 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2785 ((rgb.rgbGreen << 2) & 0x03e0) |
2786 ((rgb.rgbBlue >> 3) & 0x001f);
2788 if(pad_size) memset(dst_start + x, 0, pad_size);
2789 dst_start += dst->stride / 2;
2790 src_start += src->stride;
2797 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2799 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2800 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2803 switch(src->bit_count)
2807 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2809 if(src->funcs == &funcs_8888)
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++)
2817 src_val = *src_pixel++;
2818 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2819 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2820 put_field(src_val, dst->blue_shift, dst->blue_len);
2822 if(pad_size) memset(dst_pixel, 0, pad_size);
2823 dst_start += dst->stride / 2;
2824 src_start += src->stride / 4;
2827 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2829 for(y = src_rect->top; y < src_rect->bottom; y++)
2831 dst_pixel = dst_start;
2832 src_pixel = src_start;
2833 for(x = src_rect->left; x < src_rect->right; x++)
2835 src_val = *src_pixel++;
2836 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2837 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2838 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2840 if(pad_size) memset(dst_pixel, 0, pad_size);
2841 dst_start += dst->stride / 2;
2842 src_start += src->stride / 4;
2847 for(y = src_rect->top; y < src_rect->bottom; y++)
2849 dst_pixel = dst_start;
2850 src_pixel = src_start;
2851 for(x = src_rect->left; x < src_rect->right; x++)
2853 src_val = *src_pixel++;
2854 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2855 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2856 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2858 if(pad_size) memset(dst_pixel, 0, pad_size);
2859 dst_start += dst->stride / 2;
2860 src_start += src->stride / 4;
2868 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2870 for(y = src_rect->top; y < src_rect->bottom; y++)
2872 dst_pixel = dst_start;
2873 src_pixel = src_start;
2874 for(x = src_rect->left; x < src_rect->right; x++)
2877 rgb.rgbBlue = *src_pixel++;
2878 rgb.rgbGreen = *src_pixel++;
2879 rgb.rgbRed = *src_pixel++;
2881 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2882 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2883 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2885 if(pad_size) memset(dst_pixel, 0, pad_size);
2886 dst_start += dst->stride / 2;
2887 src_start += src->stride;
2894 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2895 if(src->funcs == &funcs_555)
2897 for(y = src_rect->top; y < src_rect->bottom; y++)
2899 dst_pixel = dst_start;
2900 src_pixel = src_start;
2901 for(x = src_rect->left; x < src_rect->right; x++)
2903 src_val = *src_pixel++;
2904 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2905 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2906 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2908 if(pad_size) memset(dst_pixel, 0, pad_size);
2909 dst_start += dst->stride / 2;
2910 src_start += src->stride / 2;
2913 else if(bit_fields_match(src, dst))
2915 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2916 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2919 for(y = src_rect->top; y < src_rect->bottom; y++)
2921 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2922 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2923 dst_start += dst->stride / 2;
2924 src_start += src->stride / 2;
2928 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2930 for(y = src_rect->top; y < src_rect->bottom; y++)
2932 dst_pixel = dst_start;
2933 src_pixel = src_start;
2934 for(x = src_rect->left; x < src_rect->right; x++)
2936 src_val = *src_pixel++;
2937 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2938 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2939 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2940 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2941 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2942 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2944 if(pad_size) memset(dst_pixel, 0, pad_size);
2945 dst_start += dst->stride / 2;
2946 src_start += src->stride / 2;
2949 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2951 for(y = src_rect->top; y < src_rect->bottom; y++)
2953 dst_pixel = dst_start;
2954 src_pixel = src_start;
2955 for(x = src_rect->left; x < src_rect->right; x++)
2957 src_val = *src_pixel++;
2958 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2959 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2960 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2961 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2962 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2963 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2965 if(pad_size) memset(dst_pixel, 0, pad_size);
2966 dst_start += dst->stride / 2;
2967 src_start += src->stride / 2;
2972 for(y = src_rect->top; y < src_rect->bottom; y++)
2974 dst_pixel = dst_start;
2975 src_pixel = src_start;
2976 for(x = src_rect->left; x < src_rect->right; x++)
2978 src_val = *src_pixel++;
2979 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2980 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2981 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2983 if(pad_size) memset(dst_pixel, 0, pad_size);
2984 dst_start += dst->stride / 2;
2985 src_start += src->stride / 2;
2993 const RGBQUAD *color_table = get_dib_color_table( src );
2994 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2995 for(y = src_rect->top; y < src_rect->bottom; y++)
2997 dst_pixel = dst_start;
2998 src_pixel = src_start;
2999 for(x = src_rect->left; x < src_rect->right; x++)
3001 RGBQUAD rgb = color_table[*src_pixel++];
3002 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3003 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3004 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3006 if(pad_size) memset(dst_pixel, 0, pad_size);
3007 dst_start += dst->stride / 2;
3008 src_start += src->stride;
3015 const RGBQUAD *color_table = get_dib_color_table( src );
3016 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3017 for(y = src_rect->top; y < src_rect->bottom; y++)
3019 int pos = (src->rect.left + src_rect->left) & 1;
3020 src_pixel = src_start;
3021 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3025 rgb = color_table[*src_pixel++ & 0xf];
3027 rgb = color_table[*src_pixel >> 4];
3028 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3029 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3030 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3032 if(pad_size) memset(dst_start + x, 0, pad_size);
3033 dst_start += dst->stride / 2;
3034 src_start += src->stride;
3041 const RGBQUAD *color_table = get_dib_color_table( src );
3042 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3043 for(y = src_rect->top; y < src_rect->bottom; y++)
3045 int pos = (src->rect.left + src_rect->left) & 7;
3046 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3049 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3050 rgb = color_table[src_val];
3051 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3052 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3053 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3055 if(pad_size) memset(dst_start + x, 0, pad_size);
3056 dst_start += dst->stride / 2;
3057 src_start += src->stride;
3064 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
3066 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
3067 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
3070 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
3072 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
3073 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
3076 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3078 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
3079 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
3082 switch(src->bit_count)
3086 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3088 if(src->funcs == &funcs_8888)
3090 for(y = src_rect->top; y < src_rect->bottom; y++)
3092 dst_pixel = dst_start;
3093 src_pixel = src_start;
3094 for(x = src_rect->left; x < src_rect->right; x++)
3096 src_val = *src_pixel++;
3097 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
3099 if(pad_size) memset(dst_pixel, 0, pad_size);
3100 dst_start += dst->stride;
3101 src_start += src->stride / 4;
3104 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3106 for(y = src_rect->top; y < src_rect->bottom; y++)
3108 dst_pixel = dst_start;
3109 src_pixel = src_start;
3110 for(x = src_rect->left; x < src_rect->right; x++)
3112 src_val = *src_pixel++;
3113 *dst_pixel++ = rgb_lookup_colortable(dst,
3114 src_val >> src->red_shift,
3115 src_val >> src->green_shift,
3116 src_val >> src->blue_shift );
3118 if(pad_size) memset(dst_pixel, 0, pad_size);
3119 dst_start += dst->stride;
3120 src_start += src->stride / 4;
3125 for(y = src_rect->top; y < src_rect->bottom; y++)
3127 dst_pixel = dst_start;
3128 src_pixel = src_start;
3129 for(x = src_rect->left; x < src_rect->right; x++)
3131 src_val = *src_pixel++;
3132 *dst_pixel++ = rgb_lookup_colortable(dst,
3133 get_field(src_val, src->red_shift, src->red_len),
3134 get_field(src_val, src->green_shift, src->green_len),
3135 get_field(src_val, src->blue_shift, src->blue_len));
3137 if(pad_size) memset(dst_pixel, 0, pad_size);
3138 dst_start += dst->stride;
3139 src_start += src->stride / 4;
3147 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3149 for(y = src_rect->top; y < src_rect->bottom; y++)
3151 dst_pixel = dst_start;
3152 src_pixel = src_start;
3153 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3155 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
3157 if(pad_size) memset(dst_pixel, 0, pad_size);
3158 dst_start += dst->stride;
3159 src_start += src->stride;
3166 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3167 if(src->funcs == &funcs_555)
3169 for(y = src_rect->top; y < src_rect->bottom; y++)
3171 dst_pixel = dst_start;
3172 src_pixel = src_start;
3173 for(x = src_rect->left; x < src_rect->right; x++)
3175 src_val = *src_pixel++;
3176 *dst_pixel++ = rgb_lookup_colortable(dst,
3177 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3178 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3179 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3181 if(pad_size) memset(dst_pixel, 0, pad_size);
3182 dst_start += dst->stride;
3183 src_start += src->stride / 2;
3186 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3188 for(y = src_rect->top; y < src_rect->bottom; y++)
3190 dst_pixel = dst_start;
3191 src_pixel = src_start;
3192 for(x = src_rect->left; x < src_rect->right; x++)
3194 src_val = *src_pixel++;
3195 *dst_pixel++ = rgb_lookup_colortable(dst,
3196 (((src_val >> src->red_shift) << 3) & 0xf8) |
3197 (((src_val >> src->red_shift) >> 2) & 0x07),
3198 (((src_val >> src->green_shift) << 3) & 0xf8) |
3199 (((src_val >> src->green_shift) >> 2) & 0x07),
3200 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3201 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3203 if(pad_size) memset(dst_pixel, 0, pad_size);
3204 dst_start += dst->stride;
3205 src_start += src->stride / 2;
3208 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3210 for(y = src_rect->top; y < src_rect->bottom; y++)
3212 dst_pixel = dst_start;
3213 src_pixel = src_start;
3214 for(x = src_rect->left; x < src_rect->right; x++)
3216 src_val = *src_pixel++;
3217 *dst_pixel++ = rgb_lookup_colortable(dst,
3218 (((src_val >> src->red_shift) << 3) & 0xf8) |
3219 (((src_val >> src->red_shift) >> 2) & 0x07),
3220 (((src_val >> src->green_shift) << 2) & 0xfc) |
3221 (((src_val >> src->green_shift) >> 4) & 0x03),
3222 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3223 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3225 if(pad_size) memset(dst_pixel, 0, pad_size);
3226 dst_start += dst->stride;
3227 src_start += src->stride / 2;
3232 for(y = src_rect->top; y < src_rect->bottom; y++)
3234 dst_pixel = dst_start;
3235 src_pixel = src_start;
3236 for(x = src_rect->left; x < src_rect->right; x++)
3238 src_val = *src_pixel++;
3239 *dst_pixel++ = rgb_lookup_colortable(dst,
3240 get_field(src_val, src->red_shift, src->red_len),
3241 get_field(src_val, src->green_shift, src->green_len),
3242 get_field(src_val, src->blue_shift, src->blue_len));
3244 if(pad_size) memset(dst_pixel, 0, pad_size);
3245 dst_start += dst->stride;
3246 src_start += src->stride / 2;
3254 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3256 if(color_tables_match(dst, src))
3258 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3259 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3262 for(y = src_rect->top; y < src_rect->bottom; y++)
3264 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
3265 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3266 dst_start += dst->stride;
3267 src_start += src->stride;
3273 const RGBQUAD *color_table = get_dib_color_table( src );
3274 for(y = src_rect->top; y < src_rect->bottom; y++)
3276 dst_pixel = dst_start;
3277 src_pixel = src_start;
3278 for(x = src_rect->left; x < src_rect->right; x++)
3280 RGBQUAD rgb = color_table[*src_pixel++];
3281 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3283 if(pad_size) memset(dst_pixel, 0, pad_size);
3284 dst_start += dst->stride;
3285 src_start += src->stride;
3293 const RGBQUAD *color_table = get_dib_color_table( src );
3294 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3295 for(y = src_rect->top; y < src_rect->bottom; y++)
3297 int pos = (src->rect.left + src_rect->left) & 1;
3298 src_pixel = src_start;
3299 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3303 rgb = color_table[*src_pixel++ & 0xf];
3305 rgb = color_table[*src_pixel >> 4];
3306 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3308 if(pad_size) memset(dst_start + x, 0, pad_size);
3309 dst_start += dst->stride;
3310 src_start += src->stride;
3317 const RGBQUAD *color_table = get_dib_color_table( src );
3318 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3319 for(y = src_rect->top; y < src_rect->bottom; y++)
3321 int pos = (src->rect.left + src_rect->left) & 7;
3322 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3325 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3326 rgb = color_table[src_val];
3327 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3329 if(pad_size) memset(dst_start + x, 0, pad_size);
3330 dst_start += dst->stride;
3331 src_start += src->stride;
3338 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3340 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3341 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3344 switch(src->bit_count)
3348 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3350 if(src->funcs == &funcs_8888)
3352 for(y = src_rect->top; y < src_rect->bottom; y++)
3354 dst_pixel = dst_start;
3355 src_pixel = src_start;
3356 for(x = src_rect->left; x < src_rect->right; x++)
3358 src_val = *src_pixel++;
3359 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
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 / 4;
3377 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3379 for(y = src_rect->top; y < src_rect->bottom; y++)
3381 dst_pixel = dst_start;
3382 src_pixel = src_start;
3383 for(x = src_rect->left; x < src_rect->right; x++)
3385 src_val = *src_pixel++;
3386 dst_val = rgb_to_pixel_colortable(dst,
3387 src_val >> src->red_shift,
3388 src_val >> src->green_shift,
3389 src_val >> src->blue_shift);
3390 if((x - src_rect->left) & 1)
3392 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3396 *dst_pixel = (dst_val << 4) & 0xf0;
3400 if((x - src_rect->left) & 1) dst_pixel++;
3401 memset(dst_pixel, 0, pad_size);
3403 dst_start += dst->stride;
3404 src_start += src->stride / 4;
3409 for(y = src_rect->top; y < src_rect->bottom; y++)
3411 dst_pixel = dst_start;
3412 src_pixel = src_start;
3413 for(x = src_rect->left; x < src_rect->right; x++)
3415 src_val = *src_pixel++;
3416 dst_val = rgb_to_pixel_colortable(dst,
3417 get_field(src_val, src->red_shift, src->red_len),
3418 get_field(src_val, src->green_shift, src->green_len),
3419 get_field(src_val, src->blue_shift, src->blue_len));
3420 if((x - src_rect->left) & 1)
3422 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3426 *dst_pixel = (dst_val << 4) & 0xf0;
3430 if((x - src_rect->left) & 1) dst_pixel++;
3431 memset(dst_pixel, 0, pad_size);
3433 dst_start += dst->stride;
3434 src_start += src->stride / 4;
3442 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3444 for(y = src_rect->top; y < src_rect->bottom; y++)
3446 dst_pixel = dst_start;
3447 src_pixel = src_start;
3448 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3450 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3452 if((x - src_rect->left) & 1)
3454 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3458 *dst_pixel = (dst_val << 4) & 0xf0;
3462 if((x - src_rect->left) & 1) dst_pixel++;
3463 memset(dst_pixel, 0, pad_size);
3465 dst_start += dst->stride;
3466 src_start += src->stride;
3473 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3474 if(src->funcs == &funcs_555)
3476 for(y = src_rect->top; y < src_rect->bottom; y++)
3478 dst_pixel = dst_start;
3479 src_pixel = src_start;
3480 for(x = src_rect->left; x < src_rect->right; x++)
3482 src_val = *src_pixel++;
3483 dst_val = rgb_to_pixel_colortable(dst,
3484 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3485 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3486 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3487 if((x - src_rect->left) & 1)
3489 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3493 *dst_pixel = (dst_val << 4) & 0xf0;
3497 if((x - src_rect->left) & 1) dst_pixel++;
3498 memset(dst_pixel, 0, pad_size);
3500 dst_start += dst->stride;
3501 src_start += src->stride / 2;
3504 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3506 for(y = src_rect->top; y < src_rect->bottom; y++)
3508 dst_pixel = dst_start;
3509 src_pixel = src_start;
3510 for(x = src_rect->left; x < src_rect->right; x++)
3512 src_val = *src_pixel++;
3513 dst_val = rgb_to_pixel_colortable(dst,
3514 (((src_val >> src->red_shift) << 3) & 0xf8) |
3515 (((src_val >> src->red_shift) >> 2) & 0x07),
3516 (((src_val >> src->green_shift) << 3) & 0xf8) |
3517 (((src_val >> src->green_shift) >> 2) & 0x07),
3518 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3519 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3520 if((x - src_rect->left) & 1)
3522 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3526 *dst_pixel = (dst_val << 4) & 0xf0;
3530 if((x - src_rect->left) & 1) dst_pixel++;
3531 memset(dst_pixel, 0, pad_size);
3533 dst_start += dst->stride;
3534 src_start += src->stride / 2;
3537 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3539 for(y = src_rect->top; y < src_rect->bottom; y++)
3541 dst_pixel = dst_start;
3542 src_pixel = src_start;
3543 for(x = src_rect->left; x < src_rect->right; x++)
3545 src_val = *src_pixel++;
3546 dst_val = rgb_to_pixel_colortable(dst,
3547 (((src_val >> src->red_shift) << 3) & 0xf8) |
3548 (((src_val >> src->red_shift) >> 2) & 0x07),
3549 (((src_val >> src->green_shift) << 2) & 0xfc) |
3550 (((src_val >> src->green_shift) >> 4) & 0x03),
3551 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3552 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3553 if((x - src_rect->left) & 1)
3555 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3559 *dst_pixel = (dst_val << 4) & 0xf0;
3563 if((x - src_rect->left) & 1) dst_pixel++;
3564 memset(dst_pixel, 0, pad_size);
3566 dst_start += dst->stride;
3567 src_start += src->stride / 2;
3572 for(y = src_rect->top; y < src_rect->bottom; y++)
3574 dst_pixel = dst_start;
3575 src_pixel = src_start;
3576 for(x = src_rect->left; x < src_rect->right; x++)
3578 src_val = *src_pixel++;
3579 dst_val = rgb_to_pixel_colortable(dst,
3580 get_field(src_val, src->red_shift, src->red_len),
3581 get_field(src_val, src->green_shift, src->green_len),
3582 get_field(src_val, src->blue_shift, src->blue_len));
3583 if((x - src_rect->left) & 1)
3585 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3589 *dst_pixel = (dst_val << 4) & 0xf0;
3593 if((x - src_rect->left) & 1) dst_pixel++;
3594 memset(dst_pixel, 0, pad_size);
3596 dst_start += dst->stride;
3597 src_start += src->stride / 2;
3605 const RGBQUAD *color_table = get_dib_color_table( src );
3606 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3608 for(y = src_rect->top; y < src_rect->bottom; y++)
3610 dst_pixel = dst_start;
3611 src_pixel = src_start;
3612 for(x = src_rect->left; x < src_rect->right; x++)
3614 RGBQUAD rgb = color_table[*src_pixel++];
3615 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3616 if((x - src_rect->left) & 1)
3618 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3622 *dst_pixel = (dst_val << 4) & 0xf0;
3626 if((x - src_rect->left) & 1) dst_pixel++;
3627 memset(dst_pixel, 0, pad_size);
3629 dst_start += dst->stride;
3630 src_start += src->stride;
3637 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3639 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
3641 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3642 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3645 for(y = src_rect->top; y < src_rect->bottom; y++)
3647 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3648 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3649 dst_start += dst->stride;
3650 src_start += src->stride;
3656 const RGBQUAD *color_table = get_dib_color_table( src );
3657 for(y = src_rect->top; y < src_rect->bottom; y++)
3659 int pos = (src->rect.left + src_rect->left) & 1;
3660 dst_pixel = dst_start;
3661 src_pixel = src_start;
3662 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3666 rgb = color_table[*src_pixel++ & 0xf];
3668 rgb = color_table[*src_pixel >> 4];
3669 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3670 if((x - src_rect->left) & 1)
3672 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3676 *dst_pixel = (dst_val << 4) & 0xf0;
3680 if((x - src_rect->left) & 1) dst_pixel++;
3681 memset(dst_pixel, 0, pad_size);
3683 dst_start += dst->stride;
3684 src_start += src->stride;
3692 const RGBQUAD *color_table = get_dib_color_table( src );
3693 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3694 for(y = src_rect->top; y < src_rect->bottom; y++)
3696 int pos = (src->rect.left + src_rect->left) & 7;
3697 dst_pixel = dst_start;
3698 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3701 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3702 rgb = color_table[src_val];
3703 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3704 if((x - src_rect->left) & 1)
3706 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3710 *dst_pixel = (dst_val << 4) & 0xf0;
3714 if((x - src_rect->left) & 1) dst_pixel++;
3715 memset(dst_pixel, 0, pad_size);
3717 dst_start += dst->stride;
3718 src_start += src->stride;
3725 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3727 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3728 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3732 switch(src->bit_count)
3736 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3738 if(src->funcs == &funcs_8888)
3740 for(y = src_rect->top; y < src_rect->bottom; y++)
3742 dst_pixel = dst_start;
3743 src_pixel = src_start;
3744 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3746 src_val = *src_pixel++;
3747 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val >> 16, src_val >> 8, src_val);
3749 if(bit_pos == 0) *dst_pixel = 0;
3750 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3760 if(bit_pos != 0) dst_pixel++;
3761 memset(dst_pixel, 0, pad_size);
3763 dst_start += dst->stride;
3764 src_start += src->stride / 4;
3767 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3769 for(y = src_rect->top; y < src_rect->bottom; y++)
3771 dst_pixel = dst_start;
3772 src_pixel = src_start;
3773 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3775 src_val = *src_pixel++;
3776 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3777 src_val >> src->red_shift,
3778 src_val >> src->green_shift,
3779 src_val >> src->blue_shift);
3781 if(bit_pos == 0) *dst_pixel = 0;
3782 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3792 if(bit_pos != 0) dst_pixel++;
3793 memset(dst_pixel, 0, pad_size);
3795 dst_start += dst->stride;
3796 src_start += src->stride / 4;
3801 for(y = src_rect->top; y < src_rect->bottom; y++)
3803 dst_pixel = dst_start;
3804 src_pixel = src_start;
3805 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3807 src_val = *src_pixel++;
3808 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3809 get_field(src_val, src->red_shift, src->red_len),
3810 get_field(src_val, src->green_shift, src->green_len),
3811 get_field(src_val, src->blue_shift, src->blue_len));
3813 if(bit_pos == 0) *dst_pixel = 0;
3814 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3824 if(bit_pos != 0) dst_pixel++;
3825 memset(dst_pixel, 0, pad_size);
3827 dst_start += dst->stride;
3828 src_start += src->stride / 4;
3836 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3838 for(y = src_rect->top; y < src_rect->bottom; y++)
3840 dst_pixel = dst_start;
3841 src_pixel = src_start;
3842 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3844 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_pixel[2], src_pixel[1], src_pixel[0]);
3846 if(bit_pos == 0) *dst_pixel = 0;
3847 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3857 if(bit_pos != 0) dst_pixel++;
3858 memset(dst_pixel, 0, pad_size);
3860 dst_start += dst->stride;
3861 src_start += src->stride;
3868 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3869 if(src->funcs == &funcs_555)
3871 for(y = src_rect->top; y < src_rect->bottom; y++)
3873 dst_pixel = dst_start;
3874 src_pixel = src_start;
3875 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3877 src_val = *src_pixel++;
3878 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3879 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3880 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3881 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3883 if(bit_pos == 0) *dst_pixel = 0;
3884 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3894 if(bit_pos != 0) dst_pixel++;
3895 memset(dst_pixel, 0, pad_size);
3897 dst_start += dst->stride;
3898 src_start += src->stride / 2;
3901 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3903 for(y = src_rect->top; y < src_rect->bottom; y++)
3905 dst_pixel = dst_start;
3906 src_pixel = src_start;
3907 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3909 src_val = *src_pixel++;
3910 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3911 (((src_val >> src->red_shift) << 3) & 0xf8) |
3912 (((src_val >> src->red_shift) >> 2) & 0x07),
3913 (((src_val >> src->green_shift) << 3) & 0xf8) |
3914 (((src_val >> src->green_shift) >> 2) & 0x07),
3915 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3916 (((src_val >> src->blue_shift) >> 2) & 0x07));
3917 if(bit_pos == 0) *dst_pixel = 0;
3918 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3928 if(bit_pos != 0) dst_pixel++;
3929 memset(dst_pixel, 0, pad_size);
3931 dst_start += dst->stride;
3932 src_start += src->stride / 2;
3935 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3937 for(y = src_rect->top; y < src_rect->bottom; y++)
3939 dst_pixel = dst_start;
3940 src_pixel = src_start;
3941 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3943 src_val = *src_pixel++;
3944 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3945 (((src_val >> src->red_shift) << 3) & 0xf8) |
3946 (((src_val >> src->red_shift) >> 2) & 0x07),
3947 (((src_val >> src->green_shift) << 2) & 0xfc) |
3948 (((src_val >> src->green_shift) >> 4) & 0x03),
3949 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3950 (((src_val >> src->blue_shift) >> 2) & 0x07));
3951 if(bit_pos == 0) *dst_pixel = 0;
3952 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3962 if(bit_pos != 0) dst_pixel++;
3963 memset(dst_pixel, 0, pad_size);
3965 dst_start += dst->stride;
3966 src_start += src->stride / 2;
3971 for(y = src_rect->top; y < src_rect->bottom; y++)
3973 dst_pixel = dst_start;
3974 src_pixel = src_start;
3975 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3977 src_val = *src_pixel++;
3978 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3979 get_field(src_val, src->red_shift, src->red_len),
3980 get_field(src_val, src->green_shift, src->green_len),
3981 get_field(src_val, src->blue_shift, src->blue_len));
3982 if(bit_pos == 0) *dst_pixel = 0;
3983 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3993 if(bit_pos != 0) dst_pixel++;
3994 memset(dst_pixel, 0, pad_size);
3996 dst_start += dst->stride;
3997 src_start += src->stride / 2;
4005 const RGBQUAD *color_table = get_dib_color_table( src );
4006 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4008 for(y = src_rect->top; y < src_rect->bottom; y++)
4010 dst_pixel = dst_start;
4011 src_pixel = src_start;
4012 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4014 RGBQUAD rgb = color_table[*src_pixel++];
4015 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4017 if(bit_pos == 0) *dst_pixel = 0;
4018 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4028 if(bit_pos != 0) dst_pixel++;
4029 memset(dst_pixel, 0, pad_size);
4031 dst_start += dst->stride;
4032 src_start += src->stride;
4039 const RGBQUAD *color_table = get_dib_color_table( src );
4040 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4042 for(y = src_rect->top; y < src_rect->bottom; y++)
4044 int pos = (src->rect.left + src_rect->left) & 1;
4045 dst_pixel = dst_start;
4046 src_pixel = src_start;
4047 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4051 rgb = color_table[*src_pixel++ & 0xf];
4053 rgb = color_table[*src_pixel >> 4];
4054 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4056 if(bit_pos == 0) *dst_pixel = 0;
4057 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4067 if(bit_pos != 0) dst_pixel++;
4068 memset(dst_pixel, 0, pad_size);
4070 dst_start += dst->stride;
4071 src_start += src->stride;
4076 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
4077 uses text/bkgnd colours instead of the dib's colour table, this
4078 doesn't appear to be the case for a dc backed by a
4083 const RGBQUAD *color_table = get_dib_color_table( src );
4084 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4085 for(y = src_rect->top; y < src_rect->bottom; y++)
4087 int pos = (src->rect.left + src_rect->left) & 7;
4088 dst_pixel = dst_start;
4089 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4092 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4093 rgb = color_table[src_val];
4094 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4096 if(bit_pos == 0) *dst_pixel = 0;
4097 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4107 if(bit_pos != 0) dst_pixel++;
4108 memset(dst_pixel, 0, pad_size);
4110 dst_start += dst->stride;
4111 src_start += src->stride;
4118 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4122 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
4124 return (src * alpha + dst * (255 - alpha) + 127) / 255;
4127 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
4129 return (blend_color( dst, src, alpha ) |
4130 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4131 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4132 blend_color( dst >> 24, src >> 24, alpha ) << 24);
4135 static inline DWORD blend_argb_no_src_alpha( DWORD dst, DWORD src, DWORD alpha )
4137 return (blend_color( dst, src, alpha ) |
4138 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4139 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4140 blend_color( dst >> 24, 255, alpha ) << 24);
4143 static inline DWORD blend_argb( DWORD dst, DWORD src )
4146 BYTE g = (BYTE)(src >> 8);
4147 BYTE r = (BYTE)(src >> 16);
4148 DWORD alpha = (BYTE)(src >> 24);
4149 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4150 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4151 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4152 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4155 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
4157 BYTE b = ((BYTE)src * alpha + 127) / 255;
4158 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4159 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4160 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4161 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4162 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4163 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4164 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4167 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
4169 if (blend.AlphaFormat & AC_SRC_ALPHA)
4171 DWORD alpha = blend.SourceConstantAlpha;
4172 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
4173 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4174 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4175 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4176 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
4177 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
4178 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
4180 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
4181 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
4182 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
4185 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
4186 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4188 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4189 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4192 if (blend.AlphaFormat & AC_SRC_ALPHA)
4194 if (blend.SourceConstantAlpha == 255)
4195 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4196 for (x = 0; x < rc->right - rc->left; x++)
4197 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
4199 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4200 for (x = 0; x < rc->right - rc->left; x++)
4201 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4203 else if (src->compression == BI_RGB)
4204 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4205 for (x = 0; x < rc->right - rc->left; x++)
4206 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4208 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4209 for (x = 0; x < rc->right - rc->left; x++)
4210 dst_ptr[x] = blend_argb_no_src_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4213 static void blend_rect_32(const dib_info *dst, const RECT *rc,
4214 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4216 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4217 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4220 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
4222 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4224 for (x = 0; x < rc->right - rc->left; x++)
4226 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
4227 dst_ptr[x] >> dst->green_shift,
4228 dst_ptr[x] >> dst->blue_shift,
4229 src_ptr[x], blend );
4230 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
4231 (((val >> 8) & 0xff) << dst->green_shift) |
4232 (((val >> 16) & 0xff) << dst->red_shift));
4238 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4240 for (x = 0; x < rc->right - rc->left; x++)
4242 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4243 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4244 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4245 src_ptr[x], blend );
4246 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
4247 put_field( val >> 8, dst->green_shift, dst->green_len ) |
4248 put_field( val, dst->blue_shift, dst->blue_len ));
4254 static void blend_rect_24(const dib_info *dst, const RECT *rc,
4255 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4257 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4258 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
4261 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4263 for (x = 0; x < rc->right - rc->left; x++)
4265 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4266 src_ptr[x], blend );
4267 dst_ptr[x * 3] = val;
4268 dst_ptr[x * 3 + 1] = val >> 8;
4269 dst_ptr[x * 3 + 2] = val >> 16;
4274 static void blend_rect_555(const dib_info *dst, const RECT *rc,
4275 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4277 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4278 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4281 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4283 for (x = 0; x < rc->right - rc->left; x++)
4285 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4286 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4287 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4288 src_ptr[x], blend );
4289 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4294 static void blend_rect_16(const dib_info *dst, const RECT *rc,
4295 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4297 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4298 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4301 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4303 for (x = 0; x < rc->right - rc->left; x++)
4305 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4306 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4307 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4308 src_ptr[x], blend );
4309 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
4310 put_field((val >> 8), dst->green_shift, dst->green_len) |
4311 put_field( val, dst->blue_shift, dst->blue_len));
4316 static void blend_rect_8(const dib_info *dst, const RECT *rc,
4317 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4319 const RGBQUAD *color_table = get_dib_color_table( dst );
4320 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4321 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4324 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4326 for (x = 0; x < rc->right - rc->left; x++)
4328 RGBQUAD rgb = color_table[dst_ptr[x]];
4329 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4330 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4335 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4336 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4338 const RGBQUAD *color_table = get_dib_color_table( dst );
4339 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4340 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4343 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4345 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4347 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4348 RGBQUAD rgb = color_table[val];
4349 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4350 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4352 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4354 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4359 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4360 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4362 const RGBQUAD *color_table = get_dib_color_table( dst );
4363 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4364 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4367 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4369 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4371 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4372 RGBQUAD rgb = color_table[val];
4373 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4374 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4375 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4380 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4381 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4385 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4388 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4389 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4390 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4391 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4392 return a << 24 | r << 16 | g << 8 | b;
4395 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4398 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4399 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4400 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4401 return r << 16 | g << 8 | b;
4404 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4405 unsigned int x, unsigned int y )
4407 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4408 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4409 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4410 r = min( 31, max( 0, r / 16 ));
4411 g = min( 31, max( 0, g / 16 ));
4412 b = min( 31, max( 0, b / 16 ));
4413 return (r << 10) | (g << 5) | b;
4416 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4417 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4419 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4420 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4421 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4422 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4425 /* compute the left/right triangle limit for row y */
4426 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4430 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4431 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4433 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4435 *left = max( rc->left, min( x1, x2 ) );
4436 *right = min( rc->right, max( x1, x2 ) );
4439 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4440 static inline int triangle_det( const TRIVERTEX *v )
4442 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);
4445 /* compute the barycentric weights for a given point inside the triangle */
4446 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4448 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4449 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4452 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4457 triangle_weights( v, x, y, &l1, &l2 );
4458 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4459 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4460 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4461 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4462 return a << 24 | r << 16 | g << 8 | b;
4465 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4470 triangle_weights( v, x, y, &l1, &l2 );
4471 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4472 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4473 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4474 return r << 16 | g << 8 | b;
4477 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4482 triangle_weights( v, x, y, &l1, &l2 );
4483 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4484 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4485 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4486 r = min( 31, max( 0, r / 16 ));
4487 g = min( 31, max( 0, g / 16 ));
4488 b = min( 31, max( 0, b / 16 ));
4489 return (r << 10) | (g << 5) | b;
4492 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4497 triangle_weights( v, x, y, &l1, &l2 );
4498 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4499 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4500 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4501 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4504 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4506 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4507 int x, y, left, right, det;
4511 case GRADIENT_FILL_RECT_H:
4512 for (x = 0; x < rc->right - rc->left; x++)
4513 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4515 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4516 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4519 case GRADIENT_FILL_RECT_V:
4520 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4522 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4523 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4527 case GRADIENT_FILL_TRIANGLE:
4528 if (!(det = triangle_det( v ))) return FALSE;
4529 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4531 triangle_coords( v, rc, y, &left, &right );
4532 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4539 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4541 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4542 int x, y, left, right, det;
4546 case GRADIENT_FILL_RECT_H:
4547 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4549 for (x = 0; x < rc->right - rc->left; x++)
4551 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4552 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4553 (((val >> 8) & 0xff) << dib->green_shift) |
4554 (((val >> 16) & 0xff) << dib->red_shift));
4559 for (x = 0; x < rc->right - rc->left; x++)
4561 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4562 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4563 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4564 put_field( val, dib->blue_shift, dib->blue_len ));
4568 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4569 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4572 case GRADIENT_FILL_RECT_V:
4573 for (y = rc->top; y < rc->bottom; y++)
4575 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4576 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4577 val = ((( val & 0xff) << dib->blue_shift) |
4578 (((val >> 8) & 0xff) << dib->green_shift) |
4579 (((val >> 16) & 0xff) << dib->red_shift));
4581 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4582 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4583 put_field( val, dib->blue_shift, dib->blue_len ));
4585 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4586 ptr += dib->stride / 4;
4590 case GRADIENT_FILL_TRIANGLE:
4591 if (!(det = triangle_det( v ))) return FALSE;
4592 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4594 triangle_coords( v, rc, y, &left, &right );
4596 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4597 for (x = left; x < right; x++)
4599 DWORD val = gradient_triangle_24( v, x, y, det );
4600 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4601 (((val >> 8) & 0xff) << dib->green_shift) |
4602 (((val >> 16) & 0xff) << dib->red_shift));
4605 for (x = left; x < right; x++)
4607 DWORD val = gradient_triangle_24( v, x, y, det );
4608 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4609 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4610 put_field( val, dib->blue_shift, dib->blue_len ));
4618 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4620 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4621 int x, y, left, right, det;
4625 case GRADIENT_FILL_RECT_H:
4626 for (x = 0; x < rc->right - rc->left; x++)
4628 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4630 ptr[x * 3 + 1] = val >> 8;
4631 ptr[x * 3 + 2] = val >> 16;
4634 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4635 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4638 case GRADIENT_FILL_RECT_V:
4639 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4641 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4642 for (x = 0; x < rc->right - rc->left; x++)
4645 ptr[x * 3 + 1] = val >> 8;
4646 ptr[x * 3 + 2] = val >> 16;
4651 case GRADIENT_FILL_TRIANGLE:
4652 if (!(det = triangle_det( v ))) return FALSE;
4653 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4655 triangle_coords( v, rc, y, &left, &right );
4656 for (x = left; x < right; x++)
4658 DWORD val = gradient_triangle_24( v, x, y, det );
4659 ptr[(x - rc->left) * 3] = val;
4660 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4661 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4669 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4671 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4672 int x, y, left, right, det;
4676 case GRADIENT_FILL_RECT_H:
4677 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4678 for (x = rc->left; x < rc->right; x++)
4679 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4680 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4681 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4684 case GRADIENT_FILL_RECT_V:
4685 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4688 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4689 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4693 case GRADIENT_FILL_TRIANGLE:
4694 if (!(det = triangle_det( v ))) return FALSE;
4695 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4697 triangle_coords( v, rc, y, &left, &right );
4698 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4705 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4707 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4708 int x, y, left, right, det;
4712 case GRADIENT_FILL_RECT_H:
4713 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4714 for (x = rc->left; x < rc->right; x++)
4716 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4717 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4718 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4719 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4721 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4722 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4725 case GRADIENT_FILL_RECT_V:
4726 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4729 for (x = 0; x < 4; x++)
4731 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4732 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4733 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4734 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4736 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4740 case GRADIENT_FILL_TRIANGLE:
4741 if (!(det = triangle_det( v ))) return FALSE;
4742 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4744 triangle_coords( v, rc, y, &left, &right );
4745 for (x = left; x < right; x++)
4747 WORD val = gradient_triangle_555( v, x, y, det );
4748 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4749 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4750 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4758 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4760 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4761 int x, y, left, right, det;
4765 case GRADIENT_FILL_RECT_H:
4766 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4767 for (x = rc->left; x < rc->right; x++)
4768 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4769 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4770 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4773 case GRADIENT_FILL_RECT_V:
4774 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4777 for (x = 0; x < 16; x++)
4778 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4779 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4783 case GRADIENT_FILL_TRIANGLE:
4784 if (!(det = triangle_det( v ))) return FALSE;
4785 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4787 triangle_coords( v, rc, y, &left, &right );
4788 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4795 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4797 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4798 int x, y, left, right, det, pos;
4802 case GRADIENT_FILL_RECT_H:
4803 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4805 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4807 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4809 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4811 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4814 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4817 pos = (dib->rect.left + rc->left) & 1;
4820 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4824 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4826 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4830 case GRADIENT_FILL_RECT_V:
4831 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4834 for (x = 0; x < 16; x++)
4835 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4836 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4838 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4840 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4844 case GRADIENT_FILL_TRIANGLE:
4845 if (!(det = triangle_det( v ))) return FALSE;
4846 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4848 triangle_coords( v, rc, y, &left, &right );
4849 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4851 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4853 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4855 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4863 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4865 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4866 int x, y, left, right, det, pos;
4870 case GRADIENT_FILL_RECT_H:
4871 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4873 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4875 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4876 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4879 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4880 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4881 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4882 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4885 case GRADIENT_FILL_RECT_V:
4886 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4889 for (x = 0; x < 16; x++)
4890 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4891 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4892 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4893 (values[x % 16] & pixel_masks_1[pos % 8]);
4897 case GRADIENT_FILL_TRIANGLE:
4898 if (!(det = triangle_det( v ))) return FALSE;
4899 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4901 triangle_coords( v, rc, y, &left, &right );
4902 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4904 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4905 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4913 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4918 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4920 if (dst == text) return dst;
4924 DWORD diff = dst - text;
4925 DWORD range = max_comp - text;
4926 dst = text + (diff * range ) / (0xff - text);
4931 DWORD diff = text - dst;
4932 DWORD range = text - min_comp;
4933 dst = text - (diff * range) / text;
4938 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4940 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4941 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4942 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4945 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4946 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4948 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4949 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4952 for (y = rect->top; y < rect->bottom; y++)
4954 for (x = 0; x < rect->right - rect->left; x++)
4956 if (glyph_ptr[x] <= 1) continue;
4957 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4958 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4960 dst_ptr += dib->stride / 4;
4961 glyph_ptr += glyph->stride;
4965 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4966 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4968 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4969 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4973 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4974 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4975 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4977 for (y = rect->top; y < rect->bottom; y++)
4979 for (x = 0; x < rect->right - rect->left; x++)
4981 if (glyph_ptr[x] <= 1) continue;
4982 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4983 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4984 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4985 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4986 text, ranges + glyph_ptr[x] );
4987 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4988 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4989 put_field( val, dib->blue_shift, dib->blue_len ));
4991 dst_ptr += dib->stride / 4;
4992 glyph_ptr += glyph->stride;
4996 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4997 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4999 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
5000 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5004 for (y = rect->top; y < rect->bottom; y++)
5006 for (x = 0; x < rect->right - rect->left; x++)
5008 if (glyph_ptr[x] <= 1) continue;
5009 if (glyph_ptr[x] >= 16)
5012 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
5013 text_pixel, ranges + glyph_ptr[x] );
5014 dst_ptr[x * 3] = val;
5015 dst_ptr[x * 3 + 1] = val >> 8;
5016 dst_ptr[x * 3 + 2] = val >> 16;
5018 dst_ptr += dib->stride;
5019 glyph_ptr += glyph->stride;
5023 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5024 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5026 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5027 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5031 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
5032 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
5033 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
5035 for (y = rect->top; y < rect->bottom; y++)
5037 for (x = 0; x < rect->right - rect->left; x++)
5039 if (glyph_ptr[x] <= 1) continue;
5040 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
5041 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
5042 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
5043 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
5044 text, ranges + glyph_ptr[x] );
5045 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
5047 dst_ptr += dib->stride / 2;
5048 glyph_ptr += glyph->stride;
5052 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5053 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5055 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5056 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5060 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
5061 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5062 get_field( text_pixel, dib->blue_shift, dib->blue_len );
5064 for (y = rect->top; y < rect->bottom; y++)
5066 for (x = 0; x < rect->right - rect->left; x++)
5068 if (glyph_ptr[x] <= 1) continue;
5069 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
5070 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
5071 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5072 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
5073 text, ranges + glyph_ptr[x] );
5074 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
5075 put_field( val >> 8, dib->green_shift, dib->green_len ) |
5076 put_field( val, dib->blue_shift, dib->blue_len ));
5078 dst_ptr += dib->stride / 2;
5079 glyph_ptr += glyph->stride;
5083 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5084 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5086 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
5087 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5090 for (y = rect->top; y < rect->bottom; y++)
5092 for (x = 0; x < rect->right - rect->left; x++)
5094 /* no antialiasing, glyph should only contain 0 or 16. */
5095 if (glyph_ptr[x] >= 16)
5096 dst_ptr[x] = text_pixel;
5098 dst_ptr += dib->stride;
5099 glyph_ptr += glyph->stride;
5103 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5104 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5106 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
5107 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5110 for (y = rect->top; y < rect->bottom; y++)
5112 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
5114 /* no antialiasing, glyph should only contain 0 or 16. */
5115 if (glyph_ptr[x] >= 16)
5118 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
5120 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
5123 dst_ptr += dib->stride;
5124 glyph_ptr += glyph->stride;
5128 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5129 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5131 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
5132 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5134 BYTE text = (text_pixel & 1) ? 0xff : 0;
5136 for (y = rect->top; y < rect->bottom; y++)
5138 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
5140 /* no antialiasing, glyph should only contain 0 or 16. */
5141 if (glyph_ptr[x] >= 16)
5142 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5143 (text & pixel_masks_1[pos % 8]);
5145 dst_ptr += dib->stride;
5146 glyph_ptr += glyph->stride;
5150 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5151 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5156 static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha )
5158 return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 |
5159 blend_color( g, text >> 8, (BYTE)(alpha >> 8) ) << 8 |
5160 blend_color( b, text, (BYTE) alpha );
5163 static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5164 const POINT *origin, DWORD text_pixel )
5166 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
5167 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5170 for (y = rect->top; y < rect->bottom; y++)
5172 for (x = 0; x < rect->right - rect->left; x++)
5174 if (glyph_ptr[x] == 0) continue;
5175 dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, glyph_ptr[x] );
5177 dst_ptr += dib->stride / 4;
5178 glyph_ptr += glyph->stride / 4;
5182 static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5183 const POINT *origin, DWORD text_pixel )
5185 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
5186 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5190 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
5191 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5192 get_field( text_pixel, dib->blue_shift, dib->blue_len );
5194 for (y = rect->top; y < rect->bottom; y++)
5196 for (x = 0; x < rect->right - rect->left; x++)
5198 if (glyph_ptr[x] == 0) continue;
5199 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
5200 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5201 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
5202 text, glyph_ptr[x] );
5203 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
5204 put_field( val >> 8, dib->green_shift, dib->green_len ) |
5205 put_field( val, dib->blue_shift, dib->blue_len ));
5207 dst_ptr += dib->stride / 4;
5208 glyph_ptr += glyph->stride / 4;
5212 static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5213 const POINT *origin, DWORD text_pixel )
5215 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
5216 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5220 for (y = rect->top; y < rect->bottom; y++)
5222 for (x = 0; x < rect->right - rect->left; x++)
5224 if (glyph_ptr[x] == 0) continue;
5225 val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
5226 text_pixel, glyph_ptr[x] );
5227 dst_ptr[x * 3] = val;
5228 dst_ptr[x * 3 + 1] = val >> 8;
5229 dst_ptr[x * 3 + 2] = val >> 16;
5231 dst_ptr += dib->stride;
5232 glyph_ptr += glyph->stride / 4;
5236 static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5237 const POINT *origin, DWORD text_pixel )
5239 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5240 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5244 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
5245 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
5246 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
5248 for (y = rect->top; y < rect->bottom; y++)
5250 for (x = 0; x < rect->right - rect->left; x++)
5252 if (glyph_ptr[x] == 0) continue;
5253 val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
5254 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
5255 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
5256 text, glyph_ptr[x] );
5257 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
5259 dst_ptr += dib->stride / 2;
5260 glyph_ptr += glyph->stride / 4;
5264 static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5265 const POINT *origin, DWORD text_pixel )
5267 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5268 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5272 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
5273 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5274 get_field( text_pixel, dib->blue_shift, dib->blue_len );
5276 for (y = rect->top; y < rect->bottom; y++)
5278 for (x = 0; x < rect->right - rect->left; x++)
5280 if (glyph_ptr[x] == 0) continue;
5281 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
5282 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5283 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
5284 text, glyph_ptr[x] );
5285 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
5286 put_field( val >> 8, dib->green_shift, dib->green_len ) |
5287 put_field( val, dib->blue_shift, dib->blue_len ));
5289 dst_ptr += dib->stride / 2;
5290 glyph_ptr += glyph->stride / 4;
5294 static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5295 const POINT *origin, DWORD text_pixel )
5300 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
5301 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5303 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
5306 /* masks are always 8x8 */
5307 assert( dib->width == 8 );
5308 assert( dib->height == 8 );
5310 for(y = 0; y < 8; y++, hatch_ptr++)
5312 for(x = 0; x < 8; x++)
5314 if(*hatch_ptr & pixel_masks_1[x])
5316 and_bits[x] = fg->and;
5317 xor_bits[x] = fg->xor;
5321 and_bits[x] = bg->and;
5322 xor_bits[x] = bg->xor;
5325 and_bits += dib->stride / 4;
5326 xor_bits += dib->stride / 4;
5330 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
5331 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5333 DWORD mask_start = 0, mask_offset;
5334 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5337 /* masks are always 8x8 */
5338 assert( dib->width == 8 );
5339 assert( dib->height == 8 );
5341 for(y = 0; y < 8; y++, hatch_ptr++)
5343 mask_offset = mask_start;
5344 for(x = 0; x < 8; x++)
5346 if(*hatch_ptr & pixel_masks_1[x])
5348 and_bits[mask_offset] = fg->and & 0xff;
5349 xor_bits[mask_offset++] = fg->xor & 0xff;
5350 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
5351 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
5352 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
5353 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
5357 and_bits[mask_offset] = bg->and & 0xff;
5358 xor_bits[mask_offset++] = bg->xor & 0xff;
5359 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
5360 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
5361 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
5362 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
5365 mask_start += dib->stride;
5369 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
5370 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5372 WORD *and_bits = bits->and, *xor_bits = bits->xor;
5375 /* masks are always 8x8 */
5376 assert( dib->width == 8 );
5377 assert( dib->height == 8 );
5379 for(y = 0; y < 8; y++, hatch_ptr++)
5381 for(x = 0; x < 8; x++)
5383 if(*hatch_ptr & pixel_masks_1[x])
5385 and_bits[x] = fg->and;
5386 xor_bits[x] = fg->xor;
5390 and_bits[x] = bg->and;
5391 xor_bits[x] = bg->xor;
5394 and_bits += dib->stride / 2;
5395 xor_bits += dib->stride / 2;
5399 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
5400 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5402 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5405 /* masks are always 8x8 */
5406 assert( dib->width == 8 );
5407 assert( dib->height == 8 );
5409 for(y = 0; y < 8; y++, hatch_ptr++)
5411 for(x = 0; x < 8; x++)
5413 if(*hatch_ptr & pixel_masks_1[x])
5415 and_bits[x] = fg->and;
5416 xor_bits[x] = fg->xor;
5420 and_bits[x] = bg->and;
5421 xor_bits[x] = bg->xor;
5424 and_bits += dib->stride;
5425 xor_bits += dib->stride;
5429 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
5430 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5433 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5434 const rop_mask *rop_mask;
5437 /* masks are always 8x8 */
5438 assert( dib->width == 8 );
5439 assert( dib->height == 8 );
5441 for(y = 0; y < 8; y++, hatch_ptr++)
5443 for(x = mask_offset = 0; x < 8; x++)
5445 if(*hatch_ptr & pixel_masks_1[x])
5452 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
5453 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
5458 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
5459 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
5462 and_bits += dib->stride;
5463 xor_bits += dib->stride;
5467 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
5468 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5470 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5474 /* masks are always 8x8 */
5475 assert( dib->width == 8 );
5476 assert( dib->height == 8 );
5478 for(y = 0; y < 8; y++, hatch_ptr++)
5480 *and_bits = *xor_bits = 0;
5481 for(x = 0; x < 8; x++)
5483 if(*hatch_ptr & pixel_masks_1[x])
5485 rop_mask.and = (fg->and & 1) ? 0xff : 0;
5486 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
5490 rop_mask.and = (bg->and & 1) ? 0xff : 0;
5491 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5493 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5494 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5496 and_bits += dib->stride;
5497 xor_bits += dib->stride;
5501 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
5502 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5506 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5508 /* mapping between RGB triples and the default color table */
5509 static const BYTE mapping[27] =
5511 0, /* 000000 -> 000000 */
5512 4, /* 00007f -> 000080 */
5513 252, /* 0000ff -> 0000ff */
5514 2, /* 007f00 -> 008000 */
5515 6, /* 007f7f -> 008080 */
5516 224, /* 007fff -> 0080c0 */
5517 250, /* 00ff00 -> 00ff00 */
5518 184, /* 00ff7f -> 00e080 */
5519 254, /* 00ffff -> 00ffff */
5520 1, /* 7f0000 -> 800000 */
5521 5, /* 7f007f -> 800080 */
5522 196, /* 7f00ff -> 8000c0 */
5523 3, /* 7f7f00 -> 808000 */
5524 248, /* 7f7f7f -> 808080 */
5525 228, /* 7f7fff -> 8080c0 */
5526 60, /* 7fff00 -> 80e000 */
5527 188, /* 7fff7f -> 80e080 */
5528 244, /* 7fffff -> 80c0c0 */
5529 249, /* ff0000 -> ff0000 */
5530 135, /* ff007f -> e00080 */
5531 253, /* ff00ff -> ff00ff */
5532 39, /* ff7f00 -> e08000 */
5533 167, /* ff7f7f -> e08080 */
5534 231, /* ff7fff -> e080c0 */
5535 251, /* ffff00 -> ffff00 */
5536 191, /* ffff7f -> e0e080 */
5537 255 /* ffffff -> ffffff */
5540 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5541 struct rop_codes codes;
5544 /* masks are always 8x8 */
5545 assert( dib->width == 8 );
5546 assert( dib->height == 8 );
5548 get_rop_codes( rop2, &codes );
5550 for (y = 0; y < 8; y++)
5552 for (x = 0; x < 8; x++)
5554 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5555 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5556 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5557 DWORD pixel = mapping[r * 9 + g * 3 + b];
5558 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
5559 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
5561 and_bits += dib->stride;
5562 xor_bits += dib->stride;
5566 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5568 /* mapping between RGB triples and the default color table */
5569 static const BYTE mapping[27] =
5571 0, /* 000000 -> 000000 */
5572 4, /* 00007f -> 000080 */
5573 12, /* 0000ff -> 0000ff */
5574 2, /* 007f00 -> 008000 */
5575 6, /* 007f7f -> 008080 */
5576 6, /* 007fff -> 008080 */
5577 10, /* 00ff00 -> 00ff00 */
5578 6, /* 00ff7f -> 008080 */
5579 14, /* 00ffff -> 00ffff */
5580 1, /* 7f0000 -> 800000 */
5581 5, /* 7f007f -> 800080 */
5582 5, /* 7f00ff -> 800080 */
5583 3, /* 7f7f00 -> 808000 */
5584 7, /* 7f7f7f -> 808080 */
5585 8, /* 7f7fff -> c0c0c0 */
5586 3, /* 7fff00 -> 808000 */
5587 8, /* 7fff7f -> c0c0c0 */
5588 8, /* 7fffff -> c0c0c0 */
5589 9, /* ff0000 -> ff0000 */
5590 5, /* ff007f -> 800080 */
5591 13, /* ff00ff -> ff00ff */
5592 3, /* ff7f00 -> 808000 */
5593 8, /* ff7f7f -> c0c0c0 */
5594 8, /* ff7fff -> c0c0c0 */
5595 11, /* ffff00 -> ffff00 */
5596 8, /* ffff7f -> c0c0c0 */
5597 15 /* ffffff -> ffffff */
5600 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5601 struct rop_codes codes;
5604 /* masks are always 8x8 */
5605 assert( dib->width == 8 );
5606 assert( dib->height == 8 );
5608 get_rop_codes( rop2, &codes );
5610 for (y = 0; y < 8; y++)
5612 for (x = 0; x < 8; x++)
5614 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5615 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5616 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5617 DWORD pixel = mapping[r * 9 + g * 3 + b];
5620 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
5621 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
5625 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
5626 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
5629 and_bits += dib->stride;
5630 xor_bits += dib->stride;
5634 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5636 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5637 struct rop_codes codes;
5639 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
5641 /* masks are always 8x8 */
5642 assert( dib->width == 8 );
5643 assert( dib->height == 8 );
5645 get_rop_codes( rop2, &codes );
5647 for (y = 0; y < 8; y++)
5649 *and_bits = *xor_bits = 0;
5650 for (x = 0; x < 8; x++)
5652 if (grey + bayer_8x8[y][x] > 63)
5654 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
5655 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
5659 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
5660 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
5662 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5663 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5665 and_bits += dib->stride;
5666 xor_bits += dib->stride;
5670 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5674 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5679 case STRETCH_DELETESCANS:
5680 get_rop_codes( R2_COPYPEN, codes );
5682 case STRETCH_ORSCANS:
5683 get_rop_codes( R2_MERGEPEN, codes );
5685 case STRETCH_ANDSCANS:
5686 get_rop_codes( R2_MASKPEN, codes );
5692 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5693 const dib_info *src_dib, const POINT *src_start,
5694 const struct stretch_params *params, int mode,
5697 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5698 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5699 int err = params->err_start;
5701 struct rop_codes codes;
5703 rop_codes_from_stretch_mode( mode, &codes );
5704 for (width = params->length; width; width--)
5706 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5707 dst_ptr += params->dst_inc;
5710 src_ptr += params->src_inc;
5711 err += params->err_add_1;
5713 else err += params->err_add_2;
5717 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5718 const dib_info *src_dib, const POINT *src_start,
5719 const struct stretch_params *params, int mode,
5722 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5723 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5724 int err = params->err_start;
5726 struct rop_codes codes;
5728 rop_codes_from_stretch_mode( mode, &codes );
5729 for (width = params->length; width; width--)
5731 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5732 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5733 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5734 dst_ptr += 3 * params->dst_inc;
5737 src_ptr += 3 * params->src_inc;
5738 err += params->err_add_1;
5740 else err += params->err_add_2;
5744 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5745 const dib_info *src_dib, const POINT *src_start,
5746 const struct stretch_params *params, int mode,
5749 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5750 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5751 int err = params->err_start;
5753 struct rop_codes codes;
5755 rop_codes_from_stretch_mode( mode, &codes );
5756 for (width = params->length; width; width--)
5758 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5759 dst_ptr += params->dst_inc;
5762 src_ptr += params->src_inc;
5763 err += params->err_add_1;
5765 else err += params->err_add_2;
5769 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5770 const dib_info *src_dib, const POINT *src_start,
5771 const struct stretch_params *params, int mode,
5774 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5775 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5776 int err = params->err_start;
5778 struct rop_codes codes;
5780 rop_codes_from_stretch_mode( mode, &codes );
5781 for (width = params->length; width; width--)
5783 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5784 dst_ptr += params->dst_inc;
5787 src_ptr += params->src_inc;
5788 err += params->err_add_1;
5790 else err += params->err_add_2;
5794 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5795 const dib_info *src_dib, const POINT *src_start,
5796 const struct stretch_params *params, int mode,
5799 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5800 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5801 int err = params->err_start;
5802 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5803 struct rop_codes codes;
5806 rop_codes_from_stretch_mode( mode, &codes );
5807 for (width = params->length; width; width--)
5809 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5810 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5812 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5814 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5815 dst_ptr += params->dst_inc;
5816 dst_x += params->dst_inc;
5820 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5821 src_ptr += params->src_inc;
5822 src_x += params->src_inc;
5823 err += params->err_add_1;
5825 else err += params->err_add_2;
5829 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5830 const dib_info *src_dib, const POINT *src_start,
5831 const struct stretch_params *params, int mode,
5834 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5835 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5836 int err = params->err_start;
5837 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5838 struct rop_codes codes;
5841 rop_codes_from_stretch_mode( mode, &codes );
5842 for (width = params->length; width; width--)
5844 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5845 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5847 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5848 dst_ptr += params->dst_inc;
5849 dst_x += params->dst_inc;
5853 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5854 src_ptr += params->src_inc;
5855 src_x += params->src_inc;
5856 err += params->err_add_1;
5858 else err += params->err_add_2;
5862 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5863 const dib_info *src_dib, const POINT *src_start,
5864 const struct stretch_params *params, int mode,
5867 FIXME("bit count %d\n", dst_dib->bit_count);
5871 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5872 const dib_info *src_dib, const POINT *src_start,
5873 const struct stretch_params *params, int mode,
5876 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5877 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5878 int err = params->err_start;
5880 struct rop_codes codes;
5881 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5882 BOOL new_pix = TRUE;
5884 rop_codes_from_stretch_mode( mode, &codes );
5885 for (width = params->length; width; width--)
5887 if (new_pix && !keep_dst) *dst_ptr = init_val;
5888 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5890 src_ptr += params->src_inc;
5893 dst_ptr += params->dst_inc;
5895 err += params->err_add_1;
5897 else err += params->err_add_2;
5901 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5902 const dib_info *src_dib, const POINT *src_start,
5903 const struct stretch_params *params, int mode,
5906 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5907 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5908 int err = params->err_start;
5910 struct rop_codes codes;
5911 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5912 BOOL new_pix = TRUE;
5914 rop_codes_from_stretch_mode( mode, &codes );
5915 for (width = params->length; width; width--)
5917 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5918 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5919 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5920 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5922 src_ptr += 3 * params->src_inc;
5925 dst_ptr += 3 * params->dst_inc;
5927 err += params->err_add_1;
5929 else err += params->err_add_2;
5933 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5934 const dib_info *src_dib, const POINT *src_start,
5935 const struct stretch_params *params, int mode,
5938 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5939 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5940 int err = params->err_start;
5942 struct rop_codes codes;
5943 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5944 BOOL new_pix = TRUE;
5946 rop_codes_from_stretch_mode( mode, &codes );
5947 for (width = params->length; width; width--)
5949 if (new_pix && !keep_dst) *dst_ptr = init_val;
5950 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5952 src_ptr += params->src_inc;
5955 dst_ptr += params->dst_inc;
5957 err += params->err_add_1;
5959 else err += params->err_add_2;
5963 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5964 const dib_info *src_dib, const POINT *src_start,
5965 const struct stretch_params *params, int mode,
5968 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5969 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5970 int err = params->err_start;
5972 struct rop_codes codes;
5973 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5974 BOOL new_pix = TRUE;
5976 rop_codes_from_stretch_mode( mode, &codes );
5977 for (width = params->length; width; width--)
5979 if (new_pix && !keep_dst) *dst_ptr = init_val;
5980 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5982 src_ptr += params->src_inc;
5985 dst_ptr += params->dst_inc;
5987 err += params->err_add_1;
5989 else err += params->err_add_2;
5993 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5994 const dib_info *src_dib, const POINT *src_start,
5995 const struct stretch_params *params, int mode,
5998 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5999 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
6000 int err = params->err_start;
6001 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6002 struct rop_codes codes;
6003 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
6004 BOOL new_pix = TRUE;
6006 rop_codes_from_stretch_mode( mode, &codes );
6007 for (width = params->length; width; width--)
6009 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
6011 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
6012 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
6014 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
6017 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
6018 src_ptr += params->src_inc;
6019 src_x += params->src_inc;
6023 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
6024 dst_ptr += params->dst_inc;
6025 dst_x += params->dst_inc;
6027 err += params->err_add_1;
6029 else err += params->err_add_2;
6033 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
6034 const dib_info *src_dib, const POINT *src_start,
6035 const struct stretch_params *params, int mode,
6038 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
6039 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
6040 int err = params->err_start;
6041 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6042 struct rop_codes codes;
6043 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
6044 BOOL new_pix = TRUE;
6046 rop_codes_from_stretch_mode( mode, &codes );
6047 for (width = params->length; width; width--)
6049 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
6050 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
6051 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
6054 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
6055 src_ptr += params->src_inc;
6056 src_x += params->src_inc;
6060 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
6061 dst_ptr += params->dst_inc;
6062 dst_x += params->dst_inc;
6064 err += params->err_add_1;
6066 else err += params->err_add_2;
6070 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
6071 const dib_info *src_dib, const POINT *src_start,
6072 const struct stretch_params *params, int mode,
6075 FIXME("bit count %d\n", dst_dib->bit_count);
6079 const primitive_funcs funcs_8888 =
6088 draw_subpixel_glyph_8888,
6090 colorref_to_pixel_888,
6091 pixel_to_colorref_888,
6093 create_rop_masks_32,
6094 create_dither_masks_null,
6099 const primitive_funcs funcs_32 =
6108 draw_subpixel_glyph_32,
6110 colorref_to_pixel_masks,
6111 pixel_to_colorref_masks,
6113 create_rop_masks_32,
6114 create_dither_masks_null,
6119 const primitive_funcs funcs_24 =
6128 draw_subpixel_glyph_24,
6130 colorref_to_pixel_888,
6131 pixel_to_colorref_888,
6133 create_rop_masks_24,
6134 create_dither_masks_null,
6139 const primitive_funcs funcs_555 =
6148 draw_subpixel_glyph_555,
6150 colorref_to_pixel_555,
6151 pixel_to_colorref_555,
6153 create_rop_masks_16,
6154 create_dither_masks_null,
6159 const primitive_funcs funcs_16 =
6168 draw_subpixel_glyph_16,
6170 colorref_to_pixel_masks,
6171 pixel_to_colorref_masks,
6173 create_rop_masks_16,
6174 create_dither_masks_null,
6179 const primitive_funcs funcs_8 =
6188 draw_subpixel_glyph_null,
6190 colorref_to_pixel_colortable,
6191 pixel_to_colorref_colortable,
6194 create_dither_masks_8,
6199 const primitive_funcs funcs_4 =
6208 draw_subpixel_glyph_null,
6210 colorref_to_pixel_colortable,
6211 pixel_to_colorref_colortable,
6214 create_dither_masks_4,
6219 const primitive_funcs funcs_1 =
6228 draw_subpixel_glyph_null,
6230 colorref_to_pixel_colortable,
6231 pixel_to_colorref_colortable,
6234 create_dither_masks_1,
6239 const primitive_funcs funcs_null =
6248 draw_subpixel_glyph_null,
6250 colorref_to_pixel_null,
6251 pixel_to_colorref_null,
6253 create_rop_masks_null,
6254 create_dither_masks_null,