gdi32: Add support for DIBINDEX colors in 1-bpp blits.
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blobe740ef87cd88754aaa0f8a6005d071c23a14f8c2
1 /*
2 * DIB driver primitives.
4 * Copyright 2011 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
23 #include "gdi_private.h"
24 #include "dibdrv.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dib);
30 /* Bayer matrices for dithering */
32 static const BYTE bayer_4x4[4][4] =
34 { 0, 8, 2, 10 },
35 { 12, 4, 14, 6 },
36 { 3, 11, 1, 9 },
37 { 15, 7, 13, 5 }
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};
109 static const BYTE edge_masks_1[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
111 #define FILTER_DIBINDEX(rgbquad,other_val) \
112 (HIWORD( *(DWORD *)(&rgbquad) ) == 0x10ff ? LOWORD( *(DWORD *)(&rgbquad) ) : (other_val))
114 #define ROPS_WITHOUT_COPY( _d, _s ) \
115 case R2_BLACK: LOOP( (_d) = 0 ) break; \
116 case R2_NOTMERGEPEN: LOOP( (_d) = ~((_d) | (_s)) ) break; \
117 case R2_MASKNOTPEN: LOOP( (_d) &= ~(_s) ) break; \
118 case R2_NOTCOPYPEN: LOOP( (_d) = ~(_s) ) break; \
119 case R2_MASKPENNOT: LOOP( (_d) = (~(_d) & (_s)) ) break; \
120 case R2_NOT: LOOP( (_d) = ~(_d) ) break; \
121 case R2_XORPEN: LOOP( (_d) ^= (_s) ) break; \
122 case R2_NOTMASKPEN: LOOP( (_d) = ~((_d) & (_s)) ) break; \
123 case R2_MASKPEN: LOOP( (_d) &= (_s) ) break; \
124 case R2_NOTXORPEN: LOOP( (_d) = ~((_d) ^ (_s)) ) break; \
125 case R2_NOP: break; \
126 case R2_MERGENOTPEN: LOOP( (_d) = ((_d) | ~(_s)) ) break; \
127 case R2_MERGEPENNOT: LOOP( (_d) = (~(_d) | (_s)) ) break; \
128 case R2_MERGEPEN: LOOP( (_d) |= (_s) ) break; \
129 case R2_WHITE: LOOP( (_d) = ~0 ) break;
131 #define ROPS_ALL( _d, _s ) \
132 case R2_COPYPEN: LOOP( (_d) = (_s) ) break; \
133 ROPS_WITHOUT_COPY( (_d), (_s) )
135 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
137 *ptr = (*ptr & and) ^ xor;
140 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
142 *ptr = (*ptr & and) ^ xor;
145 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
147 *ptr = (*ptr & and) ^ xor;
150 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
152 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
155 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
157 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
160 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
162 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
165 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
167 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
170 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
172 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
175 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
177 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
180 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
182 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
183 do_rop_codes_16( dst, *src, codes );
186 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
188 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
191 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
193 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
194 do_rop_codes_8( dst, *src, codes );
197 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
198 struct rop_codes *codes, int len)
200 BYTE src_val;
202 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
204 if (dst_x & 1)
206 if (src_x & 1) src_val = *src++;
207 else src_val = *src >> 4;
208 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
210 else
212 if (src_x & 1) src_val = *src++ << 4;
213 else src_val = *src;
214 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
219 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
220 struct rop_codes *codes, int len)
222 BYTE src_val;
224 src_x += len - 1;
225 dst_x += len - 1;
226 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
228 if (dst_x & 1)
230 if (src_x & 1) src_val = *src;
231 else src_val = *src-- >> 4;
232 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
234 else
236 if (src_x & 1) src_val = *src << 4;
237 else src_val = *src--;
238 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
243 static inline void memset_32( DWORD *start, DWORD val, DWORD size )
245 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
246 DWORD dummy;
247 __asm__ __volatile__( "cld; rep; stosl"
248 : "=c" (dummy), "=D" (dummy)
249 : "a" (val), "0" (size), "1" (start) );
250 #else
251 while (size--) *start++ = val;
252 #endif
255 static inline void memset_16( WORD *start, WORD val, DWORD size )
257 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
258 DWORD dummy;
259 __asm__ __volatile__( "cld; rep; stosw"
260 : "=c" (dummy), "=D" (dummy)
261 : "a" (val), "0" (size), "1" (start) );
262 #else
263 while (size--) *start++ = val;
264 #endif
267 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
269 DWORD *ptr, *start;
270 int x, y, i;
272 for(i = 0; i < num; i++, rc++)
274 assert( !is_rect_empty( rc ));
276 start = get_pixel_ptr_32(dib, rc->left, rc->top);
277 if (and)
278 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
279 for(x = rc->left, ptr = start; x < rc->right; x++)
280 do_rop_32(ptr++, and, xor);
281 else
282 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
283 memset_32( start, xor, rc->right - rc->left );
287 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
289 DWORD *ptr, *start;
290 BYTE *byte_ptr, *byte_start;
291 int x, y, i;
292 DWORD and_masks[3], xor_masks[3];
294 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
295 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
296 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
297 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
298 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
299 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
301 for(i = 0; i < num; i++, rc++)
303 int left = dib->rect.left + rc->left;
304 int right = dib->rect.left + rc->right;
306 assert( !is_rect_empty( rc ));
308 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
310 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
311 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
313 for(x = left, byte_ptr = byte_start; x < right; x++)
315 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
316 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
317 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
321 else if (and)
323 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
324 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
326 ptr = start;
328 switch(left & 3)
330 case 1:
331 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
332 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
333 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
334 break;
335 case 2:
336 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
337 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
338 break;
339 case 3:
340 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
341 break;
344 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
346 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
347 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
348 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
351 switch(right & 3)
353 case 1:
354 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
355 break;
356 case 2:
357 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
358 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
359 break;
360 case 3:
361 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
362 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
363 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
364 break;
368 else
370 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
371 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
373 ptr = start;
375 switch(left & 3)
377 case 1:
378 do_rop_32(ptr++, 0x00ffffff, xor_masks[0] & 0xff000000);
379 *ptr++ = xor_masks[1];
380 *ptr++ = xor_masks[2];
381 break;
382 case 2:
383 do_rop_32(ptr++, 0x0000ffff, xor_masks[1] & 0xffff0000);
384 *ptr++ = xor_masks[2];
385 break;
386 case 3:
387 do_rop_32(ptr++, 0x000000ff, xor_masks[2] & 0xffffff00);
388 break;
391 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
393 *ptr++ = xor_masks[0];
394 *ptr++ = xor_masks[1];
395 *ptr++ = xor_masks[2];
398 switch(right & 3)
400 case 1:
401 do_rop_32(ptr, 0xff000000, xor_masks[0] & 0x00ffffff);
402 break;
403 case 2:
404 *ptr++ = xor_masks[0];
405 do_rop_32(ptr, 0xffff0000, xor_masks[1] & 0x0000ffff);
406 break;
407 case 3:
408 *ptr++ = xor_masks[0];
409 *ptr++ = xor_masks[1];
410 do_rop_32(ptr, 0xffffff00, xor_masks[2] & 0x000000ff);
411 break;
418 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
420 WORD *ptr, *start;
421 int x, y, i;
423 for(i = 0; i < num; i++, rc++)
425 assert( !is_rect_empty( rc ));
427 start = get_pixel_ptr_16(dib, rc->left, rc->top);
428 if (and)
429 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
430 for(x = rc->left, ptr = start; x < rc->right; x++)
431 do_rop_16(ptr++, and, xor);
432 else
433 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
434 memset_16( start, xor, rc->right - rc->left );
438 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
440 BYTE *ptr, *start;
441 int x, y, i;
443 for(i = 0; i < num; i++, rc++)
445 assert( !is_rect_empty( rc ));
447 start = get_pixel_ptr_8(dib, rc->left, rc->top);
448 if (and)
449 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
450 for(x = rc->left, ptr = start; x < rc->right; x++)
451 do_rop_8(ptr++, and, xor);
452 else
453 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
454 memset( start, xor, rc->right - rc->left );
458 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
460 BYTE *ptr, *start;
461 int x, y, i;
462 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
463 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
465 for(i = 0; i < num; i++, rc++)
467 int left = dib->rect.left + rc->left;
468 int right = dib->rect.left + rc->right;
470 assert( !is_rect_empty( rc ));
472 start = get_pixel_ptr_4(dib, rc->left, rc->top);
473 if (and)
475 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
477 ptr = start;
478 if(left & 1) /* upper nibble untouched */
479 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
481 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
482 do_rop_8(ptr++, byte_and, byte_xor);
484 if(right & 1) /* lower nibble untouched */
485 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
488 else
490 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
492 unsigned int byte_len = (right - ((left + 1) & ~1)) / 2;
494 ptr = start;
495 if(left & 1) /* upper nibble untouched */
496 do_rop_8(ptr++, 0xf0, byte_xor & 0x0f);
498 memset( ptr, byte_xor, byte_len );
500 if(right & 1) /* lower nibble untouched */
501 do_rop_8(ptr + byte_len, 0x0f, byte_xor & 0xf0);
507 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
509 BYTE *ptr, *start;
510 int x, y, i;
511 BYTE byte_and = (and & 1) ? 0xff : 0;
512 BYTE byte_xor = (xor & 1) ? 0xff : 0;
514 for(i = 0; i < num; i++, rc++)
516 int left = dib->rect.left + rc->left;
517 int right = dib->rect.left + rc->right;
519 assert( !is_rect_empty( rc ));
521 start = get_pixel_ptr_1(dib, rc->left, rc->top);
523 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
525 BYTE mask = edge_masks_1[left & 7] & ~edge_masks_1[right & 7];
527 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
529 do_rop_8(start, byte_and | ~mask, byte_xor & mask);
532 else if (and)
534 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
536 ptr = start;
538 if(left & 7)
539 do_rop_8(ptr++, byte_and | ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
541 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
542 do_rop_8(ptr++, byte_and, byte_xor);
544 if(right & 7)
545 /* this is inverted wrt start mask */
546 do_rop_8(ptr, byte_and | edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
549 else
551 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
553 unsigned int byte_len = (right - ((left + 7) & ~7)) / 8;
555 ptr = start;
557 if(left & 7)
558 do_rop_8(ptr++, ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
560 memset( ptr, byte_xor, byte_len );
562 if(right & 7)
563 do_rop_8(ptr + byte_len, edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
569 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
571 return;
574 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
575 DWORD and, DWORD xor)
577 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
578 int len = params->length, err = params->err_start;
579 int major_inc, minor_inc;
581 if (params->x_major)
583 major_inc = params->x_inc;
584 minor_inc = (dib->stride * params->y_inc) / 4;
586 else
588 major_inc = (dib->stride * params->y_inc) / 4;
589 minor_inc = params->x_inc;
592 while (len--)
594 do_rop_32( ptr, and, xor );
595 if (err + params->bias > 0)
597 ptr += minor_inc;
598 err += params->err_add_1;
600 else err += params->err_add_2;
601 ptr += major_inc;
605 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
606 DWORD and, DWORD xor)
608 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
609 int len = params->length, err = params->err_start;
610 int major_inc, minor_inc;
612 if (params->x_major)
614 major_inc = params->x_inc * 3;
615 minor_inc = dib->stride * params->y_inc;
617 else
619 major_inc = dib->stride * params->y_inc;
620 minor_inc = params->x_inc * 3;
623 while (len--)
625 do_rop_8( ptr, and, xor );
626 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
627 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
628 if (err + params->bias > 0)
630 ptr += minor_inc;
631 err += params->err_add_1;
633 else err += params->err_add_2;
634 ptr += major_inc;
638 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
639 DWORD and, DWORD xor)
641 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
642 int len = params->length, err = params->err_start;
643 int major_inc, minor_inc;
645 if (params->x_major)
647 major_inc = params->x_inc;
648 minor_inc = (dib->stride * params->y_inc) / 2;
650 else
652 major_inc = (dib->stride * params->y_inc) / 2;
653 minor_inc = params->x_inc;
656 while (len--)
658 do_rop_16( ptr, and, xor );
659 if (err + params->bias > 0)
661 ptr += minor_inc;
662 err += params->err_add_1;
664 else err += params->err_add_2;
665 ptr += major_inc;
669 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
670 DWORD and, DWORD xor)
672 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
673 int len = params->length, err = params->err_start;
674 int major_inc, minor_inc;
676 if (params->x_major)
678 major_inc = params->x_inc;
679 minor_inc = dib->stride * params->y_inc;
681 else
683 major_inc = dib->stride * params->y_inc;
684 minor_inc = params->x_inc;
687 while (len--)
689 do_rop_8( ptr, and, xor );
690 if (err + params->bias > 0)
692 ptr += minor_inc;
693 err += params->err_add_1;
695 else err += params->err_add_2;
696 ptr += major_inc;
700 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
701 DWORD and, DWORD xor)
703 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
704 int len = params->length, err = params->err_start;
705 int x = dib->rect.left + start->x;
707 and = (and & 0x0f) | ((and << 4) & 0xf0);
708 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
710 if (params->x_major)
712 while (len--)
714 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
715 if (err + params->bias > 0)
717 ptr += dib->stride * params->y_inc;
718 err += params->err_add_1;
720 else err += params->err_add_2;
721 if ((x / 2) != ((x + params->x_inc) / 2))
722 ptr += params->x_inc;
723 x += params->x_inc;
726 else
728 while (len--)
730 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
731 if (err + params->bias > 0)
733 if ((x / 2) != ((x + params->x_inc) / 2))
734 ptr += params->x_inc;
735 x += params->x_inc;
736 err += params->err_add_1;
738 else err += params->err_add_2;
739 ptr += dib->stride * params->y_inc;
744 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
745 DWORD and, DWORD xor)
747 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
748 int len = params->length, err = params->err_start;
749 int x = dib->rect.left + start->x;
751 and = (and & 0x1) ? 0xff : 0;
752 xor = (xor & 0x1) ? 0xff : 0;
754 if (params->x_major)
756 while (len--)
758 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
759 if (err + params->bias > 0)
761 ptr += dib->stride * params->y_inc;
762 err += params->err_add_1;
764 else err += params->err_add_2;
765 if ((x / 8) != ((x + params->x_inc) / 8))
766 ptr += params->x_inc;
767 x += params->x_inc;
770 else
772 while (len--)
774 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
775 if (err + params->bias > 0)
777 if ((x / 8) != ((x + params->x_inc) / 8))
778 ptr += params->x_inc;
779 x += params->x_inc;
780 err += params->err_add_1;
782 else err += params->err_add_2;
783 ptr += dib->stride * params->y_inc;
788 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
789 DWORD and, DWORD xor)
791 return;
794 static inline INT calc_offset(INT edge, INT size, INT origin)
796 INT offset;
798 if(edge - origin >= 0)
799 offset = (edge - origin) % size;
800 else
802 offset = (origin - edge) % size;
803 if(offset) offset = size - offset;
805 return offset;
808 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
810 POINT offset;
812 offset.x = calc_offset(rc->left, brush->width, origin->x);
813 offset.y = calc_offset(rc->top, brush->height, origin->y);
815 return offset;
818 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
819 const dib_info *brush, const rop_mask_bits *bits)
821 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
822 int x, y, i, len, brush_x;
823 POINT offset;
825 for(i = 0; i < num; i++, rc++)
827 offset = calc_brush_offset(rc, brush, origin);
828 start = get_pixel_ptr_32(dib, rc->left, rc->top);
829 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
831 if (bits->and)
833 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
835 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
837 and_ptr = start_and + offset.x;
838 xor_ptr = start_xor + offset.x;
840 for(x = rc->left, ptr = start; x < rc->right; x++)
842 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
843 if(and_ptr == start_and + brush->width)
845 and_ptr = start_and;
846 xor_ptr = start_xor;
850 offset.y++;
851 if(offset.y == brush->height)
853 start_and = bits->and;
854 start_xor = bits->xor;
855 offset.y = 0;
857 else
859 start_and += brush->stride / 4;
860 start_xor += brush->stride / 4;
864 else
866 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
868 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
870 len = min( rc->right - x, brush->width - brush_x );
871 memcpy( start + x - rc->left, start_xor + brush_x, len * 4 );
872 brush_x = 0;
875 start_xor += brush->stride / 4;
876 offset.y++;
877 if(offset.y == brush->height)
879 start_xor = bits->xor;
880 offset.y = 0;
887 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
888 const dib_info *brush, const rop_mask_bits *bits)
890 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
891 int x, y, i, len, brush_x;
892 POINT offset;
894 for(i = 0; i < num; i++, rc++)
896 offset = calc_brush_offset(rc, brush, origin);
898 start = get_pixel_ptr_24(dib, rc->left, rc->top);
899 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
901 if (bits->and)
903 start_and = (BYTE*)bits->and + offset.y * brush->stride;
904 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
906 and_ptr = start_and + offset.x * 3;
907 xor_ptr = start_xor + offset.x * 3;
909 for(x = rc->left, ptr = start; x < rc->right; x++)
911 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
912 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
913 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
914 if(and_ptr == start_and + brush->width * 3)
916 and_ptr = start_and;
917 xor_ptr = start_xor;
921 offset.y++;
922 if(offset.y == brush->height)
924 start_and = bits->and;
925 start_xor = bits->xor;
926 offset.y = 0;
928 else
930 start_and += brush->stride;
931 start_xor += brush->stride;
935 else
937 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
939 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
941 len = min( rc->right - x, brush->width - brush_x );
942 memcpy( start + (x - rc->left) * 3, start_xor + brush_x * 3, len * 3 );
943 brush_x = 0;
946 start_xor += brush->stride;
947 offset.y++;
948 if(offset.y == brush->height)
950 start_xor = bits->xor;
951 offset.y = 0;
958 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
959 const dib_info *brush, const rop_mask_bits *bits)
961 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
962 int x, y, i, len, brush_x;
963 POINT offset;
965 for(i = 0; i < num; i++, rc++)
967 offset = calc_brush_offset(rc, brush, origin);
969 start = get_pixel_ptr_16(dib, rc->left, rc->top);
970 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
972 if (bits->and)
974 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
975 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
977 and_ptr = start_and + offset.x;
978 xor_ptr = start_xor + offset.x;
980 for(x = rc->left, ptr = start; x < rc->right; x++)
982 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
983 if(and_ptr == start_and + brush->width)
985 and_ptr = start_and;
986 xor_ptr = start_xor;
990 offset.y++;
991 if(offset.y == brush->height)
993 start_and = bits->and;
994 start_xor = bits->xor;
995 offset.y = 0;
997 else
999 start_and += brush->stride / 2;
1000 start_xor += brush->stride / 2;
1004 else
1006 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
1008 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1010 len = min( rc->right - x, brush->width - brush_x );
1011 memcpy( start + x - rc->left, start_xor + brush_x, len * 2 );
1012 brush_x = 0;
1015 start_xor += brush->stride / 2;
1016 offset.y++;
1017 if(offset.y == brush->height)
1019 start_xor = bits->xor;
1020 offset.y = 0;
1027 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1028 const dib_info *brush, const rop_mask_bits *bits)
1030 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1031 int x, y, i, len, brush_x;
1032 POINT offset;
1034 for(i = 0; i < num; i++, rc++)
1036 offset = calc_brush_offset(rc, brush, origin);
1038 start = get_pixel_ptr_8(dib, rc->left, rc->top);
1039 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1041 if (bits->and)
1043 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1044 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1046 and_ptr = start_and + offset.x;
1047 xor_ptr = start_xor + offset.x;
1049 for(x = rc->left, ptr = start; x < rc->right; x++)
1051 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1052 if(and_ptr == start_and + brush->width)
1054 and_ptr = start_and;
1055 xor_ptr = start_xor;
1059 offset.y++;
1060 if(offset.y == brush->height)
1062 start_and = bits->and;
1063 start_xor = bits->xor;
1064 offset.y = 0;
1066 else
1068 start_and += brush->stride;
1069 start_xor += brush->stride;
1073 else
1075 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1077 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1079 len = min( rc->right - x, brush->width - brush_x );
1080 memcpy( start + x - rc->left, start_xor + brush_x, len );
1081 brush_x = 0;
1084 start_xor += brush->stride;
1085 offset.y++;
1086 if(offset.y == brush->height)
1088 start_xor = bits->xor;
1089 offset.y = 0;
1096 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1097 const dib_info *brush, const rop_mask_bits *bits)
1099 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1100 int x, y, i, left, right;
1101 POINT offset;
1103 for(i = 0; i < num; i++, rc++)
1105 offset = calc_brush_offset(rc, brush, origin);
1106 left = dib->rect.left + rc->left;
1107 right = dib->rect.left + rc->right;
1109 start = get_pixel_ptr_4(dib, rc->left, rc->top);
1110 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1112 if (bits->and)
1114 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1115 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1117 INT brush_x = offset.x;
1118 BYTE byte_and, byte_xor;
1120 and_ptr = start_and + brush_x / 2;
1121 xor_ptr = start_xor + brush_x / 2;
1123 for(x = left, ptr = start; x < right; x++)
1125 /* FIXME: Two pixels at a time */
1126 if(x & 1) /* lower dst nibble */
1128 if(brush_x & 1) /* lower pat nibble */
1130 byte_and = *and_ptr++ | 0xf0;
1131 byte_xor = *xor_ptr++ & 0x0f;
1133 else /* upper pat nibble */
1135 byte_and = (*and_ptr >> 4) | 0xf0;
1136 byte_xor = (*xor_ptr >> 4) & 0x0f;
1139 else /* upper dst nibble */
1141 if(brush_x & 1) /* lower pat nibble */
1143 byte_and = (*and_ptr++ << 4) | 0x0f;
1144 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1146 else /* upper pat nibble */
1148 byte_and = *and_ptr | 0x0f;
1149 byte_xor = *xor_ptr & 0xf0;
1152 do_rop_8(ptr, byte_and, byte_xor);
1154 if(x & 1) ptr++;
1156 if(++brush_x == brush->width)
1158 brush_x = 0;
1159 and_ptr = start_and;
1160 xor_ptr = start_xor;
1164 offset.y++;
1165 if(offset.y == brush->height)
1167 start_and = bits->and;
1168 start_xor = bits->xor;
1169 offset.y = 0;
1171 else
1173 start_and += brush->stride;
1174 start_xor += brush->stride;
1178 else
1180 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1182 INT brush_x = offset.x;
1183 BYTE byte_xor;
1185 xor_ptr = start_xor + brush_x / 2;
1187 for(x = left, ptr = start; x < right; x++)
1189 /* FIXME: Two pixels at a time */
1190 if(x & 1) /* lower dst nibble */
1192 if(brush_x & 1) /* lower pat nibble */
1193 byte_xor = *xor_ptr++ & 0x0f;
1194 else /* upper pat nibble */
1195 byte_xor = (*xor_ptr >> 4) & 0x0f;
1196 do_rop_8(ptr, 0xf0, byte_xor);
1198 else /* upper dst nibble */
1200 if(brush_x & 1) /* lower pat nibble */
1201 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1202 else /* upper pat nibble */
1203 byte_xor = *xor_ptr & 0xf0;
1204 do_rop_8(ptr, 0x0f, byte_xor);
1207 if(x & 1) ptr++;
1209 if(++brush_x == brush->width)
1211 brush_x = 0;
1212 xor_ptr = start_xor;
1216 start_xor += brush->stride;
1217 offset.y++;
1218 if(offset.y == brush->height)
1220 start_xor = bits->xor;
1221 offset.y = 0;
1228 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1229 const dib_info *brush, const rop_mask_bits *bits)
1231 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1232 int x, y, i, left, right;
1233 POINT offset;
1235 for(i = 0; i < num; i++, rc++)
1237 offset = calc_brush_offset(rc, brush, origin);
1238 left = dib->rect.left + rc->left;
1239 right = dib->rect.left + rc->right;
1241 start = get_pixel_ptr_1(dib, rc->left, rc->top);
1242 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1244 if (bits->and)
1246 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1247 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1249 INT brush_x = offset.x;
1250 BYTE byte_and, byte_xor;
1252 and_ptr = start_and + brush_x / 8;
1253 xor_ptr = start_xor + brush_x / 8;
1255 for(x = left, ptr = start; x < right; x++)
1257 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1258 byte_and |= ~pixel_masks_1[x % 8];
1259 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1260 byte_xor &= pixel_masks_1[x % 8];
1262 do_rop_8(ptr, byte_and, byte_xor);
1264 if((x & 7) == 7) ptr++;
1266 if((brush_x & 7) == 7)
1268 and_ptr++;
1269 xor_ptr++;
1272 if(++brush_x == brush->width)
1274 brush_x = 0;
1275 and_ptr = start_and;
1276 xor_ptr = start_xor;
1280 offset.y++;
1281 if(offset.y == brush->height)
1283 start_and = bits->and;
1284 start_xor = bits->xor;
1285 offset.y = 0;
1287 else
1289 start_and += brush->stride;
1290 start_xor += brush->stride;
1294 else
1296 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1298 INT brush_x = offset.x;
1300 xor_ptr = start_xor + brush_x / 8;
1302 for(x = left, ptr = start; x < right; x++)
1304 BYTE byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1305 byte_xor &= pixel_masks_1[x % 8];
1307 do_rop_8(ptr, ~pixel_masks_1[x % 8], byte_xor);
1309 if((x & 7) == 7) ptr++;
1310 if((brush_x & 7) == 7) xor_ptr++;
1312 if(++brush_x == brush->width)
1314 brush_x = 0;
1315 xor_ptr = start_xor;
1319 start_xor += brush->stride;
1320 offset.y++;
1321 if(offset.y == brush->height)
1323 start_xor = bits->xor;
1324 offset.y = 0;
1331 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1332 const dib_info *brush, const rop_mask_bits *bits)
1334 return;
1337 static inline void copy_rect_bits_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1338 int dst_stride, int src_stride, int rop2 )
1340 const DWORD *src;
1341 DWORD *dst;
1342 int x, y;
1344 #define LOOP( op ) \
1345 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1346 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src++, dst++) \
1349 switch (rop2)
1351 ROPS_WITHOUT_COPY( dst[0], src[0] )
1353 #undef LOOP
1356 static inline void copy_rect_bits_rev_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1357 int dst_stride, int src_stride, int rop2 )
1359 const DWORD *src;
1360 DWORD *dst;
1361 int x, y;
1363 src_start += size->cx - 1;
1364 dst_start += size->cx - 1;
1366 #define LOOP( op ) \
1367 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1368 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src--, dst--) \
1371 switch (rop2)
1373 ROPS_WITHOUT_COPY( dst[0], src[0] )
1375 #undef LOOP
1378 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1379 const dib_info *src, const POINT *origin, int rop2, int overlap)
1381 DWORD *dst_start, *src_start;
1382 int y, dst_stride, src_stride;
1383 SIZE size;
1385 if (overlap & OVERLAP_BELOW)
1387 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1388 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1389 dst_stride = -dst->stride / 4;
1390 src_stride = -src->stride / 4;
1392 else
1394 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1395 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1396 dst_stride = dst->stride / 4;
1397 src_stride = src->stride / 4;
1400 if (rop2 == R2_COPYPEN)
1402 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1403 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1404 return;
1407 size.cx = rc->right - rc->left;
1408 size.cy = rc->bottom - rc->top;
1410 if (overlap & OVERLAP_RIGHT)
1411 copy_rect_bits_rev_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1412 else
1413 copy_rect_bits_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1416 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1417 const dib_info *src, const POINT *origin, int rop2, int overlap)
1419 BYTE *dst_start, *src_start;
1420 int y, dst_stride, src_stride;
1421 struct rop_codes codes;
1423 if (overlap & OVERLAP_BELOW)
1425 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1426 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1427 dst_stride = -dst->stride;
1428 src_stride = -src->stride;
1430 else
1432 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1433 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1434 dst_stride = dst->stride;
1435 src_stride = src->stride;
1438 if (rop2 == R2_COPYPEN)
1440 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1441 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1442 return;
1445 get_rop_codes( rop2, &codes );
1446 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1448 if (overlap & OVERLAP_RIGHT)
1449 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1450 else
1451 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1455 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1456 const dib_info *src, const POINT *origin, int rop2, int overlap)
1458 WORD *dst_start, *src_start;
1459 int y, dst_stride, src_stride;
1460 struct rop_codes codes;
1462 if (overlap & OVERLAP_BELOW)
1464 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1465 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1466 dst_stride = -dst->stride / 2;
1467 src_stride = -src->stride / 2;
1469 else
1471 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1472 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1473 dst_stride = dst->stride / 2;
1474 src_stride = src->stride / 2;
1477 if (rop2 == R2_COPYPEN)
1479 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1480 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1481 return;
1484 get_rop_codes( rop2, &codes );
1485 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1487 if (overlap & OVERLAP_RIGHT)
1488 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1489 else
1490 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1494 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1495 const dib_info *src, const POINT *origin, int rop2, int overlap)
1497 BYTE *dst_start, *src_start;
1498 int y, dst_stride, src_stride;
1499 struct rop_codes codes;
1501 if (overlap & OVERLAP_BELOW)
1503 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1504 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1505 dst_stride = -dst->stride;
1506 src_stride = -src->stride;
1508 else
1510 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1511 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1512 dst_stride = dst->stride;
1513 src_stride = src->stride;
1516 if (rop2 == R2_COPYPEN)
1518 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1519 memmove( dst_start, src_start, (rc->right - rc->left) );
1520 return;
1523 get_rop_codes( rop2, &codes );
1524 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1526 if (overlap & OVERLAP_RIGHT)
1527 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1528 else
1529 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1533 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1534 const dib_info *src, const POINT *origin, int rop2, int overlap)
1536 BYTE *dst_start, *src_start;
1537 int y, dst_stride, src_stride;
1538 struct rop_codes codes;
1539 int left = dst->rect.left + rc->left;
1540 int right = dst->rect.left + rc->right;
1541 int org_x = src->rect.left + origin->x;
1543 if (overlap & OVERLAP_BELOW)
1545 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1546 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1547 dst_stride = -dst->stride;
1548 src_stride = -src->stride;
1550 else
1552 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1553 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1554 dst_stride = dst->stride;
1555 src_stride = src->stride;
1558 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1560 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1561 memmove( dst_start, src_start, (right - left) / 2 );
1562 return;
1565 get_rop_codes( rop2, &codes );
1566 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1568 if (overlap & OVERLAP_RIGHT)
1569 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1570 else
1571 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1575 static inline void copy_rect_bits_partial_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1576 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1578 const BYTE *src;
1579 BYTE *dst, src_val, mask;
1580 int dst_end = dst_x + size->cx, y;
1581 int off = (src_x & 7) - (dst_x & 7);
1582 struct rop_codes codes;
1584 get_rop_codes( rop2, &codes );
1586 src_start += src_x / 8;
1587 dst_start += dst_x / 8;
1589 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1591 dst = dst_start;
1592 src = src_start;
1593 if (off == 0)
1594 src_val = src[0];
1595 else if (off > 0)
1597 src_val = src[0] << off;
1598 if ((dst_end & 7) + off > 8)
1599 src_val |= (src[1] >> (8 - off));
1601 else
1602 src_val = src[0] >> -off;
1604 mask = edge_masks_1[dst_x & 7];
1605 if (dst_end & 7)
1606 mask &= ~edge_masks_1[dst_end & 7];
1607 do_rop_codes_mask_8( dst, src_val, &codes, mask );
1611 static inline void copy_rect_bits_align_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1612 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1614 const BYTE *src;
1615 BYTE *dst, mask;
1616 int y, i, full_bytes, dst_end = dst_x + size->cx;
1617 struct rop_codes codes;
1619 get_rop_codes( rop2, &codes );
1621 src_start += src_x / 8;
1622 dst_start += dst_x / 8;
1623 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1625 switch( rop2 )
1627 case R2_COPYPEN:
1628 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1630 dst = dst_start;
1631 src = src_start;
1632 if (dst_x & 7)
1634 mask = edge_masks_1[dst_x & 7];
1635 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1636 src++;
1637 dst++;
1639 memmove( dst, src, full_bytes );
1640 src += full_bytes;
1641 dst += full_bytes;
1642 if (dst_end & 7)
1644 mask = ~edge_masks_1[dst_end & 7];
1645 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1648 break;
1650 #define LOOP( op ) \
1651 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1653 dst = dst_start; \
1654 src = src_start; \
1655 if (dst_x & 7) \
1657 mask = edge_masks_1[dst_x & 7]; \
1658 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1659 src++; \
1660 dst++; \
1662 for (i = 0; i < full_bytes; i++, src++, dst++) \
1663 op; \
1664 if (dst_end & 7) \
1666 mask = ~edge_masks_1[dst_end & 7]; \
1667 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1671 ROPS_WITHOUT_COPY( dst[0], src[0] );
1673 #undef LOOP
1676 static inline void copy_rect_bits_shl_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1677 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1679 const BYTE *src;
1680 BYTE *dst, mask, src_val;
1681 int y, i, full_bytes, dst_end = dst_x + size->cx;
1682 int off = (src_x & 7) - (dst_x & 7);
1683 struct rop_codes codes;
1685 get_rop_codes( rop2, &codes );
1687 src_start += src_x / 8;
1688 dst_start += dst_x / 8;
1689 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1691 #define LOOP( op ) \
1692 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1694 dst = dst_start; \
1695 src = src_start; \
1696 if (dst_x & 7) \
1698 src_val = (src[0] << off) | (src[1] >> (8 - off)); \
1699 mask = edge_masks_1[dst_x & 7]; \
1700 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1701 src++; \
1702 dst++; \
1704 for (i = 0; i < full_bytes; i++, src++, dst++) \
1705 op; \
1706 if (dst_end & 7) \
1708 src_val = src[0] << off; \
1709 if ((dst_end & 7) + off > 8) \
1710 src_val |= (src[1] >> (8 - off)); \
1711 mask = ~edge_masks_1[dst_end & 7]; \
1712 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1716 switch( rop2 )
1718 ROPS_ALL( dst[0], ((src[0] << off) | (src[1] >> (8 - off))) );
1720 #undef LOOP
1723 static inline void copy_rect_bits_shr_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1724 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1726 const BYTE *src;
1727 BYTE *dst, mask, src_val, last_src;
1728 int y, i, full_bytes, dst_end = dst_x + size->cx;
1729 int off = (src_x & 7) - (dst_x & 7);
1730 struct rop_codes codes;
1732 get_rop_codes( rop2, &codes );
1734 src_start += src_x / 8;
1735 dst_start += dst_x / 8;
1736 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1738 #define LOOP( op ) \
1739 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1741 dst = dst_start; \
1742 src = src_start; \
1743 last_src = 0; \
1744 if (dst_x & 7) \
1746 last_src = src[0]; \
1747 mask = edge_masks_1[dst_x & 7]; \
1748 do_rop_codes_mask_8( dst, src[0] >> -off, &codes, mask ); \
1749 src++; \
1750 dst++; \
1752 for (i = 0; i < full_bytes; i++, src++, dst++) \
1754 src_val = (last_src << (8 + off)) | (src[0] >> -off); \
1755 last_src = src[0]; \
1756 op; \
1758 if (dst_end & 7) \
1760 src_val = last_src << (8 + off); \
1761 if ((dst_end & 7) + off > 0) \
1762 src_val |= (src[0] >> -off); \
1763 mask = ~edge_masks_1[dst_end & 7]; \
1764 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1768 switch( rop2 )
1770 ROPS_ALL( dst[0], src_val )
1772 #undef LOOP
1775 static inline void copy_rect_bits_rev_align_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1776 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1778 const BYTE *src;
1779 BYTE *dst, mask;
1780 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1781 struct rop_codes codes;
1783 get_rop_codes( rop2, &codes );
1785 src_start += (src_end - 1) / 8;
1786 dst_start += (dst_end - 1) / 8;
1787 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1789 switch( rop2 )
1791 case R2_COPYPEN:
1792 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1794 dst = dst_start;
1795 src = src_start;
1796 if (dst_end & 7)
1798 mask = ~edge_masks_1[dst_end & 7];
1799 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1800 src--;
1801 dst--;
1803 memmove( dst, src, full_bytes );
1804 src -= full_bytes;
1805 dst -= full_bytes;
1806 if (dst_x & 7)
1808 mask = edge_masks_1[dst_x & 7];
1809 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1812 break;
1814 #define LOOP( op ) \
1815 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1817 dst = dst_start; \
1818 src = src_start; \
1819 if (dst_end & 7) \
1821 mask = ~edge_masks_1[dst_end & 7]; \
1822 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1823 src--; \
1824 dst--; \
1826 for (i = 0; i < full_bytes; i++, src--, dst--) \
1827 op; \
1828 if (dst_x & 7) \
1830 mask = edge_masks_1[dst_x & 7]; \
1831 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1835 ROPS_WITHOUT_COPY( dst[0], src[0] );
1837 #undef LOOP
1840 static inline void copy_rect_bits_rev_shl_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1841 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1843 const BYTE *src;
1844 BYTE *dst, mask, src_val, last_src;
1845 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1846 int off = ((src_end - 1) & 7) - ((dst_end - 1) & 7);
1847 struct rop_codes codes;
1849 get_rop_codes( rop2, &codes );
1851 src_start += (src_end - 1) / 8;
1852 dst_start += (dst_end - 1) / 8;
1853 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1855 #define LOOP( op ) \
1856 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1858 dst = dst_start; \
1859 src = src_start; \
1860 last_src = 0; \
1861 if (dst_end & 7) \
1863 last_src = src[0]; \
1864 mask = ~edge_masks_1[dst_end & 7]; \
1865 do_rop_codes_mask_8( dst, src[0] << off, &codes, mask ); \
1866 src--; \
1867 dst--; \
1869 for (i = 0; i < full_bytes; i++, src--, dst--) \
1871 src_val = (src[0] << off) | (last_src >> (8 - off)); \
1872 last_src = src[0]; \
1873 op; \
1875 if (dst_x & 7) \
1877 src_val = last_src >> (8 - off); \
1878 if ((dst_x & 7) + off < 8) \
1879 src_val |= (src[0] << off); \
1880 mask = edge_masks_1[dst_x & 7]; \
1881 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1885 switch( rop2 )
1887 ROPS_ALL( dst[0], src_val );
1889 #undef LOOP
1892 static inline void copy_rect_bits_rev_shr_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1893 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1895 const BYTE *src;
1896 BYTE *dst, mask, src_val;
1897 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1898 int off = ((src_end - 1) & 7) - ((dst_end - 1) & 7);
1899 struct rop_codes codes;
1901 get_rop_codes( rop2, &codes );
1903 src_start += (src_end - 1) / 8;
1904 dst_start += (dst_end - 1) / 8;
1905 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1907 #define LOOP( op ) \
1908 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1910 dst = dst_start; \
1911 src = src_start; \
1912 if (dst_end & 7) \
1914 mask = edge_masks_1[dst_x & 7]; \
1915 do_rop_codes_mask_8( dst, (src[-1] << (8 + off)) | (src[0] >> -off), &codes, mask ); \
1916 src--; \
1917 dst--; \
1919 for (i = 0; i < full_bytes; i++, src--, dst--) \
1920 op; \
1921 if (dst_x & 7) \
1923 src_val = src[0] >> -off; \
1924 if ((dst_x & 7) + off < 0) \
1925 src_val |= (src[-1] << (8 + off)); \
1926 mask = edge_masks_1[dst_x & 7]; \
1927 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1931 switch( rop2 )
1933 ROPS_ALL( dst[0], (src[-1] << (8 + off)) | (src[0] >> -off) );
1935 #undef LOOP
1938 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1939 const dib_info *src, const POINT *origin, int rop2, int overlap)
1941 BYTE *dst_start, *src_start;
1942 int y, dst_stride, src_stride;
1943 int left = dst->rect.left + rc->left;
1944 int right = dst->rect.left + rc->right;
1945 int org_x = src->rect.left + origin->x;
1946 SIZE size;
1948 if (overlap & OVERLAP_BELOW)
1950 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1951 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1952 dst_stride = -dst->stride;
1953 src_stride = -src->stride;
1955 else
1957 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1958 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1959 dst_stride = dst->stride;
1960 src_stride = src->stride;
1963 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1965 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1966 memmove( dst_start, src_start, (right - left) / 8 );
1967 return;
1970 size.cx = right - left;
1971 size.cy = rc->bottom - rc->top;
1973 /* Special case starting and finishing in same byte, neither on byte boundary */
1974 if ((left & 7) && (right & 7) && (left & ~7) == (right & ~7))
1975 copy_rect_bits_partial_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1976 else if (overlap & OVERLAP_RIGHT)
1978 int off = ((org_x + right - left - 1) & 7) - ((right - 1) & 7);
1980 if (off == 0)
1981 copy_rect_bits_rev_align_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1982 else if (off > 0)
1983 copy_rect_bits_rev_shl_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1984 else
1985 copy_rect_bits_rev_shr_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1987 else
1989 int off = (org_x & 7) - (left & 7);
1991 if (off == 0)
1992 copy_rect_bits_align_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1993 else if (off > 0)
1994 copy_rect_bits_shl_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1995 else
1996 copy_rect_bits_shr_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
2000 static void copy_rect_null(const dib_info *dst, const RECT *rc,
2001 const dib_info *src, const POINT *origin, int rop2, int overlap)
2003 return;
2006 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
2008 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
2009 return *ptr;
2012 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
2014 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
2015 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
2018 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
2020 WORD *ptr = get_pixel_ptr_16( dib, x, y );
2021 return *ptr;
2024 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
2026 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
2027 return *ptr;
2030 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
2032 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
2034 if ((dib->rect.left + x) & 1)
2035 return *ptr & 0x0f;
2036 else
2037 return (*ptr >> 4) & 0x0f;
2040 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
2042 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
2043 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
2046 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
2048 return 0;
2051 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
2053 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
2056 static const DWORD field_masks[33] =
2058 0x00, /* should never happen */
2059 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
2060 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2061 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2062 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2065 static inline DWORD get_field(DWORD field, int shift, int len)
2067 shift = shift - (8 - len);
2068 if (shift < 0)
2069 field <<= -shift;
2070 else
2071 field >>= shift;
2072 field &= field_masks[len];
2073 field |= field >> len;
2074 return field;
2077 static inline DWORD put_field(DWORD field, int shift, int len)
2079 shift = shift - (8 - len);
2080 field &= field_masks[len];
2081 if (shift < 0)
2082 field >>= -shift;
2083 else
2084 field <<= shift;
2085 return field;
2088 static DWORD rgb_to_pixel_masks(const dib_info *dib, DWORD r, DWORD g, DWORD b)
2090 return put_field(r, dib->red_shift, dib->red_len) |
2091 put_field(g, dib->green_shift, dib->green_len) |
2092 put_field(b, dib->blue_shift, dib->blue_len);
2095 static DWORD rgbquad_to_pixel_masks(const dib_info *dib, RGBQUAD rgb)
2097 return rgb_to_pixel_masks(dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2100 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
2102 return rgb_to_pixel_masks(dib, GetRValue(colour), GetGValue(colour), GetBValue(colour));
2105 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
2107 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
2110 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
2112 const RGBQUAD *color_table = get_dib_color_table( dib );
2113 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
2114 int i, best_index = 0;
2115 DWORD diff, best_diff = 0xffffffff;
2117 for(i = 0; i < size; i++)
2119 const RGBQUAD *cur = color_table + i;
2120 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
2121 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
2122 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
2124 if(diff == 0)
2126 best_index = i;
2127 break;
2130 if(diff < best_diff)
2132 best_diff = diff;
2133 best_index = i;
2136 return best_index;
2139 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y,
2140 DWORD src_pixel, DWORD bg_pixel, BYTE r, BYTE g, BYTE b)
2142 DWORD ret;
2144 if (dither)
2145 ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255;
2146 else if (dib->color_table_size == 1)
2147 ret = (src_pixel == bg_pixel);
2148 else
2149 ret = rgb_to_pixel_colortable( dib, r, g, b );
2151 return ret ? 0xff : 0;
2154 static DWORD rgbquad_to_pixel_colortable(const dib_info *dib, RGBQUAD rgb)
2156 return rgb_to_pixel_colortable( dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue );
2159 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
2161 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
2164 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
2166 return 0;
2169 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
2171 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
2174 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
2176 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
2177 get_field( pixel, dib->green_shift, dib->green_len ),
2178 get_field( pixel, dib->blue_shift, dib->blue_len ) );
2181 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
2183 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
2184 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
2185 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
2188 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
2190 const RGBQUAD *color_table = get_dib_color_table( dib );
2192 if (!dib->color_table || pixel < dib->color_table_size)
2194 RGBQUAD quad = color_table[pixel];
2195 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
2197 return 0;
2200 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
2202 return 0;
2205 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
2207 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
2209 return d1->red_mask == d2->red_mask &&
2210 d1->green_mask == d2->green_mask &&
2211 d1->blue_mask == d2->blue_mask;
2214 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2216 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2217 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2219 switch(src->bit_count)
2221 case 32:
2223 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2224 if(src->funcs == &funcs_8888)
2226 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2227 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2228 else
2230 for(y = src_rect->top; y < src_rect->bottom; y++)
2232 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2233 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2234 dst_start += dst->stride / 4;
2235 src_start += src->stride / 4;
2239 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
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 src_val = *src_pixel++;
2248 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
2249 (((src_val >> src->green_shift) & 0xff) << 8) |
2250 ((src_val >> src->blue_shift) & 0xff);
2252 if(pad_size) memset(dst_pixel, 0, pad_size);
2253 dst_start += dst->stride / 4;
2254 src_start += src->stride / 4;
2257 else
2259 for(y = src_rect->top; y < src_rect->bottom; y++)
2261 dst_pixel = dst_start;
2262 src_pixel = src_start;
2263 for(x = src_rect->left; x < src_rect->right; x++)
2265 src_val = *src_pixel++;
2266 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2267 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2268 get_field( src_val, src->blue_shift, src->blue_len ));
2270 if(pad_size) memset(dst_pixel, 0, pad_size);
2271 dst_start += dst->stride / 4;
2272 src_start += src->stride / 4;
2275 break;
2278 case 24:
2280 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2282 for(y = src_rect->top; y < src_rect->bottom; y++)
2284 dst_pixel = dst_start;
2285 src_pixel = src_start;
2286 for(x = src_rect->left; x < src_rect->right; x++)
2288 RGBQUAD rgb;
2289 rgb.rgbBlue = *src_pixel++;
2290 rgb.rgbGreen = *src_pixel++;
2291 rgb.rgbRed = *src_pixel++;
2293 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
2295 if(pad_size) memset(dst_pixel, 0, pad_size);
2296 dst_start += dst->stride / 4;
2297 src_start += src->stride;
2299 break;
2302 case 16:
2304 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2305 if(src->funcs == &funcs_555)
2307 for(y = src_rect->top; y < src_rect->bottom; y++)
2309 dst_pixel = dst_start;
2310 src_pixel = src_start;
2311 for(x = src_rect->left; x < src_rect->right; x++)
2313 src_val = *src_pixel++;
2314 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
2315 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
2316 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
2318 if(pad_size) memset(dst_pixel, 0, pad_size);
2319 dst_start += dst->stride / 4;
2320 src_start += src->stride / 2;
2323 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2325 for(y = src_rect->top; y < src_rect->bottom; y++)
2327 dst_pixel = dst_start;
2328 src_pixel = src_start;
2329 for(x = src_rect->left; x < src_rect->right; x++)
2331 src_val = *src_pixel++;
2332 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2333 (((src_val >> src->red_shift) << 14) & 0x070000) |
2334 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2335 (((src_val >> src->green_shift) << 6) & 0x000700) |
2336 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2337 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2339 if(pad_size) memset(dst_pixel, 0, pad_size);
2340 dst_start += dst->stride / 4;
2341 src_start += src->stride / 2;
2344 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2346 for(y = src_rect->top; y < src_rect->bottom; y++)
2348 dst_pixel = dst_start;
2349 src_pixel = src_start;
2350 for(x = src_rect->left; x < src_rect->right; x++)
2352 src_val = *src_pixel++;
2353 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2354 (((src_val >> src->red_shift) << 14) & 0x070000) |
2355 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2356 (((src_val >> src->green_shift) << 4) & 0x000300) |
2357 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2358 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2360 if(pad_size) memset(dst_pixel, 0, pad_size);
2361 dst_start += dst->stride / 4;
2362 src_start += src->stride / 2;
2365 else
2367 for(y = src_rect->top; y < src_rect->bottom; y++)
2369 dst_pixel = dst_start;
2370 src_pixel = src_start;
2371 for(x = src_rect->left; x < src_rect->right; x++)
2373 src_val = *src_pixel++;
2374 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2375 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2376 get_field( src_val, src->blue_shift, src->blue_len ));
2378 if(pad_size) memset(dst_pixel, 0, pad_size);
2379 dst_start += dst->stride / 4;
2380 src_start += src->stride / 2;
2383 break;
2386 case 8:
2388 const RGBQUAD *color_table = get_dib_color_table( src );
2389 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2390 DWORD dst_colors[256], i;
2392 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2393 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2394 color_table[i].rgbBlue;
2396 for(y = src_rect->top; y < src_rect->bottom; y++)
2398 dst_pixel = dst_start;
2399 src_pixel = src_start;
2400 for(x = src_rect->left; x < src_rect->right; x++)
2401 *dst_pixel++ = dst_colors[*src_pixel++];
2403 if(pad_size) memset(dst_pixel, 0, pad_size);
2404 dst_start += dst->stride / 4;
2405 src_start += src->stride;
2407 break;
2410 case 4:
2412 const RGBQUAD *color_table = get_dib_color_table( src );
2413 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2414 DWORD dst_colors[16], i;
2416 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2417 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2418 color_table[i].rgbBlue;
2420 for(y = src_rect->top; y < src_rect->bottom; y++)
2422 int pos = (src->rect.left + src_rect->left) & 1;
2423 src_pixel = src_start;
2424 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2426 if (pos & 1)
2427 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2428 else
2429 dst_start[x] = dst_colors[*src_pixel >> 4];
2431 if(pad_size) memset(dst_start + x, 0, pad_size);
2432 dst_start += dst->stride / 4;
2433 src_start += src->stride;
2435 break;
2438 case 1:
2440 const RGBQUAD *color_table = get_dib_color_table( src );
2441 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2442 DWORD dst_colors[2], i;
2444 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2445 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2446 color_table[i].rgbBlue;
2448 for(y = src_rect->top; y < src_rect->bottom; y++)
2450 int pos = (src->rect.left + src_rect->left) & 7;
2451 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2453 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2454 dst_start[x] = dst_colors[src_val];
2456 if(pad_size) memset(dst_start + x, 0, pad_size);
2457 dst_start += dst->stride / 4;
2458 src_start += src->stride;
2460 break;
2465 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2467 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2468 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2470 switch(src->bit_count)
2472 case 32:
2474 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2476 if(src->funcs == &funcs_8888)
2478 for(y = src_rect->top; y < src_rect->bottom; y++)
2480 dst_pixel = dst_start;
2481 src_pixel = src_start;
2482 for(x = src_rect->left; x < src_rect->right; x++)
2484 src_val = *src_pixel++;
2485 *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val);
2487 if(pad_size) memset(dst_pixel, 0, pad_size);
2488 dst_start += dst->stride / 4;
2489 src_start += src->stride / 4;
2492 else if(bit_fields_match(src, dst))
2494 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2495 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2496 else
2498 for(y = src_rect->top; y < src_rect->bottom; y++)
2500 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2501 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2502 dst_start += dst->stride / 4;
2503 src_start += src->stride / 4;
2507 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
2508 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
2510 for(y = src_rect->top; y < src_rect->bottom; y++)
2512 dst_pixel = dst_start;
2513 src_pixel = src_start;
2514 for(x = src_rect->left; x < src_rect->right; x++)
2516 src_val = *src_pixel++;
2517 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
2518 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
2519 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
2521 if(pad_size) memset(dst_pixel, 0, pad_size);
2522 dst_start += dst->stride / 4;
2523 src_start += src->stride / 4;
2526 else
2528 for(y = src_rect->top; y < src_rect->bottom; y++)
2530 dst_pixel = dst_start;
2531 src_pixel = src_start;
2532 for(x = src_rect->left; x < src_rect->right; x++)
2534 src_val = *src_pixel++;
2535 *dst_pixel++ = rgb_to_pixel_masks(dst,
2536 get_field(src_val, src->red_shift, src->red_len),
2537 get_field(src_val, src->green_shift, src->green_len),
2538 get_field(src_val, src->blue_shift, src->blue_len));
2540 if(pad_size) memset(dst_pixel, 0, pad_size);
2541 dst_start += dst->stride / 4;
2542 src_start += src->stride / 4;
2545 break;
2548 case 24:
2550 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2552 for(y = src_rect->top; y < src_rect->bottom; y++)
2554 dst_pixel = dst_start;
2555 src_pixel = src_start;
2556 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2557 *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2558 if(pad_size) memset(dst_pixel, 0, pad_size);
2559 dst_start += dst->stride / 4;
2560 src_start += src->stride;
2562 break;
2565 case 16:
2567 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2568 if(src->funcs == &funcs_555)
2570 for(y = src_rect->top; y < src_rect->bottom; y++)
2572 dst_pixel = dst_start;
2573 src_pixel = src_start;
2574 for(x = src_rect->left; x < src_rect->right; x++)
2576 src_val = *src_pixel++;
2577 *dst_pixel++ = rgb_to_pixel_masks(dst,
2578 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2579 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2580 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
2582 if(pad_size) memset(dst_pixel, 0, pad_size);
2583 dst_start += dst->stride / 4;
2584 src_start += src->stride / 2;
2587 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2589 for(y = src_rect->top; y < src_rect->bottom; y++)
2591 dst_pixel = dst_start;
2592 src_pixel = src_start;
2593 for(x = src_rect->left; x < src_rect->right; x++)
2595 src_val = *src_pixel++;
2596 *dst_pixel++ = rgb_to_pixel_masks(dst,
2597 (((src_val >> src->red_shift) << 3) & 0xf8) |
2598 (((src_val >> src->red_shift) >> 2) & 0x07),
2599 (((src_val >> src->green_shift) << 3) & 0xf8) |
2600 (((src_val >> src->green_shift) >> 2) & 0x07),
2601 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2602 (((src_val >> src->blue_shift) >> 2) & 0x07));
2604 if(pad_size) memset(dst_pixel, 0, pad_size);
2605 dst_start += dst->stride / 4;
2606 src_start += src->stride / 2;
2609 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2611 for(y = src_rect->top; y < src_rect->bottom; y++)
2613 dst_pixel = dst_start;
2614 src_pixel = src_start;
2615 for(x = src_rect->left; x < src_rect->right; x++)
2617 src_val = *src_pixel++;
2618 *dst_pixel++ = rgb_to_pixel_masks(dst,
2619 (((src_val >> src->red_shift) << 3) & 0xf8) |
2620 (((src_val >> src->red_shift) >> 2) & 0x07),
2621 (((src_val >> src->green_shift) << 2) & 0xfc) |
2622 (((src_val >> src->green_shift) >> 4) & 0x03),
2623 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2624 (((src_val >> src->blue_shift) >> 2) & 0x07));
2626 if(pad_size) memset(dst_pixel, 0, pad_size);
2627 dst_start += dst->stride / 4;
2628 src_start += src->stride / 2;
2631 else
2633 for(y = src_rect->top; y < src_rect->bottom; y++)
2635 dst_pixel = dst_start;
2636 src_pixel = src_start;
2637 for(x = src_rect->left; x < src_rect->right; x++)
2639 src_val = *src_pixel++;
2640 *dst_pixel++ = rgb_to_pixel_masks(dst,
2641 get_field(src_val, src->red_shift, src->red_len),
2642 get_field(src_val, src->green_shift, src->green_len),
2643 get_field(src_val, src->blue_shift, src->blue_len));
2645 if(pad_size) memset(dst_pixel, 0, pad_size);
2646 dst_start += dst->stride / 4;
2647 src_start += src->stride / 2;
2650 break;
2653 case 8:
2655 const RGBQUAD *color_table = get_dib_color_table( src );
2656 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2657 DWORD dst_colors[256], i;
2659 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2660 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2662 for(y = src_rect->top; y < src_rect->bottom; y++)
2664 dst_pixel = dst_start;
2665 src_pixel = src_start;
2666 for(x = src_rect->left; x < src_rect->right; x++)
2667 *dst_pixel++ = dst_colors[*src_pixel++];
2669 if(pad_size) memset(dst_pixel, 0, pad_size);
2670 dst_start += dst->stride / 4;
2671 src_start += src->stride;
2673 break;
2676 case 4:
2678 const RGBQUAD *color_table = get_dib_color_table( src );
2679 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2680 DWORD dst_colors[16], i;
2682 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2683 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2685 for(y = src_rect->top; y < src_rect->bottom; y++)
2687 int pos = (src->rect.left + src_rect->left) & 1;
2688 src_pixel = src_start;
2689 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2691 if (pos & 1)
2692 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2693 else
2694 dst_start[x] = dst_colors[*src_pixel >> 4];
2696 if(pad_size) memset(dst_start + x, 0, pad_size);
2697 dst_start += dst->stride / 4;
2698 src_start += src->stride;
2700 break;
2703 case 1:
2705 const RGBQUAD *color_table = get_dib_color_table( src );
2706 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2707 DWORD dst_colors[2], i;
2709 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2710 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2712 for(y = src_rect->top; y < src_rect->bottom; y++)
2714 int pos = (src->rect.left + src_rect->left) & 7;
2715 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2717 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2718 dst_start[x] = dst_colors[src_val];
2720 if(pad_size) memset(dst_start + x, 0, pad_size);
2721 dst_start += dst->stride / 4;
2722 src_start += src->stride;
2724 break;
2729 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2731 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2732 DWORD src_val;
2733 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2735 switch(src->bit_count)
2737 case 32:
2739 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2740 if(src->funcs == &funcs_8888)
2742 for(y = src_rect->top; y < src_rect->bottom; y++)
2744 dst_pixel = dst_start;
2745 src_pixel = src_start;
2746 for(x = src_rect->left; x < src_rect->right; x++)
2748 src_val = *src_pixel++;
2749 *dst_pixel++ = src_val & 0xff;
2750 *dst_pixel++ = (src_val >> 8) & 0xff;
2751 *dst_pixel++ = (src_val >> 16) & 0xff;
2753 if(pad_size) memset(dst_pixel, 0, pad_size);
2754 dst_start += dst->stride;
2755 src_start += src->stride / 4;
2758 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2760 for(y = src_rect->top; y < src_rect->bottom; y++)
2762 dst_pixel = dst_start;
2763 src_pixel = src_start;
2764 for(x = src_rect->left; x < src_rect->right; x++)
2766 src_val = *src_pixel++;
2767 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2768 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2769 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2771 if(pad_size) memset(dst_pixel, 0, pad_size);
2772 dst_start += dst->stride;
2773 src_start += src->stride / 4;
2776 else
2778 for(y = src_rect->top; y < src_rect->bottom; y++)
2780 dst_pixel = dst_start;
2781 src_pixel = src_start;
2782 for(x = src_rect->left; x < src_rect->right; x++)
2784 src_val = *src_pixel++;
2785 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2786 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2787 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2789 if(pad_size) memset(dst_pixel, 0, pad_size);
2790 dst_start += dst->stride;
2791 src_start += src->stride / 4;
2794 break;
2797 case 24:
2799 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2801 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2802 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2803 else
2805 for(y = src_rect->top; y < src_rect->bottom; y++)
2807 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2808 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2809 dst_start += dst->stride;
2810 src_start += src->stride;
2813 break;
2816 case 16:
2818 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2819 if(src->funcs == &funcs_555)
2821 for(y = src_rect->top; y < src_rect->bottom; y++)
2823 dst_pixel = dst_start;
2824 src_pixel = src_start;
2825 for(x = src_rect->left; x < src_rect->right; x++)
2827 src_val = *src_pixel++;
2828 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2829 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2830 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2832 if(pad_size) memset(dst_pixel, 0, pad_size);
2833 dst_start += dst->stride;
2834 src_start += src->stride / 2;
2837 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2839 for(y = src_rect->top; y < src_rect->bottom; y++)
2841 dst_pixel = dst_start;
2842 src_pixel = src_start;
2843 for(x = src_rect->left; x < src_rect->right; x++)
2845 src_val = *src_pixel++;
2846 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2847 (((src_val >> src->blue_shift) >> 2) & 0x07);
2848 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2849 (((src_val >> src->green_shift) >> 2) & 0x07);
2850 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2851 (((src_val >> src->red_shift) >> 2) & 0x07);
2853 if(pad_size) memset(dst_pixel, 0, pad_size);
2854 dst_start += dst->stride;
2855 src_start += src->stride / 2;
2858 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2860 for(y = src_rect->top; y < src_rect->bottom; y++)
2862 dst_pixel = dst_start;
2863 src_pixel = src_start;
2864 for(x = src_rect->left; x < src_rect->right; x++)
2866 src_val = *src_pixel++;
2867 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2868 (((src_val >> src->blue_shift) >> 2) & 0x07);
2869 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2870 (((src_val >> src->green_shift) >> 4) & 0x03);
2871 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2872 (((src_val >> src->red_shift) >> 2) & 0x07);
2874 if(pad_size) memset(dst_pixel, 0, pad_size);
2875 dst_start += dst->stride;
2876 src_start += src->stride / 2;
2879 else
2881 for(y = src_rect->top; y < src_rect->bottom; y++)
2883 dst_pixel = dst_start;
2884 src_pixel = src_start;
2885 for(x = src_rect->left; x < src_rect->right; x++)
2887 src_val = *src_pixel++;
2888 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2889 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2890 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2892 if(pad_size) memset(dst_pixel, 0, pad_size);
2893 dst_start += dst->stride;
2894 src_start += src->stride / 2;
2897 break;
2900 case 8:
2902 const RGBQUAD *color_table = get_dib_color_table( src );
2903 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2904 for(y = src_rect->top; y < src_rect->bottom; y++)
2906 dst_pixel = dst_start;
2907 src_pixel = src_start;
2908 for(x = src_rect->left; x < src_rect->right; x++)
2910 RGBQUAD rgb = color_table[*src_pixel++];
2911 *dst_pixel++ = rgb.rgbBlue;
2912 *dst_pixel++ = rgb.rgbGreen;
2913 *dst_pixel++ = rgb.rgbRed;
2915 if(pad_size) memset(dst_pixel, 0, pad_size);
2916 dst_start += dst->stride;
2917 src_start += src->stride;
2919 break;
2922 case 4:
2924 const RGBQUAD *color_table = get_dib_color_table( src );
2925 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2926 for(y = src_rect->top; y < src_rect->bottom; y++)
2928 int pos = (src->rect.left + src_rect->left) & 1;
2929 src_pixel = src_start;
2930 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2932 RGBQUAD rgb;
2933 if (pos & 1)
2934 rgb = color_table[*src_pixel++ & 0xf];
2935 else
2936 rgb = color_table[*src_pixel >> 4];
2937 dst_start[x * 3] = rgb.rgbBlue;
2938 dst_start[x * 3 + 1] = rgb.rgbGreen;
2939 dst_start[x * 3 + 2] = rgb.rgbRed;
2941 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2942 dst_start += dst->stride;
2943 src_start += src->stride;
2945 break;
2948 case 1:
2950 const RGBQUAD *color_table = get_dib_color_table( src );
2951 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2952 for(y = src_rect->top; y < src_rect->bottom; y++)
2954 int pos = (src->rect.left + src_rect->left) & 7;
2955 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2957 RGBQUAD rgb;
2958 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2959 rgb = color_table[src_val];
2960 dst_start[x * 3] = rgb.rgbBlue;
2961 dst_start[x * 3 + 1] = rgb.rgbGreen;
2962 dst_start[x * 3 + 2] = rgb.rgbRed;
2964 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2965 dst_start += dst->stride;
2966 src_start += src->stride;
2968 break;
2973 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2975 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2976 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2977 DWORD src_val;
2979 switch(src->bit_count)
2981 case 32:
2983 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2985 if(src->funcs == &funcs_8888)
2987 for(y = src_rect->top; y < src_rect->bottom; y++)
2989 dst_pixel = dst_start;
2990 src_pixel = src_start;
2991 for(x = src_rect->left; x < src_rect->right; x++)
2993 src_val = *src_pixel++;
2994 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2995 ((src_val >> 6) & 0x03e0) |
2996 ((src_val >> 3) & 0x001f);
2998 if(pad_size) memset(dst_pixel, 0, pad_size);
2999 dst_start += dst->stride / 2;
3000 src_start += src->stride / 4;
3003 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3005 for(y = src_rect->top; y < src_rect->bottom; y++)
3007 dst_pixel = dst_start;
3008 src_pixel = src_start;
3009 for(x = src_rect->left; x < src_rect->right; x++)
3011 src_val = *src_pixel++;
3012 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
3013 (((src_val >> src->green_shift) << 2) & 0x03e0) |
3014 (((src_val >> src->blue_shift) >> 3) & 0x001f);
3016 if(pad_size) memset(dst_pixel, 0, pad_size);
3017 dst_start += dst->stride / 2;
3018 src_start += src->stride / 4;
3021 else
3023 for(y = src_rect->top; y < src_rect->bottom; y++)
3025 dst_pixel = dst_start;
3026 src_pixel = src_start;
3027 for(x = src_rect->left; x < src_rect->right; x++)
3029 src_val = *src_pixel++;
3030 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
3031 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
3032 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
3034 if(pad_size) memset(dst_pixel, 0, pad_size);
3035 dst_start += dst->stride / 2;
3036 src_start += src->stride / 4;
3039 break;
3042 case 24:
3044 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3046 for(y = src_rect->top; y < src_rect->bottom; y++)
3048 dst_pixel = dst_start;
3049 src_pixel = src_start;
3050 for(x = src_rect->left; x < src_rect->right; x++)
3052 RGBQUAD rgb;
3053 rgb.rgbBlue = *src_pixel++;
3054 rgb.rgbGreen = *src_pixel++;
3055 rgb.rgbRed = *src_pixel++;
3057 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
3058 ((rgb.rgbGreen << 2) & 0x03e0) |
3059 ((rgb.rgbBlue >> 3) & 0x001f);
3061 if(pad_size) memset(dst_pixel, 0, pad_size);
3062 dst_start += dst->stride / 2;
3063 src_start += src->stride;
3065 break;
3068 case 16:
3070 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3071 if(src->funcs == &funcs_555)
3073 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3074 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3075 else
3077 for(y = src_rect->top; y < src_rect->bottom; y++)
3079 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
3080 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3081 dst_start += dst->stride / 2;
3082 src_start += src->stride / 2;
3086 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3088 for(y = src_rect->top; y < src_rect->bottom; y++)
3090 dst_pixel = dst_start;
3091 src_pixel = src_start;
3092 for(x = src_rect->left; x < src_rect->right; x++)
3094 src_val = *src_pixel++;
3095 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
3096 (((src_val >> src->green_shift) << 5) & 0x03e0) |
3097 ( (src_val >> src->blue_shift) & 0x001f);
3099 if(pad_size) memset(dst_pixel, 0, pad_size);
3100 dst_start += dst->stride / 2;
3101 src_start += src->stride / 2;
3104 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
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++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
3114 (((src_val >> src->green_shift) << 4) & 0x03e0) |
3115 ( (src_val >> src->blue_shift) & 0x001f);
3117 if(pad_size) memset(dst_pixel, 0, pad_size);
3118 dst_start += dst->stride / 2;
3119 src_start += src->stride / 2;
3122 else
3124 for(y = src_rect->top; y < src_rect->bottom; y++)
3126 dst_pixel = dst_start;
3127 src_pixel = src_start;
3128 for(x = src_rect->left; x < src_rect->right; x++)
3130 src_val = *src_pixel++;
3131 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
3132 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
3133 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
3135 if(pad_size) memset(dst_pixel, 0, pad_size);
3136 dst_start += dst->stride / 2;
3137 src_start += src->stride / 2;
3140 break;
3143 case 8:
3145 const RGBQUAD *color_table = get_dib_color_table( src );
3146 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3147 WORD dst_colors[256];
3148 int i;
3150 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3151 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3152 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3153 ((color_table[i].rgbBlue >> 3) & 0x001f);
3155 for(y = src_rect->top; y < src_rect->bottom; y++)
3157 dst_pixel = dst_start;
3158 src_pixel = src_start;
3159 for(x = src_rect->left; x < src_rect->right; x++)
3160 *dst_pixel++ = dst_colors[*src_pixel++];
3162 if(pad_size) memset(dst_pixel, 0, pad_size);
3163 dst_start += dst->stride / 2;
3164 src_start += src->stride;
3166 break;
3169 case 4:
3171 const RGBQUAD *color_table = get_dib_color_table( src );
3172 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3173 WORD dst_colors[16];
3174 int i;
3176 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3177 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3178 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3179 ((color_table[i].rgbBlue >> 3) & 0x001f);
3181 for(y = src_rect->top; y < src_rect->bottom; y++)
3183 int pos = (src->rect.left + src_rect->left) & 1;
3184 src_pixel = src_start;
3185 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3187 if (pos & 1)
3188 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3189 else
3190 dst_start[x] = dst_colors[*src_pixel >> 4];
3192 if(pad_size) memset(dst_start + x, 0, pad_size);
3193 dst_start += dst->stride / 2;
3194 src_start += src->stride;
3196 break;
3199 case 1:
3201 const RGBQUAD *color_table = get_dib_color_table( src );
3202 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3203 WORD dst_colors[2];
3204 int i;
3206 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3207 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3208 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3209 ((color_table[i].rgbBlue >> 3) & 0x001f);
3211 for(y = src_rect->top; y < src_rect->bottom; y++)
3213 int pos = (src->rect.left + src_rect->left) & 7;
3214 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3216 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3217 dst_start[x] = dst_colors[src_val];
3219 if(pad_size) memset(dst_start + x, 0, pad_size);
3220 dst_start += dst->stride / 2;
3221 src_start += src->stride;
3223 break;
3228 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3230 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
3231 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
3232 DWORD src_val;
3234 switch(src->bit_count)
3236 case 32:
3238 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3240 if(src->funcs == &funcs_8888)
3242 for(y = src_rect->top; y < src_rect->bottom; y++)
3244 dst_pixel = dst_start;
3245 src_pixel = src_start;
3246 for(x = src_rect->left; x < src_rect->right; x++)
3248 src_val = *src_pixel++;
3249 *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val);
3251 if(pad_size) memset(dst_pixel, 0, pad_size);
3252 dst_start += dst->stride / 2;
3253 src_start += src->stride / 4;
3256 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3258 for(y = src_rect->top; y < src_rect->bottom; y++)
3260 dst_pixel = dst_start;
3261 src_pixel = src_start;
3262 for(x = src_rect->left; x < src_rect->right; x++)
3264 src_val = *src_pixel++;
3265 *dst_pixel++ = rgb_to_pixel_masks(dst,
3266 src_val >> src->red_shift,
3267 src_val >> src->green_shift,
3268 src_val >> src->blue_shift);
3270 if(pad_size) memset(dst_pixel, 0, pad_size);
3271 dst_start += dst->stride / 2;
3272 src_start += src->stride / 4;
3275 else
3277 for(y = src_rect->top; y < src_rect->bottom; y++)
3279 dst_pixel = dst_start;
3280 src_pixel = src_start;
3281 for(x = src_rect->left; x < src_rect->right; x++)
3283 src_val = *src_pixel++;
3284 *dst_pixel++ = rgb_to_pixel_masks(dst,
3285 get_field(src_val, src->red_shift, src->red_len),
3286 get_field(src_val, src->green_shift, src->green_len),
3287 get_field(src_val, src->blue_shift, src->blue_len ));
3289 if(pad_size) memset(dst_pixel, 0, pad_size);
3290 dst_start += dst->stride / 2;
3291 src_start += src->stride / 4;
3294 break;
3297 case 24:
3299 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3301 for(y = src_rect->top; y < src_rect->bottom; y++)
3303 dst_pixel = dst_start;
3304 src_pixel = src_start;
3305 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3306 *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3307 if(pad_size) memset(dst_pixel, 0, pad_size);
3308 dst_start += dst->stride / 2;
3309 src_start += src->stride;
3311 break;
3314 case 16:
3316 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3317 if(src->funcs == &funcs_555)
3319 for(y = src_rect->top; y < src_rect->bottom; y++)
3321 dst_pixel = dst_start;
3322 src_pixel = src_start;
3323 for(x = src_rect->left; x < src_rect->right; x++)
3325 src_val = *src_pixel++;
3326 *dst_pixel++ = rgb_to_pixel_masks(dst,
3327 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3328 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3329 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3331 if(pad_size) memset(dst_pixel, 0, pad_size);
3332 dst_start += dst->stride / 2;
3333 src_start += src->stride / 2;
3336 else if(bit_fields_match(src, dst))
3338 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3339 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3340 else
3342 for(y = src_rect->top; y < src_rect->bottom; y++)
3344 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
3345 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3346 dst_start += dst->stride / 2;
3347 src_start += src->stride / 2;
3351 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3353 for(y = src_rect->top; y < src_rect->bottom; y++)
3355 dst_pixel = dst_start;
3356 src_pixel = src_start;
3357 for(x = src_rect->left; x < src_rect->right; x++)
3359 src_val = *src_pixel++;
3360 *dst_pixel++ = rgb_to_pixel_masks(dst,
3361 (((src_val >> src->red_shift) << 3) & 0xf8) |
3362 (((src_val >> src->red_shift) >> 2) & 0x07),
3363 (((src_val >> src->green_shift) << 3) & 0xf8) |
3364 (((src_val >> src->green_shift) >> 2) & 0x07),
3365 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3366 (((src_val >> src->blue_shift) >> 2) & 0x07));
3368 if(pad_size) memset(dst_pixel, 0, pad_size);
3369 dst_start += dst->stride / 2;
3370 src_start += src->stride / 2;
3373 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3375 for(y = src_rect->top; y < src_rect->bottom; y++)
3377 dst_pixel = dst_start;
3378 src_pixel = src_start;
3379 for(x = src_rect->left; x < src_rect->right; x++)
3381 src_val = *src_pixel++;
3382 *dst_pixel++ = rgb_to_pixel_masks(dst,
3383 (((src_val >> src->red_shift) << 3) & 0xf8) |
3384 (((src_val >> src->red_shift) >> 2) & 0x07),
3385 (((src_val >> src->green_shift) << 2) & 0xfc) |
3386 (((src_val >> src->green_shift) >> 4) & 0x03),
3387 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3388 (((src_val >> src->blue_shift) >> 2) & 0x07));
3390 if(pad_size) memset(dst_pixel, 0, pad_size);
3391 dst_start += dst->stride / 2;
3392 src_start += src->stride / 2;
3395 else
3397 for(y = src_rect->top; y < src_rect->bottom; y++)
3399 dst_pixel = dst_start;
3400 src_pixel = src_start;
3401 for(x = src_rect->left; x < src_rect->right; x++)
3403 src_val = *src_pixel++;
3404 *dst_pixel++ = rgb_to_pixel_masks(dst,
3405 get_field(src_val, src->red_shift, src->red_len),
3406 get_field(src_val, src->green_shift, src->green_len),
3407 get_field(src_val, src->blue_shift, src->blue_len));
3409 if(pad_size) memset(dst_pixel, 0, pad_size);
3410 dst_start += dst->stride / 2;
3411 src_start += src->stride / 2;
3414 break;
3417 case 8:
3419 const RGBQUAD *color_table = get_dib_color_table( src );
3420 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3421 WORD dst_colors[256];
3422 int i;
3424 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3425 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3427 for(y = src_rect->top; y < src_rect->bottom; y++)
3429 dst_pixel = dst_start;
3430 src_pixel = src_start;
3431 for(x = src_rect->left; x < src_rect->right; x++)
3432 *dst_pixel++ = dst_colors[*src_pixel++];
3434 if(pad_size) memset(dst_pixel, 0, pad_size);
3435 dst_start += dst->stride / 2;
3436 src_start += src->stride;
3438 break;
3441 case 4:
3443 const RGBQUAD *color_table = get_dib_color_table( src );
3444 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3445 WORD dst_colors[16];
3446 int i;
3448 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3449 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3451 for(y = src_rect->top; y < src_rect->bottom; y++)
3453 int pos = (src->rect.left + src_rect->left) & 1;
3454 src_pixel = src_start;
3455 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3457 if (pos & 1)
3458 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3459 else
3460 dst_start[x] = dst_colors[*src_pixel >> 4];
3462 if(pad_size) memset(dst_start + x, 0, pad_size);
3463 dst_start += dst->stride / 2;
3464 src_start += src->stride;
3466 break;
3469 case 1:
3471 const RGBQUAD *color_table = get_dib_color_table( src );
3472 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3473 WORD dst_colors[2];
3474 int i;
3476 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3477 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3479 for(y = src_rect->top; y < src_rect->bottom; y++)
3481 int pos = (src->rect.left + src_rect->left) & 7;
3482 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3484 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3485 dst_start[x] = dst_colors[src_val];
3487 if(pad_size) memset(dst_start + x, 0, pad_size);
3488 dst_start += dst->stride / 2;
3489 src_start += src->stride;
3491 break;
3496 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
3498 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
3499 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
3502 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
3504 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
3505 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
3508 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3510 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
3511 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
3512 DWORD src_val;
3514 switch(src->bit_count)
3516 case 32:
3518 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3520 if(src->funcs == &funcs_8888)
3522 for(y = src_rect->top; y < src_rect->bottom; y++)
3524 dst_pixel = dst_start;
3525 src_pixel = src_start;
3526 for(x = src_rect->left; x < src_rect->right; x++)
3528 src_val = *src_pixel++;
3529 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
3531 if(pad_size) memset(dst_pixel, 0, pad_size);
3532 dst_start += dst->stride;
3533 src_start += src->stride / 4;
3536 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3538 for(y = src_rect->top; y < src_rect->bottom; y++)
3540 dst_pixel = dst_start;
3541 src_pixel = src_start;
3542 for(x = src_rect->left; x < src_rect->right; x++)
3544 src_val = *src_pixel++;
3545 *dst_pixel++ = rgb_lookup_colortable(dst,
3546 src_val >> src->red_shift,
3547 src_val >> src->green_shift,
3548 src_val >> src->blue_shift );
3550 if(pad_size) memset(dst_pixel, 0, pad_size);
3551 dst_start += dst->stride;
3552 src_start += src->stride / 4;
3555 else
3557 for(y = src_rect->top; y < src_rect->bottom; y++)
3559 dst_pixel = dst_start;
3560 src_pixel = src_start;
3561 for(x = src_rect->left; x < src_rect->right; x++)
3563 src_val = *src_pixel++;
3564 *dst_pixel++ = rgb_lookup_colortable(dst,
3565 get_field(src_val, src->red_shift, src->red_len),
3566 get_field(src_val, src->green_shift, src->green_len),
3567 get_field(src_val, src->blue_shift, src->blue_len));
3569 if(pad_size) memset(dst_pixel, 0, pad_size);
3570 dst_start += dst->stride;
3571 src_start += src->stride / 4;
3574 break;
3577 case 24:
3579 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3581 for(y = src_rect->top; y < src_rect->bottom; y++)
3583 dst_pixel = dst_start;
3584 src_pixel = src_start;
3585 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3587 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
3589 if(pad_size) memset(dst_pixel, 0, pad_size);
3590 dst_start += dst->stride;
3591 src_start += src->stride;
3593 break;
3596 case 16:
3598 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3599 if(src->funcs == &funcs_555)
3601 for(y = src_rect->top; y < src_rect->bottom; y++)
3603 dst_pixel = dst_start;
3604 src_pixel = src_start;
3605 for(x = src_rect->left; x < src_rect->right; x++)
3607 src_val = *src_pixel++;
3608 *dst_pixel++ = rgb_lookup_colortable(dst,
3609 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3610 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3611 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3613 if(pad_size) memset(dst_pixel, 0, pad_size);
3614 dst_start += dst->stride;
3615 src_start += src->stride / 2;
3618 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3620 for(y = src_rect->top; y < src_rect->bottom; y++)
3622 dst_pixel = dst_start;
3623 src_pixel = src_start;
3624 for(x = src_rect->left; x < src_rect->right; x++)
3626 src_val = *src_pixel++;
3627 *dst_pixel++ = rgb_lookup_colortable(dst,
3628 (((src_val >> src->red_shift) << 3) & 0xf8) |
3629 (((src_val >> src->red_shift) >> 2) & 0x07),
3630 (((src_val >> src->green_shift) << 3) & 0xf8) |
3631 (((src_val >> src->green_shift) >> 2) & 0x07),
3632 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3633 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3635 if(pad_size) memset(dst_pixel, 0, pad_size);
3636 dst_start += dst->stride;
3637 src_start += src->stride / 2;
3640 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3642 for(y = src_rect->top; y < src_rect->bottom; y++)
3644 dst_pixel = dst_start;
3645 src_pixel = src_start;
3646 for(x = src_rect->left; x < src_rect->right; x++)
3648 src_val = *src_pixel++;
3649 *dst_pixel++ = rgb_lookup_colortable(dst,
3650 (((src_val >> src->red_shift) << 3) & 0xf8) |
3651 (((src_val >> src->red_shift) >> 2) & 0x07),
3652 (((src_val >> src->green_shift) << 2) & 0xfc) |
3653 (((src_val >> src->green_shift) >> 4) & 0x03),
3654 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3655 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3657 if(pad_size) memset(dst_pixel, 0, pad_size);
3658 dst_start += dst->stride;
3659 src_start += src->stride / 2;
3662 else
3664 for(y = src_rect->top; y < src_rect->bottom; y++)
3666 dst_pixel = dst_start;
3667 src_pixel = src_start;
3668 for(x = src_rect->left; x < src_rect->right; x++)
3670 src_val = *src_pixel++;
3671 *dst_pixel++ = rgb_lookup_colortable(dst,
3672 get_field(src_val, src->red_shift, src->red_len),
3673 get_field(src_val, src->green_shift, src->green_len),
3674 get_field(src_val, src->blue_shift, src->blue_len));
3676 if(pad_size) memset(dst_pixel, 0, pad_size);
3677 dst_start += dst->stride;
3678 src_start += src->stride / 2;
3681 break;
3684 case 8:
3686 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3688 if(color_tables_match(dst, src))
3690 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3691 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3692 else
3694 for(y = src_rect->top; y < src_rect->bottom; y++)
3696 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
3697 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3698 dst_start += dst->stride;
3699 src_start += src->stride;
3703 else
3705 const RGBQUAD *color_table = get_dib_color_table( src );
3706 BYTE dst_colors[256];
3707 int i;
3709 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3710 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
3712 for(y = src_rect->top; y < src_rect->bottom; y++)
3714 dst_pixel = dst_start;
3715 src_pixel = src_start;
3716 for(x = src_rect->left; x < src_rect->right; x++)
3717 *dst_pixel++ = dst_colors[*src_pixel++];
3719 if(pad_size) memset(dst_pixel, 0, pad_size);
3720 dst_start += dst->stride;
3721 src_start += src->stride;
3724 break;
3727 case 4:
3729 const RGBQUAD *color_table = get_dib_color_table( src );
3730 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3731 BYTE dst_colors[16];
3732 int i;
3734 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3735 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
3737 for(y = src_rect->top; y < src_rect->bottom; y++)
3739 int pos = (src->rect.left + src_rect->left) & 1;
3740 src_pixel = src_start;
3741 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3743 if (pos & 1)
3744 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3745 else
3746 dst_start[x] = dst_colors[*src_pixel >> 4];
3748 if(pad_size) memset(dst_start + x, 0, pad_size);
3749 dst_start += dst->stride;
3750 src_start += src->stride;
3752 break;
3755 case 1:
3757 const RGBQUAD *color_table = get_dib_color_table( src );
3758 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3759 BYTE dst_colors[2];
3760 int i;
3762 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3763 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
3765 for(y = src_rect->top; y < src_rect->bottom; y++)
3767 int pos = (src->rect.left + src_rect->left) & 7;
3768 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3770 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3771 dst_start[x] = dst_colors[src_val];
3773 if(pad_size) memset(dst_start + x, 0, pad_size);
3774 dst_start += dst->stride;
3775 src_start += src->stride;
3777 break;
3782 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3784 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3785 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3786 DWORD src_val;
3788 switch(src->bit_count)
3790 case 32:
3792 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3794 if(src->funcs == &funcs_8888)
3796 for(y = src_rect->top; y < src_rect->bottom; y++)
3798 dst_pixel = dst_start;
3799 src_pixel = src_start;
3800 for(x = src_rect->left; x < src_rect->right; x++)
3802 src_val = *src_pixel++;
3803 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3804 if((x - src_rect->left) & 1)
3806 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3807 dst_pixel++;
3809 else
3810 *dst_pixel = (dst_val << 4) & 0xf0;
3812 if(pad_size)
3814 if((x - src_rect->left) & 1) dst_pixel++;
3815 memset(dst_pixel, 0, pad_size);
3817 dst_start += dst->stride;
3818 src_start += src->stride / 4;
3821 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3823 for(y = src_rect->top; y < src_rect->bottom; y++)
3825 dst_pixel = dst_start;
3826 src_pixel = src_start;
3827 for(x = src_rect->left; x < src_rect->right; x++)
3829 src_val = *src_pixel++;
3830 dst_val = rgb_to_pixel_colortable(dst,
3831 src_val >> src->red_shift,
3832 src_val >> src->green_shift,
3833 src_val >> src->blue_shift);
3834 if((x - src_rect->left) & 1)
3836 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3837 dst_pixel++;
3839 else
3840 *dst_pixel = (dst_val << 4) & 0xf0;
3842 if(pad_size)
3844 if((x - src_rect->left) & 1) dst_pixel++;
3845 memset(dst_pixel, 0, pad_size);
3847 dst_start += dst->stride;
3848 src_start += src->stride / 4;
3851 else
3853 for(y = src_rect->top; y < src_rect->bottom; y++)
3855 dst_pixel = dst_start;
3856 src_pixel = src_start;
3857 for(x = src_rect->left; x < src_rect->right; x++)
3859 src_val = *src_pixel++;
3860 dst_val = rgb_to_pixel_colortable(dst,
3861 get_field(src_val, src->red_shift, src->red_len),
3862 get_field(src_val, src->green_shift, src->green_len),
3863 get_field(src_val, src->blue_shift, src->blue_len));
3864 if((x - src_rect->left) & 1)
3866 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3867 dst_pixel++;
3869 else
3870 *dst_pixel = (dst_val << 4) & 0xf0;
3872 if(pad_size)
3874 if((x - src_rect->left) & 1) dst_pixel++;
3875 memset(dst_pixel, 0, pad_size);
3877 dst_start += dst->stride;
3878 src_start += src->stride / 4;
3881 break;
3884 case 24:
3886 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3888 for(y = src_rect->top; y < src_rect->bottom; y++)
3890 dst_pixel = dst_start;
3891 src_pixel = src_start;
3892 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3894 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3896 if((x - src_rect->left) & 1)
3898 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3899 dst_pixel++;
3901 else
3902 *dst_pixel = (dst_val << 4) & 0xf0;
3904 if(pad_size)
3906 if((x - src_rect->left) & 1) dst_pixel++;
3907 memset(dst_pixel, 0, pad_size);
3909 dst_start += dst->stride;
3910 src_start += src->stride;
3912 break;
3915 case 16:
3917 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3918 if(src->funcs == &funcs_555)
3920 for(y = src_rect->top; y < src_rect->bottom; y++)
3922 dst_pixel = dst_start;
3923 src_pixel = src_start;
3924 for(x = src_rect->left; x < src_rect->right; x++)
3926 src_val = *src_pixel++;
3927 dst_val = rgb_to_pixel_colortable(dst,
3928 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3929 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3930 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3931 if((x - src_rect->left) & 1)
3933 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3934 dst_pixel++;
3936 else
3937 *dst_pixel = (dst_val << 4) & 0xf0;
3939 if(pad_size)
3941 if((x - src_rect->left) & 1) dst_pixel++;
3942 memset(dst_pixel, 0, pad_size);
3944 dst_start += dst->stride;
3945 src_start += src->stride / 2;
3948 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3950 for(y = src_rect->top; y < src_rect->bottom; y++)
3952 dst_pixel = dst_start;
3953 src_pixel = src_start;
3954 for(x = src_rect->left; x < src_rect->right; x++)
3956 src_val = *src_pixel++;
3957 dst_val = rgb_to_pixel_colortable(dst,
3958 (((src_val >> src->red_shift) << 3) & 0xf8) |
3959 (((src_val >> src->red_shift) >> 2) & 0x07),
3960 (((src_val >> src->green_shift) << 3) & 0xf8) |
3961 (((src_val >> src->green_shift) >> 2) & 0x07),
3962 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3963 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3964 if((x - src_rect->left) & 1)
3966 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3967 dst_pixel++;
3969 else
3970 *dst_pixel = (dst_val << 4) & 0xf0;
3972 if(pad_size)
3974 if((x - src_rect->left) & 1) dst_pixel++;
3975 memset(dst_pixel, 0, pad_size);
3977 dst_start += dst->stride;
3978 src_start += src->stride / 2;
3981 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3983 for(y = src_rect->top; y < src_rect->bottom; y++)
3985 dst_pixel = dst_start;
3986 src_pixel = src_start;
3987 for(x = src_rect->left; x < src_rect->right; x++)
3989 src_val = *src_pixel++;
3990 dst_val = rgb_to_pixel_colortable(dst,
3991 (((src_val >> src->red_shift) << 3) & 0xf8) |
3992 (((src_val >> src->red_shift) >> 2) & 0x07),
3993 (((src_val >> src->green_shift) << 2) & 0xfc) |
3994 (((src_val >> src->green_shift) >> 4) & 0x03),
3995 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3996 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3997 if((x - src_rect->left) & 1)
3999 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4000 dst_pixel++;
4002 else
4003 *dst_pixel = (dst_val << 4) & 0xf0;
4005 if(pad_size)
4007 if((x - src_rect->left) & 1) dst_pixel++;
4008 memset(dst_pixel, 0, pad_size);
4010 dst_start += dst->stride;
4011 src_start += src->stride / 2;
4014 else
4016 for(y = src_rect->top; y < src_rect->bottom; y++)
4018 dst_pixel = dst_start;
4019 src_pixel = src_start;
4020 for(x = src_rect->left; x < src_rect->right; x++)
4022 src_val = *src_pixel++;
4023 dst_val = rgb_to_pixel_colortable(dst,
4024 get_field(src_val, src->red_shift, src->red_len),
4025 get_field(src_val, src->green_shift, src->green_len),
4026 get_field(src_val, src->blue_shift, src->blue_len));
4027 if((x - src_rect->left) & 1)
4029 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4030 dst_pixel++;
4032 else
4033 *dst_pixel = (dst_val << 4) & 0xf0;
4035 if(pad_size)
4037 if((x - src_rect->left) & 1) dst_pixel++;
4038 memset(dst_pixel, 0, pad_size);
4040 dst_start += dst->stride;
4041 src_start += src->stride / 2;
4044 break;
4047 case 8:
4049 const RGBQUAD *color_table = get_dib_color_table( src );
4050 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4051 BYTE dst_colors[256];
4052 int i;
4054 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
4055 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
4057 for(y = src_rect->top; y < src_rect->bottom; y++)
4059 dst_pixel = dst_start;
4060 src_pixel = src_start;
4061 for(x = src_rect->left; x < src_rect->right; x++)
4063 dst_val = dst_colors[*src_pixel++];
4064 if((x - src_rect->left) & 1)
4066 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4067 dst_pixel++;
4069 else
4070 *dst_pixel = (dst_val << 4) & 0xf0;
4072 if(pad_size)
4074 if((x - src_rect->left) & 1) dst_pixel++;
4075 memset(dst_pixel, 0, pad_size);
4077 dst_start += dst->stride;
4078 src_start += src->stride;
4080 break;
4083 case 4:
4085 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4087 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
4089 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
4090 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
4091 else
4093 for(y = src_rect->top; y < src_rect->bottom; y++)
4095 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
4096 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
4097 dst_start += dst->stride;
4098 src_start += src->stride;
4102 else
4104 const RGBQUAD *color_table = get_dib_color_table( src );
4105 BYTE dst_colors[16];
4106 int i;
4108 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
4109 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
4111 for(y = src_rect->top; y < src_rect->bottom; y++)
4113 int pos = (src->rect.left + src_rect->left) & 1;
4114 dst_pixel = dst_start;
4115 src_pixel = src_start;
4116 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4118 if(pos & 1)
4119 dst_val = dst_colors[*src_pixel++ & 0xf];
4120 else
4121 dst_val = dst_colors[*src_pixel >> 4];
4122 if((x - src_rect->left) & 1)
4124 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4125 dst_pixel++;
4127 else
4128 *dst_pixel = (dst_val << 4) & 0xf0;
4130 if(pad_size)
4132 if((x - src_rect->left) & 1) dst_pixel++;
4133 memset(dst_pixel, 0, pad_size);
4135 dst_start += dst->stride;
4136 src_start += src->stride;
4139 break;
4142 case 1:
4144 const RGBQUAD *color_table = get_dib_color_table( src );
4145 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4146 BYTE dst_colors[2];
4147 int i;
4149 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
4150 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
4152 for(y = src_rect->top; y < src_rect->bottom; y++)
4154 int pos = (src->rect.left + src_rect->left) & 7;
4155 dst_pixel = dst_start;
4156 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4158 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4159 dst_val = dst_colors[src_val];
4160 if((x - src_rect->left) & 1)
4162 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4163 dst_pixel++;
4165 else
4166 *dst_pixel = (dst_val << 4) & 0xf0;
4168 if(pad_size)
4170 if((x - src_rect->left) & 1) dst_pixel++;
4171 memset(dst_pixel, 0, pad_size);
4173 dst_start += dst->stride;
4174 src_start += src->stride;
4176 break;
4181 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4183 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
4184 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
4185 RGBQUAD rgb, bg_entry = *get_dib_color_table( dst ); /* entry 0 is the background color */
4186 DWORD src_val;
4187 int bit_pos;
4189 switch(src->bit_count)
4191 case 32:
4193 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
4194 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
4196 if(src->funcs == &funcs_8888)
4198 for(y = src_rect->top; y < src_rect->bottom; y++)
4200 dst_pixel = dst_start;
4201 src_pixel = src_start;
4202 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4204 src_val = *src_pixel++;
4205 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4206 src_val >> 16, src_val >> 8, src_val);
4207 if(bit_pos == 0) *dst_pixel = 0;
4208 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4210 if(++bit_pos == 8)
4212 dst_pixel++;
4213 bit_pos = 0;
4216 if(pad_size)
4218 if(bit_pos != 0) dst_pixel++;
4219 memset(dst_pixel, 0, pad_size);
4221 dst_start += dst->stride;
4222 src_start += src->stride / 4;
4225 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
4227 for(y = src_rect->top; y < src_rect->bottom; y++)
4229 dst_pixel = dst_start;
4230 src_pixel = src_start;
4231 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4233 src_val = *src_pixel++;
4234 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4235 src_val >> src->red_shift,
4236 src_val >> src->green_shift,
4237 src_val >> src->blue_shift);
4239 if(bit_pos == 0) *dst_pixel = 0;
4240 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4242 if(++bit_pos == 8)
4244 dst_pixel++;
4245 bit_pos = 0;
4248 if(pad_size)
4250 if(bit_pos != 0) dst_pixel++;
4251 memset(dst_pixel, 0, pad_size);
4253 dst_start += dst->stride;
4254 src_start += src->stride / 4;
4257 else
4259 for(y = src_rect->top; y < src_rect->bottom; y++)
4261 dst_pixel = dst_start;
4262 src_pixel = src_start;
4263 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4265 src_val = *src_pixel++;
4266 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4267 get_field(src_val, src->red_shift, src->red_len),
4268 get_field(src_val, src->green_shift, src->green_len),
4269 get_field(src_val, src->blue_shift, src->blue_len));
4271 if(bit_pos == 0) *dst_pixel = 0;
4272 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4274 if(++bit_pos == 8)
4276 dst_pixel++;
4277 bit_pos = 0;
4280 if(pad_size)
4282 if(bit_pos != 0) dst_pixel++;
4283 memset(dst_pixel, 0, pad_size);
4285 dst_start += dst->stride;
4286 src_start += src->stride / 4;
4289 break;
4292 case 24:
4294 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
4295 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, RGB(bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue));
4297 for(y = src_rect->top; y < src_rect->bottom; y++)
4299 dst_pixel = dst_start;
4300 src_pixel = src_start;
4301 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
4303 dst_val = rgb_to_pixel_mono(dst, dither, x, y, RGB(src_pixel[2], src_pixel[1], src_pixel[0]),
4304 bg_pixel, src_pixel[2], src_pixel[1], src_pixel[0]);
4306 if(bit_pos == 0) *dst_pixel = 0;
4307 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4309 if(++bit_pos == 8)
4311 dst_pixel++;
4312 bit_pos = 0;
4315 if(pad_size)
4317 if(bit_pos != 0) dst_pixel++;
4318 memset(dst_pixel, 0, pad_size);
4320 dst_start += dst->stride;
4321 src_start += src->stride;
4323 break;
4326 case 16:
4328 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
4329 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
4331 if(src->funcs == &funcs_555)
4333 for(y = src_rect->top; y < src_rect->bottom; y++)
4335 dst_pixel = dst_start;
4336 src_pixel = src_start;
4337 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4339 src_val = *src_pixel++;
4340 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4341 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
4342 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
4343 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
4345 if(bit_pos == 0) *dst_pixel = 0;
4346 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4348 if(++bit_pos == 8)
4350 dst_pixel++;
4351 bit_pos = 0;
4354 if(pad_size)
4356 if(bit_pos != 0) dst_pixel++;
4357 memset(dst_pixel, 0, pad_size);
4359 dst_start += dst->stride;
4360 src_start += src->stride / 2;
4363 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
4365 for(y = src_rect->top; y < src_rect->bottom; y++)
4367 dst_pixel = dst_start;
4368 src_pixel = src_start;
4369 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4371 src_val = *src_pixel++;
4372 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4373 (((src_val >> src->red_shift) << 3) & 0xf8) |
4374 (((src_val >> src->red_shift) >> 2) & 0x07),
4375 (((src_val >> src->green_shift) << 3) & 0xf8) |
4376 (((src_val >> src->green_shift) >> 2) & 0x07),
4377 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4378 (((src_val >> src->blue_shift) >> 2) & 0x07));
4379 if(bit_pos == 0) *dst_pixel = 0;
4380 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4382 if(++bit_pos == 8)
4384 dst_pixel++;
4385 bit_pos = 0;
4388 if(pad_size)
4390 if(bit_pos != 0) dst_pixel++;
4391 memset(dst_pixel, 0, pad_size);
4393 dst_start += dst->stride;
4394 src_start += src->stride / 2;
4397 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
4399 for(y = src_rect->top; y < src_rect->bottom; y++)
4401 dst_pixel = dst_start;
4402 src_pixel = src_start;
4403 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4405 src_val = *src_pixel++;
4406 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4407 (((src_val >> src->red_shift) << 3) & 0xf8) |
4408 (((src_val >> src->red_shift) >> 2) & 0x07),
4409 (((src_val >> src->green_shift) << 2) & 0xfc) |
4410 (((src_val >> src->green_shift) >> 4) & 0x03),
4411 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4412 (((src_val >> src->blue_shift) >> 2) & 0x07));
4413 if(bit_pos == 0) *dst_pixel = 0;
4414 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4416 if(++bit_pos == 8)
4418 dst_pixel++;
4419 bit_pos = 0;
4422 if(pad_size)
4424 if(bit_pos != 0) dst_pixel++;
4425 memset(dst_pixel, 0, pad_size);
4427 dst_start += dst->stride;
4428 src_start += src->stride / 2;
4431 else
4433 for(y = src_rect->top; y < src_rect->bottom; y++)
4435 dst_pixel = dst_start;
4436 src_pixel = src_start;
4437 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4439 src_val = *src_pixel++;
4440 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4441 get_field(src_val, src->red_shift, src->red_len),
4442 get_field(src_val, src->green_shift, src->green_len),
4443 get_field(src_val, src->blue_shift, src->blue_len));
4444 if(bit_pos == 0) *dst_pixel = 0;
4445 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4447 if(++bit_pos == 8)
4449 dst_pixel++;
4450 bit_pos = 0;
4453 if(pad_size)
4455 if(bit_pos != 0) dst_pixel++;
4456 memset(dst_pixel, 0, pad_size);
4458 dst_start += dst->stride;
4459 src_start += src->stride / 2;
4462 break;
4465 case 8:
4467 const RGBQUAD *color_table = get_dib_color_table( src );
4468 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4469 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4471 for(y = src_rect->top; y < src_rect->bottom; y++)
4473 dst_pixel = dst_start;
4474 src_pixel = src_start;
4475 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4477 BYTE src_val = *src_pixel++;
4478 rgb = color_table[src_val];
4479 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4480 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4482 if(bit_pos == 0) *dst_pixel = 0;
4483 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4485 if(++bit_pos == 8)
4487 dst_pixel++;
4488 bit_pos = 0;
4491 if(pad_size)
4493 if(bit_pos != 0) dst_pixel++;
4494 memset(dst_pixel, 0, pad_size);
4496 dst_start += dst->stride;
4497 src_start += src->stride;
4499 break;
4502 case 4:
4504 const RGBQUAD *color_table = get_dib_color_table( src );
4505 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4506 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4508 for(y = src_rect->top; y < src_rect->bottom; y++)
4510 int pos = (src->rect.left + src_rect->left) & 1;
4511 dst_pixel = dst_start;
4512 src_pixel = src_start;
4513 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4515 src_val = (pos & 1) ? *src_pixel++ & 0xf : *src_pixel >> 4;
4516 rgb = color_table[src_val];
4517 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4518 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4520 if(bit_pos == 0) *dst_pixel = 0;
4521 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4523 if(++bit_pos == 8)
4525 dst_pixel++;
4526 bit_pos = 0;
4529 if(pad_size)
4531 if(bit_pos != 0) dst_pixel++;
4532 memset(dst_pixel, 0, pad_size);
4534 dst_start += dst->stride;
4535 src_start += src->stride;
4537 break;
4540 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
4541 uses text/bkgnd colours instead of the dib's colour table, this
4542 doesn't appear to be the case for a dc backed by a
4543 dibsection. */
4545 case 1:
4547 const RGBQUAD *color_table = get_dib_color_table( src );
4548 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4549 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4551 for(y = src_rect->top; y < src_rect->bottom; y++)
4553 int pos = (src->rect.left + src_rect->left) & 7;
4554 dst_pixel = dst_start;
4555 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4557 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4558 rgb = color_table[src_val];
4559 dst_val = FILTER_DIBINDEX(rgb, rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4560 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
4561 if(bit_pos == 0) *dst_pixel = 0;
4562 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4564 if(++bit_pos == 8)
4566 dst_pixel++;
4567 bit_pos = 0;
4570 if(pad_size)
4572 if(bit_pos != 0) dst_pixel++;
4573 memset(dst_pixel, 0, pad_size);
4575 dst_start += dst->stride;
4576 src_start += src->stride;
4578 break;
4583 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4587 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
4589 return (src * alpha + dst * (255 - alpha) + 127) / 255;
4592 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
4594 return (blend_color( dst, src, alpha ) |
4595 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4596 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4597 blend_color( dst >> 24, src >> 24, alpha ) << 24);
4600 static inline DWORD blend_argb_no_src_alpha( DWORD dst, DWORD src, DWORD alpha )
4602 return (blend_color( dst, src, alpha ) |
4603 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4604 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4605 blend_color( dst >> 24, 255, alpha ) << 24);
4608 static inline DWORD blend_argb( DWORD dst, DWORD src )
4610 BYTE b = (BYTE)src;
4611 BYTE g = (BYTE)(src >> 8);
4612 BYTE r = (BYTE)(src >> 16);
4613 DWORD alpha = (BYTE)(src >> 24);
4614 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4615 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4616 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4617 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4620 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
4622 BYTE b = ((BYTE)src * alpha + 127) / 255;
4623 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4624 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4625 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4626 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4627 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4628 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4629 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4632 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
4634 if (blend.AlphaFormat & AC_SRC_ALPHA)
4636 DWORD alpha = blend.SourceConstantAlpha;
4637 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
4638 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4639 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4640 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4641 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
4642 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
4643 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
4645 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
4646 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
4647 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
4650 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
4651 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4653 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4654 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4655 int x, y;
4657 if (blend.AlphaFormat & AC_SRC_ALPHA)
4659 if (blend.SourceConstantAlpha == 255)
4660 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4661 for (x = 0; x < rc->right - rc->left; x++)
4662 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
4663 else
4664 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4665 for (x = 0; x < rc->right - rc->left; x++)
4666 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4668 else if (src->compression == BI_RGB)
4669 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4670 for (x = 0; x < rc->right - rc->left; x++)
4671 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4672 else
4673 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4674 for (x = 0; x < rc->right - rc->left; x++)
4675 dst_ptr[x] = blend_argb_no_src_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4678 static void blend_rect_32(const dib_info *dst, const RECT *rc,
4679 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4681 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4682 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4683 int x, y;
4685 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
4687 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4689 for (x = 0; x < rc->right - rc->left; x++)
4691 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
4692 dst_ptr[x] >> dst->green_shift,
4693 dst_ptr[x] >> dst->blue_shift,
4694 src_ptr[x], blend );
4695 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
4696 (((val >> 8) & 0xff) << dst->green_shift) |
4697 (((val >> 16) & 0xff) << dst->red_shift));
4701 else
4703 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4705 for (x = 0; x < rc->right - rc->left; x++)
4707 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4708 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4709 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4710 src_ptr[x], blend );
4711 dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val );
4717 static void blend_rect_24(const dib_info *dst, const RECT *rc,
4718 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4720 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4721 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
4722 int x, y;
4724 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4726 for (x = 0; x < rc->right - rc->left; x++)
4728 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4729 src_ptr[x], blend );
4730 dst_ptr[x * 3] = val;
4731 dst_ptr[x * 3 + 1] = val >> 8;
4732 dst_ptr[x * 3 + 2] = val >> 16;
4737 static void blend_rect_555(const dib_info *dst, const RECT *rc,
4738 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4740 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4741 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4742 int x, y;
4744 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4746 for (x = 0; x < rc->right - rc->left; x++)
4748 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4749 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4750 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4751 src_ptr[x], blend );
4752 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4757 static void blend_rect_16(const dib_info *dst, const RECT *rc,
4758 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4760 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4761 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4762 int x, y;
4764 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4766 for (x = 0; x < rc->right - rc->left; x++)
4768 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4769 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4770 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4771 src_ptr[x], blend );
4772 dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val );
4777 static void blend_rect_8(const dib_info *dst, const RECT *rc,
4778 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4780 const RGBQUAD *color_table = get_dib_color_table( dst );
4781 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4782 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4783 int x, y;
4785 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4787 for (x = 0; x < rc->right - rc->left; x++)
4789 RGBQUAD rgb = color_table[dst_ptr[x]];
4790 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4791 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4796 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4797 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4799 const RGBQUAD *color_table = get_dib_color_table( dst );
4800 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4801 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4802 int i, x, y;
4804 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4806 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4808 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4809 RGBQUAD rgb = color_table[val];
4810 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4811 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4812 if (x & 1)
4813 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4814 else
4815 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4820 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4821 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4823 const RGBQUAD *color_table = get_dib_color_table( dst );
4824 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4825 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4826 int i, x, y;
4828 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4830 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4832 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4833 RGBQUAD rgb = color_table[val];
4834 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4835 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4836 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4841 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4842 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4846 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4848 BYTE r, g, b, a;
4849 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4850 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4851 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4852 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4853 return a << 24 | r << 16 | g << 8 | b;
4856 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4858 BYTE r, g, b;
4859 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4860 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4861 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4862 return r << 16 | g << 8 | b;
4865 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4866 unsigned int x, unsigned int y )
4868 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4869 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4870 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4871 r = min( 31, max( 0, r / 16 ));
4872 g = min( 31, max( 0, g / 16 ));
4873 b = min( 31, max( 0, b / 16 ));
4874 return (r << 10) | (g << 5) | b;
4877 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4878 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4880 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4881 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4882 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4883 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4886 /* compute the left/right triangle limit for row y */
4887 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4889 int x1, x2;
4891 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4892 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4894 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4896 *left = max( rc->left, min( x1, x2 ) );
4897 *right = min( rc->right, max( x1, x2 ) );
4900 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4901 static inline int triangle_det( const TRIVERTEX *v )
4903 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);
4906 /* compute the barycentric weights for a given point inside the triangle */
4907 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4909 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4910 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4913 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4915 INT64 l1, l2;
4916 BYTE r, g, b, a;
4918 triangle_weights( v, x, y, &l1, &l2 );
4919 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4920 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4921 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4922 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4923 return a << 24 | r << 16 | g << 8 | b;
4926 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4928 INT64 l1, l2;
4929 BYTE r, g, b;
4931 triangle_weights( v, x, y, &l1, &l2 );
4932 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4933 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4934 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4935 return r << 16 | g << 8 | b;
4938 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4940 INT64 l1, l2;
4941 int r, g, b;
4943 triangle_weights( v, x, y, &l1, &l2 );
4944 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4945 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4946 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4947 r = min( 31, max( 0, r / 16 ));
4948 g = min( 31, max( 0, g / 16 ));
4949 b = min( 31, max( 0, b / 16 ));
4950 return (r << 10) | (g << 5) | b;
4953 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4955 INT64 l1, l2;
4956 BYTE r, g, b;
4958 triangle_weights( v, x, y, &l1, &l2 );
4959 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4960 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4961 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4962 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4965 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4967 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4968 int x, y, left, right, det;
4970 switch (mode)
4972 case GRADIENT_FILL_RECT_H:
4973 for (x = 0; x < rc->right - rc->left; x++)
4974 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4976 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4977 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4978 break;
4980 case GRADIENT_FILL_RECT_V:
4981 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4983 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4984 memset_32( ptr, val, rc->right - rc->left );
4986 break;
4988 case GRADIENT_FILL_TRIANGLE:
4989 if (!(det = triangle_det( v ))) return FALSE;
4990 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4992 triangle_coords( v, rc, y, &left, &right );
4993 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4995 break;
4997 return TRUE;
5000 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5002 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
5003 int x, y, left, right, det;
5005 switch (mode)
5007 case GRADIENT_FILL_RECT_H:
5008 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5010 for (x = 0; x < rc->right - rc->left; x++)
5012 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5013 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
5014 (((val >> 8) & 0xff) << dib->green_shift) |
5015 (((val >> 16) & 0xff) << dib->red_shift));
5018 else
5020 for (x = 0; x < rc->right - rc->left; x++)
5022 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5023 ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5027 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
5028 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
5029 break;
5031 case GRADIENT_FILL_RECT_V:
5032 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5034 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
5035 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5036 val = ((( val & 0xff) << dib->blue_shift) |
5037 (((val >> 8) & 0xff) << dib->green_shift) |
5038 (((val >> 16) & 0xff) << dib->red_shift));
5039 else
5040 val = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5042 memset_32( ptr, val, rc->right - rc->left );
5044 break;
5046 case GRADIENT_FILL_TRIANGLE:
5047 if (!(det = triangle_det( v ))) return FALSE;
5048 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5050 triangle_coords( v, rc, y, &left, &right );
5052 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5053 for (x = left; x < right; x++)
5055 DWORD val = gradient_triangle_24( v, x, y, det );
5056 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
5057 (((val >> 8) & 0xff) << dib->green_shift) |
5058 (((val >> 16) & 0xff) << dib->red_shift));
5060 else
5061 for (x = left; x < right; x++)
5063 DWORD val = gradient_triangle_24( v, x, y, det );
5064 ptr[x - rc->left] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5067 break;
5069 return TRUE;
5072 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5074 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
5075 int x, y, left, right, det;
5077 switch (mode)
5079 case GRADIENT_FILL_RECT_H:
5080 for (x = 0; x < rc->right - rc->left; x++)
5082 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5083 ptr[x * 3] = val;
5084 ptr[x * 3 + 1] = val >> 8;
5085 ptr[x * 3 + 2] = val >> 16;
5088 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
5089 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
5090 break;
5092 case GRADIENT_FILL_RECT_V:
5093 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5095 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
5096 for (x = 0; x < rc->right - rc->left; x++)
5098 ptr[x * 3] = val;
5099 ptr[x * 3 + 1] = val >> 8;
5100 ptr[x * 3 + 2] = val >> 16;
5103 break;
5105 case GRADIENT_FILL_TRIANGLE:
5106 if (!(det = triangle_det( v ))) return FALSE;
5107 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5109 triangle_coords( v, rc, y, &left, &right );
5110 for (x = left; x < right; x++)
5112 DWORD val = gradient_triangle_24( v, x, y, det );
5113 ptr[(x - rc->left) * 3] = val;
5114 ptr[(x - rc->left) * 3 + 1] = val >> 8;
5115 ptr[(x - rc->left) * 3 + 2] = val >> 16;
5118 break;
5120 return TRUE;
5123 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5125 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5126 int x, y, left, right, det;
5128 switch (mode)
5130 case GRADIENT_FILL_RECT_H:
5131 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5132 for (x = rc->left; x < rc->right; x++)
5133 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5134 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5135 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5136 break;
5138 case GRADIENT_FILL_RECT_V:
5139 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5141 WORD values[4];
5142 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5143 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5145 break;
5147 case GRADIENT_FILL_TRIANGLE:
5148 if (!(det = triangle_det( v ))) return FALSE;
5149 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5151 triangle_coords( v, rc, y, &left, &right );
5152 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
5154 break;
5156 return TRUE;
5159 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5161 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5162 int x, y, left, right, det;
5164 switch (mode)
5166 case GRADIENT_FILL_RECT_H:
5167 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5168 for (x = rc->left; x < rc->right; x++)
5170 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5171 ptr[x - rc->left] = rgb_to_pixel_masks( dib,
5172 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5173 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5174 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5176 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5177 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5178 break;
5180 case GRADIENT_FILL_RECT_V:
5181 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5183 WORD values[4];
5184 for (x = 0; x < 4; x++)
5186 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5187 values[x] = rgb_to_pixel_masks( dib,
5188 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5189 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5190 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5192 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5194 break;
5196 case GRADIENT_FILL_TRIANGLE:
5197 if (!(det = triangle_det( v ))) return FALSE;
5198 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5200 triangle_coords( v, rc, y, &left, &right );
5201 for (x = left; x < right; x++)
5203 WORD val = gradient_triangle_555( v, x, y, det );
5204 ptr[x - rc->left] = rgb_to_pixel_masks( dib,
5205 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5206 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5207 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5210 break;
5212 return TRUE;
5215 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5217 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
5218 int x, y, left, right, det;
5220 switch (mode)
5222 case GRADIENT_FILL_RECT_H:
5223 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5224 for (x = rc->left; x < rc->right; x++)
5225 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5226 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5227 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
5228 break;
5230 case GRADIENT_FILL_RECT_V:
5231 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5233 BYTE values[16];
5234 for (x = 0; x < 16; x++)
5235 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5236 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
5238 break;
5240 case GRADIENT_FILL_TRIANGLE:
5241 if (!(det = triangle_det( v ))) return FALSE;
5242 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5244 triangle_coords( v, rc, y, &left, &right );
5245 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
5247 break;
5249 return TRUE;
5252 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5254 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
5255 int x, y, left, right, det, pos;
5257 switch (mode)
5259 case GRADIENT_FILL_RECT_H:
5260 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5262 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5264 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5265 if (pos & 1)
5266 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5267 else
5268 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5271 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5273 x = rc->left;
5274 pos = (dib->rect.left + rc->left) & 1;
5275 if (pos)
5277 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
5278 pos++;
5279 x++;
5281 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
5282 if (x < rc->right)
5283 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
5285 break;
5287 case GRADIENT_FILL_RECT_V:
5288 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5290 BYTE values[16];
5291 for (x = 0; x < 16; x++)
5292 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5293 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5294 if (pos & 1)
5295 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
5296 else
5297 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
5299 break;
5301 case GRADIENT_FILL_TRIANGLE:
5302 if (!(det = triangle_det( v ))) return FALSE;
5303 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5305 triangle_coords( v, rc, y, &left, &right );
5306 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
5308 BYTE val = gradient_triangle_8( dib, v, x, y, det );
5309 if (pos & 1)
5310 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5311 else
5312 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5315 break;
5317 return TRUE;
5320 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5322 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
5323 int x, y, left, right, det, pos;
5325 switch (mode)
5327 case GRADIENT_FILL_RECT_H:
5328 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5330 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5332 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
5333 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5336 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5337 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5338 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5339 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
5340 break;
5342 case GRADIENT_FILL_RECT_V:
5343 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5345 BYTE values[16];
5346 for (x = 0; x < 16; x++)
5347 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
5348 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5349 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5350 (values[x % 16] & pixel_masks_1[pos % 8]);
5352 break;
5354 case GRADIENT_FILL_TRIANGLE:
5355 if (!(det = triangle_det( v ))) return FALSE;
5356 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5358 triangle_coords( v, rc, y, &left, &right );
5359 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
5361 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
5362 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5365 break;
5367 return TRUE;
5370 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5372 return TRUE;
5375 static void mask_rect_32( const dib_info *dst, const RECT *rc,
5376 const dib_info *src, const POINT *origin, int rop2 )
5378 DWORD *dst_start = get_pixel_ptr_32(dst, rc->left, rc->top), dst_colors[256];
5379 DWORD src_val, bit_val, i, full, pos;
5380 int x, y, origin_end = origin->x + rc->right - rc->left;
5381 const RGBQUAD *color_table = get_dib_color_table( src );
5382 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5384 if (dst->funcs == &funcs_8888)
5385 for (i = 0; i < 2; i++)
5386 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
5387 color_table[i].rgbBlue;
5388 else
5389 for (i = 0; i < 2; i++)
5390 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
5392 /* Creating a BYTE-sized table so we don't need to mask the lsb of bit_val */
5393 for (i = 2; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5394 dst_colors[i] = dst_colors[i & 1];
5396 /* Special case starting and finishing in same byte, neither on byte boundary */
5397 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5399 struct rop_codes codes;
5401 get_rop_codes( rop2, &codes );
5403 for (y = rc->top; y < rc->bottom; y++)
5405 pos = origin->x & 7;
5406 for (x = 0; x < rc->right - rc->left; x++, pos++)
5408 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5409 do_rop_codes_32( dst_start + x, dst_colors[bit_val], &codes );
5411 dst_start += dst->stride / 4;
5412 src_start += src->stride;
5414 return;
5417 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5419 #define LOOP( op ) \
5420 for (y = rc->top; y < rc->bottom; y++) \
5422 pos = origin->x & 7; \
5423 src_val = src_start[pos / 8]; \
5424 x = 0; \
5425 switch (pos & 7) \
5427 case 1: bit_val = src_val >> 6; op; x++; \
5428 /* fall through */ \
5429 case 2: bit_val = src_val >> 5; op; x++; \
5430 /* fall through */ \
5431 case 3: bit_val = src_val >> 4; op; x++; \
5432 /* fall through */ \
5433 case 4: bit_val = src_val >> 3; op; x++; \
5434 /* fall through */ \
5435 case 5: bit_val = src_val >> 2; op; x++; \
5436 /* fall through */ \
5437 case 6: bit_val = src_val >> 1; op; x++; \
5438 /* fall through */ \
5439 case 7: bit_val = src_val; op; x++; \
5440 pos = (pos + 7) & ~7; \
5442 for (i = 0; i < full; i++, pos += 8) \
5444 src_val = src_start[pos / 8]; \
5445 bit_val = src_val >> 7; op; x++; \
5446 bit_val = src_val >> 6; op; x++; \
5447 bit_val = src_val >> 5; op; x++; \
5448 bit_val = src_val >> 4; op; x++; \
5449 bit_val = src_val >> 3; op; x++; \
5450 bit_val = src_val >> 2; op; x++; \
5451 bit_val = src_val >> 1; op; x++; \
5452 bit_val = src_val; op; x++; \
5454 if (origin_end & 7) \
5456 src_val = src_start[pos / 8]; \
5457 x += (origin_end & 7) - 1; \
5458 switch (origin_end & 7) \
5460 case 7: bit_val = src_val >> 1; op; x--; \
5461 /* fall through */ \
5462 case 6: bit_val = src_val >> 2; op; x--; \
5463 /* fall through */ \
5464 case 5: bit_val = src_val >> 3; op; x--; \
5465 /* fall through */ \
5466 case 4: bit_val = src_val >> 4; op; x--; \
5467 /* fall through */ \
5468 case 3: bit_val = src_val >> 5; op; x--; \
5469 /* fall through */ \
5470 case 2: bit_val = src_val >> 6; op; x--; \
5471 /* fall through */ \
5472 case 1: bit_val = src_val >> 7; op; \
5475 dst_start += dst->stride / 4; \
5476 src_start += src->stride; \
5479 switch (rop2)
5481 ROPS_ALL( dst_start[x], dst_colors[bit_val] )
5483 #undef LOOP
5486 static void mask_rect_24( const dib_info *dst, const RECT *rc,
5487 const dib_info *src, const POINT *origin, int rop2 )
5489 BYTE *dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
5490 DWORD src_val, bit_val, i, full, pos;
5491 struct rop_codes codes;
5492 int x, y, origin_end = origin->x + rc->right - rc->left;
5493 const RGBQUAD *color_table = get_dib_color_table( src );
5494 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5495 RGBQUAD rgb;
5497 get_rop_codes( rop2, &codes );
5499 /* Special case starting and finishing in same byte, neither on byte boundary */
5500 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5502 for (y = rc->top; y < rc->bottom; y++)
5504 pos = origin->x & 7;
5505 for (x = 0; x < rc->right - rc->left; x++, pos++)
5507 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5508 rgb = color_table[bit_val];
5509 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5510 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5511 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5513 dst_start += dst->stride;
5514 src_start += src->stride;
5516 return;
5519 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5521 for (y = rc->top; y < rc->bottom; y++)
5523 pos = origin->x & 7;
5524 src_val = src_start[pos / 8];
5525 x = 0;
5527 switch (pos & 7)
5529 case 1:
5530 bit_val = (src_val >> 6) & 1;
5531 rgb = color_table[bit_val];
5532 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5533 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5534 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5535 x++;
5536 /* fall through */
5537 case 2:
5538 bit_val = (src_val >> 5) & 1;
5539 rgb = color_table[bit_val];
5540 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5541 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5542 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5543 x++;
5544 /* fall through */
5545 case 3:
5546 bit_val = (src_val >> 4) & 1;
5547 rgb = color_table[bit_val];
5548 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5549 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5550 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5551 x++;
5552 /* fall through */
5553 case 4:
5554 bit_val = (src_val >> 3) & 1;
5555 rgb = color_table[bit_val];
5556 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5557 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5558 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5559 x++;
5560 /* fall through */
5561 case 5:
5562 bit_val = (src_val >> 2) & 1;
5563 rgb = color_table[bit_val];
5564 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5565 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5566 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5567 x++;
5568 /* fall through */
5569 case 6:
5570 bit_val = (src_val >> 1) & 1;
5571 rgb = color_table[bit_val];
5572 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5573 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5574 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5575 x++;
5576 /* fall through */
5577 case 7:
5578 bit_val = src_val & 1;
5579 rgb = color_table[bit_val];
5580 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5581 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5582 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5583 x++;
5584 pos = (pos + 7) & ~7;
5587 for (i = 0; i < full; i++, pos += 8)
5589 src_val = src_start[pos / 8];
5591 bit_val = (src_val >> 7) & 1;
5592 rgb = color_table[bit_val];
5593 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5594 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5595 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5596 x++;
5598 bit_val = (src_val >> 6) & 1;
5599 rgb = color_table[bit_val];
5600 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5601 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5602 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5603 x++;
5605 bit_val = (src_val >> 5) & 1;
5606 rgb = color_table[bit_val];
5607 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5608 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5609 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5610 x++;
5612 bit_val = (src_val >> 4) & 1;
5613 rgb = color_table[bit_val];
5614 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5615 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5616 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5617 x++;
5619 bit_val = (src_val >> 3) & 1;
5620 rgb = color_table[bit_val];
5621 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5622 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5623 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5624 x++;
5626 bit_val = (src_val >> 2) & 1;
5627 rgb = color_table[bit_val];
5628 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5629 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5630 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5631 x++;
5633 bit_val = (src_val >> 1) & 1;
5634 rgb = color_table[bit_val];
5635 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5636 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5637 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5638 x++;
5640 bit_val = src_val & 1;
5641 rgb = color_table[bit_val];
5642 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5643 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5644 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5645 x++;
5648 if (origin_end & 7)
5650 src_val = src_start[pos / 8];
5651 x += (origin_end & 7) - 1;
5653 switch (origin_end & 7)
5655 case 7:
5656 bit_val = (src_val >> 1) & 1;
5657 rgb = color_table[bit_val];
5658 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5659 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5660 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5661 x--;
5662 /* fall through */
5663 case 6:
5664 bit_val = (src_val >> 2) & 1;
5665 rgb = color_table[bit_val];
5666 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5667 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5668 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5669 x--;
5670 /* fall through */
5671 case 5:
5672 bit_val = (src_val >> 3) & 1;
5673 rgb = color_table[bit_val];
5674 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5675 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5676 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5677 x--;
5678 /* fall through */
5679 case 4:
5680 bit_val = (src_val >> 4) & 1;
5681 rgb = color_table[bit_val];
5682 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5683 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5684 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5685 x--;
5686 /* fall through */
5687 case 3:
5688 bit_val = (src_val >> 5) & 1;
5689 rgb = color_table[bit_val];
5690 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5691 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5692 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5693 x--;
5694 /* fall through */
5695 case 2:
5696 bit_val = (src_val >> 6) & 1;
5697 rgb = color_table[bit_val];
5698 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5699 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5700 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5701 x--;
5702 /* fall through */
5703 case 1:
5704 bit_val = (src_val >> 7) & 1;
5705 rgb = color_table[bit_val];
5706 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5707 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5708 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5712 dst_start += dst->stride;
5713 src_start += src->stride;
5717 static void mask_rect_16( const dib_info *dst, const RECT *rc,
5718 const dib_info *src, const POINT *origin, int rop2 )
5720 WORD *dst_start = get_pixel_ptr_16(dst, rc->left, rc->top), dst_colors[2];
5721 DWORD src_val, bit_val, i, full, pos;
5722 struct rop_codes codes;
5723 int x, y, origin_end = origin->x + rc->right - rc->left;
5724 const RGBQUAD *color_table = get_dib_color_table( src );
5725 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5727 get_rop_codes( rop2, &codes );
5729 if (dst->funcs == &funcs_555)
5730 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5731 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
5732 ((color_table[i].rgbGreen << 2) & 0x03e0) |
5733 ((color_table[i].rgbBlue >> 3) & 0x001f);
5734 else
5735 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5736 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
5738 /* Special case starting and finishing in same byte, neither on byte boundary */
5739 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5741 for (y = rc->top; y < rc->bottom; y++)
5743 pos = origin->x & 7;
5744 for (x = 0; x < rc->right - rc->left; x++, pos++)
5746 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5747 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5749 dst_start += dst->stride / 2;
5750 src_start += src->stride;
5752 return;
5755 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5757 for (y = rc->top; y < rc->bottom; y++)
5759 pos = origin->x & 7;
5760 src_val = src_start[pos / 8];
5761 x = 0;
5763 switch (pos & 7)
5765 case 1:
5766 bit_val = (src_val >> 6) & 1;
5767 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5768 /* fall through */
5769 case 2:
5770 bit_val = (src_val >> 5) & 1;
5771 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5772 /* fall through */
5773 case 3:
5774 bit_val = (src_val >> 4) & 1;
5775 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5776 /* fall through */
5777 case 4:
5778 bit_val = (src_val >> 3) & 1;
5779 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5780 /* fall through */
5781 case 5:
5782 bit_val = (src_val >> 2) & 1;
5783 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5784 /* fall through */
5785 case 6:
5786 bit_val = (src_val >> 1) & 1;
5787 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5788 /* fall through */
5789 case 7:
5790 bit_val = src_val & 1;
5791 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5792 pos = (pos + 7) & ~7;
5795 for (i = 0; i < full; i++, pos += 8)
5797 src_val = src_start[pos / 8];
5799 bit_val = (src_val >> 7) & 1;
5800 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5801 bit_val = (src_val >> 6) & 1;
5802 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5803 bit_val = (src_val >> 5) & 1;
5804 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5805 bit_val = (src_val >> 4) & 1;
5806 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5807 bit_val = (src_val >> 3) & 1;
5808 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5809 bit_val = (src_val >> 2) & 1;
5810 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5811 bit_val = (src_val >> 1) & 1;
5812 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5813 bit_val = src_val & 1;
5814 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5817 if (origin_end & 7)
5819 src_val = src_start[pos / 8];
5820 x += (origin_end & 7) - 1;
5822 switch (origin_end & 7)
5824 case 7:
5825 bit_val = (src_val >> 1) & 1;
5826 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5827 /* fall through */
5828 case 6:
5829 bit_val = (src_val >> 2) & 1;
5830 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5831 /* fall through */
5832 case 5:
5833 bit_val = (src_val >> 3) & 1;
5834 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5835 /* fall through */
5836 case 4:
5837 bit_val = (src_val >> 4) & 1;
5838 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5839 /* fall through */
5840 case 3:
5841 bit_val = (src_val >> 5) & 1;
5842 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5843 /* fall through */
5844 case 2:
5845 bit_val = (src_val >> 6) & 1;
5846 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5847 /* fall through */
5848 case 1:
5849 bit_val = (src_val >> 7) & 1;
5850 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5854 dst_start += dst->stride / 2;
5855 src_start += src->stride;
5859 static void mask_rect_8( const dib_info *dst, const RECT *rc,
5860 const dib_info *src, const POINT *origin, int rop2 )
5862 BYTE *dst_start = get_pixel_ptr_8(dst, rc->left, rc->top), dst_colors[2];
5863 DWORD src_val, bit_val, i, full, pos;
5864 struct rop_codes codes;
5865 int x, y, origin_end = origin->x + rc->right - rc->left;
5866 const RGBQUAD *color_table = get_dib_color_table( src );
5867 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5869 get_rop_codes( rop2, &codes );
5871 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5872 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
5874 /* Special case starting and finishing in same byte, neither on byte boundary */
5875 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5877 for (y = rc->top; y < rc->bottom; y++)
5879 pos = origin->x & 7;
5880 for (x = 0; x < rc->right - rc->left; x++, pos++)
5882 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5883 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
5885 dst_start += dst->stride;
5886 src_start += src->stride;
5888 return;
5891 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5893 for (y = rc->top; y < rc->bottom; y++)
5895 pos = origin->x & 7;
5896 src_val = src_start[pos / 8];
5897 x = 0;
5899 switch (pos & 7)
5901 case 1:
5902 bit_val = (src_val >> 6) & 1;
5903 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5904 /* fall through */
5905 case 2:
5906 bit_val = (src_val >> 5) & 1;
5907 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5908 /* fall through */
5909 case 3:
5910 bit_val = (src_val >> 4) & 1;
5911 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5912 /* fall through */
5913 case 4:
5914 bit_val = (src_val >> 3) & 1;
5915 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5916 /* fall through */
5917 case 5:
5918 bit_val = (src_val >> 2) & 1;
5919 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5920 /* fall through */
5921 case 6:
5922 bit_val = (src_val >> 1) & 1;
5923 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5924 /* fall through */
5925 case 7:
5926 bit_val = src_val & 1;
5927 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5928 pos = (pos + 7) & ~7;
5931 for (i = 0; i < full; i++, pos += 8)
5933 src_val = src_start[pos / 8];
5935 bit_val = (src_val >> 7) & 1;
5936 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5937 bit_val = (src_val >> 6) & 1;
5938 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5939 bit_val = (src_val >> 5) & 1;
5940 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5941 bit_val = (src_val >> 4) & 1;
5942 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5943 bit_val = (src_val >> 3) & 1;
5944 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5945 bit_val = (src_val >> 2) & 1;
5946 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5947 bit_val = (src_val >> 1) & 1;
5948 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5949 bit_val = src_val & 1;
5950 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5953 if (origin_end & 7)
5955 src_val = src_start[pos / 8];
5956 x += (origin_end & 7) - 1;
5958 switch (origin_end & 7)
5960 case 7:
5961 bit_val = (src_val >> 1) & 1;
5962 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5963 /* fall through */
5964 case 6:
5965 bit_val = (src_val >> 2) & 1;
5966 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5967 /* fall through */
5968 case 5:
5969 bit_val = (src_val >> 3) & 1;
5970 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5971 /* fall through */
5972 case 4:
5973 bit_val = (src_val >> 4) & 1;
5974 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5975 /* fall through */
5976 case 3:
5977 bit_val = (src_val >> 5) & 1;
5978 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5979 /* fall through */
5980 case 2:
5981 bit_val = (src_val >> 6) & 1;
5982 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5983 /* fall through */
5984 case 1:
5985 bit_val = (src_val >> 7) & 1;
5986 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
5990 dst_start += dst->stride;
5991 src_start += src->stride;
5995 static void mask_rect_4( const dib_info *dst, const RECT *rc,
5996 const dib_info *src, const POINT *origin, int rop2 )
5998 BYTE *dst_start = get_pixel_ptr_4(dst, rc->left, rc->top), dst_colors[2], *dst_ptr;
5999 DWORD bit_val, i, pos;
6000 struct rop_codes codes;
6001 int x, y;
6002 int left = dst->rect.left + rc->left;
6003 int right = dst->rect.left + rc->right;
6004 const RGBQUAD *color_table = get_dib_color_table( src );
6005 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
6007 get_rop_codes( rop2, &codes );
6009 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
6011 dst_colors[i] = FILTER_DIBINDEX(color_table[i],rgbquad_to_pixel_colortable(dst, color_table[i]));
6012 /* Set high nibble to match so we don't need to shift it later. */
6013 dst_colors[i] |= dst_colors[i] << 4;
6016 for (y = rc->top; y < rc->bottom; y++)
6018 pos = origin->x & 7;
6020 for (x = left, dst_ptr = dst_start; x < right; x++, pos++)
6022 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
6023 if (x & 1)
6024 do_rop_codes_mask_8( dst_ptr++, dst_colors[bit_val], &codes, 0x0f );
6025 else
6026 do_rop_codes_mask_8( dst_ptr, dst_colors[bit_val], &codes, 0xf0 );
6028 dst_start += dst->stride;
6029 src_start += src->stride;
6033 static void mask_rect_null( const dib_info *dst, const RECT *rc,
6034 const dib_info *src, const POINT *origin, int rop2 )
6038 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
6040 if (dst == text) return dst;
6042 if (dst > text)
6044 DWORD diff = dst - text;
6045 DWORD range = max_comp - text;
6046 dst = text + (diff * range ) / (0xff - text);
6047 return dst;
6049 else
6051 DWORD diff = text - dst;
6052 DWORD range = text - min_comp;
6053 dst = text - (diff * range) / text;
6054 return dst;
6058 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
6060 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
6061 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
6062 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
6065 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6066 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6068 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6069 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6070 int x, y;
6072 for (y = rect->top; y < rect->bottom; y++)
6074 for (x = 0; x < rect->right - rect->left; x++)
6076 if (glyph_ptr[x] <= 1) continue;
6077 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6078 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
6080 dst_ptr += dib->stride / 4;
6081 glyph_ptr += glyph->stride;
6085 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6086 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6088 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6089 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6090 int x, y;
6091 DWORD text, val;
6093 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6094 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6095 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6097 for (y = rect->top; y < rect->bottom; y++)
6099 for (x = 0; x < rect->right - rect->left; x++)
6101 if (glyph_ptr[x] <= 1) continue;
6102 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6103 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6104 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6105 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6106 text, ranges + glyph_ptr[x] );
6107 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6109 dst_ptr += dib->stride / 4;
6110 glyph_ptr += glyph->stride;
6114 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6115 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6117 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6118 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6119 int x, y;
6120 DWORD val;
6122 for (y = rect->top; y < rect->bottom; y++)
6124 for (x = 0; x < rect->right - rect->left; x++)
6126 if (glyph_ptr[x] <= 1) continue;
6127 if (glyph_ptr[x] >= 16)
6128 val = text_pixel;
6129 else
6130 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6131 text_pixel, ranges + glyph_ptr[x] );
6132 dst_ptr[x * 3] = val;
6133 dst_ptr[x * 3 + 1] = val >> 8;
6134 dst_ptr[x * 3 + 2] = val >> 16;
6136 dst_ptr += dib->stride;
6137 glyph_ptr += glyph->stride;
6141 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6142 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6144 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6145 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6146 int x, y;
6147 DWORD text, val;
6149 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6150 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6151 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6153 for (y = rect->top; y < rect->bottom; y++)
6155 for (x = 0; x < rect->right - rect->left; x++)
6157 if (glyph_ptr[x] <= 1) continue;
6158 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6159 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6160 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6161 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6162 text, ranges + glyph_ptr[x] );
6163 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6165 dst_ptr += dib->stride / 2;
6166 glyph_ptr += glyph->stride;
6170 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6171 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6173 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6174 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6175 int x, y;
6176 DWORD text, val;
6178 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6179 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6180 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6182 for (y = rect->top; y < rect->bottom; y++)
6184 for (x = 0; x < rect->right - rect->left; x++)
6186 if (glyph_ptr[x] <= 1) continue;
6187 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6188 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6189 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6190 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6191 text, ranges + glyph_ptr[x] );
6192 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6194 dst_ptr += dib->stride / 2;
6195 glyph_ptr += glyph->stride;
6199 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6200 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6202 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
6203 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6204 int x, y;
6206 for (y = rect->top; y < rect->bottom; y++)
6208 for (x = 0; x < rect->right - rect->left; x++)
6210 /* no antialiasing, glyph should only contain 0 or 16. */
6211 if (glyph_ptr[x] >= 16)
6212 dst_ptr[x] = text_pixel;
6214 dst_ptr += dib->stride;
6215 glyph_ptr += glyph->stride;
6219 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6220 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6222 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
6223 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6224 int x, y, pos;
6226 for (y = rect->top; y < rect->bottom; y++)
6228 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
6230 /* no antialiasing, glyph should only contain 0 or 16. */
6231 if (glyph_ptr[x] >= 16)
6233 if (pos & 1)
6234 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
6235 else
6236 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
6239 dst_ptr += dib->stride;
6240 glyph_ptr += glyph->stride;
6244 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6245 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6247 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
6248 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6249 int x, y, pos;
6250 BYTE text = (text_pixel & 1) ? 0xff : 0;
6252 for (y = rect->top; y < rect->bottom; y++)
6254 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
6256 /* no antialiasing, glyph should only contain 0 or 16. */
6257 if (glyph_ptr[x] >= 16)
6258 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
6259 (text & pixel_masks_1[pos % 8]);
6261 dst_ptr += dib->stride;
6262 glyph_ptr += glyph->stride;
6266 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6267 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6269 return;
6272 static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha )
6274 return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 |
6275 blend_color( g, text >> 8, (BYTE)(alpha >> 8) ) << 8 |
6276 blend_color( b, text, (BYTE) alpha );
6279 static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6280 const POINT *origin, DWORD text_pixel )
6282 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6283 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6284 int x, y;
6286 for (y = rect->top; y < rect->bottom; y++)
6288 for (x = 0; x < rect->right - rect->left; x++)
6290 if (glyph_ptr[x] == 0) continue;
6291 dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, glyph_ptr[x] );
6293 dst_ptr += dib->stride / 4;
6294 glyph_ptr += glyph->stride / 4;
6298 static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6299 const POINT *origin, DWORD text_pixel )
6301 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6302 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6303 int x, y;
6304 DWORD text, val;
6306 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6307 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6308 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6310 for (y = rect->top; y < rect->bottom; y++)
6312 for (x = 0; x < rect->right - rect->left; x++)
6314 if (glyph_ptr[x] == 0) continue;
6315 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6316 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6317 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6318 text, glyph_ptr[x] );
6319 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6321 dst_ptr += dib->stride / 4;
6322 glyph_ptr += glyph->stride / 4;
6326 static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6327 const POINT *origin, DWORD text_pixel )
6329 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6330 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6331 int x, y;
6332 DWORD val;
6334 for (y = rect->top; y < rect->bottom; y++)
6336 for (x = 0; x < rect->right - rect->left; x++)
6338 if (glyph_ptr[x] == 0) continue;
6339 val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6340 text_pixel, glyph_ptr[x] );
6341 dst_ptr[x * 3] = val;
6342 dst_ptr[x * 3 + 1] = val >> 8;
6343 dst_ptr[x * 3 + 2] = val >> 16;
6345 dst_ptr += dib->stride;
6346 glyph_ptr += glyph->stride / 4;
6350 static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6351 const POINT *origin, DWORD text_pixel )
6353 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6354 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6355 int x, y;
6356 DWORD text, val;
6358 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6359 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6360 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6362 for (y = rect->top; y < rect->bottom; y++)
6364 for (x = 0; x < rect->right - rect->left; x++)
6366 if (glyph_ptr[x] == 0) continue;
6367 val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6368 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6369 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6370 text, glyph_ptr[x] );
6371 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6373 dst_ptr += dib->stride / 2;
6374 glyph_ptr += glyph->stride / 4;
6378 static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6379 const POINT *origin, DWORD text_pixel )
6381 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6382 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6383 int x, y;
6384 DWORD text, val;
6386 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6387 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6388 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6390 for (y = rect->top; y < rect->bottom; y++)
6392 for (x = 0; x < rect->right - rect->left; x++)
6394 if (glyph_ptr[x] == 0) continue;
6395 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6396 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6397 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6398 text, glyph_ptr[x] );
6399 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6401 dst_ptr += dib->stride / 2;
6402 glyph_ptr += glyph->stride / 4;
6406 static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6407 const POINT *origin, DWORD text_pixel )
6409 return;
6412 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
6413 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6415 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
6416 int x, y;
6418 /* masks are always 8x8 */
6419 assert( dib->width == 8 );
6420 assert( dib->height == 8 );
6422 for(y = 0; y < 8; y++, hatch_ptr++)
6424 for(x = 0; x < 8; x++)
6426 if(*hatch_ptr & pixel_masks_1[x])
6428 and_bits[x] = fg->and;
6429 xor_bits[x] = fg->xor;
6431 else
6433 and_bits[x] = bg->and;
6434 xor_bits[x] = bg->xor;
6437 and_bits += dib->stride / 4;
6438 xor_bits += dib->stride / 4;
6442 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
6443 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6445 DWORD mask_start = 0, mask_offset;
6446 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6447 int x, y;
6449 /* masks are always 8x8 */
6450 assert( dib->width == 8 );
6451 assert( dib->height == 8 );
6453 for(y = 0; y < 8; y++, hatch_ptr++)
6455 mask_offset = mask_start;
6456 for(x = 0; x < 8; x++)
6458 if(*hatch_ptr & pixel_masks_1[x])
6460 and_bits[mask_offset] = fg->and & 0xff;
6461 xor_bits[mask_offset++] = fg->xor & 0xff;
6462 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
6463 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
6464 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
6465 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
6467 else
6469 and_bits[mask_offset] = bg->and & 0xff;
6470 xor_bits[mask_offset++] = bg->xor & 0xff;
6471 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
6472 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
6473 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
6474 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
6477 mask_start += dib->stride;
6481 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
6482 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6484 WORD *and_bits = bits->and, *xor_bits = bits->xor;
6485 int x, y;
6487 /* masks are always 8x8 */
6488 assert( dib->width == 8 );
6489 assert( dib->height == 8 );
6491 for(y = 0; y < 8; y++, hatch_ptr++)
6493 for(x = 0; x < 8; x++)
6495 if(*hatch_ptr & pixel_masks_1[x])
6497 and_bits[x] = fg->and;
6498 xor_bits[x] = fg->xor;
6500 else
6502 and_bits[x] = bg->and;
6503 xor_bits[x] = bg->xor;
6506 and_bits += dib->stride / 2;
6507 xor_bits += dib->stride / 2;
6511 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
6512 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6514 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6515 int x, y;
6517 /* masks are always 8x8 */
6518 assert( dib->width == 8 );
6519 assert( dib->height == 8 );
6521 for(y = 0; y < 8; y++, hatch_ptr++)
6523 for(x = 0; x < 8; x++)
6525 if(*hatch_ptr & pixel_masks_1[x])
6527 and_bits[x] = fg->and;
6528 xor_bits[x] = fg->xor;
6530 else
6532 and_bits[x] = bg->and;
6533 xor_bits[x] = bg->xor;
6536 and_bits += dib->stride;
6537 xor_bits += dib->stride;
6541 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
6542 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6544 DWORD mask_offset;
6545 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6546 const rop_mask *rop_mask;
6547 int x, y;
6549 /* masks are always 8x8 */
6550 assert( dib->width == 8 );
6551 assert( dib->height == 8 );
6553 for(y = 0; y < 8; y++, hatch_ptr++)
6555 for(x = mask_offset = 0; x < 8; x++)
6557 if(*hatch_ptr & pixel_masks_1[x])
6558 rop_mask = fg;
6559 else
6560 rop_mask = bg;
6562 if(x & 1)
6564 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
6565 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
6566 mask_offset++;
6568 else
6570 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
6571 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
6574 and_bits += dib->stride;
6575 xor_bits += dib->stride;
6579 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
6580 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6582 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6583 rop_mask rop_mask;
6584 int x, y;
6586 /* masks are always 8x8 */
6587 assert( dib->width == 8 );
6588 assert( dib->height == 8 );
6590 for(y = 0; y < 8; y++, hatch_ptr++)
6592 *and_bits = *xor_bits = 0;
6593 for(x = 0; x < 8; x++)
6595 if(*hatch_ptr & pixel_masks_1[x])
6597 rop_mask.and = (fg->and & 1) ? 0xff : 0;
6598 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
6600 else
6602 rop_mask.and = (bg->and & 1) ? 0xff : 0;
6603 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
6605 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6606 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6608 and_bits += dib->stride;
6609 xor_bits += dib->stride;
6613 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
6614 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6618 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6620 /* mapping between RGB triples and the default color table */
6621 static const BYTE mapping[27] =
6623 0, /* 000000 -> 000000 */
6624 4, /* 00007f -> 000080 */
6625 252, /* 0000ff -> 0000ff */
6626 2, /* 007f00 -> 008000 */
6627 6, /* 007f7f -> 008080 */
6628 224, /* 007fff -> 0080c0 */
6629 250, /* 00ff00 -> 00ff00 */
6630 184, /* 00ff7f -> 00e080 */
6631 254, /* 00ffff -> 00ffff */
6632 1, /* 7f0000 -> 800000 */
6633 5, /* 7f007f -> 800080 */
6634 196, /* 7f00ff -> 8000c0 */
6635 3, /* 7f7f00 -> 808000 */
6636 248, /* 7f7f7f -> 808080 */
6637 228, /* 7f7fff -> 8080c0 */
6638 60, /* 7fff00 -> 80e000 */
6639 188, /* 7fff7f -> 80e080 */
6640 244, /* 7fffff -> 80c0c0 */
6641 249, /* ff0000 -> ff0000 */
6642 135, /* ff007f -> e00080 */
6643 253, /* ff00ff -> ff00ff */
6644 39, /* ff7f00 -> e08000 */
6645 167, /* ff7f7f -> e08080 */
6646 231, /* ff7fff -> e080c0 */
6647 251, /* ffff00 -> ffff00 */
6648 191, /* ffff7f -> e0e080 */
6649 255 /* ffffff -> ffffff */
6652 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6653 struct rop_codes codes;
6654 int x, y;
6656 /* masks are always 8x8 */
6657 assert( dib->width == 8 );
6658 assert( dib->height == 8 );
6660 get_rop_codes( rop2, &codes );
6662 for (y = 0; y < 8; y++)
6664 for (x = 0; x < 8; x++)
6666 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6667 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6668 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6669 DWORD pixel = mapping[r * 9 + g * 3 + b];
6670 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
6671 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
6673 and_bits += dib->stride;
6674 xor_bits += dib->stride;
6678 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6680 /* mapping between RGB triples and the default color table */
6681 static const BYTE mapping[27] =
6683 0, /* 000000 -> 000000 */
6684 4, /* 00007f -> 000080 */
6685 12, /* 0000ff -> 0000ff */
6686 2, /* 007f00 -> 008000 */
6687 6, /* 007f7f -> 008080 */
6688 6, /* 007fff -> 008080 */
6689 10, /* 00ff00 -> 00ff00 */
6690 6, /* 00ff7f -> 008080 */
6691 14, /* 00ffff -> 00ffff */
6692 1, /* 7f0000 -> 800000 */
6693 5, /* 7f007f -> 800080 */
6694 5, /* 7f00ff -> 800080 */
6695 3, /* 7f7f00 -> 808000 */
6696 7, /* 7f7f7f -> 808080 */
6697 8, /* 7f7fff -> c0c0c0 */
6698 3, /* 7fff00 -> 808000 */
6699 8, /* 7fff7f -> c0c0c0 */
6700 8, /* 7fffff -> c0c0c0 */
6701 9, /* ff0000 -> ff0000 */
6702 5, /* ff007f -> 800080 */
6703 13, /* ff00ff -> ff00ff */
6704 3, /* ff7f00 -> 808000 */
6705 8, /* ff7f7f -> c0c0c0 */
6706 8, /* ff7fff -> c0c0c0 */
6707 11, /* ffff00 -> ffff00 */
6708 8, /* ffff7f -> c0c0c0 */
6709 15 /* ffffff -> ffffff */
6712 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6713 struct rop_codes codes;
6714 int x, y;
6716 /* masks are always 8x8 */
6717 assert( dib->width == 8 );
6718 assert( dib->height == 8 );
6720 get_rop_codes( rop2, &codes );
6722 for (y = 0; y < 8; y++)
6724 for (x = 0; x < 8; x++)
6726 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6727 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6728 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6729 DWORD pixel = mapping[r * 9 + g * 3 + b];
6730 if (x & 1)
6732 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
6733 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
6735 else
6737 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
6738 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
6741 and_bits += dib->stride;
6742 xor_bits += dib->stride;
6746 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6748 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6749 struct rop_codes codes;
6750 rop_mask rop_mask;
6751 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
6753 /* masks are always 8x8 */
6754 assert( dib->width == 8 );
6755 assert( dib->height == 8 );
6757 get_rop_codes( rop2, &codes );
6759 for (y = 0; y < 8; y++)
6761 *and_bits = *xor_bits = 0;
6762 for (x = 0; x < 8; x++)
6764 if (grey + bayer_8x8[y][x] > 63)
6766 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
6767 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
6769 else
6771 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
6772 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
6774 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6775 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6777 and_bits += dib->stride;
6778 xor_bits += dib->stride;
6782 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6786 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
6788 switch (mode)
6790 default:
6791 case STRETCH_DELETESCANS:
6792 get_rop_codes( R2_COPYPEN, codes );
6793 break;
6794 case STRETCH_ORSCANS:
6795 get_rop_codes( R2_MERGEPEN, codes );
6796 break;
6797 case STRETCH_ANDSCANS:
6798 get_rop_codes( R2_MASKPEN, codes );
6799 break;
6801 return;
6804 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
6805 const dib_info *src_dib, const POINT *src_start,
6806 const struct stretch_params *params, int mode,
6807 BOOL keep_dst)
6809 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
6810 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
6811 int err = params->err_start;
6812 int width;
6814 if (mode == STRETCH_DELETESCANS || !keep_dst)
6816 for (width = params->length; width; width--)
6818 *dst_ptr = *src_ptr;
6819 dst_ptr += params->dst_inc;
6820 if (err > 0)
6822 src_ptr += params->src_inc;
6823 err += params->err_add_1;
6825 else err += params->err_add_2;
6828 else
6830 struct rop_codes codes;
6832 rop_codes_from_stretch_mode( mode, &codes );
6833 for (width = params->length; width; width--)
6835 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
6836 dst_ptr += params->dst_inc;
6837 if (err > 0)
6839 src_ptr += params->src_inc;
6840 err += params->err_add_1;
6842 else err += params->err_add_2;
6847 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
6848 const dib_info *src_dib, const POINT *src_start,
6849 const struct stretch_params *params, int mode,
6850 BOOL keep_dst)
6852 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
6853 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
6854 int err = params->err_start;
6855 int width;
6857 if (mode == STRETCH_DELETESCANS || !keep_dst)
6859 for (width = params->length; width; width--)
6861 dst_ptr[0] = src_ptr[0];
6862 dst_ptr[1] = src_ptr[1];
6863 dst_ptr[2] = src_ptr[2];
6864 dst_ptr += 3 * params->dst_inc;
6865 if (err > 0)
6867 src_ptr += 3 * params->src_inc;
6868 err += params->err_add_1;
6870 else err += params->err_add_2;
6873 else
6875 struct rop_codes codes;
6877 rop_codes_from_stretch_mode( mode, &codes );
6878 for (width = params->length; width; width--)
6880 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6881 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
6882 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
6883 dst_ptr += 3 * params->dst_inc;
6884 if (err > 0)
6886 src_ptr += 3 * params->src_inc;
6887 err += params->err_add_1;
6889 else err += params->err_add_2;
6894 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
6895 const dib_info *src_dib, const POINT *src_start,
6896 const struct stretch_params *params, int mode,
6897 BOOL keep_dst)
6899 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
6900 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
6901 int err = params->err_start;
6902 int width;
6904 if (mode == STRETCH_DELETESCANS || !keep_dst)
6906 for (width = params->length; width; width--)
6908 *dst_ptr = *src_ptr;
6909 dst_ptr += params->dst_inc;
6910 if (err > 0)
6912 src_ptr += params->src_inc;
6913 err += params->err_add_1;
6915 else err += params->err_add_2;
6918 else
6920 struct rop_codes codes;
6922 rop_codes_from_stretch_mode( mode, &codes );
6923 for (width = params->length; width; width--)
6925 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
6926 dst_ptr += params->dst_inc;
6927 if (err > 0)
6929 src_ptr += params->src_inc;
6930 err += params->err_add_1;
6932 else err += params->err_add_2;
6937 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
6938 const dib_info *src_dib, const POINT *src_start,
6939 const struct stretch_params *params, int mode,
6940 BOOL keep_dst)
6942 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
6943 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
6944 int err = params->err_start;
6945 int width;
6947 if (mode == STRETCH_DELETESCANS || !keep_dst)
6949 for (width = params->length; width; width--)
6951 *dst_ptr = *src_ptr;
6952 dst_ptr += params->dst_inc;
6953 if (err > 0)
6955 src_ptr += params->src_inc;
6956 err += params->err_add_1;
6958 else err += params->err_add_2;
6961 else
6963 struct rop_codes codes;
6965 rop_codes_from_stretch_mode( mode, &codes );
6966 for (width = params->length; width; width--)
6968 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6969 dst_ptr += params->dst_inc;
6970 if (err > 0)
6972 src_ptr += params->src_inc;
6973 err += params->err_add_1;
6975 else err += params->err_add_2;
6980 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
6981 const dib_info *src_dib, const POINT *src_start,
6982 const struct stretch_params *params, int mode,
6983 BOOL keep_dst)
6985 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
6986 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
6987 int err = params->err_start;
6988 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6989 struct rop_codes codes;
6990 BYTE src_val;
6992 if (!keep_dst) mode = STRETCH_DELETESCANS;
6993 rop_codes_from_stretch_mode( mode, &codes );
6994 for (width = params->length; width; width--)
6996 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
6997 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
6999 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
7001 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
7002 dst_ptr += params->dst_inc;
7003 dst_x += params->dst_inc;
7005 if (err > 0)
7007 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
7008 src_ptr += params->src_inc;
7009 src_x += params->src_inc;
7010 err += params->err_add_1;
7012 else err += params->err_add_2;
7016 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
7017 const dib_info *src_dib, const POINT *src_start,
7018 const struct stretch_params *params, int mode,
7019 BOOL keep_dst)
7021 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
7022 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
7023 int err = params->err_start;
7024 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7025 struct rop_codes codes;
7026 BYTE src_val;
7028 if (!keep_dst) mode = STRETCH_DELETESCANS;
7029 rop_codes_from_stretch_mode( mode, &codes );
7030 for (width = params->length; width; width--)
7032 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
7033 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
7035 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
7036 dst_ptr += params->dst_inc;
7037 dst_x += params->dst_inc;
7039 if (err > 0)
7041 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
7042 src_ptr += params->src_inc;
7043 src_x += params->src_inc;
7044 err += params->err_add_1;
7046 else err += params->err_add_2;
7050 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
7051 const dib_info *src_dib, const POINT *src_start,
7052 const struct stretch_params *params, int mode,
7053 BOOL keep_dst)
7055 FIXME("bit count %d\n", dst_dib->bit_count);
7056 return;
7059 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
7060 const dib_info *src_dib, const POINT *src_start,
7061 const struct stretch_params *params, int mode,
7062 BOOL keep_dst)
7064 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
7065 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
7066 int err = params->err_start;
7067 int width;
7069 if (mode == STRETCH_DELETESCANS)
7071 for (width = params->length; width; width--)
7073 *dst_ptr = *src_ptr;
7074 src_ptr += params->src_inc;
7075 if (err > 0)
7077 dst_ptr += params->dst_inc;
7078 err += params->err_add_1;
7080 else err += params->err_add_2;
7083 else
7085 struct rop_codes codes;
7086 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
7087 BOOL new_pix = TRUE;
7089 rop_codes_from_stretch_mode( mode, &codes );
7090 for (width = params->length; width; width--)
7092 if (new_pix && !keep_dst) *dst_ptr = init_val;
7093 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
7094 new_pix = FALSE;
7095 src_ptr += params->src_inc;
7096 if (err > 0)
7098 dst_ptr += params->dst_inc;
7099 new_pix = TRUE;
7100 err += params->err_add_1;
7102 else err += params->err_add_2;
7107 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
7108 const dib_info *src_dib, const POINT *src_start,
7109 const struct stretch_params *params, int mode,
7110 BOOL keep_dst)
7112 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
7113 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
7114 int err = params->err_start;
7115 int width;
7117 if (mode == STRETCH_DELETESCANS)
7119 for (width = params->length; width; width--)
7121 dst_ptr[0] = src_ptr[0];
7122 dst_ptr[1] = src_ptr[1];
7123 dst_ptr[2] = src_ptr[2];
7124 src_ptr += 3 * params->src_inc;
7125 if (err > 0)
7127 dst_ptr += 3 * params->dst_inc;
7128 err += params->err_add_1;
7130 else err += params->err_add_2;
7133 else
7135 struct rop_codes codes;
7136 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7137 BOOL new_pix = TRUE;
7139 rop_codes_from_stretch_mode( mode, &codes );
7140 for (width = params->length; width; width--)
7142 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
7143 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7144 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
7145 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
7146 new_pix = FALSE;
7147 src_ptr += 3 * params->src_inc;
7148 if (err > 0)
7150 dst_ptr += 3 * params->dst_inc;
7151 new_pix = TRUE;
7152 err += params->err_add_1;
7154 else err += params->err_add_2;
7159 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
7160 const dib_info *src_dib, const POINT *src_start,
7161 const struct stretch_params *params, int mode,
7162 BOOL keep_dst)
7164 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
7165 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
7166 int err = params->err_start;
7167 int width;
7169 if (mode == STRETCH_DELETESCANS)
7171 for (width = params->length; width; width--)
7173 *dst_ptr = *src_ptr;
7174 src_ptr += params->src_inc;
7175 if (err > 0)
7177 dst_ptr += params->dst_inc;
7178 err += params->err_add_1;
7180 else err += params->err_add_2;
7183 else
7185 struct rop_codes codes;
7186 WORD init_val = (mode == STRETCH_ANDSCANS) ? 0xffff : 0;
7187 BOOL new_pix = TRUE;
7189 rop_codes_from_stretch_mode( mode, &codes );
7190 for (width = params->length; width; width--)
7192 if (new_pix && !keep_dst) *dst_ptr = init_val;
7193 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
7194 new_pix = FALSE;
7195 src_ptr += params->src_inc;
7196 if (err > 0)
7198 dst_ptr += params->dst_inc;
7199 new_pix = TRUE;
7200 err += params->err_add_1;
7202 else err += params->err_add_2;
7207 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
7208 const dib_info *src_dib, const POINT *src_start,
7209 const struct stretch_params *params, int mode,
7210 BOOL keep_dst)
7212 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
7213 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
7214 int err = params->err_start;
7215 int width;
7217 if (mode == STRETCH_DELETESCANS)
7219 for (width = params->length; width; width--)
7221 *dst_ptr = *src_ptr;
7222 src_ptr += params->src_inc;
7223 if (err > 0)
7225 dst_ptr += params->dst_inc;
7226 err += params->err_add_1;
7228 else err += params->err_add_2;
7231 else
7233 struct rop_codes codes;
7234 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7235 BOOL new_pix = TRUE;
7237 rop_codes_from_stretch_mode( mode, &codes );
7238 for (width = params->length; width; width--)
7240 if (new_pix && !keep_dst) *dst_ptr = init_val;
7241 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7242 new_pix = FALSE;
7243 src_ptr += params->src_inc;
7244 if (err > 0)
7246 dst_ptr += params->dst_inc;
7247 new_pix = TRUE;
7248 err += params->err_add_1;
7250 else err += params->err_add_2;
7255 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
7256 const dib_info *src_dib, const POINT *src_start,
7257 const struct stretch_params *params, int mode,
7258 BOOL keep_dst)
7260 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
7261 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
7262 int err = params->err_start;
7263 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7264 struct rop_codes codes;
7265 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7266 BOOL new_pix = TRUE;
7268 rop_codes_from_stretch_mode( mode, &codes );
7269 for (width = params->length; width; width--)
7271 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
7273 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
7274 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
7276 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
7277 new_pix = FALSE;
7279 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
7280 src_ptr += params->src_inc;
7281 src_x += params->src_inc;
7283 if (err > 0)
7285 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
7286 dst_ptr += params->dst_inc;
7287 dst_x += params->dst_inc;
7288 new_pix = TRUE;
7289 err += params->err_add_1;
7291 else err += params->err_add_2;
7295 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
7296 const dib_info *src_dib, const POINT *src_start,
7297 const struct stretch_params *params, int mode,
7298 BOOL keep_dst)
7300 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
7301 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
7302 int err = params->err_start;
7303 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7304 struct rop_codes codes;
7305 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7306 BOOL new_pix = TRUE;
7308 rop_codes_from_stretch_mode( mode, &codes );
7309 for (width = params->length; width; width--)
7311 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
7312 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
7313 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
7314 new_pix = FALSE;
7316 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
7317 src_ptr += params->src_inc;
7318 src_x += params->src_inc;
7320 if (err > 0)
7322 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
7323 dst_ptr += params->dst_inc;
7324 dst_x += params->dst_inc;
7325 new_pix = TRUE;
7326 err += params->err_add_1;
7328 else err += params->err_add_2;
7332 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
7333 const dib_info *src_dib, const POINT *src_start,
7334 const struct stretch_params *params, int mode,
7335 BOOL keep_dst)
7337 FIXME("bit count %d\n", dst_dib->bit_count);
7338 return;
7341 const primitive_funcs funcs_8888 =
7343 solid_rects_32,
7344 solid_line_32,
7345 pattern_rects_32,
7346 copy_rect_32,
7347 blend_rect_8888,
7348 gradient_rect_8888,
7349 mask_rect_32,
7350 draw_glyph_8888,
7351 draw_subpixel_glyph_8888,
7352 get_pixel_32,
7353 colorref_to_pixel_888,
7354 pixel_to_colorref_888,
7355 convert_to_8888,
7356 create_rop_masks_32,
7357 create_dither_masks_null,
7358 stretch_row_32,
7359 shrink_row_32
7362 const primitive_funcs funcs_32 =
7364 solid_rects_32,
7365 solid_line_32,
7366 pattern_rects_32,
7367 copy_rect_32,
7368 blend_rect_32,
7369 gradient_rect_32,
7370 mask_rect_32,
7371 draw_glyph_32,
7372 draw_subpixel_glyph_32,
7373 get_pixel_32,
7374 colorref_to_pixel_masks,
7375 pixel_to_colorref_masks,
7376 convert_to_32,
7377 create_rop_masks_32,
7378 create_dither_masks_null,
7379 stretch_row_32,
7380 shrink_row_32
7383 const primitive_funcs funcs_24 =
7385 solid_rects_24,
7386 solid_line_24,
7387 pattern_rects_24,
7388 copy_rect_24,
7389 blend_rect_24,
7390 gradient_rect_24,
7391 mask_rect_24,
7392 draw_glyph_24,
7393 draw_subpixel_glyph_24,
7394 get_pixel_24,
7395 colorref_to_pixel_888,
7396 pixel_to_colorref_888,
7397 convert_to_24,
7398 create_rop_masks_24,
7399 create_dither_masks_null,
7400 stretch_row_24,
7401 shrink_row_24
7404 const primitive_funcs funcs_555 =
7406 solid_rects_16,
7407 solid_line_16,
7408 pattern_rects_16,
7409 copy_rect_16,
7410 blend_rect_555,
7411 gradient_rect_555,
7412 mask_rect_16,
7413 draw_glyph_555,
7414 draw_subpixel_glyph_555,
7415 get_pixel_16,
7416 colorref_to_pixel_555,
7417 pixel_to_colorref_555,
7418 convert_to_555,
7419 create_rop_masks_16,
7420 create_dither_masks_null,
7421 stretch_row_16,
7422 shrink_row_16
7425 const primitive_funcs funcs_16 =
7427 solid_rects_16,
7428 solid_line_16,
7429 pattern_rects_16,
7430 copy_rect_16,
7431 blend_rect_16,
7432 gradient_rect_16,
7433 mask_rect_16,
7434 draw_glyph_16,
7435 draw_subpixel_glyph_16,
7436 get_pixel_16,
7437 colorref_to_pixel_masks,
7438 pixel_to_colorref_masks,
7439 convert_to_16,
7440 create_rop_masks_16,
7441 create_dither_masks_null,
7442 stretch_row_16,
7443 shrink_row_16
7446 const primitive_funcs funcs_8 =
7448 solid_rects_8,
7449 solid_line_8,
7450 pattern_rects_8,
7451 copy_rect_8,
7452 blend_rect_8,
7453 gradient_rect_8,
7454 mask_rect_8,
7455 draw_glyph_8,
7456 draw_subpixel_glyph_null,
7457 get_pixel_8,
7458 colorref_to_pixel_colortable,
7459 pixel_to_colorref_colortable,
7460 convert_to_8,
7461 create_rop_masks_8,
7462 create_dither_masks_8,
7463 stretch_row_8,
7464 shrink_row_8
7467 const primitive_funcs funcs_4 =
7469 solid_rects_4,
7470 solid_line_4,
7471 pattern_rects_4,
7472 copy_rect_4,
7473 blend_rect_4,
7474 gradient_rect_4,
7475 mask_rect_4,
7476 draw_glyph_4,
7477 draw_subpixel_glyph_null,
7478 get_pixel_4,
7479 colorref_to_pixel_colortable,
7480 pixel_to_colorref_colortable,
7481 convert_to_4,
7482 create_rop_masks_4,
7483 create_dither_masks_4,
7484 stretch_row_4,
7485 shrink_row_4
7488 const primitive_funcs funcs_1 =
7490 solid_rects_1,
7491 solid_line_1,
7492 pattern_rects_1,
7493 copy_rect_1,
7494 blend_rect_1,
7495 gradient_rect_1,
7496 mask_rect_null,
7497 draw_glyph_1,
7498 draw_subpixel_glyph_null,
7499 get_pixel_1,
7500 colorref_to_pixel_colortable,
7501 pixel_to_colorref_colortable,
7502 convert_to_1,
7503 create_rop_masks_1,
7504 create_dither_masks_1,
7505 stretch_row_1,
7506 shrink_row_1
7509 const primitive_funcs funcs_null =
7511 solid_rects_null,
7512 solid_line_null,
7513 pattern_rects_null,
7514 copy_rect_null,
7515 blend_rect_null,
7516 gradient_rect_null,
7517 mask_rect_null,
7518 draw_glyph_null,
7519 draw_subpixel_glyph_null,
7520 get_pixel_null,
7521 colorref_to_pixel_null,
7522 pixel_to_colorref_null,
7523 convert_to_null,
7524 create_rop_masks_null,
7525 create_dither_masks_null,
7526 stretch_row_null,
7527 shrink_row_null