gdi32: Explicitly write out the rops for mask_rect_32().
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blobabfb1b5615b1d6d114f8af5575abfff8998c6c05
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 ROPS_WITHOUT_COPY( _d, _s ) \
112 case R2_BLACK: LOOP( (_d) = 0 ) break; \
113 case R2_NOTMERGEPEN: LOOP( (_d) = ~((_d) | (_s)) ) break; \
114 case R2_MASKNOTPEN: LOOP( (_d) &= ~(_s) ) break; \
115 case R2_NOTCOPYPEN: LOOP( (_d) = ~(_s) ) break; \
116 case R2_MASKPENNOT: LOOP( (_d) = (~(_d) & (_s)) ) break; \
117 case R2_NOT: LOOP( (_d) = ~(_d) ) break; \
118 case R2_XORPEN: LOOP( (_d) ^= (_s) ) break; \
119 case R2_NOTMASKPEN: LOOP( (_d) = ~((_d) & (_s)) ) break; \
120 case R2_MASKPEN: LOOP( (_d) &= (_s) ) break; \
121 case R2_NOTXORPEN: LOOP( (_d) = ~((_d) ^ (_s)) ) break; \
122 case R2_NOP: break; \
123 case R2_MERGENOTPEN: LOOP( (_d) = ((_d) | ~(_s)) ) break; \
124 case R2_MERGEPENNOT: LOOP( (_d) = (~(_d) | (_s)) ) break; \
125 case R2_MERGEPEN: LOOP( (_d) |= (_s) ) break; \
126 case R2_WHITE: LOOP( (_d) = ~0 ) break;
128 #define ROPS_ALL( _d, _s ) \
129 case R2_COPYPEN: LOOP( (_d) = (_s) ) break; \
130 ROPS_WITHOUT_COPY( (_d), (_s) )
132 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
134 *ptr = (*ptr & and) ^ xor;
137 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
139 *ptr = (*ptr & and) ^ xor;
142 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
144 *ptr = (*ptr & and) ^ xor;
147 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
149 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
152 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
154 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
157 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
159 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
162 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
164 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
167 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
169 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
172 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
174 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
177 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
179 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
180 do_rop_codes_16( dst, *src, codes );
183 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
185 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
188 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
190 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
191 do_rop_codes_8( dst, *src, codes );
194 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
195 struct rop_codes *codes, int len)
197 BYTE src_val;
199 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
201 if (dst_x & 1)
203 if (src_x & 1) src_val = *src++;
204 else src_val = *src >> 4;
205 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
207 else
209 if (src_x & 1) src_val = *src++ << 4;
210 else src_val = *src;
211 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
216 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
217 struct rop_codes *codes, int len)
219 BYTE src_val;
221 src_x += len - 1;
222 dst_x += len - 1;
223 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
225 if (dst_x & 1)
227 if (src_x & 1) src_val = *src;
228 else src_val = *src-- >> 4;
229 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
231 else
233 if (src_x & 1) src_val = *src << 4;
234 else src_val = *src--;
235 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
240 /**************************************************
241 * get_src_byte_1
243 * Return a byte representing 8 pixels of src data
244 * that is aligned with the dst.
246 * off is the number of bits that src is ahead of dst
247 * measured from the start. If off is +ve then we need to
248 * grab data from src[0] and src[1]. If off is -ve we use
249 * last (which is equivalent to src[-1]) and src[0]. For
250 * the first call in a line the last component will not be
251 * needed so it's safe for the caller to zero-init it.
253 * S |.....xxx|xxxxxxxx
254 * D |..xxxxxx|xxxxxxxx off = +3
256 * S |..xxxxxx|xxxxxxxx
257 * D |.....xxx|xxxxxxxx off = -3
259 static inline BYTE get_src_byte_1(const BYTE *src, int off, BYTE *last)
261 BYTE src_val;
263 if (off == 0)
264 src_val = src[0];
265 else if (off > 0)
266 src_val = (src[0] << off) | (src[1] >> (8 - off));
267 else
269 src_val = (*last << (8 + off)) | (src[0] >> -off);
270 *last = src[0];
273 return src_val;
276 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
277 struct rop_codes *codes, int len, int rop2)
279 BYTE src_val, last_src = 0;
280 int off = (src_x & 7) - (dst_x & 7), i, full_bytes;
281 int dst_end = dst_x + len;
282 BYTE mask;
284 src += src_x / 8;
285 dst += dst_x / 8;
287 /* Handle special case of all of dst in one byte. */
288 if ((dst_x & ~7) == ((dst_end - 1) & ~7))
290 if (off == 0)
291 src_val = src[0];
292 else if (off > 0)
294 src_val = src[0] << off;
295 if ((dst_end & 7) + off > 8)
296 src_val |= (src[1] >> (8 - off));
298 else
299 src_val = src[0] >> -off;
301 mask = edge_masks_1[dst_x & 7];
302 if (dst_end & 7)
303 mask &= ~edge_masks_1[dst_end & 7];
304 do_rop_codes_mask_8( dst, src_val, codes, mask );
305 return;
308 if (dst_x & 7)
310 src_val = get_src_byte_1( src, off, &last_src );
311 mask = edge_masks_1[dst_x & 7];
312 do_rop_codes_mask_8( dst, src_val, codes, mask );
313 src++;
314 dst++;
317 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
319 if (off == 0)
321 if (rop2 == R2_COPYPEN)
323 memmove( dst, src, full_bytes );
324 src += full_bytes;
325 dst += full_bytes;
327 else
329 for (i = 0; i < full_bytes; i++, src++, dst++)
330 do_rop_codes_8( dst, src[0], codes );
333 else if (off > 0)
335 if (rop2 == R2_COPYPEN)
337 for (i = 0; i < full_bytes; i++, src++, dst++)
338 dst[0] = (src[0] << off) | (src[1] >> (8 - off));
340 else
342 for (i = 0; i < full_bytes; i++, src++, dst++)
343 do_rop_codes_8( dst, (src[0] << off) | (src[1] >> (8 - off)), codes );
346 else
348 if (rop2 == R2_COPYPEN)
350 for (i = 0; i < full_bytes; i++, src++, dst++)
352 src_val = (last_src << (8 + off)) | (src[0] >> -off);
353 last_src = src[0];
354 dst[0] = src_val;
357 else
359 for (i = 0; i < full_bytes; i++, src++, dst++)
361 src_val = (last_src << (8 + off)) | (src[0] >> -off);
362 last_src = src[0];
363 do_rop_codes_8( dst, src_val, codes );
368 if (dst_end & 7)
370 if (off > 0 && (dst_end & 7) + off <= 8)
371 /* Don't read src[1] if everything's in src[0]. */
372 src_val = src[0] << off;
373 else if (off < 0 && (dst_end & 7) + off <= 0)
374 /* Don't read src[0] if everything's in last_src. */
375 src_val = last_src << (8 + off);
376 else
377 src_val = get_src_byte_1( src, off, &last_src );
378 mask = ~edge_masks_1[dst_end & 7];
379 do_rop_codes_mask_8( dst, src_val, codes, mask );
383 /**************************************************
384 * get_src_byte_rev_1
386 * Return a byte representing 8 pixels of src data
387 * that is aligned with the dst.
389 * off is the number of bits that src is ahead of dst
390 * measured from the end. If off is +ve then we need to
391 * grab data from src[0] and last (which is equivalent to src[1]).
392 * If off is -ve we use src[-1]) and src[0]. For the first call
393 * in a line the last component wil not be needed so it is safe
394 * for the caller to zero-init it.
396 * S xxxxxxxx|xxxxxx..|
397 * D xxxxxxxx|xxx.....| off = +3
399 * S xxxxxxxx|xxx.....|
400 * D xxxxxxxx|xxxxxx..| off = -3
402 static inline BYTE get_src_byte_rev_1(const BYTE *src, int off, BYTE *last)
404 BYTE src_val;
406 if (off == 0)
407 src_val = src[0];
408 else if (off > 0)
410 src_val = (src[0] << off) | (*last >> (8 - off));
411 *last = *src;
413 else
414 src_val = (src[-1] << (8 + off)) | (src[0] >> -off);
416 return src_val;
419 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
420 struct rop_codes *codes, int len, int rop2)
422 BYTE src_val, last_src = 0;
423 int src_end = src_x + len, dst_end = dst_x + len;
424 int off = ((src_end - 1) & 7) - ((dst_end - 1) & 7), i, full_bytes;
425 BYTE mask;
427 /* Handle special case of all of dst in one byte. */
428 if ((dst_x & ~7) == ((dst_end - 1) & ~7))
430 do_rop_codes_line_1(dst, dst_x, src, src_x, codes, len, rop2);
431 return;
434 src += (src_end - 1) / 8;
435 dst += (dst_end - 1) / 8;
437 if (dst_end & 7)
439 src_val = get_src_byte_rev_1( src, off, &last_src );
440 mask = ~edge_masks_1[dst_end & 7];
441 do_rop_codes_mask_8( dst, src_val, codes, mask );
442 src--;
443 dst--;
446 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
448 if (off == 0)
450 if (rop2 == R2_COPYPEN)
452 memmove( dst, src, full_bytes );
453 src -= full_bytes;
454 dst -= full_bytes;
456 else
458 for (i = 0; i < full_bytes; i++, src--, dst--)
459 do_rop_codes_8( dst, src[0], codes );
462 else if (off > 0)
464 if (rop2 == R2_COPYPEN)
466 for (i = 0; i < full_bytes; i++, src--, dst--)
468 src_val = (src[0] << off) | (last_src >> (8 - off));
469 last_src = src[0];
470 dst[0] = src_val;
473 else
475 for (i = 0; i < full_bytes; i++, src--, dst--)
477 src_val = (src[0] << off) | (last_src >> (8 - off));
478 last_src = src[0];
479 do_rop_codes_8( dst, src_val, codes );
483 else
485 if (rop2 == R2_COPYPEN)
487 for (i = 0; i < full_bytes; i++, src--, dst--)
488 dst[0] = (src[-1] << (8 + off)) | (src[0] >> -off);
490 else
492 for (i = 0; i < full_bytes; i++, src--, dst--)
493 do_rop_codes_8( dst, (src[-1] << (8 + off)) | (src[0] >> -off), codes );
497 if (dst_x & 7)
499 if (off < 0 && (dst_x & 7) + off >= 0)
500 /* Don't read src[-1] if everything's in src[0]. */
501 src_val = src[0] >> -off;
502 else if (off > 0 && (dst_x & 7) + off >= 8)
503 /* Don't read src[0] if everything's in last_src. */
504 src_val = last_src >> (8 - off);
505 else
506 src_val = get_src_byte_rev_1( src, off, &last_src );
507 mask = edge_masks_1[dst_x & 7];
508 do_rop_codes_mask_8( dst, src_val, codes, mask );
512 static inline void memset_32( DWORD *start, DWORD val, DWORD size )
514 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
515 DWORD dummy;
516 __asm__ __volatile__( "cld; rep; stosl"
517 : "=c" (dummy), "=D" (dummy)
518 : "a" (val), "0" (size), "1" (start) );
519 #else
520 while (size--) *start++ = val;
521 #endif
524 static inline void memset_16( WORD *start, WORD val, DWORD size )
526 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
527 DWORD dummy;
528 __asm__ __volatile__( "cld; rep; stosw"
529 : "=c" (dummy), "=D" (dummy)
530 : "a" (val), "0" (size), "1" (start) );
531 #else
532 while (size--) *start++ = val;
533 #endif
536 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
538 DWORD *ptr, *start;
539 int x, y, i;
541 for(i = 0; i < num; i++, rc++)
543 assert( !is_rect_empty( rc ));
545 start = get_pixel_ptr_32(dib, rc->left, rc->top);
546 if (and)
547 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
548 for(x = rc->left, ptr = start; x < rc->right; x++)
549 do_rop_32(ptr++, and, xor);
550 else
551 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
552 memset_32( start, xor, rc->right - rc->left );
556 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
558 DWORD *ptr, *start;
559 BYTE *byte_ptr, *byte_start;
560 int x, y, i;
561 DWORD and_masks[3], xor_masks[3];
563 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
564 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
565 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
566 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
567 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
568 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
570 for(i = 0; i < num; i++, rc++)
572 int left = dib->rect.left + rc->left;
573 int right = dib->rect.left + rc->right;
575 assert( !is_rect_empty( rc ));
577 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
579 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
580 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
582 for(x = left, byte_ptr = byte_start; x < right; x++)
584 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
585 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
586 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
590 else if (and)
592 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
593 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
595 ptr = start;
597 switch(left & 3)
599 case 1:
600 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
601 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
602 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
603 break;
604 case 2:
605 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
606 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
607 break;
608 case 3:
609 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
610 break;
613 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
615 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
616 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
617 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
620 switch(right & 3)
622 case 1:
623 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
624 break;
625 case 2:
626 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
627 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
628 break;
629 case 3:
630 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
631 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
632 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
633 break;
637 else
639 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
640 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
642 ptr = start;
644 switch(left & 3)
646 case 1:
647 do_rop_32(ptr++, 0x00ffffff, xor_masks[0] & 0xff000000);
648 *ptr++ = xor_masks[1];
649 *ptr++ = xor_masks[2];
650 break;
651 case 2:
652 do_rop_32(ptr++, 0x0000ffff, xor_masks[1] & 0xffff0000);
653 *ptr++ = xor_masks[2];
654 break;
655 case 3:
656 do_rop_32(ptr++, 0x000000ff, xor_masks[2] & 0xffffff00);
657 break;
660 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
662 *ptr++ = xor_masks[0];
663 *ptr++ = xor_masks[1];
664 *ptr++ = xor_masks[2];
667 switch(right & 3)
669 case 1:
670 do_rop_32(ptr, 0xff000000, xor_masks[0] & 0x00ffffff);
671 break;
672 case 2:
673 *ptr++ = xor_masks[0];
674 do_rop_32(ptr, 0xffff0000, xor_masks[1] & 0x0000ffff);
675 break;
676 case 3:
677 *ptr++ = xor_masks[0];
678 *ptr++ = xor_masks[1];
679 do_rop_32(ptr, 0xffffff00, xor_masks[2] & 0x000000ff);
680 break;
687 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
689 WORD *ptr, *start;
690 int x, y, i;
692 for(i = 0; i < num; i++, rc++)
694 assert( !is_rect_empty( rc ));
696 start = get_pixel_ptr_16(dib, rc->left, rc->top);
697 if (and)
698 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
699 for(x = rc->left, ptr = start; x < rc->right; x++)
700 do_rop_16(ptr++, and, xor);
701 else
702 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
703 memset_16( start, xor, rc->right - rc->left );
707 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
709 BYTE *ptr, *start;
710 int x, y, i;
712 for(i = 0; i < num; i++, rc++)
714 assert( !is_rect_empty( rc ));
716 start = get_pixel_ptr_8(dib, rc->left, rc->top);
717 if (and)
718 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
719 for(x = rc->left, ptr = start; x < rc->right; x++)
720 do_rop_8(ptr++, and, xor);
721 else
722 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
723 memset( start, xor, rc->right - rc->left );
727 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
729 BYTE *ptr, *start;
730 int x, y, i;
731 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
732 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
734 for(i = 0; i < num; i++, rc++)
736 int left = dib->rect.left + rc->left;
737 int right = dib->rect.left + rc->right;
739 assert( !is_rect_empty( rc ));
741 start = get_pixel_ptr_4(dib, rc->left, rc->top);
742 if (and)
744 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
746 ptr = start;
747 if(left & 1) /* upper nibble untouched */
748 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
750 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
751 do_rop_8(ptr++, byte_and, byte_xor);
753 if(right & 1) /* lower nibble untouched */
754 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
757 else
759 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
761 unsigned int byte_len = (right - ((left + 1) & ~1)) / 2;
763 ptr = start;
764 if(left & 1) /* upper nibble untouched */
765 do_rop_8(ptr++, 0xf0, byte_xor & 0x0f);
767 memset( ptr, byte_xor, byte_len );
769 if(right & 1) /* lower nibble untouched */
770 do_rop_8(ptr + byte_len, 0x0f, byte_xor & 0xf0);
776 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
778 BYTE *ptr, *start;
779 int x, y, i;
780 BYTE byte_and = (and & 1) ? 0xff : 0;
781 BYTE byte_xor = (xor & 1) ? 0xff : 0;
783 for(i = 0; i < num; i++, rc++)
785 int left = dib->rect.left + rc->left;
786 int right = dib->rect.left + rc->right;
788 assert( !is_rect_empty( rc ));
790 start = get_pixel_ptr_1(dib, rc->left, rc->top);
792 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
794 BYTE mask = edge_masks_1[left & 7] & ~edge_masks_1[right & 7];
796 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
798 do_rop_8(start, byte_and | ~mask, byte_xor & mask);
801 else if (and)
803 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
805 ptr = start;
807 if(left & 7)
808 do_rop_8(ptr++, byte_and | ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
810 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
811 do_rop_8(ptr++, byte_and, byte_xor);
813 if(right & 7)
814 /* this is inverted wrt start mask */
815 do_rop_8(ptr, byte_and | edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
818 else
820 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
822 unsigned int byte_len = (right - ((left + 7) & ~7)) / 8;
824 ptr = start;
826 if(left & 7)
827 do_rop_8(ptr++, ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
829 memset( ptr, byte_xor, byte_len );
831 if(right & 7)
832 do_rop_8(ptr + byte_len, edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
838 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
840 return;
843 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
844 DWORD and, DWORD xor)
846 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
847 int len = params->length, err = params->err_start;
848 int major_inc, minor_inc;
850 if (params->x_major)
852 major_inc = params->x_inc;
853 minor_inc = (dib->stride * params->y_inc) / 4;
855 else
857 major_inc = (dib->stride * params->y_inc) / 4;
858 minor_inc = params->x_inc;
861 while (len--)
863 do_rop_32( ptr, and, xor );
864 if (err + params->bias > 0)
866 ptr += minor_inc;
867 err += params->err_add_1;
869 else err += params->err_add_2;
870 ptr += major_inc;
874 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
875 DWORD and, DWORD xor)
877 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
878 int len = params->length, err = params->err_start;
879 int major_inc, minor_inc;
881 if (params->x_major)
883 major_inc = params->x_inc * 3;
884 minor_inc = dib->stride * params->y_inc;
886 else
888 major_inc = dib->stride * params->y_inc;
889 minor_inc = params->x_inc * 3;
892 while (len--)
894 do_rop_8( ptr, and, xor );
895 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
896 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
897 if (err + params->bias > 0)
899 ptr += minor_inc;
900 err += params->err_add_1;
902 else err += params->err_add_2;
903 ptr += major_inc;
907 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
908 DWORD and, DWORD xor)
910 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
911 int len = params->length, err = params->err_start;
912 int major_inc, minor_inc;
914 if (params->x_major)
916 major_inc = params->x_inc;
917 minor_inc = (dib->stride * params->y_inc) / 2;
919 else
921 major_inc = (dib->stride * params->y_inc) / 2;
922 minor_inc = params->x_inc;
925 while (len--)
927 do_rop_16( ptr, and, xor );
928 if (err + params->bias > 0)
930 ptr += minor_inc;
931 err += params->err_add_1;
933 else err += params->err_add_2;
934 ptr += major_inc;
938 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
939 DWORD and, DWORD xor)
941 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
942 int len = params->length, err = params->err_start;
943 int major_inc, minor_inc;
945 if (params->x_major)
947 major_inc = params->x_inc;
948 minor_inc = dib->stride * params->y_inc;
950 else
952 major_inc = dib->stride * params->y_inc;
953 minor_inc = params->x_inc;
956 while (len--)
958 do_rop_8( ptr, and, xor );
959 if (err + params->bias > 0)
961 ptr += minor_inc;
962 err += params->err_add_1;
964 else err += params->err_add_2;
965 ptr += major_inc;
969 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
970 DWORD and, DWORD xor)
972 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
973 int len = params->length, err = params->err_start;
974 int x = dib->rect.left + start->x;
976 and = (and & 0x0f) | ((and << 4) & 0xf0);
977 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
979 if (params->x_major)
981 while (len--)
983 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
984 if (err + params->bias > 0)
986 ptr += dib->stride * params->y_inc;
987 err += params->err_add_1;
989 else err += params->err_add_2;
990 if ((x / 2) != ((x + params->x_inc) / 2))
991 ptr += params->x_inc;
992 x += params->x_inc;
995 else
997 while (len--)
999 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
1000 if (err + params->bias > 0)
1002 if ((x / 2) != ((x + params->x_inc) / 2))
1003 ptr += params->x_inc;
1004 x += params->x_inc;
1005 err += params->err_add_1;
1007 else err += params->err_add_2;
1008 ptr += dib->stride * params->y_inc;
1013 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
1014 DWORD and, DWORD xor)
1016 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
1017 int len = params->length, err = params->err_start;
1018 int x = dib->rect.left + start->x;
1020 and = (and & 0x1) ? 0xff : 0;
1021 xor = (xor & 0x1) ? 0xff : 0;
1023 if (params->x_major)
1025 while (len--)
1027 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
1028 if (err + params->bias > 0)
1030 ptr += dib->stride * params->y_inc;
1031 err += params->err_add_1;
1033 else err += params->err_add_2;
1034 if ((x / 8) != ((x + params->x_inc) / 8))
1035 ptr += params->x_inc;
1036 x += params->x_inc;
1039 else
1041 while (len--)
1043 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
1044 if (err + params->bias > 0)
1046 if ((x / 8) != ((x + params->x_inc) / 8))
1047 ptr += params->x_inc;
1048 x += params->x_inc;
1049 err += params->err_add_1;
1051 else err += params->err_add_2;
1052 ptr += dib->stride * params->y_inc;
1057 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
1058 DWORD and, DWORD xor)
1060 return;
1063 static inline INT calc_offset(INT edge, INT size, INT origin)
1065 INT offset;
1067 if(edge - origin >= 0)
1068 offset = (edge - origin) % size;
1069 else
1071 offset = (origin - edge) % size;
1072 if(offset) offset = size - offset;
1074 return offset;
1077 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
1079 POINT offset;
1081 offset.x = calc_offset(rc->left, brush->width, origin->x);
1082 offset.y = calc_offset(rc->top, brush->height, origin->y);
1084 return offset;
1087 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1088 const dib_info *brush, const rop_mask_bits *bits)
1090 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1091 int x, y, i, len, brush_x;
1092 POINT offset;
1094 for(i = 0; i < num; i++, rc++)
1096 offset = calc_brush_offset(rc, brush, origin);
1097 start = get_pixel_ptr_32(dib, rc->left, rc->top);
1098 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
1100 if (bits->and)
1102 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
1104 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
1106 and_ptr = start_and + offset.x;
1107 xor_ptr = start_xor + offset.x;
1109 for(x = rc->left, ptr = start; x < rc->right; x++)
1111 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
1112 if(and_ptr == start_and + brush->width)
1114 and_ptr = start_and;
1115 xor_ptr = start_xor;
1119 offset.y++;
1120 if(offset.y == brush->height)
1122 start_and = bits->and;
1123 start_xor = bits->xor;
1124 offset.y = 0;
1126 else
1128 start_and += brush->stride / 4;
1129 start_xor += brush->stride / 4;
1133 else
1135 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
1137 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1139 len = min( rc->right - x, brush->width - brush_x );
1140 memcpy( start + x - rc->left, start_xor + brush_x, len * 4 );
1141 brush_x = 0;
1144 start_xor += brush->stride / 4;
1145 offset.y++;
1146 if(offset.y == brush->height)
1148 start_xor = bits->xor;
1149 offset.y = 0;
1156 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1157 const dib_info *brush, const rop_mask_bits *bits)
1159 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1160 int x, y, i, len, brush_x;
1161 POINT offset;
1163 for(i = 0; i < num; i++, rc++)
1165 offset = calc_brush_offset(rc, brush, origin);
1167 start = get_pixel_ptr_24(dib, rc->left, rc->top);
1168 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1170 if (bits->and)
1172 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1173 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1175 and_ptr = start_and + offset.x * 3;
1176 xor_ptr = start_xor + offset.x * 3;
1178 for(x = rc->left, ptr = start; x < rc->right; x++)
1180 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1181 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1182 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1183 if(and_ptr == start_and + brush->width * 3)
1185 and_ptr = start_and;
1186 xor_ptr = start_xor;
1190 offset.y++;
1191 if(offset.y == brush->height)
1193 start_and = bits->and;
1194 start_xor = bits->xor;
1195 offset.y = 0;
1197 else
1199 start_and += brush->stride;
1200 start_xor += brush->stride;
1204 else
1206 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1208 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1210 len = min( rc->right - x, brush->width - brush_x );
1211 memcpy( start + (x - rc->left) * 3, start_xor + brush_x * 3, len * 3 );
1212 brush_x = 0;
1215 start_xor += brush->stride;
1216 offset.y++;
1217 if(offset.y == brush->height)
1219 start_xor = bits->xor;
1220 offset.y = 0;
1227 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1228 const dib_info *brush, const rop_mask_bits *bits)
1230 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1231 int x, y, i, len, brush_x;
1232 POINT offset;
1234 for(i = 0; i < num; i++, rc++)
1236 offset = calc_brush_offset(rc, brush, origin);
1238 start = get_pixel_ptr_16(dib, rc->left, rc->top);
1239 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
1241 if (bits->and)
1243 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
1244 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
1246 and_ptr = start_and + offset.x;
1247 xor_ptr = start_xor + offset.x;
1249 for(x = rc->left, ptr = start; x < rc->right; x++)
1251 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
1252 if(and_ptr == start_and + brush->width)
1254 and_ptr = start_and;
1255 xor_ptr = start_xor;
1259 offset.y++;
1260 if(offset.y == brush->height)
1262 start_and = bits->and;
1263 start_xor = bits->xor;
1264 offset.y = 0;
1266 else
1268 start_and += brush->stride / 2;
1269 start_xor += brush->stride / 2;
1273 else
1275 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
1277 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1279 len = min( rc->right - x, brush->width - brush_x );
1280 memcpy( start + x - rc->left, start_xor + brush_x, len * 2 );
1281 brush_x = 0;
1284 start_xor += brush->stride / 2;
1285 offset.y++;
1286 if(offset.y == brush->height)
1288 start_xor = bits->xor;
1289 offset.y = 0;
1296 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1297 const dib_info *brush, const rop_mask_bits *bits)
1299 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1300 int x, y, i, len, brush_x;
1301 POINT offset;
1303 for(i = 0; i < num; i++, rc++)
1305 offset = calc_brush_offset(rc, brush, origin);
1307 start = get_pixel_ptr_8(dib, rc->left, rc->top);
1308 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1310 if (bits->and)
1312 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1313 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1315 and_ptr = start_and + offset.x;
1316 xor_ptr = start_xor + offset.x;
1318 for(x = rc->left, ptr = start; x < rc->right; x++)
1320 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1321 if(and_ptr == start_and + brush->width)
1323 and_ptr = start_and;
1324 xor_ptr = start_xor;
1328 offset.y++;
1329 if(offset.y == brush->height)
1331 start_and = bits->and;
1332 start_xor = bits->xor;
1333 offset.y = 0;
1335 else
1337 start_and += brush->stride;
1338 start_xor += brush->stride;
1342 else
1344 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1346 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1348 len = min( rc->right - x, brush->width - brush_x );
1349 memcpy( start + x - rc->left, start_xor + brush_x, len );
1350 brush_x = 0;
1353 start_xor += brush->stride;
1354 offset.y++;
1355 if(offset.y == brush->height)
1357 start_xor = bits->xor;
1358 offset.y = 0;
1365 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1366 const dib_info *brush, const rop_mask_bits *bits)
1368 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1369 int x, y, i, left, right;
1370 POINT offset;
1372 for(i = 0; i < num; i++, rc++)
1374 offset = calc_brush_offset(rc, brush, origin);
1375 left = dib->rect.left + rc->left;
1376 right = dib->rect.left + rc->right;
1378 start = get_pixel_ptr_4(dib, rc->left, rc->top);
1379 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1381 if (bits->and)
1383 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1384 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1386 INT brush_x = offset.x;
1387 BYTE byte_and, byte_xor;
1389 and_ptr = start_and + brush_x / 2;
1390 xor_ptr = start_xor + brush_x / 2;
1392 for(x = left, ptr = start; x < right; x++)
1394 /* FIXME: Two pixels at a time */
1395 if(x & 1) /* lower dst nibble */
1397 if(brush_x & 1) /* lower pat nibble */
1399 byte_and = *and_ptr++ | 0xf0;
1400 byte_xor = *xor_ptr++ & 0x0f;
1402 else /* upper pat nibble */
1404 byte_and = (*and_ptr >> 4) | 0xf0;
1405 byte_xor = (*xor_ptr >> 4) & 0x0f;
1408 else /* upper dst nibble */
1410 if(brush_x & 1) /* lower pat nibble */
1412 byte_and = (*and_ptr++ << 4) | 0x0f;
1413 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1415 else /* upper pat nibble */
1417 byte_and = *and_ptr | 0x0f;
1418 byte_xor = *xor_ptr & 0xf0;
1421 do_rop_8(ptr, byte_and, byte_xor);
1423 if(x & 1) ptr++;
1425 if(++brush_x == brush->width)
1427 brush_x = 0;
1428 and_ptr = start_and;
1429 xor_ptr = start_xor;
1433 offset.y++;
1434 if(offset.y == brush->height)
1436 start_and = bits->and;
1437 start_xor = bits->xor;
1438 offset.y = 0;
1440 else
1442 start_and += brush->stride;
1443 start_xor += brush->stride;
1447 else
1449 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1451 INT brush_x = offset.x;
1452 BYTE byte_xor;
1454 xor_ptr = start_xor + brush_x / 2;
1456 for(x = left, ptr = start; x < right; x++)
1458 /* FIXME: Two pixels at a time */
1459 if(x & 1) /* lower dst nibble */
1461 if(brush_x & 1) /* lower pat nibble */
1462 byte_xor = *xor_ptr++ & 0x0f;
1463 else /* upper pat nibble */
1464 byte_xor = (*xor_ptr >> 4) & 0x0f;
1465 do_rop_8(ptr, 0xf0, byte_xor);
1467 else /* upper dst nibble */
1469 if(brush_x & 1) /* lower pat nibble */
1470 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1471 else /* upper pat nibble */
1472 byte_xor = *xor_ptr & 0xf0;
1473 do_rop_8(ptr, 0x0f, byte_xor);
1476 if(x & 1) ptr++;
1478 if(++brush_x == brush->width)
1480 brush_x = 0;
1481 xor_ptr = start_xor;
1485 start_xor += brush->stride;
1486 offset.y++;
1487 if(offset.y == brush->height)
1489 start_xor = bits->xor;
1490 offset.y = 0;
1497 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1498 const dib_info *brush, const rop_mask_bits *bits)
1500 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1501 int x, y, i, left, right;
1502 POINT offset;
1504 for(i = 0; i < num; i++, rc++)
1506 offset = calc_brush_offset(rc, brush, origin);
1507 left = dib->rect.left + rc->left;
1508 right = dib->rect.left + rc->right;
1510 start = get_pixel_ptr_1(dib, rc->left, rc->top);
1511 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1513 if (bits->and)
1515 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1516 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1518 INT brush_x = offset.x;
1519 BYTE byte_and, byte_xor;
1521 and_ptr = start_and + brush_x / 8;
1522 xor_ptr = start_xor + brush_x / 8;
1524 for(x = left, ptr = start; x < right; x++)
1526 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1527 byte_and |= ~pixel_masks_1[x % 8];
1528 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1529 byte_xor &= pixel_masks_1[x % 8];
1531 do_rop_8(ptr, byte_and, byte_xor);
1533 if((x & 7) == 7) ptr++;
1535 if((brush_x & 7) == 7)
1537 and_ptr++;
1538 xor_ptr++;
1541 if(++brush_x == brush->width)
1543 brush_x = 0;
1544 and_ptr = start_and;
1545 xor_ptr = start_xor;
1549 offset.y++;
1550 if(offset.y == brush->height)
1552 start_and = bits->and;
1553 start_xor = bits->xor;
1554 offset.y = 0;
1556 else
1558 start_and += brush->stride;
1559 start_xor += brush->stride;
1563 else
1565 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1567 INT brush_x = offset.x;
1569 xor_ptr = start_xor + brush_x / 8;
1571 for(x = left, ptr = start; x < right; x++)
1573 BYTE byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1574 byte_xor &= pixel_masks_1[x % 8];
1576 do_rop_8(ptr, ~pixel_masks_1[x % 8], byte_xor);
1578 if((x & 7) == 7) ptr++;
1579 if((brush_x & 7) == 7) xor_ptr++;
1581 if(++brush_x == brush->width)
1583 brush_x = 0;
1584 xor_ptr = start_xor;
1588 start_xor += brush->stride;
1589 offset.y++;
1590 if(offset.y == brush->height)
1592 start_xor = bits->xor;
1593 offset.y = 0;
1600 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1601 const dib_info *brush, const rop_mask_bits *bits)
1603 return;
1606 static inline void copy_rect_bits_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1607 int dst_stride, int src_stride, int rop2 )
1609 const DWORD *src;
1610 DWORD *dst;
1611 int x, y;
1613 #define LOOP( op ) \
1614 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1615 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src++, dst++) \
1618 switch (rop2)
1620 ROPS_WITHOUT_COPY( dst[0], src[0] )
1622 #undef LOOP
1625 static inline void copy_rect_bits_rev_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1626 int dst_stride, int src_stride, int rop2 )
1628 const DWORD *src;
1629 DWORD *dst;
1630 int x, y;
1632 src_start += size->cx - 1;
1633 dst_start += size->cx - 1;
1635 #define LOOP( op ) \
1636 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1637 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src--, dst--) \
1640 switch (rop2)
1642 ROPS_WITHOUT_COPY( dst[0], src[0] )
1644 #undef LOOP
1647 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1648 const dib_info *src, const POINT *origin, int rop2, int overlap)
1650 DWORD *dst_start, *src_start;
1651 int y, dst_stride, src_stride;
1652 SIZE size;
1654 if (overlap & OVERLAP_BELOW)
1656 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1657 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1658 dst_stride = -dst->stride / 4;
1659 src_stride = -src->stride / 4;
1661 else
1663 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1664 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1665 dst_stride = dst->stride / 4;
1666 src_stride = src->stride / 4;
1669 if (rop2 == R2_COPYPEN)
1671 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1672 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1673 return;
1676 size.cx = rc->right - rc->left;
1677 size.cy = rc->bottom - rc->top;
1679 if (overlap & OVERLAP_RIGHT)
1680 copy_rect_bits_rev_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1681 else
1682 copy_rect_bits_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1685 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1686 const dib_info *src, const POINT *origin, int rop2, int overlap)
1688 BYTE *dst_start, *src_start;
1689 int y, dst_stride, src_stride;
1690 struct rop_codes codes;
1692 if (overlap & OVERLAP_BELOW)
1694 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1695 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1696 dst_stride = -dst->stride;
1697 src_stride = -src->stride;
1699 else
1701 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1702 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1703 dst_stride = dst->stride;
1704 src_stride = src->stride;
1707 if (rop2 == R2_COPYPEN)
1709 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1710 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1711 return;
1714 get_rop_codes( rop2, &codes );
1715 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1717 if (overlap & OVERLAP_RIGHT)
1718 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1719 else
1720 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1724 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1725 const dib_info *src, const POINT *origin, int rop2, int overlap)
1727 WORD *dst_start, *src_start;
1728 int y, dst_stride, src_stride;
1729 struct rop_codes codes;
1731 if (overlap & OVERLAP_BELOW)
1733 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1734 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1735 dst_stride = -dst->stride / 2;
1736 src_stride = -src->stride / 2;
1738 else
1740 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1741 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1742 dst_stride = dst->stride / 2;
1743 src_stride = src->stride / 2;
1746 if (rop2 == R2_COPYPEN)
1748 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1749 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1750 return;
1753 get_rop_codes( rop2, &codes );
1754 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1756 if (overlap & OVERLAP_RIGHT)
1757 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1758 else
1759 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1763 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1764 const dib_info *src, const POINT *origin, int rop2, int overlap)
1766 BYTE *dst_start, *src_start;
1767 int y, dst_stride, src_stride;
1768 struct rop_codes codes;
1770 if (overlap & OVERLAP_BELOW)
1772 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1773 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1774 dst_stride = -dst->stride;
1775 src_stride = -src->stride;
1777 else
1779 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1780 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1781 dst_stride = dst->stride;
1782 src_stride = src->stride;
1785 if (rop2 == R2_COPYPEN)
1787 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1788 memmove( dst_start, src_start, (rc->right - rc->left) );
1789 return;
1792 get_rop_codes( rop2, &codes );
1793 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1795 if (overlap & OVERLAP_RIGHT)
1796 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1797 else
1798 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1802 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1803 const dib_info *src, const POINT *origin, int rop2, int overlap)
1805 BYTE *dst_start, *src_start;
1806 int y, dst_stride, src_stride;
1807 struct rop_codes codes;
1808 int left = dst->rect.left + rc->left;
1809 int right = dst->rect.left + rc->right;
1810 int org_x = src->rect.left + origin->x;
1812 if (overlap & OVERLAP_BELOW)
1814 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1815 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1816 dst_stride = -dst->stride;
1817 src_stride = -src->stride;
1819 else
1821 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1822 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1823 dst_stride = dst->stride;
1824 src_stride = src->stride;
1827 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1829 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1830 memmove( dst_start, src_start, (right - left) / 2 );
1831 return;
1834 get_rop_codes( rop2, &codes );
1835 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1837 if (overlap & OVERLAP_RIGHT)
1838 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1839 else
1840 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1844 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1845 const dib_info *src, const POINT *origin, int rop2, int overlap)
1847 BYTE *dst_start, *src_start;
1848 int y, dst_stride, src_stride;
1849 struct rop_codes codes;
1850 int left = dst->rect.left + rc->left;
1851 int right = dst->rect.left + rc->right;
1852 int org_x = src->rect.left + origin->x;
1854 if (overlap & OVERLAP_BELOW)
1856 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1857 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1858 dst_stride = -dst->stride;
1859 src_stride = -src->stride;
1861 else
1863 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1864 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1865 dst_stride = dst->stride;
1866 src_stride = src->stride;
1869 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1871 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1872 memmove( dst_start, src_start, (right - left) / 8 );
1873 return;
1876 get_rop_codes( rop2, &codes );
1877 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1879 if (overlap & OVERLAP_RIGHT)
1880 do_rop_codes_line_rev_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left, rop2 );
1881 else
1882 do_rop_codes_line_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left, rop2 );
1886 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1887 const dib_info *src, const POINT *origin, int rop2, int overlap)
1889 return;
1892 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
1894 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1895 return *ptr;
1898 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1900 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1901 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1904 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1906 WORD *ptr = get_pixel_ptr_16( dib, x, y );
1907 return *ptr;
1910 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1912 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1913 return *ptr;
1916 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1918 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1920 if ((dib->rect.left + x) & 1)
1921 return *ptr & 0x0f;
1922 else
1923 return (*ptr >> 4) & 0x0f;
1926 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1928 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1929 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
1932 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
1934 return 0;
1937 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1939 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1942 static const DWORD field_masks[33] =
1944 0x00, /* should never happen */
1945 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1946 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1947 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1948 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1951 static inline DWORD get_field(DWORD field, int shift, int len)
1953 shift = shift - (8 - len);
1954 if (shift < 0)
1955 field <<= -shift;
1956 else
1957 field >>= shift;
1958 field &= field_masks[len];
1959 field |= field >> len;
1960 return field;
1963 static inline DWORD put_field(DWORD field, int shift, int len)
1965 shift = shift - (8 - len);
1966 field &= field_masks[len];
1967 if (shift < 0)
1968 field >>= -shift;
1969 else
1970 field <<= shift;
1971 return field;
1974 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1976 DWORD r,g,b;
1978 r = GetRValue(colour);
1979 g = GetGValue(colour);
1980 b = GetBValue(colour);
1982 return put_field(r, dib->red_shift, dib->red_len) |
1983 put_field(g, dib->green_shift, dib->green_len) |
1984 put_field(b, dib->blue_shift, dib->blue_len);
1987 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1989 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1992 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1994 const RGBQUAD *color_table = get_dib_color_table( dib );
1995 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
1996 int i, best_index = 0;
1997 DWORD diff, best_diff = 0xffffffff;
1999 /* special case for conversion to 1-bpp without a color table:
2000 * we get a 1-entry table containing the background color
2002 if (dib->bit_count == 1 && size == 1)
2003 return (r == color_table[0].rgbRed &&
2004 g == color_table[0].rgbGreen &&
2005 b == color_table[0].rgbBlue);
2007 for(i = 0; i < size; i++)
2009 const RGBQUAD *cur = color_table + i;
2010 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
2011 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
2012 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
2014 if(diff == 0)
2016 best_index = i;
2017 break;
2020 if(diff < best_diff)
2022 best_diff = diff;
2023 best_index = i;
2026 return best_index;
2029 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, BYTE r, BYTE g, BYTE b)
2031 DWORD ret;
2033 if (!dither)
2034 ret = rgb_to_pixel_colortable( dib, r, g, b );
2035 else
2036 ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255;
2038 return ret ? 0xff : 0;
2041 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
2043 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
2046 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
2048 return 0;
2051 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
2053 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
2056 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
2058 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
2059 get_field( pixel, dib->green_shift, dib->green_len ),
2060 get_field( pixel, dib->blue_shift, dib->blue_len ) );
2063 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
2065 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
2066 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
2067 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
2070 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
2072 const RGBQUAD *color_table = get_dib_color_table( dib );
2074 if (!dib->color_table || pixel < dib->color_table_size)
2076 RGBQUAD quad = color_table[pixel];
2077 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
2079 return 0;
2082 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
2084 return 0;
2087 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
2089 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
2091 return d1->red_mask == d2->red_mask &&
2092 d1->green_mask == d2->green_mask &&
2093 d1->blue_mask == d2->blue_mask;
2096 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2098 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2099 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2101 switch(src->bit_count)
2103 case 32:
2105 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2106 if(src->funcs == &funcs_8888)
2108 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2109 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2110 else
2112 for(y = src_rect->top; y < src_rect->bottom; y++)
2114 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2115 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2116 dst_start += dst->stride / 4;
2117 src_start += src->stride / 4;
2121 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2123 for(y = src_rect->top; y < src_rect->bottom; y++)
2125 dst_pixel = dst_start;
2126 src_pixel = src_start;
2127 for(x = src_rect->left; x < src_rect->right; x++)
2129 src_val = *src_pixel++;
2130 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
2131 (((src_val >> src->green_shift) & 0xff) << 8) |
2132 ((src_val >> src->blue_shift) & 0xff);
2134 if(pad_size) memset(dst_pixel, 0, pad_size);
2135 dst_start += dst->stride / 4;
2136 src_start += src->stride / 4;
2139 else
2141 for(y = src_rect->top; y < src_rect->bottom; y++)
2143 dst_pixel = dst_start;
2144 src_pixel = src_start;
2145 for(x = src_rect->left; x < src_rect->right; x++)
2147 src_val = *src_pixel++;
2148 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2149 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2150 get_field( src_val, src->blue_shift, src->blue_len ));
2152 if(pad_size) memset(dst_pixel, 0, pad_size);
2153 dst_start += dst->stride / 4;
2154 src_start += src->stride / 4;
2157 break;
2160 case 24:
2162 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2164 for(y = src_rect->top; y < src_rect->bottom; y++)
2166 dst_pixel = dst_start;
2167 src_pixel = src_start;
2168 for(x = src_rect->left; x < src_rect->right; x++)
2170 RGBQUAD rgb;
2171 rgb.rgbBlue = *src_pixel++;
2172 rgb.rgbGreen = *src_pixel++;
2173 rgb.rgbRed = *src_pixel++;
2175 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
2177 if(pad_size) memset(dst_pixel, 0, pad_size);
2178 dst_start += dst->stride / 4;
2179 src_start += src->stride;
2181 break;
2184 case 16:
2186 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2187 if(src->funcs == &funcs_555)
2189 for(y = src_rect->top; y < src_rect->bottom; y++)
2191 dst_pixel = dst_start;
2192 src_pixel = src_start;
2193 for(x = src_rect->left; x < src_rect->right; x++)
2195 src_val = *src_pixel++;
2196 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
2197 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
2198 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
2200 if(pad_size) memset(dst_pixel, 0, pad_size);
2201 dst_start += dst->stride / 4;
2202 src_start += src->stride / 2;
2205 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2207 for(y = src_rect->top; y < src_rect->bottom; y++)
2209 dst_pixel = dst_start;
2210 src_pixel = src_start;
2211 for(x = src_rect->left; x < src_rect->right; x++)
2213 src_val = *src_pixel++;
2214 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2215 (((src_val >> src->red_shift) << 14) & 0x070000) |
2216 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2217 (((src_val >> src->green_shift) << 6) & 0x000700) |
2218 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2219 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2221 if(pad_size) memset(dst_pixel, 0, pad_size);
2222 dst_start += dst->stride / 4;
2223 src_start += src->stride / 2;
2226 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2228 for(y = src_rect->top; y < src_rect->bottom; y++)
2230 dst_pixel = dst_start;
2231 src_pixel = src_start;
2232 for(x = src_rect->left; x < src_rect->right; x++)
2234 src_val = *src_pixel++;
2235 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2236 (((src_val >> src->red_shift) << 14) & 0x070000) |
2237 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2238 (((src_val >> src->green_shift) << 4) & 0x000300) |
2239 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2240 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2242 if(pad_size) memset(dst_pixel, 0, pad_size);
2243 dst_start += dst->stride / 4;
2244 src_start += src->stride / 2;
2247 else
2249 for(y = src_rect->top; y < src_rect->bottom; y++)
2251 dst_pixel = dst_start;
2252 src_pixel = src_start;
2253 for(x = src_rect->left; x < src_rect->right; x++)
2255 src_val = *src_pixel++;
2256 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2257 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2258 get_field( src_val, src->blue_shift, src->blue_len ));
2260 if(pad_size) memset(dst_pixel, 0, pad_size);
2261 dst_start += dst->stride / 4;
2262 src_start += src->stride / 2;
2265 break;
2268 case 8:
2270 const RGBQUAD *color_table = get_dib_color_table( src );
2271 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2272 DWORD dst_colors[256], i;
2274 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2275 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2276 color_table[i].rgbBlue;
2278 for(y = src_rect->top; y < src_rect->bottom; y++)
2280 dst_pixel = dst_start;
2281 src_pixel = src_start;
2282 for(x = src_rect->left; x < src_rect->right; x++)
2283 *dst_pixel++ = dst_colors[*src_pixel++];
2285 if(pad_size) memset(dst_pixel, 0, pad_size);
2286 dst_start += dst->stride / 4;
2287 src_start += src->stride;
2289 break;
2292 case 4:
2294 const RGBQUAD *color_table = get_dib_color_table( src );
2295 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2296 DWORD dst_colors[16], i;
2298 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2299 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2300 color_table[i].rgbBlue;
2302 for(y = src_rect->top; y < src_rect->bottom; y++)
2304 int pos = (src->rect.left + src_rect->left) & 1;
2305 src_pixel = src_start;
2306 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2308 if (pos & 1)
2309 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2310 else
2311 dst_start[x] = dst_colors[*src_pixel >> 4];
2313 if(pad_size) memset(dst_start + x, 0, pad_size);
2314 dst_start += dst->stride / 4;
2315 src_start += src->stride;
2317 break;
2320 case 1:
2322 const RGBQUAD *color_table = get_dib_color_table( src );
2323 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2324 DWORD dst_colors[2], i;
2326 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2327 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2328 color_table[i].rgbBlue;
2330 for(y = src_rect->top; y < src_rect->bottom; y++)
2332 int pos = (src->rect.left + src_rect->left) & 7;
2333 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2335 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2336 dst_start[x] = dst_colors[src_val];
2338 if(pad_size) memset(dst_start + x, 0, pad_size);
2339 dst_start += dst->stride / 4;
2340 src_start += src->stride;
2342 break;
2347 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2349 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2350 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2352 switch(src->bit_count)
2354 case 32:
2356 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2358 if(src->funcs == &funcs_8888)
2360 for(y = src_rect->top; y < src_rect->bottom; y++)
2362 dst_pixel = dst_start;
2363 src_pixel = src_start;
2364 for(x = src_rect->left; x < src_rect->right; x++)
2366 src_val = *src_pixel++;
2367 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2368 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2369 put_field(src_val, dst->blue_shift, dst->blue_len);
2371 if(pad_size) memset(dst_pixel, 0, pad_size);
2372 dst_start += dst->stride / 4;
2373 src_start += src->stride / 4;
2376 else if(bit_fields_match(src, dst))
2378 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2379 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2380 else
2382 for(y = src_rect->top; y < src_rect->bottom; y++)
2384 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2385 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2386 dst_start += dst->stride / 4;
2387 src_start += src->stride / 4;
2391 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
2392 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
2394 for(y = src_rect->top; y < src_rect->bottom; y++)
2396 dst_pixel = dst_start;
2397 src_pixel = src_start;
2398 for(x = src_rect->left; x < src_rect->right; x++)
2400 src_val = *src_pixel++;
2401 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
2402 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
2403 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
2405 if(pad_size) memset(dst_pixel, 0, pad_size);
2406 dst_start += dst->stride / 4;
2407 src_start += src->stride / 4;
2410 else
2412 for(y = src_rect->top; y < src_rect->bottom; y++)
2414 dst_pixel = dst_start;
2415 src_pixel = src_start;
2416 for(x = src_rect->left; x < src_rect->right; x++)
2418 src_val = *src_pixel++;
2419 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2420 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2421 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2423 if(pad_size) memset(dst_pixel, 0, pad_size);
2424 dst_start += dst->stride / 4;
2425 src_start += src->stride / 4;
2428 break;
2431 case 24:
2433 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2435 for(y = src_rect->top; y < src_rect->bottom; y++)
2437 dst_pixel = dst_start;
2438 src_pixel = src_start;
2439 for(x = src_rect->left; x < src_rect->right; x++)
2441 RGBQUAD rgb;
2442 rgb.rgbBlue = *src_pixel++;
2443 rgb.rgbGreen = *src_pixel++;
2444 rgb.rgbRed = *src_pixel++;
2446 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2447 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2448 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2450 if(pad_size) memset(dst_pixel, 0, pad_size);
2451 dst_start += dst->stride / 4;
2452 src_start += src->stride;
2454 break;
2457 case 16:
2459 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2460 if(src->funcs == &funcs_555)
2462 for(y = src_rect->top; y < src_rect->bottom; y++)
2464 dst_pixel = dst_start;
2465 src_pixel = src_start;
2466 for(x = src_rect->left; x < src_rect->right; x++)
2468 src_val = *src_pixel++;
2469 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2470 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2471 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2473 if(pad_size) memset(dst_pixel, 0, pad_size);
2474 dst_start += dst->stride / 4;
2475 src_start += src->stride / 2;
2478 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2480 for(y = src_rect->top; y < src_rect->bottom; y++)
2482 dst_pixel = dst_start;
2483 src_pixel = src_start;
2484 for(x = src_rect->left; x < src_rect->right; x++)
2486 src_val = *src_pixel++;
2487 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2488 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2489 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2490 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2491 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2492 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2494 if(pad_size) memset(dst_pixel, 0, pad_size);
2495 dst_start += dst->stride / 4;
2496 src_start += src->stride / 2;
2499 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2501 for(y = src_rect->top; y < src_rect->bottom; y++)
2503 dst_pixel = dst_start;
2504 src_pixel = src_start;
2505 for(x = src_rect->left; x < src_rect->right; x++)
2507 src_val = *src_pixel++;
2508 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2509 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2510 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2511 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2512 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2513 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2515 if(pad_size) memset(dst_pixel, 0, pad_size);
2516 dst_start += dst->stride / 4;
2517 src_start += src->stride / 2;
2520 else
2522 for(y = src_rect->top; y < src_rect->bottom; y++)
2524 dst_pixel = dst_start;
2525 src_pixel = src_start;
2526 for(x = src_rect->left; x < src_rect->right; x++)
2528 src_val = *src_pixel++;
2529 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2530 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2531 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2533 if(pad_size) memset(dst_pixel, 0, pad_size);
2534 dst_start += dst->stride / 4;
2535 src_start += src->stride / 2;
2538 break;
2541 case 8:
2543 const RGBQUAD *color_table = get_dib_color_table( src );
2544 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2545 DWORD dst_colors[256], i;
2547 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2549 RGBQUAD rgb = color_table[i];
2550 dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2551 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2552 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2555 for(y = src_rect->top; y < src_rect->bottom; y++)
2557 dst_pixel = dst_start;
2558 src_pixel = src_start;
2559 for(x = src_rect->left; x < src_rect->right; x++)
2560 *dst_pixel++ = dst_colors[*src_pixel++];
2562 if(pad_size) memset(dst_pixel, 0, pad_size);
2563 dst_start += dst->stride / 4;
2564 src_start += src->stride;
2566 break;
2569 case 4:
2571 const RGBQUAD *color_table = get_dib_color_table( src );
2572 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2573 DWORD dst_colors[16], i;
2575 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2577 RGBQUAD rgb = color_table[i];
2578 dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2579 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2580 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2583 for(y = src_rect->top; y < src_rect->bottom; y++)
2585 int pos = (src->rect.left + src_rect->left) & 1;
2586 src_pixel = src_start;
2587 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2589 if (pos & 1)
2590 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2591 else
2592 dst_start[x] = dst_colors[*src_pixel >> 4];
2594 if(pad_size) memset(dst_start + x, 0, pad_size);
2595 dst_start += dst->stride / 4;
2596 src_start += src->stride;
2598 break;
2601 case 1:
2603 const RGBQUAD *color_table = get_dib_color_table( src );
2604 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2605 DWORD dst_colors[2], i;
2607 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
2609 RGBQUAD rgb = color_table[i];
2610 dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2611 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2612 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2615 for(y = src_rect->top; y < src_rect->bottom; y++)
2617 int pos = (src->rect.left + src_rect->left) & 7;
2618 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2620 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2621 dst_start[x] = dst_colors[src_val];
2623 if(pad_size) memset(dst_start + x, 0, pad_size);
2624 dst_start += dst->stride / 4;
2625 src_start += src->stride;
2627 break;
2632 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2634 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2635 DWORD src_val;
2636 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2638 switch(src->bit_count)
2640 case 32:
2642 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2643 if(src->funcs == &funcs_8888)
2645 for(y = src_rect->top; y < src_rect->bottom; y++)
2647 dst_pixel = dst_start;
2648 src_pixel = src_start;
2649 for(x = src_rect->left; x < src_rect->right; x++)
2651 src_val = *src_pixel++;
2652 *dst_pixel++ = src_val & 0xff;
2653 *dst_pixel++ = (src_val >> 8) & 0xff;
2654 *dst_pixel++ = (src_val >> 16) & 0xff;
2656 if(pad_size) memset(dst_pixel, 0, pad_size);
2657 dst_start += dst->stride;
2658 src_start += src->stride / 4;
2661 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2663 for(y = src_rect->top; y < src_rect->bottom; y++)
2665 dst_pixel = dst_start;
2666 src_pixel = src_start;
2667 for(x = src_rect->left; x < src_rect->right; x++)
2669 src_val = *src_pixel++;
2670 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2671 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2672 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2674 if(pad_size) memset(dst_pixel, 0, pad_size);
2675 dst_start += dst->stride;
2676 src_start += src->stride / 4;
2679 else
2681 for(y = src_rect->top; y < src_rect->bottom; y++)
2683 dst_pixel = dst_start;
2684 src_pixel = src_start;
2685 for(x = src_rect->left; x < src_rect->right; x++)
2687 src_val = *src_pixel++;
2688 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2689 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2690 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2692 if(pad_size) memset(dst_pixel, 0, pad_size);
2693 dst_start += dst->stride;
2694 src_start += src->stride / 4;
2697 break;
2700 case 24:
2702 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2704 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2705 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2706 else
2708 for(y = src_rect->top; y < src_rect->bottom; y++)
2710 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2711 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2712 dst_start += dst->stride;
2713 src_start += src->stride;
2716 break;
2719 case 16:
2721 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2722 if(src->funcs == &funcs_555)
2724 for(y = src_rect->top; y < src_rect->bottom; y++)
2726 dst_pixel = dst_start;
2727 src_pixel = src_start;
2728 for(x = src_rect->left; x < src_rect->right; x++)
2730 src_val = *src_pixel++;
2731 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2732 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2733 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2735 if(pad_size) memset(dst_pixel, 0, pad_size);
2736 dst_start += dst->stride;
2737 src_start += src->stride / 2;
2740 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
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 >> src->blue_shift) << 3) & 0xf8) |
2750 (((src_val >> src->blue_shift) >> 2) & 0x07);
2751 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2752 (((src_val >> src->green_shift) >> 2) & 0x07);
2753 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2754 (((src_val >> src->red_shift) >> 2) & 0x07);
2756 if(pad_size) memset(dst_pixel, 0, pad_size);
2757 dst_start += dst->stride;
2758 src_start += src->stride / 2;
2761 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2763 for(y = src_rect->top; y < src_rect->bottom; y++)
2765 dst_pixel = dst_start;
2766 src_pixel = src_start;
2767 for(x = src_rect->left; x < src_rect->right; x++)
2769 src_val = *src_pixel++;
2770 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2771 (((src_val >> src->blue_shift) >> 2) & 0x07);
2772 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2773 (((src_val >> src->green_shift) >> 4) & 0x03);
2774 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2775 (((src_val >> src->red_shift) >> 2) & 0x07);
2777 if(pad_size) memset(dst_pixel, 0, pad_size);
2778 dst_start += dst->stride;
2779 src_start += src->stride / 2;
2782 else
2784 for(y = src_rect->top; y < src_rect->bottom; y++)
2786 dst_pixel = dst_start;
2787 src_pixel = src_start;
2788 for(x = src_rect->left; x < src_rect->right; x++)
2790 src_val = *src_pixel++;
2791 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2792 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2793 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2795 if(pad_size) memset(dst_pixel, 0, pad_size);
2796 dst_start += dst->stride;
2797 src_start += src->stride / 2;
2800 break;
2803 case 8:
2805 const RGBQUAD *color_table = get_dib_color_table( src );
2806 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2807 for(y = src_rect->top; y < src_rect->bottom; y++)
2809 dst_pixel = dst_start;
2810 src_pixel = src_start;
2811 for(x = src_rect->left; x < src_rect->right; x++)
2813 RGBQUAD rgb = color_table[*src_pixel++];
2814 *dst_pixel++ = rgb.rgbBlue;
2815 *dst_pixel++ = rgb.rgbGreen;
2816 *dst_pixel++ = rgb.rgbRed;
2818 if(pad_size) memset(dst_pixel, 0, pad_size);
2819 dst_start += dst->stride;
2820 src_start += src->stride;
2822 break;
2825 case 4:
2827 const RGBQUAD *color_table = get_dib_color_table( src );
2828 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2829 for(y = src_rect->top; y < src_rect->bottom; y++)
2831 int pos = (src->rect.left + src_rect->left) & 1;
2832 src_pixel = src_start;
2833 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2835 RGBQUAD rgb;
2836 if (pos & 1)
2837 rgb = color_table[*src_pixel++ & 0xf];
2838 else
2839 rgb = color_table[*src_pixel >> 4];
2840 dst_start[x * 3] = rgb.rgbBlue;
2841 dst_start[x * 3 + 1] = rgb.rgbGreen;
2842 dst_start[x * 3 + 2] = rgb.rgbRed;
2844 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2845 dst_start += dst->stride;
2846 src_start += src->stride;
2848 break;
2851 case 1:
2853 const RGBQUAD *color_table = get_dib_color_table( src );
2854 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2855 for(y = src_rect->top; y < src_rect->bottom; y++)
2857 int pos = (src->rect.left + src_rect->left) & 7;
2858 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2860 RGBQUAD rgb;
2861 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2862 rgb = color_table[src_val];
2863 dst_start[x * 3] = rgb.rgbBlue;
2864 dst_start[x * 3 + 1] = rgb.rgbGreen;
2865 dst_start[x * 3 + 2] = rgb.rgbRed;
2867 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2868 dst_start += dst->stride;
2869 src_start += src->stride;
2871 break;
2876 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2878 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2879 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2880 DWORD src_val;
2882 switch(src->bit_count)
2884 case 32:
2886 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2888 if(src->funcs == &funcs_8888)
2890 for(y = src_rect->top; y < src_rect->bottom; y++)
2892 dst_pixel = dst_start;
2893 src_pixel = src_start;
2894 for(x = src_rect->left; x < src_rect->right; x++)
2896 src_val = *src_pixel++;
2897 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2898 ((src_val >> 6) & 0x03e0) |
2899 ((src_val >> 3) & 0x001f);
2901 if(pad_size) memset(dst_pixel, 0, pad_size);
2902 dst_start += dst->stride / 2;
2903 src_start += src->stride / 4;
2906 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2908 for(y = src_rect->top; y < src_rect->bottom; y++)
2910 dst_pixel = dst_start;
2911 src_pixel = src_start;
2912 for(x = src_rect->left; x < src_rect->right; x++)
2914 src_val = *src_pixel++;
2915 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2916 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2917 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2919 if(pad_size) memset(dst_pixel, 0, pad_size);
2920 dst_start += dst->stride / 2;
2921 src_start += src->stride / 4;
2924 else
2926 for(y = src_rect->top; y < src_rect->bottom; y++)
2928 dst_pixel = dst_start;
2929 src_pixel = src_start;
2930 for(x = src_rect->left; x < src_rect->right; x++)
2932 src_val = *src_pixel++;
2933 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2934 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2935 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2937 if(pad_size) memset(dst_pixel, 0, pad_size);
2938 dst_start += dst->stride / 2;
2939 src_start += src->stride / 4;
2942 break;
2945 case 24:
2947 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2949 for(y = src_rect->top; y < src_rect->bottom; y++)
2951 dst_pixel = dst_start;
2952 src_pixel = src_start;
2953 for(x = src_rect->left; x < src_rect->right; x++)
2955 RGBQUAD rgb;
2956 rgb.rgbBlue = *src_pixel++;
2957 rgb.rgbGreen = *src_pixel++;
2958 rgb.rgbRed = *src_pixel++;
2960 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2961 ((rgb.rgbGreen << 2) & 0x03e0) |
2962 ((rgb.rgbBlue >> 3) & 0x001f);
2964 if(pad_size) memset(dst_pixel, 0, pad_size);
2965 dst_start += dst->stride / 2;
2966 src_start += src->stride;
2968 break;
2971 case 16:
2973 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2974 if(src->funcs == &funcs_555)
2976 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2977 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2978 else
2980 for(y = src_rect->top; y < src_rect->bottom; y++)
2982 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2983 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2984 dst_start += dst->stride / 2;
2985 src_start += src->stride / 2;
2989 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2991 for(y = src_rect->top; y < src_rect->bottom; y++)
2993 dst_pixel = dst_start;
2994 src_pixel = src_start;
2995 for(x = src_rect->left; x < src_rect->right; x++)
2997 src_val = *src_pixel++;
2998 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2999 (((src_val >> src->green_shift) << 5) & 0x03e0) |
3000 ( (src_val >> src->blue_shift) & 0x001f);
3002 if(pad_size) memset(dst_pixel, 0, pad_size);
3003 dst_start += dst->stride / 2;
3004 src_start += src->stride / 2;
3007 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3009 for(y = src_rect->top; y < src_rect->bottom; y++)
3011 dst_pixel = dst_start;
3012 src_pixel = src_start;
3013 for(x = src_rect->left; x < src_rect->right; x++)
3015 src_val = *src_pixel++;
3016 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
3017 (((src_val >> src->green_shift) << 4) & 0x03e0) |
3018 ( (src_val >> src->blue_shift) & 0x001f);
3020 if(pad_size) memset(dst_pixel, 0, pad_size);
3021 dst_start += dst->stride / 2;
3022 src_start += src->stride / 2;
3025 else
3027 for(y = src_rect->top; y < src_rect->bottom; y++)
3029 dst_pixel = dst_start;
3030 src_pixel = src_start;
3031 for(x = src_rect->left; x < src_rect->right; x++)
3033 src_val = *src_pixel++;
3034 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
3035 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
3036 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
3038 if(pad_size) memset(dst_pixel, 0, pad_size);
3039 dst_start += dst->stride / 2;
3040 src_start += src->stride / 2;
3043 break;
3046 case 8:
3048 const RGBQUAD *color_table = get_dib_color_table( src );
3049 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3050 WORD dst_colors[256];
3051 int i;
3053 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3054 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3055 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3056 ((color_table[i].rgbBlue >> 3) & 0x001f);
3058 for(y = src_rect->top; y < src_rect->bottom; y++)
3060 dst_pixel = dst_start;
3061 src_pixel = src_start;
3062 for(x = src_rect->left; x < src_rect->right; x++)
3063 *dst_pixel++ = dst_colors[*src_pixel++];
3065 if(pad_size) memset(dst_pixel, 0, pad_size);
3066 dst_start += dst->stride / 2;
3067 src_start += src->stride;
3069 break;
3072 case 4:
3074 const RGBQUAD *color_table = get_dib_color_table( src );
3075 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3076 WORD dst_colors[16];
3077 int i;
3079 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3080 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3081 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3082 ((color_table[i].rgbBlue >> 3) & 0x001f);
3084 for(y = src_rect->top; y < src_rect->bottom; y++)
3086 int pos = (src->rect.left + src_rect->left) & 1;
3087 src_pixel = src_start;
3088 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3090 if (pos & 1)
3091 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3092 else
3093 dst_start[x] = dst_colors[*src_pixel >> 4];
3095 if(pad_size) memset(dst_start + x, 0, pad_size);
3096 dst_start += dst->stride / 2;
3097 src_start += src->stride;
3099 break;
3102 case 1:
3104 const RGBQUAD *color_table = get_dib_color_table( src );
3105 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3106 WORD dst_colors[2];
3107 int i;
3109 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3110 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3111 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3112 ((color_table[i].rgbBlue >> 3) & 0x001f);
3114 for(y = src_rect->top; y < src_rect->bottom; y++)
3116 int pos = (src->rect.left + src_rect->left) & 7;
3117 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3119 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3120 dst_start[x] = dst_colors[src_val];
3122 if(pad_size) memset(dst_start + x, 0, pad_size);
3123 dst_start += dst->stride / 2;
3124 src_start += src->stride;
3126 break;
3131 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3133 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
3134 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
3135 DWORD src_val;
3137 switch(src->bit_count)
3139 case 32:
3141 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3143 if(src->funcs == &funcs_8888)
3145 for(y = src_rect->top; y < src_rect->bottom; y++)
3147 dst_pixel = dst_start;
3148 src_pixel = src_start;
3149 for(x = src_rect->left; x < src_rect->right; x++)
3151 src_val = *src_pixel++;
3152 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
3153 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
3154 put_field(src_val, dst->blue_shift, dst->blue_len);
3156 if(pad_size) memset(dst_pixel, 0, pad_size);
3157 dst_start += dst->stride / 2;
3158 src_start += src->stride / 4;
3161 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3163 for(y = src_rect->top; y < src_rect->bottom; y++)
3165 dst_pixel = dst_start;
3166 src_pixel = src_start;
3167 for(x = src_rect->left; x < src_rect->right; x++)
3169 src_val = *src_pixel++;
3170 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
3171 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
3172 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
3174 if(pad_size) memset(dst_pixel, 0, pad_size);
3175 dst_start += dst->stride / 2;
3176 src_start += src->stride / 4;
3179 else
3181 for(y = src_rect->top; y < src_rect->bottom; y++)
3183 dst_pixel = dst_start;
3184 src_pixel = src_start;
3185 for(x = src_rect->left; x < src_rect->right; x++)
3187 src_val = *src_pixel++;
3188 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
3189 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
3190 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
3192 if(pad_size) memset(dst_pixel, 0, pad_size);
3193 dst_start += dst->stride / 2;
3194 src_start += src->stride / 4;
3197 break;
3200 case 24:
3202 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3204 for(y = src_rect->top; y < src_rect->bottom; y++)
3206 dst_pixel = dst_start;
3207 src_pixel = src_start;
3208 for(x = src_rect->left; x < src_rect->right; x++)
3210 RGBQUAD rgb;
3211 rgb.rgbBlue = *src_pixel++;
3212 rgb.rgbGreen = *src_pixel++;
3213 rgb.rgbRed = *src_pixel++;
3215 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3216 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3217 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3219 if(pad_size) memset(dst_pixel, 0, pad_size);
3220 dst_start += dst->stride / 2;
3221 src_start += src->stride;
3223 break;
3226 case 16:
3228 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3229 if(src->funcs == &funcs_555)
3231 for(y = src_rect->top; y < src_rect->bottom; y++)
3233 dst_pixel = dst_start;
3234 src_pixel = src_start;
3235 for(x = src_rect->left; x < src_rect->right; x++)
3237 src_val = *src_pixel++;
3238 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
3239 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
3240 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
3242 if(pad_size) memset(dst_pixel, 0, pad_size);
3243 dst_start += dst->stride / 2;
3244 src_start += src->stride / 2;
3247 else if(bit_fields_match(src, dst))
3249 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3250 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3251 else
3253 for(y = src_rect->top; y < src_rect->bottom; y++)
3255 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
3256 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3257 dst_start += dst->stride / 2;
3258 src_start += src->stride / 2;
3262 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3264 for(y = src_rect->top; y < src_rect->bottom; y++)
3266 dst_pixel = dst_start;
3267 src_pixel = src_start;
3268 for(x = src_rect->left; x < src_rect->right; x++)
3270 src_val = *src_pixel++;
3271 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
3272 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
3273 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
3274 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
3275 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
3276 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
3278 if(pad_size) memset(dst_pixel, 0, pad_size);
3279 dst_start += dst->stride / 2;
3280 src_start += src->stride / 2;
3283 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3285 for(y = src_rect->top; y < src_rect->bottom; y++)
3287 dst_pixel = dst_start;
3288 src_pixel = src_start;
3289 for(x = src_rect->left; x < src_rect->right; x++)
3291 src_val = *src_pixel++;
3292 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
3293 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
3294 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
3295 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
3296 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
3297 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
3299 if(pad_size) memset(dst_pixel, 0, pad_size);
3300 dst_start += dst->stride / 2;
3301 src_start += src->stride / 2;
3304 else
3306 for(y = src_rect->top; y < src_rect->bottom; y++)
3308 dst_pixel = dst_start;
3309 src_pixel = src_start;
3310 for(x = src_rect->left; x < src_rect->right; x++)
3312 src_val = *src_pixel++;
3313 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
3314 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
3315 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
3317 if(pad_size) memset(dst_pixel, 0, pad_size);
3318 dst_start += dst->stride / 2;
3319 src_start += src->stride / 2;
3322 break;
3325 case 8:
3327 const RGBQUAD *color_table = get_dib_color_table( src );
3328 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3329 WORD dst_colors[256];
3330 int i;
3332 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3334 RGBQUAD rgb = color_table[i];
3335 dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3336 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3337 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3340 for(y = src_rect->top; y < src_rect->bottom; y++)
3342 dst_pixel = dst_start;
3343 src_pixel = src_start;
3344 for(x = src_rect->left; x < src_rect->right; x++)
3345 *dst_pixel++ = dst_colors[*src_pixel++];
3347 if(pad_size) memset(dst_pixel, 0, pad_size);
3348 dst_start += dst->stride / 2;
3349 src_start += src->stride;
3351 break;
3354 case 4:
3356 const RGBQUAD *color_table = get_dib_color_table( src );
3357 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3358 WORD dst_colors[16];
3359 int i;
3361 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3363 RGBQUAD rgb = color_table[i];
3364 dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3365 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3366 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3369 for(y = src_rect->top; y < src_rect->bottom; y++)
3371 int pos = (src->rect.left + src_rect->left) & 1;
3372 src_pixel = src_start;
3373 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3375 if (pos & 1)
3376 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3377 else
3378 dst_start[x] = dst_colors[*src_pixel >> 4];
3380 if(pad_size) memset(dst_start + x, 0, pad_size);
3381 dst_start += dst->stride / 2;
3382 src_start += src->stride;
3384 break;
3387 case 1:
3389 const RGBQUAD *color_table = get_dib_color_table( src );
3390 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3391 WORD dst_colors[2];
3392 int i;
3394 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3396 RGBQUAD rgb = color_table[i];
3397 dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3398 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3399 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3402 for(y = src_rect->top; y < src_rect->bottom; y++)
3404 int pos = (src->rect.left + src_rect->left) & 7;
3405 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3407 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3408 dst_start[x] = dst_colors[src_val];
3410 if(pad_size) memset(dst_start + x, 0, pad_size);
3411 dst_start += dst->stride / 2;
3412 src_start += src->stride;
3414 break;
3419 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
3421 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
3422 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
3425 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
3427 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
3428 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
3431 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3433 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
3434 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
3435 DWORD src_val;
3437 switch(src->bit_count)
3439 case 32:
3441 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3443 if(src->funcs == &funcs_8888)
3445 for(y = src_rect->top; y < src_rect->bottom; y++)
3447 dst_pixel = dst_start;
3448 src_pixel = src_start;
3449 for(x = src_rect->left; x < src_rect->right; x++)
3451 src_val = *src_pixel++;
3452 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
3454 if(pad_size) memset(dst_pixel, 0, pad_size);
3455 dst_start += dst->stride;
3456 src_start += src->stride / 4;
3459 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3461 for(y = src_rect->top; y < src_rect->bottom; y++)
3463 dst_pixel = dst_start;
3464 src_pixel = src_start;
3465 for(x = src_rect->left; x < src_rect->right; x++)
3467 src_val = *src_pixel++;
3468 *dst_pixel++ = rgb_lookup_colortable(dst,
3469 src_val >> src->red_shift,
3470 src_val >> src->green_shift,
3471 src_val >> src->blue_shift );
3473 if(pad_size) memset(dst_pixel, 0, pad_size);
3474 dst_start += dst->stride;
3475 src_start += src->stride / 4;
3478 else
3480 for(y = src_rect->top; y < src_rect->bottom; y++)
3482 dst_pixel = dst_start;
3483 src_pixel = src_start;
3484 for(x = src_rect->left; x < src_rect->right; x++)
3486 src_val = *src_pixel++;
3487 *dst_pixel++ = rgb_lookup_colortable(dst,
3488 get_field(src_val, src->red_shift, src->red_len),
3489 get_field(src_val, src->green_shift, src->green_len),
3490 get_field(src_val, src->blue_shift, src->blue_len));
3492 if(pad_size) memset(dst_pixel, 0, pad_size);
3493 dst_start += dst->stride;
3494 src_start += src->stride / 4;
3497 break;
3500 case 24:
3502 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3504 for(y = src_rect->top; y < src_rect->bottom; y++)
3506 dst_pixel = dst_start;
3507 src_pixel = src_start;
3508 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3510 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
3512 if(pad_size) memset(dst_pixel, 0, pad_size);
3513 dst_start += dst->stride;
3514 src_start += src->stride;
3516 break;
3519 case 16:
3521 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3522 if(src->funcs == &funcs_555)
3524 for(y = src_rect->top; y < src_rect->bottom; y++)
3526 dst_pixel = dst_start;
3527 src_pixel = src_start;
3528 for(x = src_rect->left; x < src_rect->right; x++)
3530 src_val = *src_pixel++;
3531 *dst_pixel++ = rgb_lookup_colortable(dst,
3532 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3533 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3534 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3536 if(pad_size) memset(dst_pixel, 0, pad_size);
3537 dst_start += dst->stride;
3538 src_start += src->stride / 2;
3541 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3543 for(y = src_rect->top; y < src_rect->bottom; y++)
3545 dst_pixel = dst_start;
3546 src_pixel = src_start;
3547 for(x = src_rect->left; x < src_rect->right; x++)
3549 src_val = *src_pixel++;
3550 *dst_pixel++ = rgb_lookup_colortable(dst,
3551 (((src_val >> src->red_shift) << 3) & 0xf8) |
3552 (((src_val >> src->red_shift) >> 2) & 0x07),
3553 (((src_val >> src->green_shift) << 3) & 0xf8) |
3554 (((src_val >> src->green_shift) >> 2) & 0x07),
3555 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3556 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3558 if(pad_size) memset(dst_pixel, 0, pad_size);
3559 dst_start += dst->stride;
3560 src_start += src->stride / 2;
3563 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3565 for(y = src_rect->top; y < src_rect->bottom; y++)
3567 dst_pixel = dst_start;
3568 src_pixel = src_start;
3569 for(x = src_rect->left; x < src_rect->right; x++)
3571 src_val = *src_pixel++;
3572 *dst_pixel++ = rgb_lookup_colortable(dst,
3573 (((src_val >> src->red_shift) << 3) & 0xf8) |
3574 (((src_val >> src->red_shift) >> 2) & 0x07),
3575 (((src_val >> src->green_shift) << 2) & 0xfc) |
3576 (((src_val >> src->green_shift) >> 4) & 0x03),
3577 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3578 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3580 if(pad_size) memset(dst_pixel, 0, pad_size);
3581 dst_start += dst->stride;
3582 src_start += src->stride / 2;
3585 else
3587 for(y = src_rect->top; y < src_rect->bottom; y++)
3589 dst_pixel = dst_start;
3590 src_pixel = src_start;
3591 for(x = src_rect->left; x < src_rect->right; x++)
3593 src_val = *src_pixel++;
3594 *dst_pixel++ = rgb_lookup_colortable(dst,
3595 get_field(src_val, src->red_shift, src->red_len),
3596 get_field(src_val, src->green_shift, src->green_len),
3597 get_field(src_val, src->blue_shift, src->blue_len));
3599 if(pad_size) memset(dst_pixel, 0, pad_size);
3600 dst_start += dst->stride;
3601 src_start += src->stride / 2;
3604 break;
3607 case 8:
3609 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3611 if(color_tables_match(dst, src))
3613 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3614 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3615 else
3617 for(y = src_rect->top; y < src_rect->bottom; y++)
3619 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
3620 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3621 dst_start += dst->stride;
3622 src_start += src->stride;
3626 else
3628 const RGBQUAD *color_table = get_dib_color_table( src );
3629 BYTE dst_colors[256];
3630 int i;
3632 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3634 RGBQUAD rgb = color_table[i];
3635 dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3638 for(y = src_rect->top; y < src_rect->bottom; y++)
3640 dst_pixel = dst_start;
3641 src_pixel = src_start;
3642 for(x = src_rect->left; x < src_rect->right; x++)
3643 *dst_pixel++ = dst_colors[*src_pixel++];
3645 if(pad_size) memset(dst_pixel, 0, pad_size);
3646 dst_start += dst->stride;
3647 src_start += src->stride;
3650 break;
3653 case 4:
3655 const RGBQUAD *color_table = get_dib_color_table( src );
3656 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3657 BYTE dst_colors[16];
3658 int i;
3660 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3662 RGBQUAD rgb = color_table[i];
3663 dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3666 for(y = src_rect->top; y < src_rect->bottom; y++)
3668 int pos = (src->rect.left + src_rect->left) & 1;
3669 src_pixel = src_start;
3670 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3672 if (pos & 1)
3673 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3674 else
3675 dst_start[x] = dst_colors[*src_pixel >> 4];
3677 if(pad_size) memset(dst_start + x, 0, pad_size);
3678 dst_start += dst->stride;
3679 src_start += src->stride;
3681 break;
3684 case 1:
3686 const RGBQUAD *color_table = get_dib_color_table( src );
3687 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3688 BYTE dst_colors[2];
3689 int i;
3691 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3693 RGBQUAD rgb = color_table[i];
3694 dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3697 for(y = src_rect->top; y < src_rect->bottom; y++)
3699 int pos = (src->rect.left + src_rect->left) & 7;
3700 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3702 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3703 dst_start[x] = dst_colors[src_val];
3705 if(pad_size) memset(dst_start + x, 0, pad_size);
3706 dst_start += dst->stride;
3707 src_start += src->stride;
3709 break;
3714 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3716 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3717 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3718 DWORD src_val;
3720 switch(src->bit_count)
3722 case 32:
3724 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3726 if(src->funcs == &funcs_8888)
3728 for(y = src_rect->top; y < src_rect->bottom; y++)
3730 dst_pixel = dst_start;
3731 src_pixel = src_start;
3732 for(x = src_rect->left; x < src_rect->right; x++)
3734 src_val = *src_pixel++;
3735 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3736 if((x - src_rect->left) & 1)
3738 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3739 dst_pixel++;
3741 else
3742 *dst_pixel = (dst_val << 4) & 0xf0;
3744 if(pad_size)
3746 if((x - src_rect->left) & 1) dst_pixel++;
3747 memset(dst_pixel, 0, pad_size);
3749 dst_start += dst->stride;
3750 src_start += src->stride / 4;
3753 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3755 for(y = src_rect->top; y < src_rect->bottom; y++)
3757 dst_pixel = dst_start;
3758 src_pixel = src_start;
3759 for(x = src_rect->left; x < src_rect->right; x++)
3761 src_val = *src_pixel++;
3762 dst_val = rgb_to_pixel_colortable(dst,
3763 src_val >> src->red_shift,
3764 src_val >> src->green_shift,
3765 src_val >> src->blue_shift);
3766 if((x - src_rect->left) & 1)
3768 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3769 dst_pixel++;
3771 else
3772 *dst_pixel = (dst_val << 4) & 0xf0;
3774 if(pad_size)
3776 if((x - src_rect->left) & 1) dst_pixel++;
3777 memset(dst_pixel, 0, pad_size);
3779 dst_start += dst->stride;
3780 src_start += src->stride / 4;
3783 else
3785 for(y = src_rect->top; y < src_rect->bottom; y++)
3787 dst_pixel = dst_start;
3788 src_pixel = src_start;
3789 for(x = src_rect->left; x < src_rect->right; x++)
3791 src_val = *src_pixel++;
3792 dst_val = rgb_to_pixel_colortable(dst,
3793 get_field(src_val, src->red_shift, src->red_len),
3794 get_field(src_val, src->green_shift, src->green_len),
3795 get_field(src_val, src->blue_shift, src->blue_len));
3796 if((x - src_rect->left) & 1)
3798 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3799 dst_pixel++;
3801 else
3802 *dst_pixel = (dst_val << 4) & 0xf0;
3804 if(pad_size)
3806 if((x - src_rect->left) & 1) dst_pixel++;
3807 memset(dst_pixel, 0, pad_size);
3809 dst_start += dst->stride;
3810 src_start += src->stride / 4;
3813 break;
3816 case 24:
3818 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3820 for(y = src_rect->top; y < src_rect->bottom; y++)
3822 dst_pixel = dst_start;
3823 src_pixel = src_start;
3824 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3826 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3828 if((x - src_rect->left) & 1)
3830 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3831 dst_pixel++;
3833 else
3834 *dst_pixel = (dst_val << 4) & 0xf0;
3836 if(pad_size)
3838 if((x - src_rect->left) & 1) dst_pixel++;
3839 memset(dst_pixel, 0, pad_size);
3841 dst_start += dst->stride;
3842 src_start += src->stride;
3844 break;
3847 case 16:
3849 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3850 if(src->funcs == &funcs_555)
3852 for(y = src_rect->top; y < src_rect->bottom; y++)
3854 dst_pixel = dst_start;
3855 src_pixel = src_start;
3856 for(x = src_rect->left; x < src_rect->right; x++)
3858 src_val = *src_pixel++;
3859 dst_val = rgb_to_pixel_colortable(dst,
3860 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3861 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3862 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3863 if((x - src_rect->left) & 1)
3865 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3866 dst_pixel++;
3868 else
3869 *dst_pixel = (dst_val << 4) & 0xf0;
3871 if(pad_size)
3873 if((x - src_rect->left) & 1) dst_pixel++;
3874 memset(dst_pixel, 0, pad_size);
3876 dst_start += dst->stride;
3877 src_start += src->stride / 2;
3880 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3882 for(y = src_rect->top; y < src_rect->bottom; y++)
3884 dst_pixel = dst_start;
3885 src_pixel = src_start;
3886 for(x = src_rect->left; x < src_rect->right; x++)
3888 src_val = *src_pixel++;
3889 dst_val = rgb_to_pixel_colortable(dst,
3890 (((src_val >> src->red_shift) << 3) & 0xf8) |
3891 (((src_val >> src->red_shift) >> 2) & 0x07),
3892 (((src_val >> src->green_shift) << 3) & 0xf8) |
3893 (((src_val >> src->green_shift) >> 2) & 0x07),
3894 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3895 (((src_val >> src->blue_shift) >> 2) & 0x07) );
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 / 2;
3913 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3915 for(y = src_rect->top; y < src_rect->bottom; y++)
3917 dst_pixel = dst_start;
3918 src_pixel = src_start;
3919 for(x = src_rect->left; x < src_rect->right; x++)
3921 src_val = *src_pixel++;
3922 dst_val = rgb_to_pixel_colortable(dst,
3923 (((src_val >> src->red_shift) << 3) & 0xf8) |
3924 (((src_val >> src->red_shift) >> 2) & 0x07),
3925 (((src_val >> src->green_shift) << 2) & 0xfc) |
3926 (((src_val >> src->green_shift) >> 4) & 0x03),
3927 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3928 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3929 if((x - src_rect->left) & 1)
3931 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3932 dst_pixel++;
3934 else
3935 *dst_pixel = (dst_val << 4) & 0xf0;
3937 if(pad_size)
3939 if((x - src_rect->left) & 1) dst_pixel++;
3940 memset(dst_pixel, 0, pad_size);
3942 dst_start += dst->stride;
3943 src_start += src->stride / 2;
3946 else
3948 for(y = src_rect->top; y < src_rect->bottom; y++)
3950 dst_pixel = dst_start;
3951 src_pixel = src_start;
3952 for(x = src_rect->left; x < src_rect->right; x++)
3954 src_val = *src_pixel++;
3955 dst_val = rgb_to_pixel_colortable(dst,
3956 get_field(src_val, src->red_shift, src->red_len),
3957 get_field(src_val, src->green_shift, src->green_len),
3958 get_field(src_val, src->blue_shift, src->blue_len));
3959 if((x - src_rect->left) & 1)
3961 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3962 dst_pixel++;
3964 else
3965 *dst_pixel = (dst_val << 4) & 0xf0;
3967 if(pad_size)
3969 if((x - src_rect->left) & 1) dst_pixel++;
3970 memset(dst_pixel, 0, pad_size);
3972 dst_start += dst->stride;
3973 src_start += src->stride / 2;
3976 break;
3979 case 8:
3981 const RGBQUAD *color_table = get_dib_color_table( src );
3982 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3983 BYTE dst_colors[256];
3984 int i;
3986 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
3988 RGBQUAD rgb = color_table[i];
3989 dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3992 for(y = src_rect->top; y < src_rect->bottom; y++)
3994 dst_pixel = dst_start;
3995 src_pixel = src_start;
3996 for(x = src_rect->left; x < src_rect->right; x++)
3998 dst_val = dst_colors[*src_pixel++];
3999 if((x - src_rect->left) & 1)
4001 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4002 dst_pixel++;
4004 else
4005 *dst_pixel = (dst_val << 4) & 0xf0;
4007 if(pad_size)
4009 if((x - src_rect->left) & 1) dst_pixel++;
4010 memset(dst_pixel, 0, pad_size);
4012 dst_start += dst->stride;
4013 src_start += src->stride;
4015 break;
4018 case 4:
4020 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4022 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
4024 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
4025 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
4026 else
4028 for(y = src_rect->top; y < src_rect->bottom; y++)
4030 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
4031 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
4032 dst_start += dst->stride;
4033 src_start += src->stride;
4037 else
4039 const RGBQUAD *color_table = get_dib_color_table( src );
4040 BYTE dst_colors[16];
4041 int i;
4043 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
4045 RGBQUAD rgb = color_table[i];
4046 dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4049 for(y = src_rect->top; y < src_rect->bottom; y++)
4051 int pos = (src->rect.left + src_rect->left) & 1;
4052 dst_pixel = dst_start;
4053 src_pixel = src_start;
4054 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4056 if(pos & 1)
4057 dst_val = dst_colors[*src_pixel++ & 0xf];
4058 else
4059 dst_val = dst_colors[*src_pixel >> 4];
4060 if((x - src_rect->left) & 1)
4062 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4063 dst_pixel++;
4065 else
4066 *dst_pixel = (dst_val << 4) & 0xf0;
4068 if(pad_size)
4070 if((x - src_rect->left) & 1) dst_pixel++;
4071 memset(dst_pixel, 0, pad_size);
4073 dst_start += dst->stride;
4074 src_start += src->stride;
4077 break;
4080 case 1:
4082 const RGBQUAD *color_table = get_dib_color_table( src );
4083 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4084 BYTE dst_colors[2];
4085 int i;
4087 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
4089 RGBQUAD rgb = color_table[i];
4090 dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4093 for(y = src_rect->top; y < src_rect->bottom; y++)
4095 int pos = (src->rect.left + src_rect->left) & 7;
4096 dst_pixel = dst_start;
4097 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4099 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4100 dst_val = dst_colors[src_val];
4101 if((x - src_rect->left) & 1)
4103 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4104 dst_pixel++;
4106 else
4107 *dst_pixel = (dst_val << 4) & 0xf0;
4109 if(pad_size)
4111 if((x - src_rect->left) & 1) dst_pixel++;
4112 memset(dst_pixel, 0, pad_size);
4114 dst_start += dst->stride;
4115 src_start += src->stride;
4117 break;
4122 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4124 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
4125 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
4126 DWORD src_val;
4127 int bit_pos;
4129 switch(src->bit_count)
4131 case 32:
4133 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
4135 if(src->funcs == &funcs_8888)
4137 for(y = src_rect->top; y < src_rect->bottom; y++)
4139 dst_pixel = dst_start;
4140 src_pixel = src_start;
4141 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4143 src_val = *src_pixel++;
4144 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val >> 16, src_val >> 8, src_val);
4146 if(bit_pos == 0) *dst_pixel = 0;
4147 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4149 if(++bit_pos == 8)
4151 dst_pixel++;
4152 bit_pos = 0;
4155 if(pad_size)
4157 if(bit_pos != 0) dst_pixel++;
4158 memset(dst_pixel, 0, pad_size);
4160 dst_start += dst->stride;
4161 src_start += src->stride / 4;
4164 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
4166 for(y = src_rect->top; y < src_rect->bottom; y++)
4168 dst_pixel = dst_start;
4169 src_pixel = src_start;
4170 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4172 src_val = *src_pixel++;
4173 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
4174 src_val >> src->red_shift,
4175 src_val >> src->green_shift,
4176 src_val >> src->blue_shift);
4178 if(bit_pos == 0) *dst_pixel = 0;
4179 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4181 if(++bit_pos == 8)
4183 dst_pixel++;
4184 bit_pos = 0;
4187 if(pad_size)
4189 if(bit_pos != 0) dst_pixel++;
4190 memset(dst_pixel, 0, pad_size);
4192 dst_start += dst->stride;
4193 src_start += src->stride / 4;
4196 else
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,
4206 get_field(src_val, src->red_shift, src->red_len),
4207 get_field(src_val, src->green_shift, src->green_len),
4208 get_field(src_val, src->blue_shift, src->blue_len));
4210 if(bit_pos == 0) *dst_pixel = 0;
4211 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4213 if(++bit_pos == 8)
4215 dst_pixel++;
4216 bit_pos = 0;
4219 if(pad_size)
4221 if(bit_pos != 0) dst_pixel++;
4222 memset(dst_pixel, 0, pad_size);
4224 dst_start += dst->stride;
4225 src_start += src->stride / 4;
4228 break;
4231 case 24:
4233 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
4235 for(y = src_rect->top; y < src_rect->bottom; y++)
4237 dst_pixel = dst_start;
4238 src_pixel = src_start;
4239 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
4241 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_pixel[2], src_pixel[1], src_pixel[0]);
4243 if(bit_pos == 0) *dst_pixel = 0;
4244 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4246 if(++bit_pos == 8)
4248 dst_pixel++;
4249 bit_pos = 0;
4252 if(pad_size)
4254 if(bit_pos != 0) dst_pixel++;
4255 memset(dst_pixel, 0, pad_size);
4257 dst_start += dst->stride;
4258 src_start += src->stride;
4260 break;
4263 case 16:
4265 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
4266 if(src->funcs == &funcs_555)
4268 for(y = src_rect->top; y < src_rect->bottom; y++)
4270 dst_pixel = dst_start;
4271 src_pixel = src_start;
4272 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4274 src_val = *src_pixel++;
4275 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
4276 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
4277 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
4278 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
4280 if(bit_pos == 0) *dst_pixel = 0;
4281 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4283 if(++bit_pos == 8)
4285 dst_pixel++;
4286 bit_pos = 0;
4289 if(pad_size)
4291 if(bit_pos != 0) dst_pixel++;
4292 memset(dst_pixel, 0, pad_size);
4294 dst_start += dst->stride;
4295 src_start += src->stride / 2;
4298 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
4300 for(y = src_rect->top; y < src_rect->bottom; y++)
4302 dst_pixel = dst_start;
4303 src_pixel = src_start;
4304 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4306 src_val = *src_pixel++;
4307 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
4308 (((src_val >> src->red_shift) << 3) & 0xf8) |
4309 (((src_val >> src->red_shift) >> 2) & 0x07),
4310 (((src_val >> src->green_shift) << 3) & 0xf8) |
4311 (((src_val >> src->green_shift) >> 2) & 0x07),
4312 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4313 (((src_val >> src->blue_shift) >> 2) & 0x07));
4314 if(bit_pos == 0) *dst_pixel = 0;
4315 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4317 if(++bit_pos == 8)
4319 dst_pixel++;
4320 bit_pos = 0;
4323 if(pad_size)
4325 if(bit_pos != 0) dst_pixel++;
4326 memset(dst_pixel, 0, pad_size);
4328 dst_start += dst->stride;
4329 src_start += src->stride / 2;
4332 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
4334 for(y = src_rect->top; y < src_rect->bottom; y++)
4336 dst_pixel = dst_start;
4337 src_pixel = src_start;
4338 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4340 src_val = *src_pixel++;
4341 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
4342 (((src_val >> src->red_shift) << 3) & 0xf8) |
4343 (((src_val >> src->red_shift) >> 2) & 0x07),
4344 (((src_val >> src->green_shift) << 2) & 0xfc) |
4345 (((src_val >> src->green_shift) >> 4) & 0x03),
4346 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4347 (((src_val >> src->blue_shift) >> 2) & 0x07));
4348 if(bit_pos == 0) *dst_pixel = 0;
4349 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4351 if(++bit_pos == 8)
4353 dst_pixel++;
4354 bit_pos = 0;
4357 if(pad_size)
4359 if(bit_pos != 0) dst_pixel++;
4360 memset(dst_pixel, 0, pad_size);
4362 dst_start += dst->stride;
4363 src_start += src->stride / 2;
4366 else
4368 for(y = src_rect->top; y < src_rect->bottom; y++)
4370 dst_pixel = dst_start;
4371 src_pixel = src_start;
4372 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4374 src_val = *src_pixel++;
4375 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
4376 get_field(src_val, src->red_shift, src->red_len),
4377 get_field(src_val, src->green_shift, src->green_len),
4378 get_field(src_val, src->blue_shift, src->blue_len));
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 break;
4400 case 8:
4402 const RGBQUAD *color_table = get_dib_color_table( src );
4403 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4405 for(y = src_rect->top; y < src_rect->bottom; y++)
4407 dst_pixel = dst_start;
4408 src_pixel = src_start;
4409 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4411 RGBQUAD rgb = color_table[*src_pixel++];
4412 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4414 if(bit_pos == 0) *dst_pixel = 0;
4415 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4417 if(++bit_pos == 8)
4419 dst_pixel++;
4420 bit_pos = 0;
4423 if(pad_size)
4425 if(bit_pos != 0) dst_pixel++;
4426 memset(dst_pixel, 0, pad_size);
4428 dst_start += dst->stride;
4429 src_start += src->stride;
4431 break;
4434 case 4:
4436 const RGBQUAD *color_table = get_dib_color_table( src );
4437 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4439 for(y = src_rect->top; y < src_rect->bottom; y++)
4441 int pos = (src->rect.left + src_rect->left) & 1;
4442 dst_pixel = dst_start;
4443 src_pixel = src_start;
4444 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4446 RGBQUAD rgb;
4447 if (pos & 1)
4448 rgb = color_table[*src_pixel++ & 0xf];
4449 else
4450 rgb = color_table[*src_pixel >> 4];
4451 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4453 if(bit_pos == 0) *dst_pixel = 0;
4454 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4456 if(++bit_pos == 8)
4458 dst_pixel++;
4459 bit_pos = 0;
4462 if(pad_size)
4464 if(bit_pos != 0) dst_pixel++;
4465 memset(dst_pixel, 0, pad_size);
4467 dst_start += dst->stride;
4468 src_start += src->stride;
4470 break;
4473 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
4474 uses text/bkgnd colours instead of the dib's colour table, this
4475 doesn't appear to be the case for a dc backed by a
4476 dibsection. */
4478 case 1:
4480 const RGBQUAD *color_table = get_dib_color_table( src );
4481 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4482 for(y = src_rect->top; y < src_rect->bottom; y++)
4484 int pos = (src->rect.left + src_rect->left) & 7;
4485 dst_pixel = dst_start;
4486 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4488 RGBQUAD rgb;
4489 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4490 rgb = color_table[src_val];
4491 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4493 if(bit_pos == 0) *dst_pixel = 0;
4494 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4496 if(++bit_pos == 8)
4498 dst_pixel++;
4499 bit_pos = 0;
4502 if(pad_size)
4504 if(bit_pos != 0) dst_pixel++;
4505 memset(dst_pixel, 0, pad_size);
4507 dst_start += dst->stride;
4508 src_start += src->stride;
4510 break;
4515 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4519 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
4521 return (src * alpha + dst * (255 - alpha) + 127) / 255;
4524 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
4526 return (blend_color( dst, src, alpha ) |
4527 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4528 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4529 blend_color( dst >> 24, src >> 24, alpha ) << 24);
4532 static inline DWORD blend_argb_no_src_alpha( DWORD dst, DWORD src, DWORD alpha )
4534 return (blend_color( dst, src, alpha ) |
4535 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4536 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4537 blend_color( dst >> 24, 255, alpha ) << 24);
4540 static inline DWORD blend_argb( DWORD dst, DWORD src )
4542 BYTE b = (BYTE)src;
4543 BYTE g = (BYTE)(src >> 8);
4544 BYTE r = (BYTE)(src >> 16);
4545 DWORD alpha = (BYTE)(src >> 24);
4546 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4547 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4548 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4549 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4552 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
4554 BYTE b = ((BYTE)src * alpha + 127) / 255;
4555 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4556 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4557 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4558 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4559 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4560 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4561 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4564 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
4566 if (blend.AlphaFormat & AC_SRC_ALPHA)
4568 DWORD alpha = blend.SourceConstantAlpha;
4569 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
4570 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4571 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4572 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4573 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
4574 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
4575 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
4577 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
4578 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
4579 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
4582 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
4583 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4585 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4586 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4587 int x, y;
4589 if (blend.AlphaFormat & AC_SRC_ALPHA)
4591 if (blend.SourceConstantAlpha == 255)
4592 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4593 for (x = 0; x < rc->right - rc->left; x++)
4594 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
4595 else
4596 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4597 for (x = 0; x < rc->right - rc->left; x++)
4598 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4600 else if (src->compression == BI_RGB)
4601 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4602 for (x = 0; x < rc->right - rc->left; x++)
4603 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4604 else
4605 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4606 for (x = 0; x < rc->right - rc->left; x++)
4607 dst_ptr[x] = blend_argb_no_src_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4610 static void blend_rect_32(const dib_info *dst, const RECT *rc,
4611 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4613 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4614 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4615 int x, y;
4617 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
4619 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4621 for (x = 0; x < rc->right - rc->left; x++)
4623 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
4624 dst_ptr[x] >> dst->green_shift,
4625 dst_ptr[x] >> dst->blue_shift,
4626 src_ptr[x], blend );
4627 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
4628 (((val >> 8) & 0xff) << dst->green_shift) |
4629 (((val >> 16) & 0xff) << dst->red_shift));
4633 else
4635 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4637 for (x = 0; x < rc->right - rc->left; x++)
4639 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4640 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4641 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4642 src_ptr[x], blend );
4643 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
4644 put_field( val >> 8, dst->green_shift, dst->green_len ) |
4645 put_field( val, dst->blue_shift, dst->blue_len ));
4651 static void blend_rect_24(const dib_info *dst, const RECT *rc,
4652 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4654 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4655 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
4656 int x, y;
4658 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4660 for (x = 0; x < rc->right - rc->left; x++)
4662 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4663 src_ptr[x], blend );
4664 dst_ptr[x * 3] = val;
4665 dst_ptr[x * 3 + 1] = val >> 8;
4666 dst_ptr[x * 3 + 2] = val >> 16;
4671 static void blend_rect_555(const dib_info *dst, const RECT *rc,
4672 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4674 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4675 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4676 int x, y;
4678 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4680 for (x = 0; x < rc->right - rc->left; x++)
4682 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4683 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4684 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4685 src_ptr[x], blend );
4686 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4691 static void blend_rect_16(const dib_info *dst, const RECT *rc,
4692 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4694 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4695 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4696 int x, y;
4698 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4700 for (x = 0; x < rc->right - rc->left; x++)
4702 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4703 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4704 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4705 src_ptr[x], blend );
4706 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
4707 put_field((val >> 8), dst->green_shift, dst->green_len) |
4708 put_field( val, dst->blue_shift, dst->blue_len));
4713 static void blend_rect_8(const dib_info *dst, const RECT *rc,
4714 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4716 const RGBQUAD *color_table = get_dib_color_table( dst );
4717 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4718 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4719 int x, y;
4721 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4723 for (x = 0; x < rc->right - rc->left; x++)
4725 RGBQUAD rgb = color_table[dst_ptr[x]];
4726 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4727 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4732 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4733 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4735 const RGBQUAD *color_table = get_dib_color_table( dst );
4736 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4737 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4738 int i, x, y;
4740 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4742 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4744 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4745 RGBQUAD rgb = color_table[val];
4746 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4747 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4748 if (x & 1)
4749 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4750 else
4751 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4756 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4757 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4759 const RGBQUAD *color_table = get_dib_color_table( dst );
4760 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4761 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4762 int i, x, y;
4764 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4766 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4768 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4769 RGBQUAD rgb = color_table[val];
4770 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4771 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4772 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4777 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4778 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4782 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4784 BYTE r, g, b, a;
4785 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4786 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4787 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4788 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4789 return a << 24 | r << 16 | g << 8 | b;
4792 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4794 BYTE r, g, b;
4795 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4796 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4797 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4798 return r << 16 | g << 8 | b;
4801 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4802 unsigned int x, unsigned int y )
4804 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4805 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4806 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4807 r = min( 31, max( 0, r / 16 ));
4808 g = min( 31, max( 0, g / 16 ));
4809 b = min( 31, max( 0, b / 16 ));
4810 return (r << 10) | (g << 5) | b;
4813 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4814 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4816 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4817 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4818 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4819 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4822 /* compute the left/right triangle limit for row y */
4823 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4825 int x1, x2;
4827 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4828 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4830 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4832 *left = max( rc->left, min( x1, x2 ) );
4833 *right = min( rc->right, max( x1, x2 ) );
4836 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4837 static inline int triangle_det( const TRIVERTEX *v )
4839 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);
4842 /* compute the barycentric weights for a given point inside the triangle */
4843 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4845 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4846 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4849 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4851 INT64 l1, l2;
4852 BYTE r, g, b, a;
4854 triangle_weights( v, x, y, &l1, &l2 );
4855 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4856 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4857 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4858 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4859 return a << 24 | r << 16 | g << 8 | b;
4862 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4864 INT64 l1, l2;
4865 BYTE r, g, b;
4867 triangle_weights( v, x, y, &l1, &l2 );
4868 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4869 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4870 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4871 return r << 16 | g << 8 | b;
4874 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4876 INT64 l1, l2;
4877 int r, g, b;
4879 triangle_weights( v, x, y, &l1, &l2 );
4880 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4881 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4882 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4883 r = min( 31, max( 0, r / 16 ));
4884 g = min( 31, max( 0, g / 16 ));
4885 b = min( 31, max( 0, b / 16 ));
4886 return (r << 10) | (g << 5) | b;
4889 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4891 INT64 l1, l2;
4892 BYTE r, g, b;
4894 triangle_weights( v, x, y, &l1, &l2 );
4895 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4896 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4897 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4898 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4901 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4903 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4904 int x, y, left, right, det;
4906 switch (mode)
4908 case GRADIENT_FILL_RECT_H:
4909 for (x = 0; x < rc->right - rc->left; x++)
4910 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4912 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4913 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4914 break;
4916 case GRADIENT_FILL_RECT_V:
4917 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4919 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4920 memset_32( ptr, val, rc->right - rc->left );
4922 break;
4924 case GRADIENT_FILL_TRIANGLE:
4925 if (!(det = triangle_det( v ))) return FALSE;
4926 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4928 triangle_coords( v, rc, y, &left, &right );
4929 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4931 break;
4933 return TRUE;
4936 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4938 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4939 int x, y, left, right, det;
4941 switch (mode)
4943 case GRADIENT_FILL_RECT_H:
4944 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4946 for (x = 0; x < rc->right - rc->left; x++)
4948 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4949 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4950 (((val >> 8) & 0xff) << dib->green_shift) |
4951 (((val >> 16) & 0xff) << dib->red_shift));
4954 else
4956 for (x = 0; x < rc->right - rc->left; x++)
4958 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4959 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4960 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4961 put_field( val, dib->blue_shift, dib->blue_len ));
4965 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4966 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4967 break;
4969 case GRADIENT_FILL_RECT_V:
4970 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4972 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4973 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4974 val = ((( val & 0xff) << dib->blue_shift) |
4975 (((val >> 8) & 0xff) << dib->green_shift) |
4976 (((val >> 16) & 0xff) << dib->red_shift));
4977 else
4978 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4979 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4980 put_field( val, dib->blue_shift, dib->blue_len ));
4982 memset_32( ptr, val, rc->right - rc->left );
4984 break;
4986 case GRADIENT_FILL_TRIANGLE:
4987 if (!(det = triangle_det( v ))) return FALSE;
4988 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4990 triangle_coords( v, rc, y, &left, &right );
4992 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4993 for (x = left; x < right; x++)
4995 DWORD val = gradient_triangle_24( v, x, y, det );
4996 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4997 (((val >> 8) & 0xff) << dib->green_shift) |
4998 (((val >> 16) & 0xff) << dib->red_shift));
5000 else
5001 for (x = left; x < right; x++)
5003 DWORD val = gradient_triangle_24( v, x, y, det );
5004 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
5005 put_field( val >> 8, dib->green_shift, dib->green_len ) |
5006 put_field( val, dib->blue_shift, dib->blue_len ));
5009 break;
5011 return TRUE;
5014 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5016 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
5017 int x, y, left, right, det;
5019 switch (mode)
5021 case GRADIENT_FILL_RECT_H:
5022 for (x = 0; x < rc->right - rc->left; x++)
5024 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5025 ptr[x * 3] = val;
5026 ptr[x * 3 + 1] = val >> 8;
5027 ptr[x * 3 + 2] = val >> 16;
5030 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
5031 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
5032 break;
5034 case GRADIENT_FILL_RECT_V:
5035 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5037 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
5038 for (x = 0; x < rc->right - rc->left; x++)
5040 ptr[x * 3] = val;
5041 ptr[x * 3 + 1] = val >> 8;
5042 ptr[x * 3 + 2] = val >> 16;
5045 break;
5047 case GRADIENT_FILL_TRIANGLE:
5048 if (!(det = triangle_det( v ))) return FALSE;
5049 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5051 triangle_coords( v, rc, y, &left, &right );
5052 for (x = left; x < right; x++)
5054 DWORD val = gradient_triangle_24( v, x, y, det );
5055 ptr[(x - rc->left) * 3] = val;
5056 ptr[(x - rc->left) * 3 + 1] = val >> 8;
5057 ptr[(x - rc->left) * 3 + 2] = val >> 16;
5060 break;
5062 return TRUE;
5065 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5067 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5068 int x, y, left, right, det;
5070 switch (mode)
5072 case GRADIENT_FILL_RECT_H:
5073 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5074 for (x = rc->left; x < rc->right; x++)
5075 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5076 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5077 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5078 break;
5080 case GRADIENT_FILL_RECT_V:
5081 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5083 WORD values[4];
5084 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5085 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5087 break;
5089 case GRADIENT_FILL_TRIANGLE:
5090 if (!(det = triangle_det( v ))) return FALSE;
5091 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5093 triangle_coords( v, rc, y, &left, &right );
5094 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
5096 break;
5098 return TRUE;
5101 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5103 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5104 int x, y, left, right, det;
5106 switch (mode)
5108 case GRADIENT_FILL_RECT_H:
5109 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5110 for (x = rc->left; x < rc->right; x++)
5112 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5113 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
5114 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
5115 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
5117 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5118 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5119 break;
5121 case GRADIENT_FILL_RECT_V:
5122 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5124 WORD values[4];
5125 for (x = 0; x < 4; x++)
5127 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5128 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
5129 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
5130 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
5132 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5134 break;
5136 case GRADIENT_FILL_TRIANGLE:
5137 if (!(det = triangle_det( v ))) return FALSE;
5138 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5140 triangle_coords( v, rc, y, &left, &right );
5141 for (x = left; x < right; x++)
5143 WORD val = gradient_triangle_555( v, x, y, det );
5144 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
5145 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
5146 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
5149 break;
5151 return TRUE;
5154 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5156 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
5157 int x, y, left, right, det;
5159 switch (mode)
5161 case GRADIENT_FILL_RECT_H:
5162 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5163 for (x = rc->left; x < rc->right; x++)
5164 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5165 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5166 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
5167 break;
5169 case GRADIENT_FILL_RECT_V:
5170 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5172 BYTE values[16];
5173 for (x = 0; x < 16; x++)
5174 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5175 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
5177 break;
5179 case GRADIENT_FILL_TRIANGLE:
5180 if (!(det = triangle_det( v ))) return FALSE;
5181 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5183 triangle_coords( v, rc, y, &left, &right );
5184 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
5186 break;
5188 return TRUE;
5191 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5193 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
5194 int x, y, left, right, det, pos;
5196 switch (mode)
5198 case GRADIENT_FILL_RECT_H:
5199 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5201 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5203 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5204 if (pos & 1)
5205 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5206 else
5207 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5210 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5212 x = rc->left;
5213 pos = (dib->rect.left + rc->left) & 1;
5214 if (pos)
5216 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
5217 pos++;
5218 x++;
5220 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
5221 if (x < rc->right)
5222 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
5224 break;
5226 case GRADIENT_FILL_RECT_V:
5227 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5229 BYTE values[16];
5230 for (x = 0; x < 16; x++)
5231 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5232 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5233 if (pos & 1)
5234 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
5235 else
5236 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
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, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
5247 BYTE val = gradient_triangle_8( dib, v, x, y, det );
5248 if (pos & 1)
5249 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5250 else
5251 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5254 break;
5256 return TRUE;
5259 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5261 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
5262 int x, y, left, right, det, pos;
5264 switch (mode)
5266 case GRADIENT_FILL_RECT_H:
5267 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5269 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5271 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
5272 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5275 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5276 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5277 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5278 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
5279 break;
5281 case GRADIENT_FILL_RECT_V:
5282 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5284 BYTE values[16];
5285 for (x = 0; x < 16; x++)
5286 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
5287 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5288 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5289 (values[x % 16] & pixel_masks_1[pos % 8]);
5291 break;
5293 case GRADIENT_FILL_TRIANGLE:
5294 if (!(det = triangle_det( v ))) return FALSE;
5295 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5297 triangle_coords( v, rc, y, &left, &right );
5298 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
5300 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
5301 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5304 break;
5306 return TRUE;
5309 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5311 return TRUE;
5314 static void mask_rect_32( const dib_info *dst, const RECT *rc,
5315 const dib_info *src, const POINT *origin, int rop2 )
5317 DWORD *dst_start = get_pixel_ptr_32(dst, rc->left, rc->top), dst_colors[256];
5318 DWORD src_val, bit_val, i, full, pos;
5319 int x, y, origin_end = origin->x + rc->right - rc->left;
5320 const RGBQUAD *color_table = get_dib_color_table( src );
5321 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5323 if (dst->funcs == &funcs_8888)
5324 for (i = 0; i < 2; i++)
5325 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
5326 color_table[i].rgbBlue;
5327 else
5328 for (i = 0; i < 2; i++)
5329 dst_colors[i] = put_field(color_table[i].rgbRed, dst->red_shift, dst->red_len) |
5330 put_field(color_table[i].rgbGreen, dst->green_shift, dst->green_len) |
5331 put_field(color_table[i].rgbBlue, dst->blue_shift, dst->blue_len);
5333 /* Creating a BYTE-sized table so we don't need to mask the lsb of bit_val */
5334 for (i = 2; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5335 dst_colors[i] = dst_colors[i & 1];
5337 /* Special case starting and finishing in same byte, neither on byte boundary */
5338 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5340 struct rop_codes codes;
5342 get_rop_codes( rop2, &codes );
5344 for (y = rc->top; y < rc->bottom; y++)
5346 pos = origin->x & 7;
5347 for (x = 0; x < rc->right - rc->left; x++, pos++)
5349 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5350 do_rop_codes_32( dst_start + x, dst_colors[bit_val], &codes );
5352 dst_start += dst->stride / 4;
5353 src_start += src->stride;
5355 return;
5358 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5360 #define LOOP( op ) \
5361 for (y = rc->top; y < rc->bottom; y++) \
5363 pos = origin->x & 7; \
5364 src_val = src_start[pos / 8]; \
5365 x = 0; \
5366 switch (pos & 7) \
5368 case 1: bit_val = src_val >> 6; op; x++; \
5369 /* fall through */ \
5370 case 2: bit_val = src_val >> 5; op; x++; \
5371 /* fall through */ \
5372 case 3: bit_val = src_val >> 4; op; x++; \
5373 /* fall through */ \
5374 case 4: bit_val = src_val >> 3; op; x++; \
5375 /* fall through */ \
5376 case 5: bit_val = src_val >> 2; op; x++; \
5377 /* fall through */ \
5378 case 6: bit_val = src_val >> 1; op; x++; \
5379 /* fall through */ \
5380 case 7: bit_val = src_val; op; x++; \
5381 pos = (pos + 7) & ~7; \
5383 for (i = 0; i < full; i++, pos += 8) \
5385 src_val = src_start[pos / 8]; \
5386 bit_val = src_val >> 7; op; x++; \
5387 bit_val = src_val >> 6; op; x++; \
5388 bit_val = src_val >> 5; op; x++; \
5389 bit_val = src_val >> 4; op; x++; \
5390 bit_val = src_val >> 3; op; x++; \
5391 bit_val = src_val >> 2; op; x++; \
5392 bit_val = src_val >> 1; op; x++; \
5393 bit_val = src_val; op; x++; \
5395 if (origin_end & 7) \
5397 src_val = src_start[pos / 8]; \
5398 x += (origin_end & 7) - 1; \
5399 switch (origin_end & 7) \
5401 case 7: bit_val = src_val >> 1; op; x--; \
5402 /* fall through */ \
5403 case 6: bit_val = src_val >> 2; op; x--; \
5404 /* fall through */ \
5405 case 5: bit_val = src_val >> 3; op; x--; \
5406 /* fall through */ \
5407 case 4: bit_val = src_val >> 4; op; x--; \
5408 /* fall through */ \
5409 case 3: bit_val = src_val >> 5; op; x--; \
5410 /* fall through */ \
5411 case 2: bit_val = src_val >> 6; op; x--; \
5412 /* fall through */ \
5413 case 1: bit_val = src_val >> 7; op; \
5416 dst_start += dst->stride / 4; \
5417 src_start += src->stride; \
5420 switch (rop2)
5422 ROPS_ALL( dst_start[x], dst_colors[bit_val] )
5424 #undef LOOP
5427 static void mask_rect_24( const dib_info *dst, const RECT *rc,
5428 const dib_info *src, const POINT *origin, int rop2 )
5430 BYTE *dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
5431 DWORD src_val, bit_val, i, full, pos;
5432 struct rop_codes codes;
5433 int x, y, origin_end = origin->x + rc->right - rc->left;
5434 const RGBQUAD *color_table = get_dib_color_table( src );
5435 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5436 RGBQUAD rgb;
5438 get_rop_codes( rop2, &codes );
5440 /* Special case starting and finishing in same byte, neither on byte boundary */
5441 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5443 for (y = rc->top; y < rc->bottom; y++)
5445 pos = origin->x & 7;
5446 for (x = 0; x < rc->right - rc->left; x++, pos++)
5448 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5449 rgb = color_table[bit_val];
5450 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5451 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5452 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5454 dst_start += dst->stride;
5455 src_start += src->stride;
5457 return;
5460 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5462 for (y = rc->top; y < rc->bottom; y++)
5464 pos = origin->x & 7;
5465 src_val = src_start[pos / 8];
5466 x = 0;
5468 switch (pos & 7)
5470 case 1:
5471 bit_val = (src_val >> 6) & 1;
5472 rgb = color_table[bit_val];
5473 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5474 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5475 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5476 x++;
5477 /* fall through */
5478 case 2:
5479 bit_val = (src_val >> 5) & 1;
5480 rgb = color_table[bit_val];
5481 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5482 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5483 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5484 x++;
5485 /* fall through */
5486 case 3:
5487 bit_val = (src_val >> 4) & 1;
5488 rgb = color_table[bit_val];
5489 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5490 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5491 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5492 x++;
5493 /* fall through */
5494 case 4:
5495 bit_val = (src_val >> 3) & 1;
5496 rgb = color_table[bit_val];
5497 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5498 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5499 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5500 x++;
5501 /* fall through */
5502 case 5:
5503 bit_val = (src_val >> 2) & 1;
5504 rgb = color_table[bit_val];
5505 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5506 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5507 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5508 x++;
5509 /* fall through */
5510 case 6:
5511 bit_val = (src_val >> 1) & 1;
5512 rgb = color_table[bit_val];
5513 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5514 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5515 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5516 x++;
5517 /* fall through */
5518 case 7:
5519 bit_val = src_val & 1;
5520 rgb = color_table[bit_val];
5521 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5522 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5523 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5524 x++;
5525 pos = (pos + 7) & ~7;
5528 for (i = 0; i < full; i++, pos += 8)
5530 src_val = src_start[pos / 8];
5532 bit_val = (src_val >> 7) & 1;
5533 rgb = color_table[bit_val];
5534 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5535 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5536 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5537 x++;
5539 bit_val = (src_val >> 6) & 1;
5540 rgb = color_table[bit_val];
5541 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5542 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5543 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5544 x++;
5546 bit_val = (src_val >> 5) & 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++;
5553 bit_val = (src_val >> 4) & 1;
5554 rgb = color_table[bit_val];
5555 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5556 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5557 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5558 x++;
5560 bit_val = (src_val >> 3) & 1;
5561 rgb = color_table[bit_val];
5562 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5563 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5564 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5565 x++;
5567 bit_val = (src_val >> 2) & 1;
5568 rgb = color_table[bit_val];
5569 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5570 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5571 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5572 x++;
5574 bit_val = (src_val >> 1) & 1;
5575 rgb = color_table[bit_val];
5576 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5577 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5578 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5579 x++;
5581 bit_val = src_val & 1;
5582 rgb = color_table[bit_val];
5583 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5584 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5585 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5586 x++;
5589 if (origin_end & 7)
5591 src_val = src_start[pos / 8];
5592 x += (origin_end & 7) - 1;
5594 switch (origin_end & 7)
5596 case 7:
5597 bit_val = (src_val >> 1) & 1;
5598 rgb = color_table[bit_val];
5599 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5600 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5601 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5602 x--;
5603 /* fall through */
5604 case 6:
5605 bit_val = (src_val >> 2) & 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--;
5611 /* fall through */
5612 case 5:
5613 bit_val = (src_val >> 3) & 1;
5614 rgb = color_table[bit_val];
5615 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5616 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5617 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5618 x--;
5619 /* fall through */
5620 case 4:
5621 bit_val = (src_val >> 4) & 1;
5622 rgb = color_table[bit_val];
5623 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5624 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5625 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5626 x--;
5627 /* fall through */
5628 case 3:
5629 bit_val = (src_val >> 5) & 1;
5630 rgb = color_table[bit_val];
5631 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5632 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5633 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5634 x--;
5635 /* fall through */
5636 case 2:
5637 bit_val = (src_val >> 6) & 1;
5638 rgb = color_table[bit_val];
5639 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5640 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5641 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5642 x--;
5643 /* fall through */
5644 case 1:
5645 bit_val = (src_val >> 7) & 1;
5646 rgb = color_table[bit_val];
5647 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5648 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5649 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5653 dst_start += dst->stride;
5654 src_start += src->stride;
5658 static void mask_rect_16( const dib_info *dst, const RECT *rc,
5659 const dib_info *src, const POINT *origin, int rop2 )
5661 WORD *dst_start = get_pixel_ptr_16(dst, rc->left, rc->top), dst_colors[2];
5662 DWORD src_val, bit_val, i, full, pos;
5663 struct rop_codes codes;
5664 int x, y, origin_end = origin->x + rc->right - rc->left;
5665 const RGBQUAD *color_table = get_dib_color_table( src );
5666 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5668 get_rop_codes( rop2, &codes );
5670 if (dst->funcs == &funcs_555)
5671 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5672 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
5673 ((color_table[i].rgbGreen << 2) & 0x03e0) |
5674 ((color_table[i].rgbBlue >> 3) & 0x001f);
5675 else
5676 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5677 dst_colors[i] = put_field(color_table[i].rgbRed, dst->red_shift, dst->red_len) |
5678 put_field(color_table[i].rgbGreen, dst->green_shift, dst->green_len) |
5679 put_field(color_table[i].rgbBlue, dst->blue_shift, dst->blue_len);
5681 /* Special case starting and finishing in same byte, neither on byte boundary */
5682 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5684 for (y = rc->top; y < rc->bottom; y++)
5686 pos = origin->x & 7;
5687 for (x = 0; x < rc->right - rc->left; x++, pos++)
5689 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5690 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5692 dst_start += dst->stride / 2;
5693 src_start += src->stride;
5695 return;
5698 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5700 for (y = rc->top; y < rc->bottom; y++)
5702 pos = origin->x & 7;
5703 src_val = src_start[pos / 8];
5704 x = 0;
5706 switch (pos & 7)
5708 case 1:
5709 bit_val = (src_val >> 6) & 1;
5710 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5711 /* fall through */
5712 case 2:
5713 bit_val = (src_val >> 5) & 1;
5714 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5715 /* fall through */
5716 case 3:
5717 bit_val = (src_val >> 4) & 1;
5718 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5719 /* fall through */
5720 case 4:
5721 bit_val = (src_val >> 3) & 1;
5722 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5723 /* fall through */
5724 case 5:
5725 bit_val = (src_val >> 2) & 1;
5726 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5727 /* fall through */
5728 case 6:
5729 bit_val = (src_val >> 1) & 1;
5730 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5731 /* fall through */
5732 case 7:
5733 bit_val = src_val & 1;
5734 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5735 pos = (pos + 7) & ~7;
5738 for (i = 0; i < full; i++, pos += 8)
5740 src_val = src_start[pos / 8];
5742 bit_val = (src_val >> 7) & 1;
5743 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5744 bit_val = (src_val >> 6) & 1;
5745 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5746 bit_val = (src_val >> 5) & 1;
5747 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5748 bit_val = (src_val >> 4) & 1;
5749 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5750 bit_val = (src_val >> 3) & 1;
5751 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5752 bit_val = (src_val >> 2) & 1;
5753 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5754 bit_val = (src_val >> 1) & 1;
5755 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5756 bit_val = src_val & 1;
5757 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5760 if (origin_end & 7)
5762 src_val = src_start[pos / 8];
5763 x += (origin_end & 7) - 1;
5765 switch (origin_end & 7)
5767 case 7:
5768 bit_val = (src_val >> 1) & 1;
5769 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5770 /* fall through */
5771 case 6:
5772 bit_val = (src_val >> 2) & 1;
5773 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5774 /* fall through */
5775 case 5:
5776 bit_val = (src_val >> 3) & 1;
5777 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5778 /* fall through */
5779 case 4:
5780 bit_val = (src_val >> 4) & 1;
5781 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5782 /* fall through */
5783 case 3:
5784 bit_val = (src_val >> 5) & 1;
5785 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5786 /* fall through */
5787 case 2:
5788 bit_val = (src_val >> 6) & 1;
5789 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5790 /* fall through */
5791 case 1:
5792 bit_val = (src_val >> 7) & 1;
5793 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5797 dst_start += dst->stride / 2;
5798 src_start += src->stride;
5802 static void mask_rect_8( const dib_info *dst, const RECT *rc,
5803 const dib_info *src, const POINT *origin, int rop2 )
5805 BYTE *dst_start = get_pixel_ptr_8(dst, rc->left, rc->top), dst_colors[2];
5806 DWORD src_val, bit_val, i, full, pos;
5807 struct rop_codes codes;
5808 int x, y, origin_end = origin->x + rc->right - rc->left;
5809 const RGBQUAD *color_table = get_dib_color_table( src );
5810 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5812 get_rop_codes( rop2, &codes );
5814 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5815 dst_colors[i] = rgb_to_pixel_colortable( dst, color_table[i].rgbRed, color_table[i].rgbGreen,
5816 color_table[i].rgbBlue );
5818 /* Special case starting and finishing in same byte, neither on byte boundary */
5819 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5821 for (y = rc->top; y < rc->bottom; y++)
5823 pos = origin->x & 7;
5824 for (x = 0; x < rc->right - rc->left; x++, pos++)
5826 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5827 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
5829 dst_start += dst->stride;
5830 src_start += src->stride;
5832 return;
5835 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5837 for (y = rc->top; y < rc->bottom; y++)
5839 pos = origin->x & 7;
5840 src_val = src_start[pos / 8];
5841 x = 0;
5843 switch (pos & 7)
5845 case 1:
5846 bit_val = (src_val >> 6) & 1;
5847 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5848 /* fall through */
5849 case 2:
5850 bit_val = (src_val >> 5) & 1;
5851 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5852 /* fall through */
5853 case 3:
5854 bit_val = (src_val >> 4) & 1;
5855 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5856 /* fall through */
5857 case 4:
5858 bit_val = (src_val >> 3) & 1;
5859 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5860 /* fall through */
5861 case 5:
5862 bit_val = (src_val >> 2) & 1;
5863 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5864 /* fall through */
5865 case 6:
5866 bit_val = (src_val >> 1) & 1;
5867 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5868 /* fall through */
5869 case 7:
5870 bit_val = src_val & 1;
5871 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5872 pos = (pos + 7) & ~7;
5875 for (i = 0; i < full; i++, pos += 8)
5877 src_val = src_start[pos / 8];
5879 bit_val = (src_val >> 7) & 1;
5880 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5881 bit_val = (src_val >> 6) & 1;
5882 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5883 bit_val = (src_val >> 5) & 1;
5884 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5885 bit_val = (src_val >> 4) & 1;
5886 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5887 bit_val = (src_val >> 3) & 1;
5888 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5889 bit_val = (src_val >> 2) & 1;
5890 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5891 bit_val = (src_val >> 1) & 1;
5892 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5893 bit_val = src_val & 1;
5894 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5897 if (origin_end & 7)
5899 src_val = src_start[pos / 8];
5900 x += (origin_end & 7) - 1;
5902 switch (origin_end & 7)
5904 case 7:
5905 bit_val = (src_val >> 1) & 1;
5906 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5907 /* fall through */
5908 case 6:
5909 bit_val = (src_val >> 2) & 1;
5910 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5911 /* fall through */
5912 case 5:
5913 bit_val = (src_val >> 3) & 1;
5914 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5915 /* fall through */
5916 case 4:
5917 bit_val = (src_val >> 4) & 1;
5918 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5919 /* fall through */
5920 case 3:
5921 bit_val = (src_val >> 5) & 1;
5922 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5923 /* fall through */
5924 case 2:
5925 bit_val = (src_val >> 6) & 1;
5926 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5927 /* fall through */
5928 case 1:
5929 bit_val = (src_val >> 7) & 1;
5930 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
5934 dst_start += dst->stride;
5935 src_start += src->stride;
5939 static void mask_rect_4( const dib_info *dst, const RECT *rc,
5940 const dib_info *src, const POINT *origin, int rop2 )
5942 BYTE *dst_start = get_pixel_ptr_4(dst, rc->left, rc->top), dst_colors[2], *dst_ptr;
5943 DWORD bit_val, i, pos;
5944 struct rop_codes codes;
5945 int x, y;
5946 int left = dst->rect.left + rc->left;
5947 int right = dst->rect.left + rc->right;
5948 const RGBQUAD *color_table = get_dib_color_table( src );
5949 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5951 get_rop_codes( rop2, &codes );
5953 for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
5955 dst_colors[i] = rgb_to_pixel_colortable( dst, color_table[i].rgbRed, color_table[i].rgbGreen,
5956 color_table[i].rgbBlue );
5957 /* Set high nibble to match so we don't need to shift it later. */
5958 dst_colors[i] |= dst_colors[i] << 4;
5961 for (y = rc->top; y < rc->bottom; y++)
5963 pos = origin->x & 7;
5965 for (x = left, dst_ptr = dst_start; x < right; x++, pos++)
5967 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5968 if (x & 1)
5969 do_rop_codes_mask_8( dst_ptr++, dst_colors[bit_val], &codes, 0x0f );
5970 else
5971 do_rop_codes_mask_8( dst_ptr, dst_colors[bit_val], &codes, 0xf0 );
5973 dst_start += dst->stride;
5974 src_start += src->stride;
5978 static void mask_rect_null( const dib_info *dst, const RECT *rc,
5979 const dib_info *src, const POINT *origin, int rop2 )
5983 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
5985 if (dst == text) return dst;
5987 if (dst > text)
5989 DWORD diff = dst - text;
5990 DWORD range = max_comp - text;
5991 dst = text + (diff * range ) / (0xff - text);
5992 return dst;
5994 else
5996 DWORD diff = text - dst;
5997 DWORD range = text - min_comp;
5998 dst = text - (diff * range) / text;
5999 return dst;
6003 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
6005 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
6006 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
6007 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
6010 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6011 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6013 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6014 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6015 int x, y;
6017 for (y = rect->top; y < rect->bottom; y++)
6019 for (x = 0; x < rect->right - rect->left; x++)
6021 if (glyph_ptr[x] <= 1) continue;
6022 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6023 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
6025 dst_ptr += dib->stride / 4;
6026 glyph_ptr += glyph->stride;
6030 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6031 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6033 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6034 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6035 int x, y;
6036 DWORD text, val;
6038 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6039 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6040 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6042 for (y = rect->top; y < rect->bottom; y++)
6044 for (x = 0; x < rect->right - rect->left; x++)
6046 if (glyph_ptr[x] <= 1) continue;
6047 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6048 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6049 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6050 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6051 text, ranges + glyph_ptr[x] );
6052 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
6053 put_field( val >> 8, dib->green_shift, dib->green_len ) |
6054 put_field( val, dib->blue_shift, dib->blue_len ));
6056 dst_ptr += dib->stride / 4;
6057 glyph_ptr += glyph->stride;
6061 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6062 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6064 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6065 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6066 int x, y;
6067 DWORD val;
6069 for (y = rect->top; y < rect->bottom; y++)
6071 for (x = 0; x < rect->right - rect->left; x++)
6073 if (glyph_ptr[x] <= 1) continue;
6074 if (glyph_ptr[x] >= 16)
6075 val = text_pixel;
6076 else
6077 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6078 text_pixel, ranges + glyph_ptr[x] );
6079 dst_ptr[x * 3] = val;
6080 dst_ptr[x * 3 + 1] = val >> 8;
6081 dst_ptr[x * 3 + 2] = val >> 16;
6083 dst_ptr += dib->stride;
6084 glyph_ptr += glyph->stride;
6088 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6089 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6091 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6092 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6093 int x, y;
6094 DWORD text, val;
6096 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6097 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6098 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6100 for (y = rect->top; y < rect->bottom; y++)
6102 for (x = 0; x < rect->right - rect->left; x++)
6104 if (glyph_ptr[x] <= 1) continue;
6105 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6106 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6107 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6108 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6109 text, ranges + glyph_ptr[x] );
6110 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6112 dst_ptr += dib->stride / 2;
6113 glyph_ptr += glyph->stride;
6117 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6118 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6120 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6121 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6122 int x, y;
6123 DWORD text, val;
6125 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6126 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6127 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6129 for (y = rect->top; y < rect->bottom; y++)
6131 for (x = 0; x < rect->right - rect->left; x++)
6133 if (glyph_ptr[x] <= 1) continue;
6134 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6135 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6136 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6137 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6138 text, ranges + glyph_ptr[x] );
6139 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
6140 put_field( val >> 8, dib->green_shift, dib->green_len ) |
6141 put_field( val, dib->blue_shift, dib->blue_len ));
6143 dst_ptr += dib->stride / 2;
6144 glyph_ptr += glyph->stride;
6148 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6149 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6151 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
6152 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6153 int x, y;
6155 for (y = rect->top; y < rect->bottom; y++)
6157 for (x = 0; x < rect->right - rect->left; x++)
6159 /* no antialiasing, glyph should only contain 0 or 16. */
6160 if (glyph_ptr[x] >= 16)
6161 dst_ptr[x] = text_pixel;
6163 dst_ptr += dib->stride;
6164 glyph_ptr += glyph->stride;
6168 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6169 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6171 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
6172 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6173 int x, y, pos;
6175 for (y = rect->top; y < rect->bottom; y++)
6177 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
6179 /* no antialiasing, glyph should only contain 0 or 16. */
6180 if (glyph_ptr[x] >= 16)
6182 if (pos & 1)
6183 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
6184 else
6185 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
6188 dst_ptr += dib->stride;
6189 glyph_ptr += glyph->stride;
6193 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6194 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6196 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
6197 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6198 int x, y, pos;
6199 BYTE text = (text_pixel & 1) ? 0xff : 0;
6201 for (y = rect->top; y < rect->bottom; y++)
6203 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
6205 /* no antialiasing, glyph should only contain 0 or 16. */
6206 if (glyph_ptr[x] >= 16)
6207 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
6208 (text & pixel_masks_1[pos % 8]);
6210 dst_ptr += dib->stride;
6211 glyph_ptr += glyph->stride;
6215 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6216 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6218 return;
6221 static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha )
6223 return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 |
6224 blend_color( g, text >> 8, (BYTE)(alpha >> 8) ) << 8 |
6225 blend_color( b, text, (BYTE) alpha );
6228 static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6229 const POINT *origin, DWORD text_pixel )
6231 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6232 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6233 int x, y;
6235 for (y = rect->top; y < rect->bottom; y++)
6237 for (x = 0; x < rect->right - rect->left; x++)
6239 if (glyph_ptr[x] == 0) continue;
6240 dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, glyph_ptr[x] );
6242 dst_ptr += dib->stride / 4;
6243 glyph_ptr += glyph->stride / 4;
6247 static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6248 const POINT *origin, DWORD text_pixel )
6250 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6251 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6252 int x, y;
6253 DWORD text, val;
6255 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6256 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6257 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6259 for (y = rect->top; y < rect->bottom; y++)
6261 for (x = 0; x < rect->right - rect->left; x++)
6263 if (glyph_ptr[x] == 0) continue;
6264 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6265 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6266 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6267 text, glyph_ptr[x] );
6268 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
6269 put_field( val >> 8, dib->green_shift, dib->green_len ) |
6270 put_field( val, dib->blue_shift, dib->blue_len ));
6272 dst_ptr += dib->stride / 4;
6273 glyph_ptr += glyph->stride / 4;
6277 static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6278 const POINT *origin, DWORD text_pixel )
6280 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6281 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6282 int x, y;
6283 DWORD val;
6285 for (y = rect->top; y < rect->bottom; y++)
6287 for (x = 0; x < rect->right - rect->left; x++)
6289 if (glyph_ptr[x] == 0) continue;
6290 val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6291 text_pixel, glyph_ptr[x] );
6292 dst_ptr[x * 3] = val;
6293 dst_ptr[x * 3 + 1] = val >> 8;
6294 dst_ptr[x * 3 + 2] = val >> 16;
6296 dst_ptr += dib->stride;
6297 glyph_ptr += glyph->stride / 4;
6301 static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6302 const POINT *origin, DWORD text_pixel )
6304 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6305 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6306 int x, y;
6307 DWORD text, val;
6309 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6310 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6311 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6313 for (y = rect->top; y < rect->bottom; y++)
6315 for (x = 0; x < rect->right - rect->left; x++)
6317 if (glyph_ptr[x] == 0) continue;
6318 val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6319 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6320 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6321 text, glyph_ptr[x] );
6322 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6324 dst_ptr += dib->stride / 2;
6325 glyph_ptr += glyph->stride / 4;
6329 static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6330 const POINT *origin, DWORD text_pixel )
6332 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6333 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6334 int x, y;
6335 DWORD text, val;
6337 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6338 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6339 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6341 for (y = rect->top; y < rect->bottom; y++)
6343 for (x = 0; x < rect->right - rect->left; x++)
6345 if (glyph_ptr[x] == 0) continue;
6346 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6347 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6348 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6349 text, glyph_ptr[x] );
6350 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
6351 put_field( val >> 8, dib->green_shift, dib->green_len ) |
6352 put_field( val, dib->blue_shift, dib->blue_len ));
6354 dst_ptr += dib->stride / 2;
6355 glyph_ptr += glyph->stride / 4;
6359 static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6360 const POINT *origin, DWORD text_pixel )
6362 return;
6365 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
6366 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6368 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
6369 int x, y;
6371 /* masks are always 8x8 */
6372 assert( dib->width == 8 );
6373 assert( dib->height == 8 );
6375 for(y = 0; y < 8; y++, hatch_ptr++)
6377 for(x = 0; x < 8; x++)
6379 if(*hatch_ptr & pixel_masks_1[x])
6381 and_bits[x] = fg->and;
6382 xor_bits[x] = fg->xor;
6384 else
6386 and_bits[x] = bg->and;
6387 xor_bits[x] = bg->xor;
6390 and_bits += dib->stride / 4;
6391 xor_bits += dib->stride / 4;
6395 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
6396 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6398 DWORD mask_start = 0, mask_offset;
6399 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6400 int x, y;
6402 /* masks are always 8x8 */
6403 assert( dib->width == 8 );
6404 assert( dib->height == 8 );
6406 for(y = 0; y < 8; y++, hatch_ptr++)
6408 mask_offset = mask_start;
6409 for(x = 0; x < 8; x++)
6411 if(*hatch_ptr & pixel_masks_1[x])
6413 and_bits[mask_offset] = fg->and & 0xff;
6414 xor_bits[mask_offset++] = fg->xor & 0xff;
6415 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
6416 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
6417 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
6418 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
6420 else
6422 and_bits[mask_offset] = bg->and & 0xff;
6423 xor_bits[mask_offset++] = bg->xor & 0xff;
6424 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
6425 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
6426 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
6427 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
6430 mask_start += dib->stride;
6434 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
6435 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6437 WORD *and_bits = bits->and, *xor_bits = bits->xor;
6438 int x, y;
6440 /* masks are always 8x8 */
6441 assert( dib->width == 8 );
6442 assert( dib->height == 8 );
6444 for(y = 0; y < 8; y++, hatch_ptr++)
6446 for(x = 0; x < 8; x++)
6448 if(*hatch_ptr & pixel_masks_1[x])
6450 and_bits[x] = fg->and;
6451 xor_bits[x] = fg->xor;
6453 else
6455 and_bits[x] = bg->and;
6456 xor_bits[x] = bg->xor;
6459 and_bits += dib->stride / 2;
6460 xor_bits += dib->stride / 2;
6464 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
6465 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6467 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6468 int x, y;
6470 /* masks are always 8x8 */
6471 assert( dib->width == 8 );
6472 assert( dib->height == 8 );
6474 for(y = 0; y < 8; y++, hatch_ptr++)
6476 for(x = 0; x < 8; x++)
6478 if(*hatch_ptr & pixel_masks_1[x])
6480 and_bits[x] = fg->and;
6481 xor_bits[x] = fg->xor;
6483 else
6485 and_bits[x] = bg->and;
6486 xor_bits[x] = bg->xor;
6489 and_bits += dib->stride;
6490 xor_bits += dib->stride;
6494 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
6495 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6497 DWORD mask_offset;
6498 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6499 const rop_mask *rop_mask;
6500 int x, y;
6502 /* masks are always 8x8 */
6503 assert( dib->width == 8 );
6504 assert( dib->height == 8 );
6506 for(y = 0; y < 8; y++, hatch_ptr++)
6508 for(x = mask_offset = 0; x < 8; x++)
6510 if(*hatch_ptr & pixel_masks_1[x])
6511 rop_mask = fg;
6512 else
6513 rop_mask = bg;
6515 if(x & 1)
6517 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
6518 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
6519 mask_offset++;
6521 else
6523 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
6524 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
6527 and_bits += dib->stride;
6528 xor_bits += dib->stride;
6532 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
6533 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6535 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6536 rop_mask rop_mask;
6537 int x, y;
6539 /* masks are always 8x8 */
6540 assert( dib->width == 8 );
6541 assert( dib->height == 8 );
6543 for(y = 0; y < 8; y++, hatch_ptr++)
6545 *and_bits = *xor_bits = 0;
6546 for(x = 0; x < 8; x++)
6548 if(*hatch_ptr & pixel_masks_1[x])
6550 rop_mask.and = (fg->and & 1) ? 0xff : 0;
6551 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
6553 else
6555 rop_mask.and = (bg->and & 1) ? 0xff : 0;
6556 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
6558 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6559 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6561 and_bits += dib->stride;
6562 xor_bits += dib->stride;
6566 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
6567 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6571 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6573 /* mapping between RGB triples and the default color table */
6574 static const BYTE mapping[27] =
6576 0, /* 000000 -> 000000 */
6577 4, /* 00007f -> 000080 */
6578 252, /* 0000ff -> 0000ff */
6579 2, /* 007f00 -> 008000 */
6580 6, /* 007f7f -> 008080 */
6581 224, /* 007fff -> 0080c0 */
6582 250, /* 00ff00 -> 00ff00 */
6583 184, /* 00ff7f -> 00e080 */
6584 254, /* 00ffff -> 00ffff */
6585 1, /* 7f0000 -> 800000 */
6586 5, /* 7f007f -> 800080 */
6587 196, /* 7f00ff -> 8000c0 */
6588 3, /* 7f7f00 -> 808000 */
6589 248, /* 7f7f7f -> 808080 */
6590 228, /* 7f7fff -> 8080c0 */
6591 60, /* 7fff00 -> 80e000 */
6592 188, /* 7fff7f -> 80e080 */
6593 244, /* 7fffff -> 80c0c0 */
6594 249, /* ff0000 -> ff0000 */
6595 135, /* ff007f -> e00080 */
6596 253, /* ff00ff -> ff00ff */
6597 39, /* ff7f00 -> e08000 */
6598 167, /* ff7f7f -> e08080 */
6599 231, /* ff7fff -> e080c0 */
6600 251, /* ffff00 -> ffff00 */
6601 191, /* ffff7f -> e0e080 */
6602 255 /* ffffff -> ffffff */
6605 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6606 struct rop_codes codes;
6607 int x, y;
6609 /* masks are always 8x8 */
6610 assert( dib->width == 8 );
6611 assert( dib->height == 8 );
6613 get_rop_codes( rop2, &codes );
6615 for (y = 0; y < 8; y++)
6617 for (x = 0; x < 8; x++)
6619 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6620 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6621 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6622 DWORD pixel = mapping[r * 9 + g * 3 + b];
6623 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
6624 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
6626 and_bits += dib->stride;
6627 xor_bits += dib->stride;
6631 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6633 /* mapping between RGB triples and the default color table */
6634 static const BYTE mapping[27] =
6636 0, /* 000000 -> 000000 */
6637 4, /* 00007f -> 000080 */
6638 12, /* 0000ff -> 0000ff */
6639 2, /* 007f00 -> 008000 */
6640 6, /* 007f7f -> 008080 */
6641 6, /* 007fff -> 008080 */
6642 10, /* 00ff00 -> 00ff00 */
6643 6, /* 00ff7f -> 008080 */
6644 14, /* 00ffff -> 00ffff */
6645 1, /* 7f0000 -> 800000 */
6646 5, /* 7f007f -> 800080 */
6647 5, /* 7f00ff -> 800080 */
6648 3, /* 7f7f00 -> 808000 */
6649 7, /* 7f7f7f -> 808080 */
6650 8, /* 7f7fff -> c0c0c0 */
6651 3, /* 7fff00 -> 808000 */
6652 8, /* 7fff7f -> c0c0c0 */
6653 8, /* 7fffff -> c0c0c0 */
6654 9, /* ff0000 -> ff0000 */
6655 5, /* ff007f -> 800080 */
6656 13, /* ff00ff -> ff00ff */
6657 3, /* ff7f00 -> 808000 */
6658 8, /* ff7f7f -> c0c0c0 */
6659 8, /* ff7fff -> c0c0c0 */
6660 11, /* ffff00 -> ffff00 */
6661 8, /* ffff7f -> c0c0c0 */
6662 15 /* ffffff -> ffffff */
6665 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6666 struct rop_codes codes;
6667 int x, y;
6669 /* masks are always 8x8 */
6670 assert( dib->width == 8 );
6671 assert( dib->height == 8 );
6673 get_rop_codes( rop2, &codes );
6675 for (y = 0; y < 8; y++)
6677 for (x = 0; x < 8; x++)
6679 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6680 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6681 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6682 DWORD pixel = mapping[r * 9 + g * 3 + b];
6683 if (x & 1)
6685 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
6686 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
6688 else
6690 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
6691 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
6694 and_bits += dib->stride;
6695 xor_bits += dib->stride;
6699 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6701 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6702 struct rop_codes codes;
6703 rop_mask rop_mask;
6704 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
6706 /* masks are always 8x8 */
6707 assert( dib->width == 8 );
6708 assert( dib->height == 8 );
6710 get_rop_codes( rop2, &codes );
6712 for (y = 0; y < 8; y++)
6714 *and_bits = *xor_bits = 0;
6715 for (x = 0; x < 8; x++)
6717 if (grey + bayer_8x8[y][x] > 63)
6719 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
6720 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
6722 else
6724 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
6725 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
6727 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6728 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6730 and_bits += dib->stride;
6731 xor_bits += dib->stride;
6735 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6739 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
6741 switch (mode)
6743 default:
6744 case STRETCH_DELETESCANS:
6745 get_rop_codes( R2_COPYPEN, codes );
6746 break;
6747 case STRETCH_ORSCANS:
6748 get_rop_codes( R2_MERGEPEN, codes );
6749 break;
6750 case STRETCH_ANDSCANS:
6751 get_rop_codes( R2_MASKPEN, codes );
6752 break;
6754 return;
6757 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
6758 const dib_info *src_dib, const POINT *src_start,
6759 const struct stretch_params *params, int mode,
6760 BOOL keep_dst)
6762 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
6763 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
6764 int err = params->err_start;
6765 int width;
6767 if (mode == STRETCH_DELETESCANS || !keep_dst)
6769 for (width = params->length; width; width--)
6771 *dst_ptr = *src_ptr;
6772 dst_ptr += params->dst_inc;
6773 if (err > 0)
6775 src_ptr += params->src_inc;
6776 err += params->err_add_1;
6778 else err += params->err_add_2;
6781 else
6783 struct rop_codes codes;
6785 rop_codes_from_stretch_mode( mode, &codes );
6786 for (width = params->length; width; width--)
6788 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
6789 dst_ptr += params->dst_inc;
6790 if (err > 0)
6792 src_ptr += params->src_inc;
6793 err += params->err_add_1;
6795 else err += params->err_add_2;
6800 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
6801 const dib_info *src_dib, const POINT *src_start,
6802 const struct stretch_params *params, int mode,
6803 BOOL keep_dst)
6805 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
6806 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
6807 int err = params->err_start;
6808 int width;
6810 if (mode == STRETCH_DELETESCANS || !keep_dst)
6812 for (width = params->length; width; width--)
6814 dst_ptr[0] = src_ptr[0];
6815 dst_ptr[1] = src_ptr[1];
6816 dst_ptr[2] = src_ptr[2];
6817 dst_ptr += 3 * params->dst_inc;
6818 if (err > 0)
6820 src_ptr += 3 * params->src_inc;
6821 err += params->err_add_1;
6823 else err += params->err_add_2;
6826 else
6828 struct rop_codes codes;
6830 rop_codes_from_stretch_mode( mode, &codes );
6831 for (width = params->length; width; width--)
6833 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6834 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
6835 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
6836 dst_ptr += 3 * params->dst_inc;
6837 if (err > 0)
6839 src_ptr += 3 * params->src_inc;
6840 err += params->err_add_1;
6842 else err += params->err_add_2;
6847 static void stretch_row_16(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 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
6853 WORD *src_ptr = get_pixel_ptr_16( 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 = *src_ptr;
6862 dst_ptr += params->dst_inc;
6863 if (err > 0)
6865 src_ptr += params->src_inc;
6866 err += params->err_add_1;
6868 else err += params->err_add_2;
6871 else
6873 struct rop_codes codes;
6875 rop_codes_from_stretch_mode( mode, &codes );
6876 for (width = params->length; width; width--)
6878 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
6879 dst_ptr += params->dst_inc;
6880 if (err > 0)
6882 src_ptr += params->src_inc;
6883 err += params->err_add_1;
6885 else err += params->err_add_2;
6890 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
6891 const dib_info *src_dib, const POINT *src_start,
6892 const struct stretch_params *params, int mode,
6893 BOOL keep_dst)
6895 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
6896 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
6897 int err = params->err_start;
6898 int width;
6900 if (mode == STRETCH_DELETESCANS || !keep_dst)
6902 for (width = params->length; width; width--)
6904 *dst_ptr = *src_ptr;
6905 dst_ptr += params->dst_inc;
6906 if (err > 0)
6908 src_ptr += params->src_inc;
6909 err += params->err_add_1;
6911 else err += params->err_add_2;
6914 else
6916 struct rop_codes codes;
6918 rop_codes_from_stretch_mode( mode, &codes );
6919 for (width = params->length; width; width--)
6921 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6922 dst_ptr += params->dst_inc;
6923 if (err > 0)
6925 src_ptr += params->src_inc;
6926 err += params->err_add_1;
6928 else err += params->err_add_2;
6933 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
6934 const dib_info *src_dib, const POINT *src_start,
6935 const struct stretch_params *params, int mode,
6936 BOOL keep_dst)
6938 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
6939 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
6940 int err = params->err_start;
6941 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6942 struct rop_codes codes;
6943 BYTE src_val;
6945 if (!keep_dst) mode = STRETCH_DELETESCANS;
6946 rop_codes_from_stretch_mode( mode, &codes );
6947 for (width = params->length; width; width--)
6949 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
6950 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
6952 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
6954 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
6955 dst_ptr += params->dst_inc;
6956 dst_x += params->dst_inc;
6958 if (err > 0)
6960 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
6961 src_ptr += params->src_inc;
6962 src_x += params->src_inc;
6963 err += params->err_add_1;
6965 else err += params->err_add_2;
6969 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
6970 const dib_info *src_dib, const POINT *src_start,
6971 const struct stretch_params *params, int mode,
6972 BOOL keep_dst)
6974 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
6975 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
6976 int err = params->err_start;
6977 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6978 struct rop_codes codes;
6979 BYTE src_val;
6981 if (!keep_dst) mode = STRETCH_DELETESCANS;
6982 rop_codes_from_stretch_mode( mode, &codes );
6983 for (width = params->length; width; width--)
6985 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
6986 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
6988 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
6989 dst_ptr += params->dst_inc;
6990 dst_x += params->dst_inc;
6992 if (err > 0)
6994 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
6995 src_ptr += params->src_inc;
6996 src_x += params->src_inc;
6997 err += params->err_add_1;
6999 else err += params->err_add_2;
7003 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
7004 const dib_info *src_dib, const POINT *src_start,
7005 const struct stretch_params *params, int mode,
7006 BOOL keep_dst)
7008 FIXME("bit count %d\n", dst_dib->bit_count);
7009 return;
7012 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
7013 const dib_info *src_dib, const POINT *src_start,
7014 const struct stretch_params *params, int mode,
7015 BOOL keep_dst)
7017 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
7018 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
7019 int err = params->err_start;
7020 int width;
7022 if (mode == STRETCH_DELETESCANS)
7024 for (width = params->length; width; width--)
7026 *dst_ptr = *src_ptr;
7027 src_ptr += params->src_inc;
7028 if (err > 0)
7030 dst_ptr += params->dst_inc;
7031 err += params->err_add_1;
7033 else err += params->err_add_2;
7036 else
7038 struct rop_codes codes;
7039 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
7040 BOOL new_pix = TRUE;
7042 rop_codes_from_stretch_mode( mode, &codes );
7043 for (width = params->length; width; width--)
7045 if (new_pix && !keep_dst) *dst_ptr = init_val;
7046 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
7047 new_pix = FALSE;
7048 src_ptr += params->src_inc;
7049 if (err > 0)
7051 dst_ptr += params->dst_inc;
7052 new_pix = TRUE;
7053 err += params->err_add_1;
7055 else err += params->err_add_2;
7060 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
7061 const dib_info *src_dib, const POINT *src_start,
7062 const struct stretch_params *params, int mode,
7063 BOOL keep_dst)
7065 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
7066 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
7067 int err = params->err_start;
7068 int width;
7070 if (mode == STRETCH_DELETESCANS)
7072 for (width = params->length; width; width--)
7074 dst_ptr[0] = src_ptr[0];
7075 dst_ptr[1] = src_ptr[1];
7076 dst_ptr[2] = src_ptr[2];
7077 src_ptr += 3 * params->src_inc;
7078 if (err > 0)
7080 dst_ptr += 3 * params->dst_inc;
7081 err += params->err_add_1;
7083 else err += params->err_add_2;
7086 else
7088 struct rop_codes codes;
7089 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7090 BOOL new_pix = TRUE;
7092 rop_codes_from_stretch_mode( mode, &codes );
7093 for (width = params->length; width; width--)
7095 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
7096 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7097 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
7098 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
7099 new_pix = FALSE;
7100 src_ptr += 3 * params->src_inc;
7101 if (err > 0)
7103 dst_ptr += 3 * params->dst_inc;
7104 new_pix = TRUE;
7105 err += params->err_add_1;
7107 else err += params->err_add_2;
7112 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
7113 const dib_info *src_dib, const POINT *src_start,
7114 const struct stretch_params *params, int mode,
7115 BOOL keep_dst)
7117 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
7118 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
7119 int err = params->err_start;
7120 int width;
7122 if (mode == STRETCH_DELETESCANS)
7124 for (width = params->length; width; width--)
7126 *dst_ptr = *src_ptr;
7127 src_ptr += params->src_inc;
7128 if (err > 0)
7130 dst_ptr += params->dst_inc;
7131 err += params->err_add_1;
7133 else err += params->err_add_2;
7136 else
7138 struct rop_codes codes;
7139 WORD init_val = (mode == STRETCH_ANDSCANS) ? 0xffff : 0;
7140 BOOL new_pix = TRUE;
7142 rop_codes_from_stretch_mode( mode, &codes );
7143 for (width = params->length; width; width--)
7145 if (new_pix && !keep_dst) *dst_ptr = init_val;
7146 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
7147 new_pix = FALSE;
7148 src_ptr += params->src_inc;
7149 if (err > 0)
7151 dst_ptr += params->dst_inc;
7152 new_pix = TRUE;
7153 err += params->err_add_1;
7155 else err += params->err_add_2;
7160 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
7161 const dib_info *src_dib, const POINT *src_start,
7162 const struct stretch_params *params, int mode,
7163 BOOL keep_dst)
7165 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
7166 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
7167 int err = params->err_start;
7168 int width;
7170 if (mode == STRETCH_DELETESCANS)
7172 for (width = params->length; width; width--)
7174 *dst_ptr = *src_ptr;
7175 src_ptr += params->src_inc;
7176 if (err > 0)
7178 dst_ptr += params->dst_inc;
7179 err += params->err_add_1;
7181 else err += params->err_add_2;
7184 else
7186 struct rop_codes codes;
7187 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7188 BOOL new_pix = TRUE;
7190 rop_codes_from_stretch_mode( mode, &codes );
7191 for (width = params->length; width; width--)
7193 if (new_pix && !keep_dst) *dst_ptr = init_val;
7194 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7195 new_pix = FALSE;
7196 src_ptr += params->src_inc;
7197 if (err > 0)
7199 dst_ptr += params->dst_inc;
7200 new_pix = TRUE;
7201 err += params->err_add_1;
7203 else err += params->err_add_2;
7208 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
7209 const dib_info *src_dib, const POINT *src_start,
7210 const struct stretch_params *params, int mode,
7211 BOOL keep_dst)
7213 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
7214 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
7215 int err = params->err_start;
7216 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7217 struct rop_codes codes;
7218 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7219 BOOL new_pix = TRUE;
7221 rop_codes_from_stretch_mode( mode, &codes );
7222 for (width = params->length; width; width--)
7224 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
7226 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
7227 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
7229 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
7230 new_pix = FALSE;
7232 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
7233 src_ptr += params->src_inc;
7234 src_x += params->src_inc;
7236 if (err > 0)
7238 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
7239 dst_ptr += params->dst_inc;
7240 dst_x += params->dst_inc;
7241 new_pix = TRUE;
7242 err += params->err_add_1;
7244 else err += params->err_add_2;
7248 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
7249 const dib_info *src_dib, const POINT *src_start,
7250 const struct stretch_params *params, int mode,
7251 BOOL keep_dst)
7253 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
7254 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
7255 int err = params->err_start;
7256 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7257 struct rop_codes codes;
7258 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7259 BOOL new_pix = TRUE;
7261 rop_codes_from_stretch_mode( mode, &codes );
7262 for (width = params->length; width; width--)
7264 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
7265 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
7266 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
7267 new_pix = FALSE;
7269 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
7270 src_ptr += params->src_inc;
7271 src_x += params->src_inc;
7273 if (err > 0)
7275 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
7276 dst_ptr += params->dst_inc;
7277 dst_x += params->dst_inc;
7278 new_pix = TRUE;
7279 err += params->err_add_1;
7281 else err += params->err_add_2;
7285 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
7286 const dib_info *src_dib, const POINT *src_start,
7287 const struct stretch_params *params, int mode,
7288 BOOL keep_dst)
7290 FIXME("bit count %d\n", dst_dib->bit_count);
7291 return;
7294 const primitive_funcs funcs_8888 =
7296 solid_rects_32,
7297 solid_line_32,
7298 pattern_rects_32,
7299 copy_rect_32,
7300 blend_rect_8888,
7301 gradient_rect_8888,
7302 mask_rect_32,
7303 draw_glyph_8888,
7304 draw_subpixel_glyph_8888,
7305 get_pixel_32,
7306 colorref_to_pixel_888,
7307 pixel_to_colorref_888,
7308 convert_to_8888,
7309 create_rop_masks_32,
7310 create_dither_masks_null,
7311 stretch_row_32,
7312 shrink_row_32
7315 const primitive_funcs funcs_32 =
7317 solid_rects_32,
7318 solid_line_32,
7319 pattern_rects_32,
7320 copy_rect_32,
7321 blend_rect_32,
7322 gradient_rect_32,
7323 mask_rect_32,
7324 draw_glyph_32,
7325 draw_subpixel_glyph_32,
7326 get_pixel_32,
7327 colorref_to_pixel_masks,
7328 pixel_to_colorref_masks,
7329 convert_to_32,
7330 create_rop_masks_32,
7331 create_dither_masks_null,
7332 stretch_row_32,
7333 shrink_row_32
7336 const primitive_funcs funcs_24 =
7338 solid_rects_24,
7339 solid_line_24,
7340 pattern_rects_24,
7341 copy_rect_24,
7342 blend_rect_24,
7343 gradient_rect_24,
7344 mask_rect_24,
7345 draw_glyph_24,
7346 draw_subpixel_glyph_24,
7347 get_pixel_24,
7348 colorref_to_pixel_888,
7349 pixel_to_colorref_888,
7350 convert_to_24,
7351 create_rop_masks_24,
7352 create_dither_masks_null,
7353 stretch_row_24,
7354 shrink_row_24
7357 const primitive_funcs funcs_555 =
7359 solid_rects_16,
7360 solid_line_16,
7361 pattern_rects_16,
7362 copy_rect_16,
7363 blend_rect_555,
7364 gradient_rect_555,
7365 mask_rect_16,
7366 draw_glyph_555,
7367 draw_subpixel_glyph_555,
7368 get_pixel_16,
7369 colorref_to_pixel_555,
7370 pixel_to_colorref_555,
7371 convert_to_555,
7372 create_rop_masks_16,
7373 create_dither_masks_null,
7374 stretch_row_16,
7375 shrink_row_16
7378 const primitive_funcs funcs_16 =
7380 solid_rects_16,
7381 solid_line_16,
7382 pattern_rects_16,
7383 copy_rect_16,
7384 blend_rect_16,
7385 gradient_rect_16,
7386 mask_rect_16,
7387 draw_glyph_16,
7388 draw_subpixel_glyph_16,
7389 get_pixel_16,
7390 colorref_to_pixel_masks,
7391 pixel_to_colorref_masks,
7392 convert_to_16,
7393 create_rop_masks_16,
7394 create_dither_masks_null,
7395 stretch_row_16,
7396 shrink_row_16
7399 const primitive_funcs funcs_8 =
7401 solid_rects_8,
7402 solid_line_8,
7403 pattern_rects_8,
7404 copy_rect_8,
7405 blend_rect_8,
7406 gradient_rect_8,
7407 mask_rect_8,
7408 draw_glyph_8,
7409 draw_subpixel_glyph_null,
7410 get_pixel_8,
7411 colorref_to_pixel_colortable,
7412 pixel_to_colorref_colortable,
7413 convert_to_8,
7414 create_rop_masks_8,
7415 create_dither_masks_8,
7416 stretch_row_8,
7417 shrink_row_8
7420 const primitive_funcs funcs_4 =
7422 solid_rects_4,
7423 solid_line_4,
7424 pattern_rects_4,
7425 copy_rect_4,
7426 blend_rect_4,
7427 gradient_rect_4,
7428 mask_rect_4,
7429 draw_glyph_4,
7430 draw_subpixel_glyph_null,
7431 get_pixel_4,
7432 colorref_to_pixel_colortable,
7433 pixel_to_colorref_colortable,
7434 convert_to_4,
7435 create_rop_masks_4,
7436 create_dither_masks_4,
7437 stretch_row_4,
7438 shrink_row_4
7441 const primitive_funcs funcs_1 =
7443 solid_rects_1,
7444 solid_line_1,
7445 pattern_rects_1,
7446 copy_rect_1,
7447 blend_rect_1,
7448 gradient_rect_1,
7449 mask_rect_null,
7450 draw_glyph_1,
7451 draw_subpixel_glyph_null,
7452 get_pixel_1,
7453 colorref_to_pixel_colortable,
7454 pixel_to_colorref_colortable,
7455 convert_to_1,
7456 create_rop_masks_1,
7457 create_dither_masks_1,
7458 stretch_row_1,
7459 shrink_row_1
7462 const primitive_funcs funcs_null =
7464 solid_rects_null,
7465 solid_line_null,
7466 pattern_rects_null,
7467 copy_rect_null,
7468 blend_rect_null,
7469 gradient_rect_null,
7470 mask_rect_null,
7471 draw_glyph_null,
7472 draw_subpixel_glyph_null,
7473 get_pixel_null,
7474 colorref_to_pixel_null,
7475 pixel_to_colorref_null,
7476 convert_to_null,
7477 create_rop_masks_null,
7478 create_dither_masks_null,
7479 stretch_row_null,
7480 shrink_row_null