TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blobc7b48ed25e99f895932794c975f875ef2f4e3ec2
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};
110 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
112 *ptr = (*ptr & and) ^ xor;
115 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
117 *ptr = (*ptr & and) ^ xor;
120 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
122 *ptr = (*ptr & and) ^ xor;
125 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
127 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
130 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
132 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
135 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
137 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
140 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
142 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
145 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
147 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
150 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
152 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
155 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
157 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
158 do_rop_codes_32( dst, *src, codes );
161 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
163 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
166 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
168 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
169 do_rop_codes_16( dst, *src, codes );
172 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
174 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
177 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
179 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
180 do_rop_codes_8( dst, *src, codes );
183 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
184 struct rop_codes *codes, int len)
186 BYTE src_val;
188 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
190 if (dst_x & 1)
192 if (src_x & 1) src_val = *src++;
193 else src_val = *src >> 4;
194 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
196 else
198 if (src_x & 1) src_val = *src++ << 4;
199 else src_val = *src;
200 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
205 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
206 struct rop_codes *codes, int len)
208 BYTE src_val;
210 src_x += len - 1;
211 dst_x += len - 1;
212 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
214 if (dst_x & 1)
216 if (src_x & 1) src_val = *src;
217 else src_val = *src-- >> 4;
218 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
220 else
222 if (src_x & 1) src_val = *src << 4;
223 else src_val = *src--;
224 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
229 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
230 struct rop_codes *codes, int len)
232 BYTE src_val;
234 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
236 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
237 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
238 if ((src_x & 7) == 7) src++;
239 if ((dst_x & 7) == 7) dst++;
243 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
244 struct rop_codes *codes, int len)
246 BYTE src_val;
248 src_x += len - 1;
249 dst_x += len - 1;
250 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
252 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
253 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
254 if ((src_x & 7) == 0) src--;
255 if ((dst_x & 7) == 0) dst--;
259 static inline void memset_32( DWORD *start, DWORD val, DWORD size )
261 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
262 DWORD dummy;
263 __asm__ __volatile__( "cld; rep; stosl"
264 : "=c" (dummy), "=D" (dummy)
265 : "a" (val), "0" (size), "1" (start) );
266 #else
267 while (size--) *start++ = val;
268 #endif
271 static inline void memset_16( WORD *start, WORD val, DWORD size )
273 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
274 DWORD dummy;
275 __asm__ __volatile__( "cld; rep; stosw"
276 : "=c" (dummy), "=D" (dummy)
277 : "a" (val), "0" (size), "1" (start) );
278 #else
279 while (size--) *start++ = val;
280 #endif
283 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
285 DWORD *ptr, *start;
286 int x, y, i;
288 for(i = 0; i < num; i++, rc++)
290 assert( !is_rect_empty( rc ));
292 start = get_pixel_ptr_32(dib, rc->left, rc->top);
293 if (and)
294 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
295 for(x = rc->left, ptr = start; x < rc->right; x++)
296 do_rop_32(ptr++, and, xor);
297 else
298 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
299 memset_32( start, xor, rc->right - rc->left );
303 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
305 DWORD *ptr, *start;
306 BYTE *byte_ptr, *byte_start;
307 int x, y, i;
308 DWORD and_masks[3], xor_masks[3];
310 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
311 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
312 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
313 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
314 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
315 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
317 for(i = 0; i < num; i++, rc++)
319 int left = dib->rect.left + rc->left;
320 int right = dib->rect.left + rc->right;
322 assert( !is_rect_empty( rc ));
324 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
326 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
327 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
329 for(x = left, byte_ptr = byte_start; x < right; x++)
331 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
332 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
333 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
337 else if (and)
339 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
340 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
342 ptr = start;
344 switch(left & 3)
346 case 1:
347 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
348 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
349 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
350 break;
351 case 2:
352 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
353 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
354 break;
355 case 3:
356 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
357 break;
360 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
362 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
363 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
364 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
367 switch(right & 3)
369 case 1:
370 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
371 break;
372 case 2:
373 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
374 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
375 break;
376 case 3:
377 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
378 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
379 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
380 break;
384 else
386 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
387 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
389 ptr = start;
391 switch(left & 3)
393 case 1:
394 do_rop_32(ptr++, 0x00ffffff, xor_masks[0] & 0xff000000);
395 *ptr++ = xor_masks[1];
396 *ptr++ = xor_masks[2];
397 break;
398 case 2:
399 do_rop_32(ptr++, 0x0000ffff, xor_masks[1] & 0xffff0000);
400 *ptr++ = xor_masks[2];
401 break;
402 case 3:
403 do_rop_32(ptr++, 0x000000ff, xor_masks[2] & 0xffffff00);
404 break;
407 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
409 *ptr++ = xor_masks[0];
410 *ptr++ = xor_masks[1];
411 *ptr++ = xor_masks[2];
414 switch(right & 3)
416 case 1:
417 do_rop_32(ptr, 0xff000000, xor_masks[0] & 0x00ffffff);
418 break;
419 case 2:
420 *ptr++ = xor_masks[0];
421 do_rop_32(ptr, 0xffff0000, xor_masks[1] & 0x0000ffff);
422 break;
423 case 3:
424 *ptr++ = xor_masks[0];
425 *ptr++ = xor_masks[1];
426 do_rop_32(ptr, 0xffffff00, xor_masks[2] & 0x000000ff);
427 break;
434 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
436 WORD *ptr, *start;
437 int x, y, i;
439 for(i = 0; i < num; i++, rc++)
441 assert( !is_rect_empty( rc ));
443 start = get_pixel_ptr_16(dib, rc->left, rc->top);
444 if (and)
445 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
446 for(x = rc->left, ptr = start; x < rc->right; x++)
447 do_rop_16(ptr++, and, xor);
448 else
449 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
450 memset_16( start, xor, rc->right - rc->left );
454 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
456 BYTE *ptr, *start;
457 int x, y, i;
459 for(i = 0; i < num; i++, rc++)
461 assert( !is_rect_empty( rc ));
463 start = get_pixel_ptr_8(dib, rc->left, rc->top);
464 if (and)
465 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
466 for(x = rc->left, ptr = start; x < rc->right; x++)
467 do_rop_8(ptr++, and, xor);
468 else
469 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
470 memset( start, xor, rc->right - rc->left );
474 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
476 BYTE *ptr, *start;
477 int x, y, i;
478 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
479 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
481 for(i = 0; i < num; i++, rc++)
483 int left = dib->rect.left + rc->left;
484 int right = dib->rect.left + rc->right;
486 assert( !is_rect_empty( rc ));
488 start = get_pixel_ptr_4(dib, rc->left, rc->top);
489 if (and)
491 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
493 ptr = start;
494 if(left & 1) /* upper nibble untouched */
495 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
497 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
498 do_rop_8(ptr++, byte_and, byte_xor);
500 if(right & 1) /* lower nibble untouched */
501 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
504 else
506 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
508 unsigned int byte_len = (right - ((left + 1) & ~1)) / 2;
510 ptr = start;
511 if(left & 1) /* upper nibble untouched */
512 do_rop_8(ptr++, 0xf0, byte_xor & 0x0f);
514 memset( ptr, byte_xor, byte_len );
516 if(right & 1) /* lower nibble untouched */
517 do_rop_8(ptr + byte_len, 0x0f, byte_xor & 0xf0);
523 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
525 BYTE *ptr, *start;
526 int x, y, i;
527 BYTE byte_and = (and & 1) ? 0xff : 0;
528 BYTE byte_xor = (xor & 1) ? 0xff : 0;
529 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
531 for(i = 0; i < num; i++, rc++)
533 int left = dib->rect.left + rc->left;
534 int right = dib->rect.left + rc->right;
536 assert( !is_rect_empty( rc ));
538 start = get_pixel_ptr_1(dib, rc->left, rc->top);
540 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
542 BYTE mask = masks[left & 7] & ~masks[right & 7];
544 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
546 do_rop_8(start, byte_and | ~mask, byte_xor & mask);
549 else if (and)
551 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
553 ptr = start;
555 if(left & 7)
556 do_rop_8(ptr++, byte_and | ~masks[left & 7], byte_xor & masks[left & 7]);
558 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
559 do_rop_8(ptr++, byte_and, byte_xor);
561 if(right & 7)
562 /* this is inverted wrt start mask */
563 do_rop_8(ptr, byte_and | masks[right & 7], byte_xor & ~masks[right & 7]);
566 else
568 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
570 unsigned int byte_len = (right - ((left + 7) & ~7)) / 8;
572 ptr = start;
574 if(left & 7)
575 do_rop_8(ptr++, ~masks[left & 7], byte_xor & masks[left & 7]);
577 memset( ptr, byte_xor, byte_len );
579 if(right & 7)
580 do_rop_8(ptr + byte_len, masks[right & 7], byte_xor & ~masks[right & 7]);
586 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
588 return;
591 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
592 DWORD and, DWORD xor)
594 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
595 int len = params->length, err = params->err_start;
596 int major_inc, minor_inc;
598 if (params->x_major)
600 major_inc = params->x_inc;
601 minor_inc = (dib->stride * params->y_inc) / 4;
603 else
605 major_inc = (dib->stride * params->y_inc) / 4;
606 minor_inc = params->x_inc;
609 while (len--)
611 do_rop_32( ptr, and, xor );
612 if (err + params->bias > 0)
614 ptr += minor_inc;
615 err += params->err_add_1;
617 else err += params->err_add_2;
618 ptr += major_inc;
622 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
623 DWORD and, DWORD xor)
625 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
626 int len = params->length, err = params->err_start;
627 int major_inc, minor_inc;
629 if (params->x_major)
631 major_inc = params->x_inc * 3;
632 minor_inc = dib->stride * params->y_inc;
634 else
636 major_inc = dib->stride * params->y_inc;
637 minor_inc = params->x_inc * 3;
640 while (len--)
642 do_rop_8( ptr, and, xor );
643 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
644 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
645 if (err + params->bias > 0)
647 ptr += minor_inc;
648 err += params->err_add_1;
650 else err += params->err_add_2;
651 ptr += major_inc;
655 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
656 DWORD and, DWORD xor)
658 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
659 int len = params->length, err = params->err_start;
660 int major_inc, minor_inc;
662 if (params->x_major)
664 major_inc = params->x_inc;
665 minor_inc = (dib->stride * params->y_inc) / 2;
667 else
669 major_inc = (dib->stride * params->y_inc) / 2;
670 minor_inc = params->x_inc;
673 while (len--)
675 do_rop_16( ptr, and, xor );
676 if (err + params->bias > 0)
678 ptr += minor_inc;
679 err += params->err_add_1;
681 else err += params->err_add_2;
682 ptr += major_inc;
686 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
687 DWORD and, DWORD xor)
689 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
690 int len = params->length, err = params->err_start;
691 int major_inc, minor_inc;
693 if (params->x_major)
695 major_inc = params->x_inc;
696 minor_inc = dib->stride * params->y_inc;
698 else
700 major_inc = dib->stride * params->y_inc;
701 minor_inc = params->x_inc;
704 while (len--)
706 do_rop_8( ptr, and, xor );
707 if (err + params->bias > 0)
709 ptr += minor_inc;
710 err += params->err_add_1;
712 else err += params->err_add_2;
713 ptr += major_inc;
717 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
718 DWORD and, DWORD xor)
720 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
721 int len = params->length, err = params->err_start;
722 int x = dib->rect.left + start->x;
724 and = (and & 0x0f) | ((and << 4) & 0xf0);
725 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
727 if (params->x_major)
729 while (len--)
731 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
732 if (err + params->bias > 0)
734 ptr += dib->stride * params->y_inc;
735 err += params->err_add_1;
737 else err += params->err_add_2;
738 if ((x / 2) != ((x + params->x_inc) / 2))
739 ptr += params->x_inc;
740 x += params->x_inc;
743 else
745 while (len--)
747 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
748 if (err + params->bias > 0)
750 if ((x / 2) != ((x + params->x_inc) / 2))
751 ptr += params->x_inc;
752 x += params->x_inc;
753 err += params->err_add_1;
755 else err += params->err_add_2;
756 ptr += dib->stride * params->y_inc;
761 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
762 DWORD and, DWORD xor)
764 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
765 int len = params->length, err = params->err_start;
766 int x = dib->rect.left + start->x;
768 and = (and & 0x1) ? 0xff : 0;
769 xor = (xor & 0x1) ? 0xff : 0;
771 if (params->x_major)
773 while (len--)
775 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
776 if (err + params->bias > 0)
778 ptr += dib->stride * params->y_inc;
779 err += params->err_add_1;
781 else err += params->err_add_2;
782 if ((x / 8) != ((x + params->x_inc) / 8))
783 ptr += params->x_inc;
784 x += params->x_inc;
787 else
789 while (len--)
791 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
792 if (err + params->bias > 0)
794 if ((x / 8) != ((x + params->x_inc) / 8))
795 ptr += params->x_inc;
796 x += params->x_inc;
797 err += params->err_add_1;
799 else err += params->err_add_2;
800 ptr += dib->stride * params->y_inc;
805 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
806 DWORD and, DWORD xor)
808 return;
811 static inline INT calc_offset(INT edge, INT size, INT origin)
813 INT offset;
815 if(edge - origin >= 0)
816 offset = (edge - origin) % size;
817 else
819 offset = (origin - edge) % size;
820 if(offset) offset = size - offset;
822 return offset;
825 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
827 POINT offset;
829 offset.x = calc_offset(rc->left, brush->width, origin->x);
830 offset.y = calc_offset(rc->top, brush->height, origin->y);
832 return offset;
835 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
836 const dib_info *brush, const rop_mask_bits *bits)
838 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
839 int x, y, i, len, brush_x;
840 POINT offset;
842 for(i = 0; i < num; i++, rc++)
844 offset = calc_brush_offset(rc, brush, origin);
845 start = get_pixel_ptr_32(dib, rc->left, rc->top);
846 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
848 if (bits->and)
850 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
852 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
854 and_ptr = start_and + offset.x;
855 xor_ptr = start_xor + offset.x;
857 for(x = rc->left, ptr = start; x < rc->right; x++)
859 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
860 if(and_ptr == start_and + brush->width)
862 and_ptr = start_and;
863 xor_ptr = start_xor;
867 offset.y++;
868 if(offset.y == brush->height)
870 start_and = bits->and;
871 start_xor = bits->xor;
872 offset.y = 0;
874 else
876 start_and += brush->stride / 4;
877 start_xor += brush->stride / 4;
881 else
883 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
885 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
887 len = min( rc->right - x, brush->width - brush_x );
888 memcpy( start + x - rc->left, start_xor + brush_x, len * 4 );
889 brush_x = 0;
892 start_xor += brush->stride / 4;
893 offset.y++;
894 if(offset.y == brush->height)
896 start_xor = bits->xor;
897 offset.y = 0;
904 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
905 const dib_info *brush, const rop_mask_bits *bits)
907 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
908 int x, y, i, len, brush_x;
909 POINT offset;
911 for(i = 0; i < num; i++, rc++)
913 offset = calc_brush_offset(rc, brush, origin);
915 start = get_pixel_ptr_24(dib, rc->left, rc->top);
916 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
918 if (bits->and)
920 start_and = (BYTE*)bits->and + offset.y * brush->stride;
921 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
923 and_ptr = start_and + offset.x * 3;
924 xor_ptr = start_xor + offset.x * 3;
926 for(x = rc->left, ptr = start; x < rc->right; x++)
928 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
929 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
930 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
931 if(and_ptr == start_and + brush->width * 3)
933 and_ptr = start_and;
934 xor_ptr = start_xor;
938 offset.y++;
939 if(offset.y == brush->height)
941 start_and = bits->and;
942 start_xor = bits->xor;
943 offset.y = 0;
945 else
947 start_and += brush->stride;
948 start_xor += brush->stride;
952 else
954 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
956 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
958 len = min( rc->right - x, brush->width - brush_x );
959 memcpy( start + (x - rc->left) * 3, start_xor + brush_x * 3, len * 3 );
960 brush_x = 0;
963 start_xor += brush->stride;
964 offset.y++;
965 if(offset.y == brush->height)
967 start_xor = bits->xor;
968 offset.y = 0;
975 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
976 const dib_info *brush, const rop_mask_bits *bits)
978 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
979 int x, y, i, len, brush_x;
980 POINT offset;
982 for(i = 0; i < num; i++, rc++)
984 offset = calc_brush_offset(rc, brush, origin);
986 start = get_pixel_ptr_16(dib, rc->left, rc->top);
987 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
989 if (bits->and)
991 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
992 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
994 and_ptr = start_and + offset.x;
995 xor_ptr = start_xor + offset.x;
997 for(x = rc->left, ptr = start; x < rc->right; x++)
999 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
1000 if(and_ptr == start_and + brush->width)
1002 and_ptr = start_and;
1003 xor_ptr = start_xor;
1007 offset.y++;
1008 if(offset.y == brush->height)
1010 start_and = bits->and;
1011 start_xor = bits->xor;
1012 offset.y = 0;
1014 else
1016 start_and += brush->stride / 2;
1017 start_xor += brush->stride / 2;
1021 else
1023 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
1025 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1027 len = min( rc->right - x, brush->width - brush_x );
1028 memcpy( start + x - rc->left, start_xor + brush_x, len * 2 );
1029 brush_x = 0;
1032 start_xor += brush->stride / 2;
1033 offset.y++;
1034 if(offset.y == brush->height)
1036 start_xor = bits->xor;
1037 offset.y = 0;
1044 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1045 const dib_info *brush, const rop_mask_bits *bits)
1047 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1048 int x, y, i, len, brush_x;
1049 POINT offset;
1051 for(i = 0; i < num; i++, rc++)
1053 offset = calc_brush_offset(rc, brush, origin);
1055 start = get_pixel_ptr_8(dib, rc->left, rc->top);
1056 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1058 if (bits->and)
1060 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1061 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1063 and_ptr = start_and + offset.x;
1064 xor_ptr = start_xor + offset.x;
1066 for(x = rc->left, ptr = start; x < rc->right; x++)
1068 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1069 if(and_ptr == start_and + brush->width)
1071 and_ptr = start_and;
1072 xor_ptr = start_xor;
1076 offset.y++;
1077 if(offset.y == brush->height)
1079 start_and = bits->and;
1080 start_xor = bits->xor;
1081 offset.y = 0;
1083 else
1085 start_and += brush->stride;
1086 start_xor += brush->stride;
1090 else
1092 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1094 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1096 len = min( rc->right - x, brush->width - brush_x );
1097 memcpy( start + x - rc->left, start_xor + brush_x, len );
1098 brush_x = 0;
1101 start_xor += brush->stride;
1102 offset.y++;
1103 if(offset.y == brush->height)
1105 start_xor = bits->xor;
1106 offset.y = 0;
1113 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1114 const dib_info *brush, const rop_mask_bits *bits)
1116 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1117 int x, y, i, left, right;
1118 POINT offset;
1120 for(i = 0; i < num; i++, rc++)
1122 offset = calc_brush_offset(rc, brush, origin);
1123 left = dib->rect.left + rc->left;
1124 right = dib->rect.left + rc->right;
1126 start = get_pixel_ptr_4(dib, rc->left, rc->top);
1127 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1129 if (bits->and)
1131 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1132 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1134 INT brush_x = offset.x;
1135 BYTE byte_and, byte_xor;
1137 and_ptr = start_and + brush_x / 2;
1138 xor_ptr = start_xor + brush_x / 2;
1140 for(x = left, ptr = start; x < right; x++)
1142 /* FIXME: Two pixels at a time */
1143 if(x & 1) /* lower dst nibble */
1145 if(brush_x & 1) /* lower pat nibble */
1147 byte_and = *and_ptr++ | 0xf0;
1148 byte_xor = *xor_ptr++ & 0x0f;
1150 else /* upper pat nibble */
1152 byte_and = (*and_ptr >> 4) | 0xf0;
1153 byte_xor = (*xor_ptr >> 4) & 0x0f;
1156 else /* upper dst nibble */
1158 if(brush_x & 1) /* lower pat nibble */
1160 byte_and = (*and_ptr++ << 4) | 0x0f;
1161 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1163 else /* upper pat nibble */
1165 byte_and = *and_ptr | 0x0f;
1166 byte_xor = *xor_ptr & 0xf0;
1169 do_rop_8(ptr, byte_and, byte_xor);
1171 if(x & 1) ptr++;
1173 if(++brush_x == brush->width)
1175 brush_x = 0;
1176 and_ptr = start_and;
1177 xor_ptr = start_xor;
1181 offset.y++;
1182 if(offset.y == brush->height)
1184 start_and = bits->and;
1185 start_xor = bits->xor;
1186 offset.y = 0;
1188 else
1190 start_and += brush->stride;
1191 start_xor += brush->stride;
1195 else
1197 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1199 INT brush_x = offset.x;
1200 BYTE byte_xor;
1202 xor_ptr = start_xor + brush_x / 2;
1204 for(x = left, ptr = start; x < right; x++)
1206 /* FIXME: Two pixels at a time */
1207 if(x & 1) /* lower dst nibble */
1209 if(brush_x & 1) /* lower pat nibble */
1210 byte_xor = *xor_ptr++ & 0x0f;
1211 else /* upper pat nibble */
1212 byte_xor = (*xor_ptr >> 4) & 0x0f;
1213 do_rop_8(ptr, 0xf0, byte_xor);
1215 else /* upper dst nibble */
1217 if(brush_x & 1) /* lower pat nibble */
1218 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1219 else /* upper pat nibble */
1220 byte_xor = *xor_ptr & 0xf0;
1221 do_rop_8(ptr, 0x0f, byte_xor);
1224 if(x & 1) ptr++;
1226 if(++brush_x == brush->width)
1228 brush_x = 0;
1229 xor_ptr = start_xor;
1233 start_xor += brush->stride;
1234 offset.y++;
1235 if(offset.y == brush->height)
1237 start_xor = bits->xor;
1238 offset.y = 0;
1245 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1246 const dib_info *brush, const rop_mask_bits *bits)
1248 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1249 int x, y, i, left, right;
1250 POINT offset;
1252 for(i = 0; i < num; i++, rc++)
1254 offset = calc_brush_offset(rc, brush, origin);
1255 left = dib->rect.left + rc->left;
1256 right = dib->rect.left + rc->right;
1258 start = get_pixel_ptr_1(dib, rc->left, rc->top);
1259 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1261 if (bits->and)
1263 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1264 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1266 INT brush_x = offset.x;
1267 BYTE byte_and, byte_xor;
1269 and_ptr = start_and + brush_x / 8;
1270 xor_ptr = start_xor + brush_x / 8;
1272 for(x = left, ptr = start; x < right; x++)
1274 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1275 byte_and |= ~pixel_masks_1[x % 8];
1276 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1277 byte_xor &= pixel_masks_1[x % 8];
1279 do_rop_8(ptr, byte_and, byte_xor);
1281 if((x & 7) == 7) ptr++;
1283 if((brush_x & 7) == 7)
1285 and_ptr++;
1286 xor_ptr++;
1289 if(++brush_x == brush->width)
1291 brush_x = 0;
1292 and_ptr = start_and;
1293 xor_ptr = start_xor;
1297 offset.y++;
1298 if(offset.y == brush->height)
1300 start_and = bits->and;
1301 start_xor = bits->xor;
1302 offset.y = 0;
1304 else
1306 start_and += brush->stride;
1307 start_xor += brush->stride;
1311 else
1313 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1315 INT brush_x = offset.x;
1317 xor_ptr = start_xor + brush_x / 8;
1319 for(x = left, ptr = start; x < right; x++)
1321 BYTE byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1322 byte_xor &= pixel_masks_1[x % 8];
1324 do_rop_8(ptr, ~pixel_masks_1[x % 8], byte_xor);
1326 if((x & 7) == 7) ptr++;
1327 if((brush_x & 7) == 7) xor_ptr++;
1329 if(++brush_x == brush->width)
1331 brush_x = 0;
1332 xor_ptr = start_xor;
1336 start_xor += brush->stride;
1337 offset.y++;
1338 if(offset.y == brush->height)
1340 start_xor = bits->xor;
1341 offset.y = 0;
1348 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1349 const dib_info *brush, const rop_mask_bits *bits)
1351 return;
1354 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1355 const dib_info *src, const POINT *origin, int rop2, int overlap)
1357 DWORD *dst_start, *src_start;
1358 struct rop_codes codes;
1359 int y, dst_stride, src_stride;
1361 if (overlap & OVERLAP_BELOW)
1363 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1364 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1365 dst_stride = -dst->stride / 4;
1366 src_stride = -src->stride / 4;
1368 else
1370 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1371 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1372 dst_stride = dst->stride / 4;
1373 src_stride = src->stride / 4;
1376 if (rop2 == R2_COPYPEN)
1378 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1379 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1380 return;
1383 get_rop_codes( rop2, &codes );
1384 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1386 if (overlap & OVERLAP_RIGHT)
1387 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1388 else
1389 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1393 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1394 const dib_info *src, const POINT *origin, int rop2, int overlap)
1396 BYTE *dst_start, *src_start;
1397 int y, dst_stride, src_stride;
1398 struct rop_codes codes;
1400 if (overlap & OVERLAP_BELOW)
1402 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1403 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1404 dst_stride = -dst->stride;
1405 src_stride = -src->stride;
1407 else
1409 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1410 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1411 dst_stride = dst->stride;
1412 src_stride = src->stride;
1415 if (rop2 == R2_COPYPEN)
1417 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1418 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1419 return;
1422 get_rop_codes( rop2, &codes );
1423 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1425 if (overlap & OVERLAP_RIGHT)
1426 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1427 else
1428 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1432 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1433 const dib_info *src, const POINT *origin, int rop2, int overlap)
1435 WORD *dst_start, *src_start;
1436 int y, dst_stride, src_stride;
1437 struct rop_codes codes;
1439 if (overlap & OVERLAP_BELOW)
1441 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1442 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1443 dst_stride = -dst->stride / 2;
1444 src_stride = -src->stride / 2;
1446 else
1448 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1449 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1450 dst_stride = dst->stride / 2;
1451 src_stride = src->stride / 2;
1454 if (rop2 == R2_COPYPEN)
1456 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1457 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1458 return;
1461 get_rop_codes( rop2, &codes );
1462 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1464 if (overlap & OVERLAP_RIGHT)
1465 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1466 else
1467 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1471 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1472 const dib_info *src, const POINT *origin, int rop2, int overlap)
1474 BYTE *dst_start, *src_start;
1475 int y, dst_stride, src_stride;
1476 struct rop_codes codes;
1478 if (overlap & OVERLAP_BELOW)
1480 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1481 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1482 dst_stride = -dst->stride;
1483 src_stride = -src->stride;
1485 else
1487 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1488 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1489 dst_stride = dst->stride;
1490 src_stride = src->stride;
1493 if (rop2 == R2_COPYPEN)
1495 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1496 memmove( dst_start, src_start, (rc->right - rc->left) );
1497 return;
1500 get_rop_codes( rop2, &codes );
1501 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1503 if (overlap & OVERLAP_RIGHT)
1504 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1505 else
1506 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1510 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1511 const dib_info *src, const POINT *origin, int rop2, int overlap)
1513 BYTE *dst_start, *src_start;
1514 int y, dst_stride, src_stride;
1515 struct rop_codes codes;
1516 int left = dst->rect.left + rc->left;
1517 int right = dst->rect.left + rc->right;
1518 int org_x = src->rect.left + origin->x;
1520 if (overlap & OVERLAP_BELOW)
1522 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1523 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1524 dst_stride = -dst->stride;
1525 src_stride = -src->stride;
1527 else
1529 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1530 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1531 dst_stride = dst->stride;
1532 src_stride = src->stride;
1535 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1537 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1538 memmove( dst_start, src_start, (right - left) / 2 );
1539 return;
1542 get_rop_codes( rop2, &codes );
1543 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1545 if (overlap & OVERLAP_RIGHT)
1546 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1547 else
1548 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1552 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1553 const dib_info *src, const POINT *origin, int rop2, int overlap)
1555 BYTE *dst_start, *src_start;
1556 int y, dst_stride, src_stride;
1557 struct rop_codes codes;
1558 int left = dst->rect.left + rc->left;
1559 int right = dst->rect.left + rc->right;
1560 int org_x = src->rect.left + origin->x;
1562 if (overlap & OVERLAP_BELOW)
1564 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1565 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1566 dst_stride = -dst->stride;
1567 src_stride = -src->stride;
1569 else
1571 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1572 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1573 dst_stride = dst->stride;
1574 src_stride = src->stride;
1577 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1579 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1580 memmove( dst_start, src_start, (right - left) / 8 );
1581 return;
1584 get_rop_codes( rop2, &codes );
1585 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1587 if (overlap & OVERLAP_RIGHT)
1588 do_rop_codes_line_rev_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1589 else
1590 do_rop_codes_line_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1594 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1595 const dib_info *src, const POINT *origin, int rop2, int overlap)
1597 return;
1600 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
1602 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1603 return *ptr;
1606 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1608 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1609 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1612 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1614 WORD *ptr = get_pixel_ptr_16( dib, x, y );
1615 return *ptr;
1618 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1620 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1621 return *ptr;
1624 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1626 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1628 if ((dib->rect.left + x) & 1)
1629 return *ptr & 0x0f;
1630 else
1631 return (*ptr >> 4) & 0x0f;
1634 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1636 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1637 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
1640 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
1642 return 0;
1645 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1647 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1650 static const DWORD field_masks[33] =
1652 0x00, /* should never happen */
1653 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1654 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1655 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1656 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1659 static inline DWORD get_field(DWORD field, int shift, int len)
1661 shift = shift - (8 - len);
1662 if (shift < 0)
1663 field <<= -shift;
1664 else
1665 field >>= shift;
1666 field &= field_masks[len];
1667 field |= field >> len;
1668 return field;
1671 static inline DWORD put_field(DWORD field, int shift, int len)
1673 shift = shift - (8 - len);
1674 field &= field_masks[len];
1675 if (shift < 0)
1676 field >>= -shift;
1677 else
1678 field <<= shift;
1679 return field;
1682 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1684 DWORD r,g,b;
1686 r = GetRValue(colour);
1687 g = GetGValue(colour);
1688 b = GetBValue(colour);
1690 return put_field(r, dib->red_shift, dib->red_len) |
1691 put_field(g, dib->green_shift, dib->green_len) |
1692 put_field(b, dib->blue_shift, dib->blue_len);
1695 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1697 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1700 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1702 const RGBQUAD *color_table = get_dib_color_table( dib );
1703 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
1704 int i, best_index = 0;
1705 DWORD diff, best_diff = 0xffffffff;
1707 /* special case for conversion to 1-bpp without a color table:
1708 * we get a 1-entry table containing the background color
1710 if (dib->bit_count == 1 && size == 1)
1711 return (r == color_table[0].rgbRed &&
1712 g == color_table[0].rgbGreen &&
1713 b == color_table[0].rgbBlue);
1715 for(i = 0; i < size; i++)
1717 const RGBQUAD *cur = color_table + i;
1718 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1719 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1720 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1722 if(diff == 0)
1724 best_index = i;
1725 break;
1728 if(diff < best_diff)
1730 best_diff = diff;
1731 best_index = i;
1734 return best_index;
1737 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, BYTE r, BYTE g, BYTE b)
1739 DWORD ret;
1741 if (!dither)
1742 ret = rgb_to_pixel_colortable( dib, r, g, b );
1743 else
1744 ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255;
1746 return ret ? 0xff : 0;
1749 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1751 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1754 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1756 return 0;
1759 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1761 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1764 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1766 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1767 get_field( pixel, dib->green_shift, dib->green_len ),
1768 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1771 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1773 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1774 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1775 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1778 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1780 const RGBQUAD *color_table = get_dib_color_table( dib );
1782 if (!dib->color_table || pixel < dib->color_table_size)
1784 RGBQUAD quad = color_table[pixel];
1785 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1787 return 0;
1790 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1792 return 0;
1795 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1797 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1799 return d1->red_mask == d2->red_mask &&
1800 d1->green_mask == d2->green_mask &&
1801 d1->blue_mask == d2->blue_mask;
1804 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1806 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1807 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1809 switch(src->bit_count)
1811 case 32:
1813 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1814 if(src->funcs == &funcs_8888)
1816 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1817 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1818 else
1820 for(y = src_rect->top; y < src_rect->bottom; y++)
1822 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1823 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1824 dst_start += dst->stride / 4;
1825 src_start += src->stride / 4;
1829 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1831 for(y = src_rect->top; y < src_rect->bottom; y++)
1833 dst_pixel = dst_start;
1834 src_pixel = src_start;
1835 for(x = src_rect->left; x < src_rect->right; x++)
1837 src_val = *src_pixel++;
1838 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1839 (((src_val >> src->green_shift) & 0xff) << 8) |
1840 ((src_val >> src->blue_shift) & 0xff);
1842 if(pad_size) memset(dst_pixel, 0, pad_size);
1843 dst_start += dst->stride / 4;
1844 src_start += src->stride / 4;
1847 else
1849 for(y = src_rect->top; y < src_rect->bottom; y++)
1851 dst_pixel = dst_start;
1852 src_pixel = src_start;
1853 for(x = src_rect->left; x < src_rect->right; x++)
1855 src_val = *src_pixel++;
1856 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1857 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1858 get_field( src_val, src->blue_shift, src->blue_len ));
1860 if(pad_size) memset(dst_pixel, 0, pad_size);
1861 dst_start += dst->stride / 4;
1862 src_start += src->stride / 4;
1865 break;
1868 case 24:
1870 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1872 for(y = src_rect->top; y < src_rect->bottom; y++)
1874 dst_pixel = dst_start;
1875 src_pixel = src_start;
1876 for(x = src_rect->left; x < src_rect->right; x++)
1878 RGBQUAD rgb;
1879 rgb.rgbBlue = *src_pixel++;
1880 rgb.rgbGreen = *src_pixel++;
1881 rgb.rgbRed = *src_pixel++;
1883 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1885 if(pad_size) memset(dst_pixel, 0, pad_size);
1886 dst_start += dst->stride / 4;
1887 src_start += src->stride;
1889 break;
1892 case 16:
1894 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1895 if(src->funcs == &funcs_555)
1897 for(y = src_rect->top; y < src_rect->bottom; y++)
1899 dst_pixel = dst_start;
1900 src_pixel = src_start;
1901 for(x = src_rect->left; x < src_rect->right; x++)
1903 src_val = *src_pixel++;
1904 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1905 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1906 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1908 if(pad_size) memset(dst_pixel, 0, pad_size);
1909 dst_start += dst->stride / 4;
1910 src_start += src->stride / 2;
1913 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1915 for(y = src_rect->top; y < src_rect->bottom; y++)
1917 dst_pixel = dst_start;
1918 src_pixel = src_start;
1919 for(x = src_rect->left; x < src_rect->right; x++)
1921 src_val = *src_pixel++;
1922 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1923 (((src_val >> src->red_shift) << 14) & 0x070000) |
1924 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1925 (((src_val >> src->green_shift) << 6) & 0x000700) |
1926 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1927 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1929 if(pad_size) memset(dst_pixel, 0, pad_size);
1930 dst_start += dst->stride / 4;
1931 src_start += src->stride / 2;
1934 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1936 for(y = src_rect->top; y < src_rect->bottom; y++)
1938 dst_pixel = dst_start;
1939 src_pixel = src_start;
1940 for(x = src_rect->left; x < src_rect->right; x++)
1942 src_val = *src_pixel++;
1943 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1944 (((src_val >> src->red_shift) << 14) & 0x070000) |
1945 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1946 (((src_val >> src->green_shift) << 4) & 0x000300) |
1947 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1948 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1950 if(pad_size) memset(dst_pixel, 0, pad_size);
1951 dst_start += dst->stride / 4;
1952 src_start += src->stride / 2;
1955 else
1957 for(y = src_rect->top; y < src_rect->bottom; y++)
1959 dst_pixel = dst_start;
1960 src_pixel = src_start;
1961 for(x = src_rect->left; x < src_rect->right; x++)
1963 src_val = *src_pixel++;
1964 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1965 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1966 get_field( src_val, src->blue_shift, src->blue_len ));
1968 if(pad_size) memset(dst_pixel, 0, pad_size);
1969 dst_start += dst->stride / 4;
1970 src_start += src->stride / 2;
1973 break;
1976 case 8:
1978 const RGBQUAD *color_table = get_dib_color_table( src );
1979 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1980 for(y = src_rect->top; y < src_rect->bottom; y++)
1982 dst_pixel = dst_start;
1983 src_pixel = src_start;
1984 for(x = src_rect->left; x < src_rect->right; x++)
1986 RGBQUAD rgb = color_table[*src_pixel++];
1987 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1989 if(pad_size) memset(dst_pixel, 0, pad_size);
1990 dst_start += dst->stride / 4;
1991 src_start += src->stride;
1993 break;
1996 case 4:
1998 const RGBQUAD *color_table = get_dib_color_table( src );
1999 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2000 for(y = src_rect->top; y < src_rect->bottom; y++)
2002 int pos = (src->rect.left + src_rect->left) & 1;
2003 src_pixel = src_start;
2004 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2006 RGBQUAD rgb;
2007 if (pos & 1)
2008 rgb = color_table[*src_pixel++ & 0xf];
2009 else
2010 rgb = color_table[*src_pixel >> 4];
2011 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
2013 if(pad_size) memset(dst_start + x, 0, pad_size);
2014 dst_start += dst->stride / 4;
2015 src_start += src->stride;
2017 break;
2020 case 1:
2022 const RGBQUAD *color_table = get_dib_color_table( src );
2023 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2024 for(y = src_rect->top; y < src_rect->bottom; y++)
2026 int pos = (src->rect.left + src_rect->left) & 7;
2027 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2029 RGBQUAD rgb;
2030 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2031 rgb = color_table[src_val];
2032 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
2034 if(pad_size) memset(dst_start + x, 0, pad_size);
2035 dst_start += dst->stride / 4;
2036 src_start += src->stride;
2038 break;
2043 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2045 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2046 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2048 switch(src->bit_count)
2050 case 32:
2052 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2054 if(src->funcs == &funcs_8888)
2056 for(y = src_rect->top; y < src_rect->bottom; y++)
2058 dst_pixel = dst_start;
2059 src_pixel = src_start;
2060 for(x = src_rect->left; x < src_rect->right; x++)
2062 src_val = *src_pixel++;
2063 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2064 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2065 put_field(src_val, dst->blue_shift, dst->blue_len);
2067 if(pad_size) memset(dst_pixel, 0, pad_size);
2068 dst_start += dst->stride / 4;
2069 src_start += src->stride / 4;
2072 else if(bit_fields_match(src, dst))
2074 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2075 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2076 else
2078 for(y = src_rect->top; y < src_rect->bottom; y++)
2080 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2081 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2082 dst_start += dst->stride / 4;
2083 src_start += src->stride / 4;
2087 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
2088 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
2090 for(y = src_rect->top; y < src_rect->bottom; y++)
2092 dst_pixel = dst_start;
2093 src_pixel = src_start;
2094 for(x = src_rect->left; x < src_rect->right; x++)
2096 src_val = *src_pixel++;
2097 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
2098 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
2099 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
2101 if(pad_size) memset(dst_pixel, 0, pad_size);
2102 dst_start += dst->stride / 4;
2103 src_start += src->stride / 4;
2106 else
2108 for(y = src_rect->top; y < src_rect->bottom; y++)
2110 dst_pixel = dst_start;
2111 src_pixel = src_start;
2112 for(x = src_rect->left; x < src_rect->right; x++)
2114 src_val = *src_pixel++;
2115 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2116 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2117 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2119 if(pad_size) memset(dst_pixel, 0, pad_size);
2120 dst_start += dst->stride / 4;
2121 src_start += src->stride / 4;
2124 break;
2127 case 24:
2129 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2131 for(y = src_rect->top; y < src_rect->bottom; y++)
2133 dst_pixel = dst_start;
2134 src_pixel = src_start;
2135 for(x = src_rect->left; x < src_rect->right; x++)
2137 RGBQUAD rgb;
2138 rgb.rgbBlue = *src_pixel++;
2139 rgb.rgbGreen = *src_pixel++;
2140 rgb.rgbRed = *src_pixel++;
2142 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2143 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2144 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2146 if(pad_size) memset(dst_pixel, 0, pad_size);
2147 dst_start += dst->stride / 4;
2148 src_start += src->stride;
2150 break;
2153 case 16:
2155 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2156 if(src->funcs == &funcs_555)
2158 for(y = src_rect->top; y < src_rect->bottom; y++)
2160 dst_pixel = dst_start;
2161 src_pixel = src_start;
2162 for(x = src_rect->left; x < src_rect->right; x++)
2164 src_val = *src_pixel++;
2165 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2166 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2167 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2169 if(pad_size) memset(dst_pixel, 0, pad_size);
2170 dst_start += dst->stride / 4;
2171 src_start += src->stride / 2;
2174 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2176 for(y = src_rect->top; y < src_rect->bottom; y++)
2178 dst_pixel = dst_start;
2179 src_pixel = src_start;
2180 for(x = src_rect->left; x < src_rect->right; x++)
2182 src_val = *src_pixel++;
2183 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2184 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2185 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2186 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2187 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2188 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2190 if(pad_size) memset(dst_pixel, 0, pad_size);
2191 dst_start += dst->stride / 4;
2192 src_start += src->stride / 2;
2195 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2197 for(y = src_rect->top; y < src_rect->bottom; y++)
2199 dst_pixel = dst_start;
2200 src_pixel = src_start;
2201 for(x = src_rect->left; x < src_rect->right; x++)
2203 src_val = *src_pixel++;
2204 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2205 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2206 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2207 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2208 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2209 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2211 if(pad_size) memset(dst_pixel, 0, pad_size);
2212 dst_start += dst->stride / 4;
2213 src_start += src->stride / 2;
2216 else
2218 for(y = src_rect->top; y < src_rect->bottom; y++)
2220 dst_pixel = dst_start;
2221 src_pixel = src_start;
2222 for(x = src_rect->left; x < src_rect->right; x++)
2224 src_val = *src_pixel++;
2225 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2226 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2227 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2229 if(pad_size) memset(dst_pixel, 0, pad_size);
2230 dst_start += dst->stride / 4;
2231 src_start += src->stride / 2;
2234 break;
2237 case 8:
2239 const RGBQUAD *color_table = get_dib_color_table( src );
2240 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2241 for(y = src_rect->top; y < src_rect->bottom; y++)
2243 dst_pixel = dst_start;
2244 src_pixel = src_start;
2245 for(x = src_rect->left; x < src_rect->right; x++)
2247 RGBQUAD rgb = color_table[*src_pixel++];
2248 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2249 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2250 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2252 if(pad_size) memset(dst_pixel, 0, pad_size);
2253 dst_start += dst->stride / 4;
2254 src_start += src->stride;
2256 break;
2259 case 4:
2261 const RGBQUAD *color_table = get_dib_color_table( src );
2262 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2263 for(y = src_rect->top; y < src_rect->bottom; y++)
2265 int pos = (src->rect.left + src_rect->left) & 1;
2266 src_pixel = src_start;
2267 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2269 RGBQUAD rgb;
2270 if (pos & 1)
2271 rgb = color_table[*src_pixel++ & 0xf];
2272 else
2273 rgb = color_table[*src_pixel >> 4];
2274 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2275 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2276 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2278 if(pad_size) memset(dst_start + x, 0, pad_size);
2279 dst_start += dst->stride / 4;
2280 src_start += src->stride;
2282 break;
2285 case 1:
2287 const RGBQUAD *color_table = get_dib_color_table( src );
2288 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2289 for(y = src_rect->top; y < src_rect->bottom; y++)
2291 int pos = (src->rect.left + src_rect->left) & 7;
2292 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2294 RGBQUAD rgb;
2295 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2296 rgb = color_table[src_val];
2297 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2298 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2299 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2301 if(pad_size) memset(dst_start + x, 0, pad_size);
2302 dst_start += dst->stride / 4;
2303 src_start += src->stride;
2305 break;
2310 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2312 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2313 DWORD src_val;
2314 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2316 switch(src->bit_count)
2318 case 32:
2320 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2321 if(src->funcs == &funcs_8888)
2323 for(y = src_rect->top; y < src_rect->bottom; y++)
2325 dst_pixel = dst_start;
2326 src_pixel = src_start;
2327 for(x = src_rect->left; x < src_rect->right; x++)
2329 src_val = *src_pixel++;
2330 *dst_pixel++ = src_val & 0xff;
2331 *dst_pixel++ = (src_val >> 8) & 0xff;
2332 *dst_pixel++ = (src_val >> 16) & 0xff;
2334 if(pad_size) memset(dst_pixel, 0, pad_size);
2335 dst_start += dst->stride;
2336 src_start += src->stride / 4;
2339 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2341 for(y = src_rect->top; y < src_rect->bottom; y++)
2343 dst_pixel = dst_start;
2344 src_pixel = src_start;
2345 for(x = src_rect->left; x < src_rect->right; x++)
2347 src_val = *src_pixel++;
2348 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2349 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2350 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2352 if(pad_size) memset(dst_pixel, 0, pad_size);
2353 dst_start += dst->stride;
2354 src_start += src->stride / 4;
2357 else
2359 for(y = src_rect->top; y < src_rect->bottom; y++)
2361 dst_pixel = dst_start;
2362 src_pixel = src_start;
2363 for(x = src_rect->left; x < src_rect->right; x++)
2365 src_val = *src_pixel++;
2366 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2367 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2368 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2370 if(pad_size) memset(dst_pixel, 0, pad_size);
2371 dst_start += dst->stride;
2372 src_start += src->stride / 4;
2375 break;
2378 case 24:
2380 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2382 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2383 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2384 else
2386 for(y = src_rect->top; y < src_rect->bottom; y++)
2388 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2389 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2390 dst_start += dst->stride;
2391 src_start += src->stride;
2394 break;
2397 case 16:
2399 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2400 if(src->funcs == &funcs_555)
2402 for(y = src_rect->top; y < src_rect->bottom; y++)
2404 dst_pixel = dst_start;
2405 src_pixel = src_start;
2406 for(x = src_rect->left; x < src_rect->right; x++)
2408 src_val = *src_pixel++;
2409 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2410 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2411 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2413 if(pad_size) memset(dst_pixel, 0, pad_size);
2414 dst_start += dst->stride;
2415 src_start += src->stride / 2;
2418 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2420 for(y = src_rect->top; y < src_rect->bottom; y++)
2422 dst_pixel = dst_start;
2423 src_pixel = src_start;
2424 for(x = src_rect->left; x < src_rect->right; x++)
2426 src_val = *src_pixel++;
2427 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2428 (((src_val >> src->blue_shift) >> 2) & 0x07);
2429 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2430 (((src_val >> src->green_shift) >> 2) & 0x07);
2431 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2432 (((src_val >> src->red_shift) >> 2) & 0x07);
2434 if(pad_size) memset(dst_pixel, 0, pad_size);
2435 dst_start += dst->stride;
2436 src_start += src->stride / 2;
2439 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2441 for(y = src_rect->top; y < src_rect->bottom; y++)
2443 dst_pixel = dst_start;
2444 src_pixel = src_start;
2445 for(x = src_rect->left; x < src_rect->right; x++)
2447 src_val = *src_pixel++;
2448 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2449 (((src_val >> src->blue_shift) >> 2) & 0x07);
2450 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2451 (((src_val >> src->green_shift) >> 4) & 0x03);
2452 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2453 (((src_val >> src->red_shift) >> 2) & 0x07);
2455 if(pad_size) memset(dst_pixel, 0, pad_size);
2456 dst_start += dst->stride;
2457 src_start += src->stride / 2;
2460 else
2462 for(y = src_rect->top; y < src_rect->bottom; y++)
2464 dst_pixel = dst_start;
2465 src_pixel = src_start;
2466 for(x = src_rect->left; x < src_rect->right; x++)
2468 src_val = *src_pixel++;
2469 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2470 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2471 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2473 if(pad_size) memset(dst_pixel, 0, pad_size);
2474 dst_start += dst->stride;
2475 src_start += src->stride / 2;
2478 break;
2481 case 8:
2483 const RGBQUAD *color_table = get_dib_color_table( src );
2484 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2485 for(y = src_rect->top; y < src_rect->bottom; y++)
2487 dst_pixel = dst_start;
2488 src_pixel = src_start;
2489 for(x = src_rect->left; x < src_rect->right; x++)
2491 RGBQUAD rgb = color_table[*src_pixel++];
2492 *dst_pixel++ = rgb.rgbBlue;
2493 *dst_pixel++ = rgb.rgbGreen;
2494 *dst_pixel++ = rgb.rgbRed;
2496 if(pad_size) memset(dst_pixel, 0, pad_size);
2497 dst_start += dst->stride;
2498 src_start += src->stride;
2500 break;
2503 case 4:
2505 const RGBQUAD *color_table = get_dib_color_table( src );
2506 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2507 for(y = src_rect->top; y < src_rect->bottom; y++)
2509 int pos = (src->rect.left + src_rect->left) & 1;
2510 src_pixel = src_start;
2511 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2513 RGBQUAD rgb;
2514 if (pos & 1)
2515 rgb = color_table[*src_pixel++ & 0xf];
2516 else
2517 rgb = color_table[*src_pixel >> 4];
2518 dst_start[x * 3] = rgb.rgbBlue;
2519 dst_start[x * 3 + 1] = rgb.rgbGreen;
2520 dst_start[x * 3 + 2] = rgb.rgbRed;
2522 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2523 dst_start += dst->stride;
2524 src_start += src->stride;
2526 break;
2529 case 1:
2531 const RGBQUAD *color_table = get_dib_color_table( src );
2532 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2533 for(y = src_rect->top; y < src_rect->bottom; y++)
2535 int pos = (src->rect.left + src_rect->left) & 7;
2536 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2538 RGBQUAD rgb;
2539 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2540 rgb = color_table[src_val];
2541 dst_start[x * 3] = rgb.rgbBlue;
2542 dst_start[x * 3 + 1] = rgb.rgbGreen;
2543 dst_start[x * 3 + 2] = rgb.rgbRed;
2545 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2546 dst_start += dst->stride;
2547 src_start += src->stride;
2549 break;
2554 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2556 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2557 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2558 DWORD src_val;
2560 switch(src->bit_count)
2562 case 32:
2564 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2566 if(src->funcs == &funcs_8888)
2568 for(y = src_rect->top; y < src_rect->bottom; y++)
2570 dst_pixel = dst_start;
2571 src_pixel = src_start;
2572 for(x = src_rect->left; x < src_rect->right; x++)
2574 src_val = *src_pixel++;
2575 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2576 ((src_val >> 6) & 0x03e0) |
2577 ((src_val >> 3) & 0x001f);
2579 if(pad_size) memset(dst_pixel, 0, pad_size);
2580 dst_start += dst->stride / 2;
2581 src_start += src->stride / 4;
2584 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2586 for(y = src_rect->top; y < src_rect->bottom; y++)
2588 dst_pixel = dst_start;
2589 src_pixel = src_start;
2590 for(x = src_rect->left; x < src_rect->right; x++)
2592 src_val = *src_pixel++;
2593 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2594 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2595 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2597 if(pad_size) memset(dst_pixel, 0, pad_size);
2598 dst_start += dst->stride / 2;
2599 src_start += src->stride / 4;
2602 else
2604 for(y = src_rect->top; y < src_rect->bottom; y++)
2606 dst_pixel = dst_start;
2607 src_pixel = src_start;
2608 for(x = src_rect->left; x < src_rect->right; x++)
2610 src_val = *src_pixel++;
2611 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2612 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2613 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2615 if(pad_size) memset(dst_pixel, 0, pad_size);
2616 dst_start += dst->stride / 2;
2617 src_start += src->stride / 4;
2620 break;
2623 case 24:
2625 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2627 for(y = src_rect->top; y < src_rect->bottom; y++)
2629 dst_pixel = dst_start;
2630 src_pixel = src_start;
2631 for(x = src_rect->left; x < src_rect->right; x++)
2633 RGBQUAD rgb;
2634 rgb.rgbBlue = *src_pixel++;
2635 rgb.rgbGreen = *src_pixel++;
2636 rgb.rgbRed = *src_pixel++;
2638 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2639 ((rgb.rgbGreen << 2) & 0x03e0) |
2640 ((rgb.rgbBlue >> 3) & 0x001f);
2642 if(pad_size) memset(dst_pixel, 0, pad_size);
2643 dst_start += dst->stride / 2;
2644 src_start += src->stride;
2646 break;
2649 case 16:
2651 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2652 if(src->funcs == &funcs_555)
2654 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2655 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2656 else
2658 for(y = src_rect->top; y < src_rect->bottom; y++)
2660 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2661 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2662 dst_start += dst->stride / 2;
2663 src_start += src->stride / 2;
2667 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2669 for(y = src_rect->top; y < src_rect->bottom; y++)
2671 dst_pixel = dst_start;
2672 src_pixel = src_start;
2673 for(x = src_rect->left; x < src_rect->right; x++)
2675 src_val = *src_pixel++;
2676 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2677 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2678 ( (src_val >> src->blue_shift) & 0x001f);
2680 if(pad_size) memset(dst_pixel, 0, pad_size);
2681 dst_start += dst->stride / 2;
2682 src_start += src->stride / 2;
2685 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2687 for(y = src_rect->top; y < src_rect->bottom; y++)
2689 dst_pixel = dst_start;
2690 src_pixel = src_start;
2691 for(x = src_rect->left; x < src_rect->right; x++)
2693 src_val = *src_pixel++;
2694 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2695 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2696 ( (src_val >> src->blue_shift) & 0x001f);
2698 if(pad_size) memset(dst_pixel, 0, pad_size);
2699 dst_start += dst->stride / 2;
2700 src_start += src->stride / 2;
2703 else
2705 for(y = src_rect->top; y < src_rect->bottom; y++)
2707 dst_pixel = dst_start;
2708 src_pixel = src_start;
2709 for(x = src_rect->left; x < src_rect->right; x++)
2711 src_val = *src_pixel++;
2712 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2713 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2714 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2716 if(pad_size) memset(dst_pixel, 0, pad_size);
2717 dst_start += dst->stride / 2;
2718 src_start += src->stride / 2;
2721 break;
2724 case 8:
2726 const RGBQUAD *color_table = get_dib_color_table( src );
2727 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2728 for(y = src_rect->top; y < src_rect->bottom; y++)
2730 dst_pixel = dst_start;
2731 src_pixel = src_start;
2732 for(x = src_rect->left; x < src_rect->right; x++)
2734 RGBQUAD rgb = color_table[*src_pixel++];
2735 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2736 ((rgb.rgbGreen << 2) & 0x03e0) |
2737 ((rgb.rgbBlue >> 3) & 0x001f);
2739 if(pad_size) memset(dst_pixel, 0, pad_size);
2740 dst_start += dst->stride / 2;
2741 src_start += src->stride;
2743 break;
2746 case 4:
2748 const RGBQUAD *color_table = get_dib_color_table( src );
2749 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2750 for(y = src_rect->top; y < src_rect->bottom; y++)
2752 int pos = (src->rect.left + src_rect->left) & 1;
2753 src_pixel = src_start;
2754 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2756 RGBQUAD rgb;
2757 if (pos & 1)
2758 rgb = color_table[*src_pixel++ & 0xf];
2759 else
2760 rgb = color_table[*src_pixel >> 4];
2761 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2762 ((rgb.rgbGreen << 2) & 0x03e0) |
2763 ((rgb.rgbBlue >> 3) & 0x001f);
2765 if(pad_size) memset(dst_start + x, 0, pad_size);
2766 dst_start += dst->stride / 2;
2767 src_start += src->stride;
2769 break;
2772 case 1:
2774 const RGBQUAD *color_table = get_dib_color_table( src );
2775 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2776 for(y = src_rect->top; y < src_rect->bottom; y++)
2778 int pos = (src->rect.left + src_rect->left) & 7;
2779 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2781 RGBQUAD rgb;
2782 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2783 rgb = color_table[src_val];
2784 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2785 ((rgb.rgbGreen << 2) & 0x03e0) |
2786 ((rgb.rgbBlue >> 3) & 0x001f);
2788 if(pad_size) memset(dst_start + x, 0, pad_size);
2789 dst_start += dst->stride / 2;
2790 src_start += src->stride;
2792 break;
2797 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2799 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2800 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2801 DWORD src_val;
2803 switch(src->bit_count)
2805 case 32:
2807 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2809 if(src->funcs == &funcs_8888)
2811 for(y = src_rect->top; y < src_rect->bottom; y++)
2813 dst_pixel = dst_start;
2814 src_pixel = src_start;
2815 for(x = src_rect->left; x < src_rect->right; x++)
2817 src_val = *src_pixel++;
2818 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2819 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2820 put_field(src_val, dst->blue_shift, dst->blue_len);
2822 if(pad_size) memset(dst_pixel, 0, pad_size);
2823 dst_start += dst->stride / 2;
2824 src_start += src->stride / 4;
2827 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2829 for(y = src_rect->top; y < src_rect->bottom; y++)
2831 dst_pixel = dst_start;
2832 src_pixel = src_start;
2833 for(x = src_rect->left; x < src_rect->right; x++)
2835 src_val = *src_pixel++;
2836 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2837 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2838 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2840 if(pad_size) memset(dst_pixel, 0, pad_size);
2841 dst_start += dst->stride / 2;
2842 src_start += src->stride / 4;
2845 else
2847 for(y = src_rect->top; y < src_rect->bottom; y++)
2849 dst_pixel = dst_start;
2850 src_pixel = src_start;
2851 for(x = src_rect->left; x < src_rect->right; x++)
2853 src_val = *src_pixel++;
2854 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2855 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2856 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2858 if(pad_size) memset(dst_pixel, 0, pad_size);
2859 dst_start += dst->stride / 2;
2860 src_start += src->stride / 4;
2863 break;
2866 case 24:
2868 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2870 for(y = src_rect->top; y < src_rect->bottom; y++)
2872 dst_pixel = dst_start;
2873 src_pixel = src_start;
2874 for(x = src_rect->left; x < src_rect->right; x++)
2876 RGBQUAD rgb;
2877 rgb.rgbBlue = *src_pixel++;
2878 rgb.rgbGreen = *src_pixel++;
2879 rgb.rgbRed = *src_pixel++;
2881 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2882 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2883 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2885 if(pad_size) memset(dst_pixel, 0, pad_size);
2886 dst_start += dst->stride / 2;
2887 src_start += src->stride;
2889 break;
2892 case 16:
2894 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2895 if(src->funcs == &funcs_555)
2897 for(y = src_rect->top; y < src_rect->bottom; y++)
2899 dst_pixel = dst_start;
2900 src_pixel = src_start;
2901 for(x = src_rect->left; x < src_rect->right; x++)
2903 src_val = *src_pixel++;
2904 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2905 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2906 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2908 if(pad_size) memset(dst_pixel, 0, pad_size);
2909 dst_start += dst->stride / 2;
2910 src_start += src->stride / 2;
2913 else if(bit_fields_match(src, dst))
2915 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2916 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2917 else
2919 for(y = src_rect->top; y < src_rect->bottom; y++)
2921 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2922 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2923 dst_start += dst->stride / 2;
2924 src_start += src->stride / 2;
2928 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2930 for(y = src_rect->top; y < src_rect->bottom; y++)
2932 dst_pixel = dst_start;
2933 src_pixel = src_start;
2934 for(x = src_rect->left; x < src_rect->right; x++)
2936 src_val = *src_pixel++;
2937 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2938 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2939 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2940 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2941 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2942 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2944 if(pad_size) memset(dst_pixel, 0, pad_size);
2945 dst_start += dst->stride / 2;
2946 src_start += src->stride / 2;
2949 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2951 for(y = src_rect->top; y < src_rect->bottom; y++)
2953 dst_pixel = dst_start;
2954 src_pixel = src_start;
2955 for(x = src_rect->left; x < src_rect->right; x++)
2957 src_val = *src_pixel++;
2958 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2959 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2960 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2961 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2962 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2963 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2965 if(pad_size) memset(dst_pixel, 0, pad_size);
2966 dst_start += dst->stride / 2;
2967 src_start += src->stride / 2;
2970 else
2972 for(y = src_rect->top; y < src_rect->bottom; y++)
2974 dst_pixel = dst_start;
2975 src_pixel = src_start;
2976 for(x = src_rect->left; x < src_rect->right; x++)
2978 src_val = *src_pixel++;
2979 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2980 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2981 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2983 if(pad_size) memset(dst_pixel, 0, pad_size);
2984 dst_start += dst->stride / 2;
2985 src_start += src->stride / 2;
2988 break;
2991 case 8:
2993 const RGBQUAD *color_table = get_dib_color_table( src );
2994 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2995 for(y = src_rect->top; y < src_rect->bottom; y++)
2997 dst_pixel = dst_start;
2998 src_pixel = src_start;
2999 for(x = src_rect->left; x < src_rect->right; x++)
3001 RGBQUAD rgb = color_table[*src_pixel++];
3002 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3003 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3004 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3006 if(pad_size) memset(dst_pixel, 0, pad_size);
3007 dst_start += dst->stride / 2;
3008 src_start += src->stride;
3010 break;
3013 case 4:
3015 const RGBQUAD *color_table = get_dib_color_table( src );
3016 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3017 for(y = src_rect->top; y < src_rect->bottom; y++)
3019 int pos = (src->rect.left + src_rect->left) & 1;
3020 src_pixel = src_start;
3021 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3023 RGBQUAD rgb;
3024 if (pos & 1)
3025 rgb = color_table[*src_pixel++ & 0xf];
3026 else
3027 rgb = color_table[*src_pixel >> 4];
3028 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3029 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3030 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3032 if(pad_size) memset(dst_start + x, 0, pad_size);
3033 dst_start += dst->stride / 2;
3034 src_start += src->stride;
3036 break;
3039 case 1:
3041 const RGBQUAD *color_table = get_dib_color_table( src );
3042 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3043 for(y = src_rect->top; y < src_rect->bottom; y++)
3045 int pos = (src->rect.left + src_rect->left) & 7;
3046 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3048 RGBQUAD rgb;
3049 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3050 rgb = color_table[src_val];
3051 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
3052 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
3053 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
3055 if(pad_size) memset(dst_start + x, 0, pad_size);
3056 dst_start += dst->stride / 2;
3057 src_start += src->stride;
3059 break;
3064 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
3066 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
3067 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
3070 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
3072 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
3073 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
3076 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3078 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
3079 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
3080 DWORD src_val;
3082 switch(src->bit_count)
3084 case 32:
3086 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3088 if(src->funcs == &funcs_8888)
3090 for(y = src_rect->top; y < src_rect->bottom; y++)
3092 dst_pixel = dst_start;
3093 src_pixel = src_start;
3094 for(x = src_rect->left; x < src_rect->right; x++)
3096 src_val = *src_pixel++;
3097 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
3099 if(pad_size) memset(dst_pixel, 0, pad_size);
3100 dst_start += dst->stride;
3101 src_start += src->stride / 4;
3104 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3106 for(y = src_rect->top; y < src_rect->bottom; y++)
3108 dst_pixel = dst_start;
3109 src_pixel = src_start;
3110 for(x = src_rect->left; x < src_rect->right; x++)
3112 src_val = *src_pixel++;
3113 *dst_pixel++ = rgb_lookup_colortable(dst,
3114 src_val >> src->red_shift,
3115 src_val >> src->green_shift,
3116 src_val >> src->blue_shift );
3118 if(pad_size) memset(dst_pixel, 0, pad_size);
3119 dst_start += dst->stride;
3120 src_start += src->stride / 4;
3123 else
3125 for(y = src_rect->top; y < src_rect->bottom; y++)
3127 dst_pixel = dst_start;
3128 src_pixel = src_start;
3129 for(x = src_rect->left; x < src_rect->right; x++)
3131 src_val = *src_pixel++;
3132 *dst_pixel++ = rgb_lookup_colortable(dst,
3133 get_field(src_val, src->red_shift, src->red_len),
3134 get_field(src_val, src->green_shift, src->green_len),
3135 get_field(src_val, src->blue_shift, src->blue_len));
3137 if(pad_size) memset(dst_pixel, 0, pad_size);
3138 dst_start += dst->stride;
3139 src_start += src->stride / 4;
3142 break;
3145 case 24:
3147 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3149 for(y = src_rect->top; y < src_rect->bottom; y++)
3151 dst_pixel = dst_start;
3152 src_pixel = src_start;
3153 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3155 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
3157 if(pad_size) memset(dst_pixel, 0, pad_size);
3158 dst_start += dst->stride;
3159 src_start += src->stride;
3161 break;
3164 case 16:
3166 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3167 if(src->funcs == &funcs_555)
3169 for(y = src_rect->top; y < src_rect->bottom; y++)
3171 dst_pixel = dst_start;
3172 src_pixel = src_start;
3173 for(x = src_rect->left; x < src_rect->right; x++)
3175 src_val = *src_pixel++;
3176 *dst_pixel++ = rgb_lookup_colortable(dst,
3177 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3178 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3179 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3181 if(pad_size) memset(dst_pixel, 0, pad_size);
3182 dst_start += dst->stride;
3183 src_start += src->stride / 2;
3186 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3188 for(y = src_rect->top; y < src_rect->bottom; y++)
3190 dst_pixel = dst_start;
3191 src_pixel = src_start;
3192 for(x = src_rect->left; x < src_rect->right; x++)
3194 src_val = *src_pixel++;
3195 *dst_pixel++ = rgb_lookup_colortable(dst,
3196 (((src_val >> src->red_shift) << 3) & 0xf8) |
3197 (((src_val >> src->red_shift) >> 2) & 0x07),
3198 (((src_val >> src->green_shift) << 3) & 0xf8) |
3199 (((src_val >> src->green_shift) >> 2) & 0x07),
3200 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3201 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3203 if(pad_size) memset(dst_pixel, 0, pad_size);
3204 dst_start += dst->stride;
3205 src_start += src->stride / 2;
3208 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3210 for(y = src_rect->top; y < src_rect->bottom; y++)
3212 dst_pixel = dst_start;
3213 src_pixel = src_start;
3214 for(x = src_rect->left; x < src_rect->right; x++)
3216 src_val = *src_pixel++;
3217 *dst_pixel++ = rgb_lookup_colortable(dst,
3218 (((src_val >> src->red_shift) << 3) & 0xf8) |
3219 (((src_val >> src->red_shift) >> 2) & 0x07),
3220 (((src_val >> src->green_shift) << 2) & 0xfc) |
3221 (((src_val >> src->green_shift) >> 4) & 0x03),
3222 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3223 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3225 if(pad_size) memset(dst_pixel, 0, pad_size);
3226 dst_start += dst->stride;
3227 src_start += src->stride / 2;
3230 else
3232 for(y = src_rect->top; y < src_rect->bottom; y++)
3234 dst_pixel = dst_start;
3235 src_pixel = src_start;
3236 for(x = src_rect->left; x < src_rect->right; x++)
3238 src_val = *src_pixel++;
3239 *dst_pixel++ = rgb_lookup_colortable(dst,
3240 get_field(src_val, src->red_shift, src->red_len),
3241 get_field(src_val, src->green_shift, src->green_len),
3242 get_field(src_val, src->blue_shift, src->blue_len));
3244 if(pad_size) memset(dst_pixel, 0, pad_size);
3245 dst_start += dst->stride;
3246 src_start += src->stride / 2;
3249 break;
3252 case 8:
3254 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3256 if(color_tables_match(dst, src))
3258 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3259 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3260 else
3262 for(y = src_rect->top; y < src_rect->bottom; y++)
3264 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
3265 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3266 dst_start += dst->stride;
3267 src_start += src->stride;
3271 else
3273 const RGBQUAD *color_table = get_dib_color_table( src );
3274 for(y = src_rect->top; y < src_rect->bottom; y++)
3276 dst_pixel = dst_start;
3277 src_pixel = src_start;
3278 for(x = src_rect->left; x < src_rect->right; x++)
3280 RGBQUAD rgb = color_table[*src_pixel++];
3281 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3283 if(pad_size) memset(dst_pixel, 0, pad_size);
3284 dst_start += dst->stride;
3285 src_start += src->stride;
3288 break;
3291 case 4:
3293 const RGBQUAD *color_table = get_dib_color_table( src );
3294 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3295 for(y = src_rect->top; y < src_rect->bottom; y++)
3297 int pos = (src->rect.left + src_rect->left) & 1;
3298 src_pixel = src_start;
3299 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3301 RGBQUAD rgb;
3302 if (pos & 1)
3303 rgb = color_table[*src_pixel++ & 0xf];
3304 else
3305 rgb = color_table[*src_pixel >> 4];
3306 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3308 if(pad_size) memset(dst_start + x, 0, pad_size);
3309 dst_start += dst->stride;
3310 src_start += src->stride;
3312 break;
3315 case 1:
3317 const RGBQUAD *color_table = get_dib_color_table( src );
3318 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3319 for(y = src_rect->top; y < src_rect->bottom; y++)
3321 int pos = (src->rect.left + src_rect->left) & 7;
3322 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3324 RGBQUAD rgb;
3325 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3326 rgb = color_table[src_val];
3327 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3329 if(pad_size) memset(dst_start + x, 0, pad_size);
3330 dst_start += dst->stride;
3331 src_start += src->stride;
3333 break;
3338 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3340 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3341 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3342 DWORD src_val;
3344 switch(src->bit_count)
3346 case 32:
3348 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3350 if(src->funcs == &funcs_8888)
3352 for(y = src_rect->top; y < src_rect->bottom; y++)
3354 dst_pixel = dst_start;
3355 src_pixel = src_start;
3356 for(x = src_rect->left; x < src_rect->right; x++)
3358 src_val = *src_pixel++;
3359 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3360 if((x - src_rect->left) & 1)
3362 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3363 dst_pixel++;
3365 else
3366 *dst_pixel = (dst_val << 4) & 0xf0;
3368 if(pad_size)
3370 if((x - src_rect->left) & 1) dst_pixel++;
3371 memset(dst_pixel, 0, pad_size);
3373 dst_start += dst->stride;
3374 src_start += src->stride / 4;
3377 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3379 for(y = src_rect->top; y < src_rect->bottom; y++)
3381 dst_pixel = dst_start;
3382 src_pixel = src_start;
3383 for(x = src_rect->left; x < src_rect->right; x++)
3385 src_val = *src_pixel++;
3386 dst_val = rgb_to_pixel_colortable(dst,
3387 src_val >> src->red_shift,
3388 src_val >> src->green_shift,
3389 src_val >> src->blue_shift);
3390 if((x - src_rect->left) & 1)
3392 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3393 dst_pixel++;
3395 else
3396 *dst_pixel = (dst_val << 4) & 0xf0;
3398 if(pad_size)
3400 if((x - src_rect->left) & 1) dst_pixel++;
3401 memset(dst_pixel, 0, pad_size);
3403 dst_start += dst->stride;
3404 src_start += src->stride / 4;
3407 else
3409 for(y = src_rect->top; y < src_rect->bottom; y++)
3411 dst_pixel = dst_start;
3412 src_pixel = src_start;
3413 for(x = src_rect->left; x < src_rect->right; x++)
3415 src_val = *src_pixel++;
3416 dst_val = rgb_to_pixel_colortable(dst,
3417 get_field(src_val, src->red_shift, src->red_len),
3418 get_field(src_val, src->green_shift, src->green_len),
3419 get_field(src_val, src->blue_shift, src->blue_len));
3420 if((x - src_rect->left) & 1)
3422 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3423 dst_pixel++;
3425 else
3426 *dst_pixel = (dst_val << 4) & 0xf0;
3428 if(pad_size)
3430 if((x - src_rect->left) & 1) dst_pixel++;
3431 memset(dst_pixel, 0, pad_size);
3433 dst_start += dst->stride;
3434 src_start += src->stride / 4;
3437 break;
3440 case 24:
3442 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3444 for(y = src_rect->top; y < src_rect->bottom; y++)
3446 dst_pixel = dst_start;
3447 src_pixel = src_start;
3448 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3450 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3452 if((x - src_rect->left) & 1)
3454 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3455 dst_pixel++;
3457 else
3458 *dst_pixel = (dst_val << 4) & 0xf0;
3460 if(pad_size)
3462 if((x - src_rect->left) & 1) dst_pixel++;
3463 memset(dst_pixel, 0, pad_size);
3465 dst_start += dst->stride;
3466 src_start += src->stride;
3468 break;
3471 case 16:
3473 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3474 if(src->funcs == &funcs_555)
3476 for(y = src_rect->top; y < src_rect->bottom; y++)
3478 dst_pixel = dst_start;
3479 src_pixel = src_start;
3480 for(x = src_rect->left; x < src_rect->right; x++)
3482 src_val = *src_pixel++;
3483 dst_val = rgb_to_pixel_colortable(dst,
3484 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3485 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3486 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3487 if((x - src_rect->left) & 1)
3489 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3490 dst_pixel++;
3492 else
3493 *dst_pixel = (dst_val << 4) & 0xf0;
3495 if(pad_size)
3497 if((x - src_rect->left) & 1) dst_pixel++;
3498 memset(dst_pixel, 0, pad_size);
3500 dst_start += dst->stride;
3501 src_start += src->stride / 2;
3504 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3506 for(y = src_rect->top; y < src_rect->bottom; y++)
3508 dst_pixel = dst_start;
3509 src_pixel = src_start;
3510 for(x = src_rect->left; x < src_rect->right; x++)
3512 src_val = *src_pixel++;
3513 dst_val = rgb_to_pixel_colortable(dst,
3514 (((src_val >> src->red_shift) << 3) & 0xf8) |
3515 (((src_val >> src->red_shift) >> 2) & 0x07),
3516 (((src_val >> src->green_shift) << 3) & 0xf8) |
3517 (((src_val >> src->green_shift) >> 2) & 0x07),
3518 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3519 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3520 if((x - src_rect->left) & 1)
3522 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3523 dst_pixel++;
3525 else
3526 *dst_pixel = (dst_val << 4) & 0xf0;
3528 if(pad_size)
3530 if((x - src_rect->left) & 1) dst_pixel++;
3531 memset(dst_pixel, 0, pad_size);
3533 dst_start += dst->stride;
3534 src_start += src->stride / 2;
3537 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3539 for(y = src_rect->top; y < src_rect->bottom; y++)
3541 dst_pixel = dst_start;
3542 src_pixel = src_start;
3543 for(x = src_rect->left; x < src_rect->right; x++)
3545 src_val = *src_pixel++;
3546 dst_val = rgb_to_pixel_colortable(dst,
3547 (((src_val >> src->red_shift) << 3) & 0xf8) |
3548 (((src_val >> src->red_shift) >> 2) & 0x07),
3549 (((src_val >> src->green_shift) << 2) & 0xfc) |
3550 (((src_val >> src->green_shift) >> 4) & 0x03),
3551 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3552 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3553 if((x - src_rect->left) & 1)
3555 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3556 dst_pixel++;
3558 else
3559 *dst_pixel = (dst_val << 4) & 0xf0;
3561 if(pad_size)
3563 if((x - src_rect->left) & 1) dst_pixel++;
3564 memset(dst_pixel, 0, pad_size);
3566 dst_start += dst->stride;
3567 src_start += src->stride / 2;
3570 else
3572 for(y = src_rect->top; y < src_rect->bottom; y++)
3574 dst_pixel = dst_start;
3575 src_pixel = src_start;
3576 for(x = src_rect->left; x < src_rect->right; x++)
3578 src_val = *src_pixel++;
3579 dst_val = rgb_to_pixel_colortable(dst,
3580 get_field(src_val, src->red_shift, src->red_len),
3581 get_field(src_val, src->green_shift, src->green_len),
3582 get_field(src_val, src->blue_shift, src->blue_len));
3583 if((x - src_rect->left) & 1)
3585 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3586 dst_pixel++;
3588 else
3589 *dst_pixel = (dst_val << 4) & 0xf0;
3591 if(pad_size)
3593 if((x - src_rect->left) & 1) dst_pixel++;
3594 memset(dst_pixel, 0, pad_size);
3596 dst_start += dst->stride;
3597 src_start += src->stride / 2;
3600 break;
3603 case 8:
3605 const RGBQUAD *color_table = get_dib_color_table( src );
3606 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3608 for(y = src_rect->top; y < src_rect->bottom; y++)
3610 dst_pixel = dst_start;
3611 src_pixel = src_start;
3612 for(x = src_rect->left; x < src_rect->right; x++)
3614 RGBQUAD rgb = color_table[*src_pixel++];
3615 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3616 if((x - src_rect->left) & 1)
3618 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3619 dst_pixel++;
3621 else
3622 *dst_pixel = (dst_val << 4) & 0xf0;
3624 if(pad_size)
3626 if((x - src_rect->left) & 1) dst_pixel++;
3627 memset(dst_pixel, 0, pad_size);
3629 dst_start += dst->stride;
3630 src_start += src->stride;
3632 break;
3635 case 4:
3637 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3639 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
3641 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3642 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3643 else
3645 for(y = src_rect->top; y < src_rect->bottom; y++)
3647 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3648 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3649 dst_start += dst->stride;
3650 src_start += src->stride;
3654 else
3656 const RGBQUAD *color_table = get_dib_color_table( src );
3657 for(y = src_rect->top; y < src_rect->bottom; y++)
3659 int pos = (src->rect.left + src_rect->left) & 1;
3660 dst_pixel = dst_start;
3661 src_pixel = src_start;
3662 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3664 RGBQUAD rgb;
3665 if(pos & 1)
3666 rgb = color_table[*src_pixel++ & 0xf];
3667 else
3668 rgb = color_table[*src_pixel >> 4];
3669 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3670 if((x - src_rect->left) & 1)
3672 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3673 dst_pixel++;
3675 else
3676 *dst_pixel = (dst_val << 4) & 0xf0;
3678 if(pad_size)
3680 if((x - src_rect->left) & 1) dst_pixel++;
3681 memset(dst_pixel, 0, pad_size);
3683 dst_start += dst->stride;
3684 src_start += src->stride;
3687 break;
3690 case 1:
3692 const RGBQUAD *color_table = get_dib_color_table( src );
3693 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3694 for(y = src_rect->top; y < src_rect->bottom; y++)
3696 int pos = (src->rect.left + src_rect->left) & 7;
3697 dst_pixel = dst_start;
3698 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3700 RGBQUAD rgb;
3701 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3702 rgb = color_table[src_val];
3703 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3704 if((x - src_rect->left) & 1)
3706 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3707 dst_pixel++;
3709 else
3710 *dst_pixel = (dst_val << 4) & 0xf0;
3712 if(pad_size)
3714 if((x - src_rect->left) & 1) dst_pixel++;
3715 memset(dst_pixel, 0, pad_size);
3717 dst_start += dst->stride;
3718 src_start += src->stride;
3720 break;
3725 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3727 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3728 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3729 DWORD src_val;
3730 int bit_pos;
3732 switch(src->bit_count)
3734 case 32:
3736 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3738 if(src->funcs == &funcs_8888)
3740 for(y = src_rect->top; y < src_rect->bottom; y++)
3742 dst_pixel = dst_start;
3743 src_pixel = src_start;
3744 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3746 src_val = *src_pixel++;
3747 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val >> 16, src_val >> 8, src_val);
3749 if(bit_pos == 0) *dst_pixel = 0;
3750 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3752 if(++bit_pos == 8)
3754 dst_pixel++;
3755 bit_pos = 0;
3758 if(pad_size)
3760 if(bit_pos != 0) dst_pixel++;
3761 memset(dst_pixel, 0, pad_size);
3763 dst_start += dst->stride;
3764 src_start += src->stride / 4;
3767 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3769 for(y = src_rect->top; y < src_rect->bottom; y++)
3771 dst_pixel = dst_start;
3772 src_pixel = src_start;
3773 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3775 src_val = *src_pixel++;
3776 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3777 src_val >> src->red_shift,
3778 src_val >> src->green_shift,
3779 src_val >> src->blue_shift);
3781 if(bit_pos == 0) *dst_pixel = 0;
3782 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3784 if(++bit_pos == 8)
3786 dst_pixel++;
3787 bit_pos = 0;
3790 if(pad_size)
3792 if(bit_pos != 0) dst_pixel++;
3793 memset(dst_pixel, 0, pad_size);
3795 dst_start += dst->stride;
3796 src_start += src->stride / 4;
3799 else
3801 for(y = src_rect->top; y < src_rect->bottom; y++)
3803 dst_pixel = dst_start;
3804 src_pixel = src_start;
3805 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3807 src_val = *src_pixel++;
3808 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3809 get_field(src_val, src->red_shift, src->red_len),
3810 get_field(src_val, src->green_shift, src->green_len),
3811 get_field(src_val, src->blue_shift, src->blue_len));
3813 if(bit_pos == 0) *dst_pixel = 0;
3814 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3816 if(++bit_pos == 8)
3818 dst_pixel++;
3819 bit_pos = 0;
3822 if(pad_size)
3824 if(bit_pos != 0) dst_pixel++;
3825 memset(dst_pixel, 0, pad_size);
3827 dst_start += dst->stride;
3828 src_start += src->stride / 4;
3831 break;
3834 case 24:
3836 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3838 for(y = src_rect->top; y < src_rect->bottom; y++)
3840 dst_pixel = dst_start;
3841 src_pixel = src_start;
3842 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3844 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_pixel[2], src_pixel[1], src_pixel[0]);
3846 if(bit_pos == 0) *dst_pixel = 0;
3847 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3849 if(++bit_pos == 8)
3851 dst_pixel++;
3852 bit_pos = 0;
3855 if(pad_size)
3857 if(bit_pos != 0) dst_pixel++;
3858 memset(dst_pixel, 0, pad_size);
3860 dst_start += dst->stride;
3861 src_start += src->stride;
3863 break;
3866 case 16:
3868 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3869 if(src->funcs == &funcs_555)
3871 for(y = src_rect->top; y < src_rect->bottom; y++)
3873 dst_pixel = dst_start;
3874 src_pixel = src_start;
3875 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3877 src_val = *src_pixel++;
3878 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3879 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3880 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3881 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3883 if(bit_pos == 0) *dst_pixel = 0;
3884 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3886 if(++bit_pos == 8)
3888 dst_pixel++;
3889 bit_pos = 0;
3892 if(pad_size)
3894 if(bit_pos != 0) dst_pixel++;
3895 memset(dst_pixel, 0, pad_size);
3897 dst_start += dst->stride;
3898 src_start += src->stride / 2;
3901 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3903 for(y = src_rect->top; y < src_rect->bottom; y++)
3905 dst_pixel = dst_start;
3906 src_pixel = src_start;
3907 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3909 src_val = *src_pixel++;
3910 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3911 (((src_val >> src->red_shift) << 3) & 0xf8) |
3912 (((src_val >> src->red_shift) >> 2) & 0x07),
3913 (((src_val >> src->green_shift) << 3) & 0xf8) |
3914 (((src_val >> src->green_shift) >> 2) & 0x07),
3915 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3916 (((src_val >> src->blue_shift) >> 2) & 0x07));
3917 if(bit_pos == 0) *dst_pixel = 0;
3918 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3920 if(++bit_pos == 8)
3922 dst_pixel++;
3923 bit_pos = 0;
3926 if(pad_size)
3928 if(bit_pos != 0) dst_pixel++;
3929 memset(dst_pixel, 0, pad_size);
3931 dst_start += dst->stride;
3932 src_start += src->stride / 2;
3935 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3937 for(y = src_rect->top; y < src_rect->bottom; y++)
3939 dst_pixel = dst_start;
3940 src_pixel = src_start;
3941 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3943 src_val = *src_pixel++;
3944 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3945 (((src_val >> src->red_shift) << 3) & 0xf8) |
3946 (((src_val >> src->red_shift) >> 2) & 0x07),
3947 (((src_val >> src->green_shift) << 2) & 0xfc) |
3948 (((src_val >> src->green_shift) >> 4) & 0x03),
3949 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3950 (((src_val >> src->blue_shift) >> 2) & 0x07));
3951 if(bit_pos == 0) *dst_pixel = 0;
3952 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3954 if(++bit_pos == 8)
3956 dst_pixel++;
3957 bit_pos = 0;
3960 if(pad_size)
3962 if(bit_pos != 0) dst_pixel++;
3963 memset(dst_pixel, 0, pad_size);
3965 dst_start += dst->stride;
3966 src_start += src->stride / 2;
3969 else
3971 for(y = src_rect->top; y < src_rect->bottom; y++)
3973 dst_pixel = dst_start;
3974 src_pixel = src_start;
3975 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3977 src_val = *src_pixel++;
3978 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3979 get_field(src_val, src->red_shift, src->red_len),
3980 get_field(src_val, src->green_shift, src->green_len),
3981 get_field(src_val, src->blue_shift, src->blue_len));
3982 if(bit_pos == 0) *dst_pixel = 0;
3983 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3985 if(++bit_pos == 8)
3987 dst_pixel++;
3988 bit_pos = 0;
3991 if(pad_size)
3993 if(bit_pos != 0) dst_pixel++;
3994 memset(dst_pixel, 0, pad_size);
3996 dst_start += dst->stride;
3997 src_start += src->stride / 2;
4000 break;
4003 case 8:
4005 const RGBQUAD *color_table = get_dib_color_table( src );
4006 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4008 for(y = src_rect->top; y < src_rect->bottom; y++)
4010 dst_pixel = dst_start;
4011 src_pixel = src_start;
4012 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4014 RGBQUAD rgb = color_table[*src_pixel++];
4015 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4017 if(bit_pos == 0) *dst_pixel = 0;
4018 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4020 if(++bit_pos == 8)
4022 dst_pixel++;
4023 bit_pos = 0;
4026 if(pad_size)
4028 if(bit_pos != 0) dst_pixel++;
4029 memset(dst_pixel, 0, pad_size);
4031 dst_start += dst->stride;
4032 src_start += src->stride;
4034 break;
4037 case 4:
4039 const RGBQUAD *color_table = get_dib_color_table( src );
4040 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4042 for(y = src_rect->top; y < src_rect->bottom; y++)
4044 int pos = (src->rect.left + src_rect->left) & 1;
4045 dst_pixel = dst_start;
4046 src_pixel = src_start;
4047 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4049 RGBQUAD rgb;
4050 if (pos & 1)
4051 rgb = color_table[*src_pixel++ & 0xf];
4052 else
4053 rgb = color_table[*src_pixel >> 4];
4054 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4056 if(bit_pos == 0) *dst_pixel = 0;
4057 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4059 if(++bit_pos == 8)
4061 dst_pixel++;
4062 bit_pos = 0;
4065 if(pad_size)
4067 if(bit_pos != 0) dst_pixel++;
4068 memset(dst_pixel, 0, pad_size);
4070 dst_start += dst->stride;
4071 src_start += src->stride;
4073 break;
4076 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
4077 uses text/bkgnd colours instead of the dib's colour table, this
4078 doesn't appear to be the case for a dc backed by a
4079 dibsection. */
4081 case 1:
4083 const RGBQUAD *color_table = get_dib_color_table( src );
4084 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4085 for(y = src_rect->top; y < src_rect->bottom; y++)
4087 int pos = (src->rect.left + src_rect->left) & 7;
4088 dst_pixel = dst_start;
4089 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4091 RGBQUAD rgb;
4092 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4093 rgb = color_table[src_val];
4094 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4096 if(bit_pos == 0) *dst_pixel = 0;
4097 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4099 if(++bit_pos == 8)
4101 dst_pixel++;
4102 bit_pos = 0;
4105 if(pad_size)
4107 if(bit_pos != 0) dst_pixel++;
4108 memset(dst_pixel, 0, pad_size);
4110 dst_start += dst->stride;
4111 src_start += src->stride;
4113 break;
4118 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4122 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
4124 return (src * alpha + dst * (255 - alpha) + 127) / 255;
4127 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
4129 return (blend_color( dst, src, alpha ) |
4130 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4131 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4132 blend_color( dst >> 24, src >> 24, alpha ) << 24);
4135 static inline DWORD blend_argb_no_src_alpha( DWORD dst, DWORD src, DWORD alpha )
4137 return (blend_color( dst, src, alpha ) |
4138 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4139 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4140 blend_color( dst >> 24, 255, alpha ) << 24);
4143 static inline DWORD blend_argb( DWORD dst, DWORD src )
4145 BYTE b = (BYTE)src;
4146 BYTE g = (BYTE)(src >> 8);
4147 BYTE r = (BYTE)(src >> 16);
4148 DWORD alpha = (BYTE)(src >> 24);
4149 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4150 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4151 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4152 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4155 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
4157 BYTE b = ((BYTE)src * alpha + 127) / 255;
4158 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4159 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4160 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4161 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4162 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4163 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4164 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4167 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
4169 if (blend.AlphaFormat & AC_SRC_ALPHA)
4171 DWORD alpha = blend.SourceConstantAlpha;
4172 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
4173 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4174 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4175 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4176 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
4177 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
4178 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
4180 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
4181 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
4182 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
4185 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
4186 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4188 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4189 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4190 int x, y;
4192 if (blend.AlphaFormat & AC_SRC_ALPHA)
4194 if (blend.SourceConstantAlpha == 255)
4195 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4196 for (x = 0; x < rc->right - rc->left; x++)
4197 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
4198 else
4199 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4200 for (x = 0; x < rc->right - rc->left; x++)
4201 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4203 else if (src->compression == BI_RGB)
4204 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4205 for (x = 0; x < rc->right - rc->left; x++)
4206 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4207 else
4208 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4209 for (x = 0; x < rc->right - rc->left; x++)
4210 dst_ptr[x] = blend_argb_no_src_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4213 static void blend_rect_32(const dib_info *dst, const RECT *rc,
4214 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4216 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4217 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4218 int x, y;
4220 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
4222 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4224 for (x = 0; x < rc->right - rc->left; x++)
4226 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
4227 dst_ptr[x] >> dst->green_shift,
4228 dst_ptr[x] >> dst->blue_shift,
4229 src_ptr[x], blend );
4230 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
4231 (((val >> 8) & 0xff) << dst->green_shift) |
4232 (((val >> 16) & 0xff) << dst->red_shift));
4236 else
4238 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4240 for (x = 0; x < rc->right - rc->left; x++)
4242 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4243 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4244 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4245 src_ptr[x], blend );
4246 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
4247 put_field( val >> 8, dst->green_shift, dst->green_len ) |
4248 put_field( val, dst->blue_shift, dst->blue_len ));
4254 static void blend_rect_24(const dib_info *dst, const RECT *rc,
4255 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4257 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4258 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
4259 int x, y;
4261 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4263 for (x = 0; x < rc->right - rc->left; x++)
4265 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4266 src_ptr[x], blend );
4267 dst_ptr[x * 3] = val;
4268 dst_ptr[x * 3 + 1] = val >> 8;
4269 dst_ptr[x * 3 + 2] = val >> 16;
4274 static void blend_rect_555(const dib_info *dst, const RECT *rc,
4275 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4277 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4278 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4279 int x, y;
4281 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4283 for (x = 0; x < rc->right - rc->left; x++)
4285 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4286 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4287 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4288 src_ptr[x], blend );
4289 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4294 static void blend_rect_16(const dib_info *dst, const RECT *rc,
4295 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4297 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4298 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4299 int x, y;
4301 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4303 for (x = 0; x < rc->right - rc->left; x++)
4305 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4306 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4307 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4308 src_ptr[x], blend );
4309 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
4310 put_field((val >> 8), dst->green_shift, dst->green_len) |
4311 put_field( val, dst->blue_shift, dst->blue_len));
4316 static void blend_rect_8(const dib_info *dst, const RECT *rc,
4317 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4319 const RGBQUAD *color_table = get_dib_color_table( dst );
4320 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4321 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4322 int x, y;
4324 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4326 for (x = 0; x < rc->right - rc->left; x++)
4328 RGBQUAD rgb = color_table[dst_ptr[x]];
4329 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4330 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4335 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4336 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4338 const RGBQUAD *color_table = get_dib_color_table( dst );
4339 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4340 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4341 int i, x, y;
4343 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4345 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4347 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4348 RGBQUAD rgb = color_table[val];
4349 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4350 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4351 if (x & 1)
4352 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4353 else
4354 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4359 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4360 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4362 const RGBQUAD *color_table = get_dib_color_table( dst );
4363 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4364 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4365 int i, x, y;
4367 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4369 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4371 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4372 RGBQUAD rgb = color_table[val];
4373 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4374 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4375 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4380 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4381 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4385 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4387 BYTE r, g, b, a;
4388 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4389 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4390 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4391 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4392 return a << 24 | r << 16 | g << 8 | b;
4395 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4397 BYTE r, g, b;
4398 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4399 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4400 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4401 return r << 16 | g << 8 | b;
4404 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4405 unsigned int x, unsigned int y )
4407 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4408 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4409 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4410 r = min( 31, max( 0, r / 16 ));
4411 g = min( 31, max( 0, g / 16 ));
4412 b = min( 31, max( 0, b / 16 ));
4413 return (r << 10) | (g << 5) | b;
4416 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4417 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4419 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4420 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4421 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4422 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4425 /* compute the left/right triangle limit for row y */
4426 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4428 int x1, x2;
4430 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4431 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4433 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4435 *left = max( rc->left, min( x1, x2 ) );
4436 *right = min( rc->right, max( x1, x2 ) );
4439 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4440 static inline int triangle_det( const TRIVERTEX *v )
4442 return (v[2].y - v[1].y) * (v[2].x - v[0].x) - (v[2].x - v[1].x) * (v[2].y - v[0].y);
4445 /* compute the barycentric weights for a given point inside the triangle */
4446 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4448 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4449 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4452 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4454 INT64 l1, l2;
4455 BYTE r, g, b, a;
4457 triangle_weights( v, x, y, &l1, &l2 );
4458 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4459 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4460 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4461 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4462 return a << 24 | r << 16 | g << 8 | b;
4465 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4467 INT64 l1, l2;
4468 BYTE r, g, b;
4470 triangle_weights( v, x, y, &l1, &l2 );
4471 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4472 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4473 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4474 return r << 16 | g << 8 | b;
4477 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4479 INT64 l1, l2;
4480 int r, g, b;
4482 triangle_weights( v, x, y, &l1, &l2 );
4483 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4484 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4485 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4486 r = min( 31, max( 0, r / 16 ));
4487 g = min( 31, max( 0, g / 16 ));
4488 b = min( 31, max( 0, b / 16 ));
4489 return (r << 10) | (g << 5) | b;
4492 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4494 INT64 l1, l2;
4495 BYTE r, g, b;
4497 triangle_weights( v, x, y, &l1, &l2 );
4498 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4499 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4500 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4501 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4504 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4506 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4507 int x, y, left, right, det;
4509 switch (mode)
4511 case GRADIENT_FILL_RECT_H:
4512 for (x = 0; x < rc->right - rc->left; x++)
4513 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4515 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4516 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4517 break;
4519 case GRADIENT_FILL_RECT_V:
4520 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4522 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4523 memset_32( ptr, val, rc->right - rc->left );
4525 break;
4527 case GRADIENT_FILL_TRIANGLE:
4528 if (!(det = triangle_det( v ))) return FALSE;
4529 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4531 triangle_coords( v, rc, y, &left, &right );
4532 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4534 break;
4536 return TRUE;
4539 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4541 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4542 int x, y, left, right, det;
4544 switch (mode)
4546 case GRADIENT_FILL_RECT_H:
4547 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4549 for (x = 0; x < rc->right - rc->left; x++)
4551 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4552 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4553 (((val >> 8) & 0xff) << dib->green_shift) |
4554 (((val >> 16) & 0xff) << dib->red_shift));
4557 else
4559 for (x = 0; x < rc->right - rc->left; x++)
4561 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4562 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4563 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4564 put_field( val, dib->blue_shift, dib->blue_len ));
4568 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4569 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4570 break;
4572 case GRADIENT_FILL_RECT_V:
4573 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4575 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4576 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4577 val = ((( val & 0xff) << dib->blue_shift) |
4578 (((val >> 8) & 0xff) << dib->green_shift) |
4579 (((val >> 16) & 0xff) << dib->red_shift));
4580 else
4581 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4582 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4583 put_field( val, dib->blue_shift, dib->blue_len ));
4585 memset_32( ptr, val, rc->right - rc->left );
4587 break;
4589 case GRADIENT_FILL_TRIANGLE:
4590 if (!(det = triangle_det( v ))) return FALSE;
4591 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4593 triangle_coords( v, rc, y, &left, &right );
4595 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4596 for (x = left; x < right; x++)
4598 DWORD val = gradient_triangle_24( v, x, y, det );
4599 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4600 (((val >> 8) & 0xff) << dib->green_shift) |
4601 (((val >> 16) & 0xff) << dib->red_shift));
4603 else
4604 for (x = left; x < right; x++)
4606 DWORD val = gradient_triangle_24( v, x, y, det );
4607 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4608 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4609 put_field( val, dib->blue_shift, dib->blue_len ));
4612 break;
4614 return TRUE;
4617 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4619 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4620 int x, y, left, right, det;
4622 switch (mode)
4624 case GRADIENT_FILL_RECT_H:
4625 for (x = 0; x < rc->right - rc->left; x++)
4627 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4628 ptr[x * 3] = val;
4629 ptr[x * 3 + 1] = val >> 8;
4630 ptr[x * 3 + 2] = val >> 16;
4633 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4634 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4635 break;
4637 case GRADIENT_FILL_RECT_V:
4638 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4640 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4641 for (x = 0; x < rc->right - rc->left; x++)
4643 ptr[x * 3] = val;
4644 ptr[x * 3 + 1] = val >> 8;
4645 ptr[x * 3 + 2] = val >> 16;
4648 break;
4650 case GRADIENT_FILL_TRIANGLE:
4651 if (!(det = triangle_det( v ))) return FALSE;
4652 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4654 triangle_coords( v, rc, y, &left, &right );
4655 for (x = left; x < right; x++)
4657 DWORD val = gradient_triangle_24( v, x, y, det );
4658 ptr[(x - rc->left) * 3] = val;
4659 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4660 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4663 break;
4665 return TRUE;
4668 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4670 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4671 int x, y, left, right, det;
4673 switch (mode)
4675 case GRADIENT_FILL_RECT_H:
4676 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4677 for (x = rc->left; x < rc->right; x++)
4678 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4679 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4680 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4681 break;
4683 case GRADIENT_FILL_RECT_V:
4684 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4686 WORD values[4];
4687 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4688 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4690 break;
4692 case GRADIENT_FILL_TRIANGLE:
4693 if (!(det = triangle_det( v ))) return FALSE;
4694 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4696 triangle_coords( v, rc, y, &left, &right );
4697 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4699 break;
4701 return TRUE;
4704 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4706 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4707 int x, y, left, right, det;
4709 switch (mode)
4711 case GRADIENT_FILL_RECT_H:
4712 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4713 for (x = rc->left; x < rc->right; x++)
4715 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4716 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4717 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4718 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4720 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4721 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4722 break;
4724 case GRADIENT_FILL_RECT_V:
4725 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4727 WORD values[4];
4728 for (x = 0; x < 4; x++)
4730 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4731 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4732 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4733 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4735 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4737 break;
4739 case GRADIENT_FILL_TRIANGLE:
4740 if (!(det = triangle_det( v ))) return FALSE;
4741 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4743 triangle_coords( v, rc, y, &left, &right );
4744 for (x = left; x < right; x++)
4746 WORD val = gradient_triangle_555( v, x, y, det );
4747 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4748 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4749 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4752 break;
4754 return TRUE;
4757 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4759 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4760 int x, y, left, right, det;
4762 switch (mode)
4764 case GRADIENT_FILL_RECT_H:
4765 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4766 for (x = rc->left; x < rc->right; x++)
4767 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4768 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4769 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4770 break;
4772 case GRADIENT_FILL_RECT_V:
4773 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4775 BYTE values[16];
4776 for (x = 0; x < 16; x++)
4777 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4778 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4780 break;
4782 case GRADIENT_FILL_TRIANGLE:
4783 if (!(det = triangle_det( v ))) return FALSE;
4784 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4786 triangle_coords( v, rc, y, &left, &right );
4787 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4789 break;
4791 return TRUE;
4794 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4796 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4797 int x, y, left, right, det, pos;
4799 switch (mode)
4801 case GRADIENT_FILL_RECT_H:
4802 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4804 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4806 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4807 if (pos & 1)
4808 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4809 else
4810 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4813 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4815 x = rc->left;
4816 pos = (dib->rect.left + rc->left) & 1;
4817 if (pos)
4819 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4820 pos++;
4821 x++;
4823 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4824 if (x < rc->right)
4825 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4827 break;
4829 case GRADIENT_FILL_RECT_V:
4830 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4832 BYTE values[16];
4833 for (x = 0; x < 16; x++)
4834 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4835 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4836 if (pos & 1)
4837 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4838 else
4839 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4841 break;
4843 case GRADIENT_FILL_TRIANGLE:
4844 if (!(det = triangle_det( v ))) return FALSE;
4845 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4847 triangle_coords( v, rc, y, &left, &right );
4848 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4850 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4851 if (pos & 1)
4852 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4853 else
4854 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4857 break;
4859 return TRUE;
4862 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4864 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4865 int x, y, left, right, det, pos;
4867 switch (mode)
4869 case GRADIENT_FILL_RECT_H:
4870 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4872 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4874 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4875 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4878 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4879 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4880 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4881 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4882 break;
4884 case GRADIENT_FILL_RECT_V:
4885 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4887 BYTE values[16];
4888 for (x = 0; x < 16; x++)
4889 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4890 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4891 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4892 (values[x % 16] & pixel_masks_1[pos % 8]);
4894 break;
4896 case GRADIENT_FILL_TRIANGLE:
4897 if (!(det = triangle_det( v ))) return FALSE;
4898 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4900 triangle_coords( v, rc, y, &left, &right );
4901 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4903 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4904 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4907 break;
4909 return TRUE;
4912 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4914 return TRUE;
4917 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4919 if (dst == text) return dst;
4921 if (dst > text)
4923 DWORD diff = dst - text;
4924 DWORD range = max_comp - text;
4925 dst = text + (diff * range ) / (0xff - text);
4926 return dst;
4928 else
4930 DWORD diff = text - dst;
4931 DWORD range = text - min_comp;
4932 dst = text - (diff * range) / text;
4933 return dst;
4937 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4939 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4940 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4941 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4944 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4945 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4947 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4948 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4949 int x, y;
4951 for (y = rect->top; y < rect->bottom; y++)
4953 for (x = 0; x < rect->right - rect->left; x++)
4955 if (glyph_ptr[x] <= 1) continue;
4956 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4957 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4959 dst_ptr += dib->stride / 4;
4960 glyph_ptr += glyph->stride;
4964 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4965 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4967 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4968 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4969 int x, y;
4970 DWORD text, val;
4972 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4973 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4974 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4976 for (y = rect->top; y < rect->bottom; y++)
4978 for (x = 0; x < rect->right - rect->left; x++)
4980 if (glyph_ptr[x] <= 1) continue;
4981 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4982 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4983 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4984 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4985 text, ranges + glyph_ptr[x] );
4986 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4987 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4988 put_field( val, dib->blue_shift, dib->blue_len ));
4990 dst_ptr += dib->stride / 4;
4991 glyph_ptr += glyph->stride;
4995 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4996 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4998 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4999 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5000 int x, y;
5001 DWORD val;
5003 for (y = rect->top; y < rect->bottom; y++)
5005 for (x = 0; x < rect->right - rect->left; x++)
5007 if (glyph_ptr[x] <= 1) continue;
5008 if (glyph_ptr[x] >= 16)
5009 val = text_pixel;
5010 else
5011 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
5012 text_pixel, ranges + glyph_ptr[x] );
5013 dst_ptr[x * 3] = val;
5014 dst_ptr[x * 3 + 1] = val >> 8;
5015 dst_ptr[x * 3 + 2] = val >> 16;
5017 dst_ptr += dib->stride;
5018 glyph_ptr += glyph->stride;
5022 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5023 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5025 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5026 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5027 int x, y;
5028 DWORD text, val;
5030 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
5031 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
5032 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
5034 for (y = rect->top; y < rect->bottom; y++)
5036 for (x = 0; x < rect->right - rect->left; x++)
5038 if (glyph_ptr[x] <= 1) continue;
5039 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
5040 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
5041 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
5042 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
5043 text, ranges + glyph_ptr[x] );
5044 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
5046 dst_ptr += dib->stride / 2;
5047 glyph_ptr += glyph->stride;
5051 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5052 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5054 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5055 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5056 int x, y;
5057 DWORD text, val;
5059 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
5060 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5061 get_field( text_pixel, dib->blue_shift, dib->blue_len );
5063 for (y = rect->top; y < rect->bottom; y++)
5065 for (x = 0; x < rect->right - rect->left; x++)
5067 if (glyph_ptr[x] <= 1) continue;
5068 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
5069 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
5070 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5071 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
5072 text, ranges + glyph_ptr[x] );
5073 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
5074 put_field( val >> 8, dib->green_shift, dib->green_len ) |
5075 put_field( val, dib->blue_shift, dib->blue_len ));
5077 dst_ptr += dib->stride / 2;
5078 glyph_ptr += glyph->stride;
5082 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5083 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5085 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
5086 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5087 int x, y;
5089 for (y = rect->top; y < rect->bottom; y++)
5091 for (x = 0; x < rect->right - rect->left; x++)
5093 /* no antialiasing, glyph should only contain 0 or 16. */
5094 if (glyph_ptr[x] >= 16)
5095 dst_ptr[x] = text_pixel;
5097 dst_ptr += dib->stride;
5098 glyph_ptr += glyph->stride;
5102 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5103 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5105 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
5106 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5107 int x, y, pos;
5109 for (y = rect->top; y < rect->bottom; y++)
5111 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
5113 /* no antialiasing, glyph should only contain 0 or 16. */
5114 if (glyph_ptr[x] >= 16)
5116 if (pos & 1)
5117 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
5118 else
5119 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
5122 dst_ptr += dib->stride;
5123 glyph_ptr += glyph->stride;
5127 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5128 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5130 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
5131 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
5132 int x, y, pos;
5133 BYTE text = (text_pixel & 1) ? 0xff : 0;
5135 for (y = rect->top; y < rect->bottom; y++)
5137 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
5139 /* no antialiasing, glyph should only contain 0 or 16. */
5140 if (glyph_ptr[x] >= 16)
5141 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5142 (text & pixel_masks_1[pos % 8]);
5144 dst_ptr += dib->stride;
5145 glyph_ptr += glyph->stride;
5149 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5150 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
5152 return;
5155 static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha )
5157 return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 |
5158 blend_color( g, text >> 8, (BYTE)(alpha >> 8) ) << 8 |
5159 blend_color( b, text, (BYTE) alpha );
5162 static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5163 const POINT *origin, DWORD text_pixel )
5165 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
5166 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5167 int x, y;
5169 for (y = rect->top; y < rect->bottom; y++)
5171 for (x = 0; x < rect->right - rect->left; x++)
5173 if (glyph_ptr[x] == 0) continue;
5174 dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, glyph_ptr[x] );
5176 dst_ptr += dib->stride / 4;
5177 glyph_ptr += glyph->stride / 4;
5181 static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5182 const POINT *origin, DWORD text_pixel )
5184 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
5185 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5186 int x, y;
5187 DWORD text, val;
5189 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
5190 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5191 get_field( text_pixel, dib->blue_shift, dib->blue_len );
5193 for (y = rect->top; y < rect->bottom; y++)
5195 for (x = 0; x < rect->right - rect->left; x++)
5197 if (glyph_ptr[x] == 0) continue;
5198 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
5199 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5200 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
5201 text, glyph_ptr[x] );
5202 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
5203 put_field( val >> 8, dib->green_shift, dib->green_len ) |
5204 put_field( val, dib->blue_shift, dib->blue_len ));
5206 dst_ptr += dib->stride / 4;
5207 glyph_ptr += glyph->stride / 4;
5211 static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5212 const POINT *origin, DWORD text_pixel )
5214 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
5215 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5216 int x, y;
5217 DWORD val;
5219 for (y = rect->top; y < rect->bottom; y++)
5221 for (x = 0; x < rect->right - rect->left; x++)
5223 if (glyph_ptr[x] == 0) continue;
5224 val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
5225 text_pixel, glyph_ptr[x] );
5226 dst_ptr[x * 3] = val;
5227 dst_ptr[x * 3 + 1] = val >> 8;
5228 dst_ptr[x * 3 + 2] = val >> 16;
5230 dst_ptr += dib->stride;
5231 glyph_ptr += glyph->stride / 4;
5235 static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5236 const POINT *origin, DWORD text_pixel )
5238 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5239 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5240 int x, y;
5241 DWORD text, val;
5243 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
5244 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
5245 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
5247 for (y = rect->top; y < rect->bottom; y++)
5249 for (x = 0; x < rect->right - rect->left; x++)
5251 if (glyph_ptr[x] == 0) continue;
5252 val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
5253 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
5254 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
5255 text, glyph_ptr[x] );
5256 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
5258 dst_ptr += dib->stride / 2;
5259 glyph_ptr += glyph->stride / 4;
5263 static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5264 const POINT *origin, DWORD text_pixel )
5266 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
5267 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
5268 int x, y;
5269 DWORD text, val;
5271 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
5272 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
5273 get_field( text_pixel, dib->blue_shift, dib->blue_len );
5275 for (y = rect->top; y < rect->bottom; y++)
5277 for (x = 0; x < rect->right - rect->left; x++)
5279 if (glyph_ptr[x] == 0) continue;
5280 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
5281 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
5282 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
5283 text, glyph_ptr[x] );
5284 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
5285 put_field( val >> 8, dib->green_shift, dib->green_len ) |
5286 put_field( val, dib->blue_shift, dib->blue_len ));
5288 dst_ptr += dib->stride / 2;
5289 glyph_ptr += glyph->stride / 4;
5293 static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
5294 const POINT *origin, DWORD text_pixel )
5296 return;
5299 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
5300 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5302 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
5303 int x, y;
5305 /* masks are always 8x8 */
5306 assert( dib->width == 8 );
5307 assert( dib->height == 8 );
5309 for(y = 0; y < 8; y++, hatch_ptr++)
5311 for(x = 0; x < 8; x++)
5313 if(*hatch_ptr & pixel_masks_1[x])
5315 and_bits[x] = fg->and;
5316 xor_bits[x] = fg->xor;
5318 else
5320 and_bits[x] = bg->and;
5321 xor_bits[x] = bg->xor;
5324 and_bits += dib->stride / 4;
5325 xor_bits += dib->stride / 4;
5329 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
5330 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5332 DWORD mask_start = 0, mask_offset;
5333 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5334 int x, y;
5336 /* masks are always 8x8 */
5337 assert( dib->width == 8 );
5338 assert( dib->height == 8 );
5340 for(y = 0; y < 8; y++, hatch_ptr++)
5342 mask_offset = mask_start;
5343 for(x = 0; x < 8; x++)
5345 if(*hatch_ptr & pixel_masks_1[x])
5347 and_bits[mask_offset] = fg->and & 0xff;
5348 xor_bits[mask_offset++] = fg->xor & 0xff;
5349 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
5350 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
5351 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
5352 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
5354 else
5356 and_bits[mask_offset] = bg->and & 0xff;
5357 xor_bits[mask_offset++] = bg->xor & 0xff;
5358 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
5359 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
5360 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
5361 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
5364 mask_start += dib->stride;
5368 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
5369 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5371 WORD *and_bits = bits->and, *xor_bits = bits->xor;
5372 int x, y;
5374 /* masks are always 8x8 */
5375 assert( dib->width == 8 );
5376 assert( dib->height == 8 );
5378 for(y = 0; y < 8; y++, hatch_ptr++)
5380 for(x = 0; x < 8; x++)
5382 if(*hatch_ptr & pixel_masks_1[x])
5384 and_bits[x] = fg->and;
5385 xor_bits[x] = fg->xor;
5387 else
5389 and_bits[x] = bg->and;
5390 xor_bits[x] = bg->xor;
5393 and_bits += dib->stride / 2;
5394 xor_bits += dib->stride / 2;
5398 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
5399 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5401 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5402 int x, y;
5404 /* masks are always 8x8 */
5405 assert( dib->width == 8 );
5406 assert( dib->height == 8 );
5408 for(y = 0; y < 8; y++, hatch_ptr++)
5410 for(x = 0; x < 8; x++)
5412 if(*hatch_ptr & pixel_masks_1[x])
5414 and_bits[x] = fg->and;
5415 xor_bits[x] = fg->xor;
5417 else
5419 and_bits[x] = bg->and;
5420 xor_bits[x] = bg->xor;
5423 and_bits += dib->stride;
5424 xor_bits += dib->stride;
5428 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
5429 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5431 DWORD mask_offset;
5432 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5433 const rop_mask *rop_mask;
5434 int x, y;
5436 /* masks are always 8x8 */
5437 assert( dib->width == 8 );
5438 assert( dib->height == 8 );
5440 for(y = 0; y < 8; y++, hatch_ptr++)
5442 for(x = mask_offset = 0; x < 8; x++)
5444 if(*hatch_ptr & pixel_masks_1[x])
5445 rop_mask = fg;
5446 else
5447 rop_mask = bg;
5449 if(x & 1)
5451 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
5452 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
5453 mask_offset++;
5455 else
5457 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
5458 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
5461 and_bits += dib->stride;
5462 xor_bits += dib->stride;
5466 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
5467 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5469 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5470 rop_mask rop_mask;
5471 int x, y;
5473 /* masks are always 8x8 */
5474 assert( dib->width == 8 );
5475 assert( dib->height == 8 );
5477 for(y = 0; y < 8; y++, hatch_ptr++)
5479 *and_bits = *xor_bits = 0;
5480 for(x = 0; x < 8; x++)
5482 if(*hatch_ptr & pixel_masks_1[x])
5484 rop_mask.and = (fg->and & 1) ? 0xff : 0;
5485 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
5487 else
5489 rop_mask.and = (bg->and & 1) ? 0xff : 0;
5490 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5492 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5493 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5495 and_bits += dib->stride;
5496 xor_bits += dib->stride;
5500 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
5501 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5505 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5507 /* mapping between RGB triples and the default color table */
5508 static const BYTE mapping[27] =
5510 0, /* 000000 -> 000000 */
5511 4, /* 00007f -> 000080 */
5512 252, /* 0000ff -> 0000ff */
5513 2, /* 007f00 -> 008000 */
5514 6, /* 007f7f -> 008080 */
5515 224, /* 007fff -> 0080c0 */
5516 250, /* 00ff00 -> 00ff00 */
5517 184, /* 00ff7f -> 00e080 */
5518 254, /* 00ffff -> 00ffff */
5519 1, /* 7f0000 -> 800000 */
5520 5, /* 7f007f -> 800080 */
5521 196, /* 7f00ff -> 8000c0 */
5522 3, /* 7f7f00 -> 808000 */
5523 248, /* 7f7f7f -> 808080 */
5524 228, /* 7f7fff -> 8080c0 */
5525 60, /* 7fff00 -> 80e000 */
5526 188, /* 7fff7f -> 80e080 */
5527 244, /* 7fffff -> 80c0c0 */
5528 249, /* ff0000 -> ff0000 */
5529 135, /* ff007f -> e00080 */
5530 253, /* ff00ff -> ff00ff */
5531 39, /* ff7f00 -> e08000 */
5532 167, /* ff7f7f -> e08080 */
5533 231, /* ff7fff -> e080c0 */
5534 251, /* ffff00 -> ffff00 */
5535 191, /* ffff7f -> e0e080 */
5536 255 /* ffffff -> ffffff */
5539 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5540 struct rop_codes codes;
5541 int x, y;
5543 /* masks are always 8x8 */
5544 assert( dib->width == 8 );
5545 assert( dib->height == 8 );
5547 get_rop_codes( rop2, &codes );
5549 for (y = 0; y < 8; y++)
5551 for (x = 0; x < 8; x++)
5553 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5554 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5555 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5556 DWORD pixel = mapping[r * 9 + g * 3 + b];
5557 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
5558 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
5560 and_bits += dib->stride;
5561 xor_bits += dib->stride;
5565 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5567 /* mapping between RGB triples and the default color table */
5568 static const BYTE mapping[27] =
5570 0, /* 000000 -> 000000 */
5571 4, /* 00007f -> 000080 */
5572 12, /* 0000ff -> 0000ff */
5573 2, /* 007f00 -> 008000 */
5574 6, /* 007f7f -> 008080 */
5575 6, /* 007fff -> 008080 */
5576 10, /* 00ff00 -> 00ff00 */
5577 6, /* 00ff7f -> 008080 */
5578 14, /* 00ffff -> 00ffff */
5579 1, /* 7f0000 -> 800000 */
5580 5, /* 7f007f -> 800080 */
5581 5, /* 7f00ff -> 800080 */
5582 3, /* 7f7f00 -> 808000 */
5583 7, /* 7f7f7f -> 808080 */
5584 8, /* 7f7fff -> c0c0c0 */
5585 3, /* 7fff00 -> 808000 */
5586 8, /* 7fff7f -> c0c0c0 */
5587 8, /* 7fffff -> c0c0c0 */
5588 9, /* ff0000 -> ff0000 */
5589 5, /* ff007f -> 800080 */
5590 13, /* ff00ff -> ff00ff */
5591 3, /* ff7f00 -> 808000 */
5592 8, /* ff7f7f -> c0c0c0 */
5593 8, /* ff7fff -> c0c0c0 */
5594 11, /* ffff00 -> ffff00 */
5595 8, /* ffff7f -> c0c0c0 */
5596 15 /* ffffff -> ffffff */
5599 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5600 struct rop_codes codes;
5601 int x, y;
5603 /* masks are always 8x8 */
5604 assert( dib->width == 8 );
5605 assert( dib->height == 8 );
5607 get_rop_codes( rop2, &codes );
5609 for (y = 0; y < 8; y++)
5611 for (x = 0; x < 8; x++)
5613 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5614 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5615 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5616 DWORD pixel = mapping[r * 9 + g * 3 + b];
5617 if (x & 1)
5619 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
5620 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
5622 else
5624 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
5625 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
5628 and_bits += dib->stride;
5629 xor_bits += dib->stride;
5633 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5635 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5636 struct rop_codes codes;
5637 rop_mask rop_mask;
5638 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
5640 /* masks are always 8x8 */
5641 assert( dib->width == 8 );
5642 assert( dib->height == 8 );
5644 get_rop_codes( rop2, &codes );
5646 for (y = 0; y < 8; y++)
5648 *and_bits = *xor_bits = 0;
5649 for (x = 0; x < 8; x++)
5651 if (grey + bayer_8x8[y][x] > 63)
5653 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
5654 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
5656 else
5658 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
5659 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
5661 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5662 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5664 and_bits += dib->stride;
5665 xor_bits += dib->stride;
5669 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5673 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5675 switch (mode)
5677 default:
5678 case STRETCH_DELETESCANS:
5679 get_rop_codes( R2_COPYPEN, codes );
5680 break;
5681 case STRETCH_ORSCANS:
5682 get_rop_codes( R2_MERGEPEN, codes );
5683 break;
5684 case STRETCH_ANDSCANS:
5685 get_rop_codes( R2_MASKPEN, codes );
5686 break;
5688 return;
5691 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5692 const dib_info *src_dib, const POINT *src_start,
5693 const struct stretch_params *params, int mode,
5694 BOOL keep_dst)
5696 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5697 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5698 int err = params->err_start;
5699 int width;
5701 if (mode == STRETCH_DELETESCANS || !keep_dst)
5703 for (width = params->length; width; width--)
5705 *dst_ptr = *src_ptr;
5706 dst_ptr += params->dst_inc;
5707 if (err > 0)
5709 src_ptr += params->src_inc;
5710 err += params->err_add_1;
5712 else err += params->err_add_2;
5715 else
5717 struct rop_codes codes;
5719 rop_codes_from_stretch_mode( mode, &codes );
5720 for (width = params->length; width; width--)
5722 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5723 dst_ptr += params->dst_inc;
5724 if (err > 0)
5726 src_ptr += params->src_inc;
5727 err += params->err_add_1;
5729 else err += params->err_add_2;
5734 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5735 const dib_info *src_dib, const POINT *src_start,
5736 const struct stretch_params *params, int mode,
5737 BOOL keep_dst)
5739 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5740 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5741 int err = params->err_start;
5742 int width;
5744 if (mode == STRETCH_DELETESCANS || !keep_dst)
5746 for (width = params->length; width; width--)
5748 dst_ptr[0] = src_ptr[0];
5749 dst_ptr[1] = src_ptr[1];
5750 dst_ptr[2] = src_ptr[2];
5751 dst_ptr += 3 * params->dst_inc;
5752 if (err > 0)
5754 src_ptr += 3 * params->src_inc;
5755 err += params->err_add_1;
5757 else err += params->err_add_2;
5760 else
5762 struct rop_codes codes;
5764 rop_codes_from_stretch_mode( mode, &codes );
5765 for (width = params->length; width; width--)
5767 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5768 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5769 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5770 dst_ptr += 3 * params->dst_inc;
5771 if (err > 0)
5773 src_ptr += 3 * params->src_inc;
5774 err += params->err_add_1;
5776 else err += params->err_add_2;
5781 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5782 const dib_info *src_dib, const POINT *src_start,
5783 const struct stretch_params *params, int mode,
5784 BOOL keep_dst)
5786 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5787 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5788 int err = params->err_start;
5789 int width;
5791 if (mode == STRETCH_DELETESCANS || !keep_dst)
5793 for (width = params->length; width; width--)
5795 *dst_ptr = *src_ptr;
5796 dst_ptr += params->dst_inc;
5797 if (err > 0)
5799 src_ptr += params->src_inc;
5800 err += params->err_add_1;
5802 else err += params->err_add_2;
5805 else
5807 struct rop_codes codes;
5809 rop_codes_from_stretch_mode( mode, &codes );
5810 for (width = params->length; width; width--)
5812 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5813 dst_ptr += params->dst_inc;
5814 if (err > 0)
5816 src_ptr += params->src_inc;
5817 err += params->err_add_1;
5819 else err += params->err_add_2;
5824 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5825 const dib_info *src_dib, const POINT *src_start,
5826 const struct stretch_params *params, int mode,
5827 BOOL keep_dst)
5829 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5830 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5831 int err = params->err_start;
5832 int width;
5834 if (mode == STRETCH_DELETESCANS || !keep_dst)
5836 for (width = params->length; width; width--)
5838 *dst_ptr = *src_ptr;
5839 dst_ptr += params->dst_inc;
5840 if (err > 0)
5842 src_ptr += params->src_inc;
5843 err += params->err_add_1;
5845 else err += params->err_add_2;
5848 else
5850 struct rop_codes codes;
5852 rop_codes_from_stretch_mode( mode, &codes );
5853 for (width = params->length; width; width--)
5855 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5856 dst_ptr += params->dst_inc;
5857 if (err > 0)
5859 src_ptr += params->src_inc;
5860 err += params->err_add_1;
5862 else err += params->err_add_2;
5867 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5868 const dib_info *src_dib, const POINT *src_start,
5869 const struct stretch_params *params, int mode,
5870 BOOL keep_dst)
5872 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5873 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5874 int err = params->err_start;
5875 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5876 struct rop_codes codes;
5877 BYTE src_val;
5879 if (!keep_dst) mode = STRETCH_DELETESCANS;
5880 rop_codes_from_stretch_mode( mode, &codes );
5881 for (width = params->length; width; width--)
5883 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5884 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5886 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5888 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5889 dst_ptr += params->dst_inc;
5890 dst_x += params->dst_inc;
5892 if (err > 0)
5894 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5895 src_ptr += params->src_inc;
5896 src_x += params->src_inc;
5897 err += params->err_add_1;
5899 else err += params->err_add_2;
5903 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5904 const dib_info *src_dib, const POINT *src_start,
5905 const struct stretch_params *params, int mode,
5906 BOOL keep_dst)
5908 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5909 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5910 int err = params->err_start;
5911 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5912 struct rop_codes codes;
5913 BYTE src_val;
5915 if (!keep_dst) mode = STRETCH_DELETESCANS;
5916 rop_codes_from_stretch_mode( mode, &codes );
5917 for (width = params->length; width; width--)
5919 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5920 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5922 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5923 dst_ptr += params->dst_inc;
5924 dst_x += params->dst_inc;
5926 if (err > 0)
5928 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5929 src_ptr += params->src_inc;
5930 src_x += params->src_inc;
5931 err += params->err_add_1;
5933 else err += params->err_add_2;
5937 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5938 const dib_info *src_dib, const POINT *src_start,
5939 const struct stretch_params *params, int mode,
5940 BOOL keep_dst)
5942 FIXME("bit count %d\n", dst_dib->bit_count);
5943 return;
5946 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5947 const dib_info *src_dib, const POINT *src_start,
5948 const struct stretch_params *params, int mode,
5949 BOOL keep_dst)
5951 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5952 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5953 int err = params->err_start;
5954 int width;
5956 if (mode == STRETCH_DELETESCANS)
5958 for (width = params->length; width; width--)
5960 *dst_ptr = *src_ptr;
5961 src_ptr += params->src_inc;
5962 if (err > 0)
5964 dst_ptr += params->dst_inc;
5965 err += params->err_add_1;
5967 else err += params->err_add_2;
5970 else
5972 struct rop_codes codes;
5973 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5974 BOOL new_pix = TRUE;
5976 rop_codes_from_stretch_mode( mode, &codes );
5977 for (width = params->length; width; width--)
5979 if (new_pix && !keep_dst) *dst_ptr = init_val;
5980 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5981 new_pix = FALSE;
5982 src_ptr += params->src_inc;
5983 if (err > 0)
5985 dst_ptr += params->dst_inc;
5986 new_pix = TRUE;
5987 err += params->err_add_1;
5989 else err += params->err_add_2;
5994 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5995 const dib_info *src_dib, const POINT *src_start,
5996 const struct stretch_params *params, int mode,
5997 BOOL keep_dst)
5999 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
6000 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
6001 int err = params->err_start;
6002 int width;
6004 if (mode == STRETCH_DELETESCANS)
6006 for (width = params->length; width; width--)
6008 dst_ptr[0] = src_ptr[0];
6009 dst_ptr[1] = src_ptr[1];
6010 dst_ptr[2] = src_ptr[2];
6011 src_ptr += 3 * params->src_inc;
6012 if (err > 0)
6014 dst_ptr += 3 * params->dst_inc;
6015 err += params->err_add_1;
6017 else err += params->err_add_2;
6020 else
6022 struct rop_codes codes;
6023 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
6024 BOOL new_pix = TRUE;
6026 rop_codes_from_stretch_mode( mode, &codes );
6027 for (width = params->length; width; width--)
6029 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
6030 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6031 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
6032 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
6033 new_pix = FALSE;
6034 src_ptr += 3 * params->src_inc;
6035 if (err > 0)
6037 dst_ptr += 3 * params->dst_inc;
6038 new_pix = TRUE;
6039 err += params->err_add_1;
6041 else err += params->err_add_2;
6046 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
6047 const dib_info *src_dib, const POINT *src_start,
6048 const struct stretch_params *params, int mode,
6049 BOOL keep_dst)
6051 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
6052 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
6053 int err = params->err_start;
6054 int width;
6056 if (mode == STRETCH_DELETESCANS)
6058 for (width = params->length; width; width--)
6060 *dst_ptr = *src_ptr;
6061 src_ptr += params->src_inc;
6062 if (err > 0)
6064 dst_ptr += params->dst_inc;
6065 err += params->err_add_1;
6067 else err += params->err_add_2;
6070 else
6072 struct rop_codes codes;
6073 WORD init_val = (mode == STRETCH_ANDSCANS) ? 0xffff : 0;
6074 BOOL new_pix = TRUE;
6076 rop_codes_from_stretch_mode( mode, &codes );
6077 for (width = params->length; width; width--)
6079 if (new_pix && !keep_dst) *dst_ptr = init_val;
6080 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
6081 new_pix = FALSE;
6082 src_ptr += params->src_inc;
6083 if (err > 0)
6085 dst_ptr += params->dst_inc;
6086 new_pix = TRUE;
6087 err += params->err_add_1;
6089 else err += params->err_add_2;
6094 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
6095 const dib_info *src_dib, const POINT *src_start,
6096 const struct stretch_params *params, int mode,
6097 BOOL keep_dst)
6099 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
6100 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
6101 int err = params->err_start;
6102 int width;
6104 if (mode == STRETCH_DELETESCANS)
6106 for (width = params->length; width; width--)
6108 *dst_ptr = *src_ptr;
6109 src_ptr += params->src_inc;
6110 if (err > 0)
6112 dst_ptr += params->dst_inc;
6113 err += params->err_add_1;
6115 else err += params->err_add_2;
6118 else
6120 struct rop_codes codes;
6121 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
6122 BOOL new_pix = TRUE;
6124 rop_codes_from_stretch_mode( mode, &codes );
6125 for (width = params->length; width; width--)
6127 if (new_pix && !keep_dst) *dst_ptr = init_val;
6128 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6129 new_pix = FALSE;
6130 src_ptr += params->src_inc;
6131 if (err > 0)
6133 dst_ptr += params->dst_inc;
6134 new_pix = TRUE;
6135 err += params->err_add_1;
6137 else err += params->err_add_2;
6142 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
6143 const dib_info *src_dib, const POINT *src_start,
6144 const struct stretch_params *params, int mode,
6145 BOOL keep_dst)
6147 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
6148 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
6149 int err = params->err_start;
6150 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6151 struct rop_codes codes;
6152 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
6153 BOOL new_pix = TRUE;
6155 rop_codes_from_stretch_mode( mode, &codes );
6156 for (width = params->length; width; width--)
6158 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
6160 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
6161 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
6163 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
6164 new_pix = FALSE;
6166 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
6167 src_ptr += params->src_inc;
6168 src_x += params->src_inc;
6170 if (err > 0)
6172 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
6173 dst_ptr += params->dst_inc;
6174 dst_x += params->dst_inc;
6175 new_pix = TRUE;
6176 err += params->err_add_1;
6178 else err += params->err_add_2;
6182 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
6183 const dib_info *src_dib, const POINT *src_start,
6184 const struct stretch_params *params, int mode,
6185 BOOL keep_dst)
6187 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
6188 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
6189 int err = params->err_start;
6190 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
6191 struct rop_codes codes;
6192 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
6193 BOOL new_pix = TRUE;
6195 rop_codes_from_stretch_mode( mode, &codes );
6196 for (width = params->length; width; width--)
6198 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
6199 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
6200 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
6201 new_pix = FALSE;
6203 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
6204 src_ptr += params->src_inc;
6205 src_x += params->src_inc;
6207 if (err > 0)
6209 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
6210 dst_ptr += params->dst_inc;
6211 dst_x += params->dst_inc;
6212 new_pix = TRUE;
6213 err += params->err_add_1;
6215 else err += params->err_add_2;
6219 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
6220 const dib_info *src_dib, const POINT *src_start,
6221 const struct stretch_params *params, int mode,
6222 BOOL keep_dst)
6224 FIXME("bit count %d\n", dst_dib->bit_count);
6225 return;
6228 const primitive_funcs funcs_8888 =
6230 solid_rects_32,
6231 solid_line_32,
6232 pattern_rects_32,
6233 copy_rect_32,
6234 blend_rect_8888,
6235 gradient_rect_8888,
6236 draw_glyph_8888,
6237 draw_subpixel_glyph_8888,
6238 get_pixel_32,
6239 colorref_to_pixel_888,
6240 pixel_to_colorref_888,
6241 convert_to_8888,
6242 create_rop_masks_32,
6243 create_dither_masks_null,
6244 stretch_row_32,
6245 shrink_row_32
6248 const primitive_funcs funcs_32 =
6250 solid_rects_32,
6251 solid_line_32,
6252 pattern_rects_32,
6253 copy_rect_32,
6254 blend_rect_32,
6255 gradient_rect_32,
6256 draw_glyph_32,
6257 draw_subpixel_glyph_32,
6258 get_pixel_32,
6259 colorref_to_pixel_masks,
6260 pixel_to_colorref_masks,
6261 convert_to_32,
6262 create_rop_masks_32,
6263 create_dither_masks_null,
6264 stretch_row_32,
6265 shrink_row_32
6268 const primitive_funcs funcs_24 =
6270 solid_rects_24,
6271 solid_line_24,
6272 pattern_rects_24,
6273 copy_rect_24,
6274 blend_rect_24,
6275 gradient_rect_24,
6276 draw_glyph_24,
6277 draw_subpixel_glyph_24,
6278 get_pixel_24,
6279 colorref_to_pixel_888,
6280 pixel_to_colorref_888,
6281 convert_to_24,
6282 create_rop_masks_24,
6283 create_dither_masks_null,
6284 stretch_row_24,
6285 shrink_row_24
6288 const primitive_funcs funcs_555 =
6290 solid_rects_16,
6291 solid_line_16,
6292 pattern_rects_16,
6293 copy_rect_16,
6294 blend_rect_555,
6295 gradient_rect_555,
6296 draw_glyph_555,
6297 draw_subpixel_glyph_555,
6298 get_pixel_16,
6299 colorref_to_pixel_555,
6300 pixel_to_colorref_555,
6301 convert_to_555,
6302 create_rop_masks_16,
6303 create_dither_masks_null,
6304 stretch_row_16,
6305 shrink_row_16
6308 const primitive_funcs funcs_16 =
6310 solid_rects_16,
6311 solid_line_16,
6312 pattern_rects_16,
6313 copy_rect_16,
6314 blend_rect_16,
6315 gradient_rect_16,
6316 draw_glyph_16,
6317 draw_subpixel_glyph_16,
6318 get_pixel_16,
6319 colorref_to_pixel_masks,
6320 pixel_to_colorref_masks,
6321 convert_to_16,
6322 create_rop_masks_16,
6323 create_dither_masks_null,
6324 stretch_row_16,
6325 shrink_row_16
6328 const primitive_funcs funcs_8 =
6330 solid_rects_8,
6331 solid_line_8,
6332 pattern_rects_8,
6333 copy_rect_8,
6334 blend_rect_8,
6335 gradient_rect_8,
6336 draw_glyph_8,
6337 draw_subpixel_glyph_null,
6338 get_pixel_8,
6339 colorref_to_pixel_colortable,
6340 pixel_to_colorref_colortable,
6341 convert_to_8,
6342 create_rop_masks_8,
6343 create_dither_masks_8,
6344 stretch_row_8,
6345 shrink_row_8
6348 const primitive_funcs funcs_4 =
6350 solid_rects_4,
6351 solid_line_4,
6352 pattern_rects_4,
6353 copy_rect_4,
6354 blend_rect_4,
6355 gradient_rect_4,
6356 draw_glyph_4,
6357 draw_subpixel_glyph_null,
6358 get_pixel_4,
6359 colorref_to_pixel_colortable,
6360 pixel_to_colorref_colortable,
6361 convert_to_4,
6362 create_rop_masks_4,
6363 create_dither_masks_4,
6364 stretch_row_4,
6365 shrink_row_4
6368 const primitive_funcs funcs_1 =
6370 solid_rects_1,
6371 solid_line_1,
6372 pattern_rects_1,
6373 copy_rect_1,
6374 blend_rect_1,
6375 gradient_rect_1,
6376 draw_glyph_1,
6377 draw_subpixel_glyph_null,
6378 get_pixel_1,
6379 colorref_to_pixel_colortable,
6380 pixel_to_colorref_colortable,
6381 convert_to_1,
6382 create_rop_masks_1,
6383 create_dither_masks_1,
6384 stretch_row_1,
6385 shrink_row_1
6388 const primitive_funcs funcs_null =
6390 solid_rects_null,
6391 solid_line_null,
6392 pattern_rects_null,
6393 copy_rect_null,
6394 blend_rect_null,
6395 gradient_rect_null,
6396 draw_glyph_null,
6397 draw_subpixel_glyph_null,
6398 get_pixel_null,
6399 colorref_to_pixel_null,
6400 pixel_to_colorref_null,
6401 convert_to_null,
6402 create_rop_masks_null,
6403 create_dither_masks_null,
6404 stretch_row_null,
6405 shrink_row_null