include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / win32u / dibdrv / primitives.c
blob3633c687e78551d74982199c5d19ac2460114265
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 #if 0
22 #pragma makedep unix
23 #endif
25 #include <assert.h>
27 #include "ntgdi_private.h"
28 #include "dibdrv.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dib);
34 /* Bayer matrices for dithering */
36 static const BYTE bayer_4x4[4][4] =
38 { 0, 8, 2, 10 },
39 { 12, 4, 14, 6 },
40 { 3, 11, 1, 9 },
41 { 15, 7, 13, 5 }
44 static const BYTE bayer_8x8[8][8] =
46 { 0, 32, 8, 40, 2, 34, 10, 42 },
47 { 48, 16, 56, 24, 50, 18, 58, 26 },
48 { 12, 44, 4, 36, 14, 46, 6, 38 },
49 { 60, 28, 52, 20, 62, 30, 54, 22 },
50 { 3, 35, 11, 43, 1, 33, 9, 41 },
51 { 51, 19, 59, 27, 49, 17, 57, 25 },
52 { 15, 47, 7, 39, 13, 45, 5, 37 },
53 { 63, 31, 55, 23, 61, 29, 53, 21 }
56 static const BYTE bayer_16x16[16][16] =
58 { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170 },
59 { 192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106 },
60 { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154 },
61 { 240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90 },
62 { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166 },
63 { 204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102 },
64 { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150 },
65 { 252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86 },
66 { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169 },
67 { 195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105 },
68 { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153 },
69 { 243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89 },
70 { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165 },
71 { 207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101 },
72 { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149 },
73 { 255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85 },
76 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
78 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 4);
81 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
83 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride) + (dib->rect.left + x) * 3 / 4;
86 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
88 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 3;
91 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
93 return (WORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 2);
96 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
98 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + dib->rect.left + x;
101 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
103 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 2;
106 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
108 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 8;
111 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
112 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
113 static const BYTE edge_masks_1[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
115 #define FILTER_DIBINDEX(rgbquad,other_val) \
116 (HIWORD( *(DWORD *)(&rgbquad) ) == 0x10ff ? LOWORD( *(DWORD *)(&rgbquad) ) : (other_val))
118 #define ROPS_WITHOUT_COPY( _d, _s ) \
119 case R2_BLACK: LOOP( (_d) = 0 ) break; \
120 case R2_NOTMERGEPEN: LOOP( (_d) = ~((_d) | (_s)) ) break; \
121 case R2_MASKNOTPEN: LOOP( (_d) &= ~(_s) ) break; \
122 case R2_NOTCOPYPEN: LOOP( (_d) = ~(_s) ) break; \
123 case R2_MASKPENNOT: LOOP( (_d) = (~(_d) & (_s)) ) break; \
124 case R2_NOT: LOOP( (_d) = ~(_d) ) break; \
125 case R2_XORPEN: LOOP( (_d) ^= (_s) ) break; \
126 case R2_NOTMASKPEN: LOOP( (_d) = ~((_d) & (_s)) ) break; \
127 case R2_MASKPEN: LOOP( (_d) &= (_s) ) break; \
128 case R2_NOTXORPEN: LOOP( (_d) = ~((_d) ^ (_s)) ) break; \
129 case R2_NOP: break; \
130 case R2_MERGENOTPEN: LOOP( (_d) = ((_d) | ~(_s)) ) break; \
131 case R2_MERGEPENNOT: LOOP( (_d) = (~(_d) | (_s)) ) break; \
132 case R2_MERGEPEN: LOOP( (_d) |= (_s) ) break; \
133 case R2_WHITE: LOOP( (_d) = ~0 ) break;
135 #define ROPS_ALL( _d, _s ) \
136 case R2_COPYPEN: LOOP( (_d) = (_s) ) break; \
137 ROPS_WITHOUT_COPY( (_d), (_s) )
139 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
141 *ptr = (*ptr & and) ^ xor;
144 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
146 *ptr = (*ptr & and) ^ xor;
149 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
151 *ptr = (*ptr & and) ^ xor;
154 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
156 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
159 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
161 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
164 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
166 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
169 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
171 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
174 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
176 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
179 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
181 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
184 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
186 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
187 do_rop_codes_16( dst, *src, codes );
190 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
192 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
195 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
197 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
198 do_rop_codes_8( dst, *src, codes );
201 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
202 struct rop_codes *codes, int len)
204 BYTE src_val;
206 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
208 if (dst_x & 1)
210 if (src_x & 1) src_val = *src++;
211 else src_val = *src >> 4;
212 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
214 else
216 if (src_x & 1) src_val = *src++ << 4;
217 else src_val = *src;
218 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
223 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
224 struct rop_codes *codes, int len)
226 BYTE src_val;
228 src_x += len - 1;
229 dst_x += len - 1;
230 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
232 if (dst_x & 1)
234 if (src_x & 1) src_val = *src;
235 else src_val = *src-- >> 4;
236 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
238 else
240 if (src_x & 1) src_val = *src << 4;
241 else src_val = *src--;
242 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
247 static inline void memset_32( DWORD *start, DWORD val, DWORD size )
249 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
250 DWORD dummy;
251 __asm__ __volatile__( "cld; rep; stosl"
252 : "=c" (dummy), "=D" (dummy)
253 : "a" (val), "0" (size), "1" (start) );
254 #else
255 while (size--) *start++ = val;
256 #endif
259 static inline void memset_16( WORD *start, WORD val, DWORD size )
261 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
262 DWORD dummy;
263 __asm__ __volatile__( "cld; rep; stosw"
264 : "=c" (dummy), "=D" (dummy)
265 : "a" (val), "0" (size), "1" (start) );
266 #else
267 while (size--) *start++ = val;
268 #endif
271 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
273 DWORD *ptr, *start;
274 int x, y, i;
276 for(i = 0; i < num; i++, rc++)
278 assert( !IsRectEmpty( rc ));
280 start = get_pixel_ptr_32(dib, rc->left, rc->top);
281 if (and)
282 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
283 for(x = rc->left, ptr = start; x < rc->right; x++)
284 do_rop_32(ptr++, and, xor);
285 else
286 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
287 memset_32( start, xor, rc->right - rc->left );
291 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
293 DWORD *ptr, *start;
294 BYTE *byte_ptr, *byte_start;
295 int x, y, i;
296 DWORD and_masks[3], xor_masks[3];
298 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
299 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
300 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
301 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
302 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
303 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
305 for(i = 0; i < num; i++, rc++)
307 int left = dib->rect.left + rc->left;
308 int right = dib->rect.left + rc->right;
310 assert( !IsRectEmpty( rc ));
312 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
314 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
315 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
317 for(x = left, byte_ptr = byte_start; x < right; x++)
319 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
320 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
321 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
325 else if (and)
327 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
328 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
330 ptr = start;
332 switch(left & 3)
334 case 1:
335 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
336 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
337 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
338 break;
339 case 2:
340 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
341 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
342 break;
343 case 3:
344 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
345 break;
348 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
350 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
351 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
352 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
355 switch(right & 3)
357 case 1:
358 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
359 break;
360 case 2:
361 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
362 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
363 break;
364 case 3:
365 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
366 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
367 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
368 break;
372 else
374 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
375 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
377 ptr = start;
379 switch(left & 3)
381 case 1:
382 do_rop_32(ptr++, 0x00ffffff, xor_masks[0] & 0xff000000);
383 *ptr++ = xor_masks[1];
384 *ptr++ = xor_masks[2];
385 break;
386 case 2:
387 do_rop_32(ptr++, 0x0000ffff, xor_masks[1] & 0xffff0000);
388 *ptr++ = xor_masks[2];
389 break;
390 case 3:
391 do_rop_32(ptr++, 0x000000ff, xor_masks[2] & 0xffffff00);
392 break;
395 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
397 *ptr++ = xor_masks[0];
398 *ptr++ = xor_masks[1];
399 *ptr++ = xor_masks[2];
402 switch(right & 3)
404 case 1:
405 do_rop_32(ptr, 0xff000000, xor_masks[0] & 0x00ffffff);
406 break;
407 case 2:
408 *ptr++ = xor_masks[0];
409 do_rop_32(ptr, 0xffff0000, xor_masks[1] & 0x0000ffff);
410 break;
411 case 3:
412 *ptr++ = xor_masks[0];
413 *ptr++ = xor_masks[1];
414 do_rop_32(ptr, 0xffffff00, xor_masks[2] & 0x000000ff);
415 break;
422 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
424 WORD *ptr, *start;
425 int x, y, i;
427 for(i = 0; i < num; i++, rc++)
429 assert( !IsRectEmpty( rc ));
431 start = get_pixel_ptr_16(dib, rc->left, rc->top);
432 if (and)
433 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
434 for(x = rc->left, ptr = start; x < rc->right; x++)
435 do_rop_16(ptr++, and, xor);
436 else
437 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
438 memset_16( start, xor, rc->right - rc->left );
442 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
444 BYTE *ptr, *start;
445 int x, y, i;
447 for(i = 0; i < num; i++, rc++)
449 assert( !IsRectEmpty( rc ));
451 start = get_pixel_ptr_8(dib, rc->left, rc->top);
452 if (and)
453 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
454 for(x = rc->left, ptr = start; x < rc->right; x++)
455 do_rop_8(ptr++, and, xor);
456 else
457 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
458 memset( start, xor, rc->right - rc->left );
462 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
464 BYTE *ptr, *start;
465 int x, y, i;
466 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
467 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
469 for(i = 0; i < num; i++, rc++)
471 int left = dib->rect.left + rc->left;
472 int right = dib->rect.left + rc->right;
474 assert( !IsRectEmpty( rc ));
476 start = get_pixel_ptr_4(dib, rc->left, rc->top);
477 if (and)
479 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
481 ptr = start;
482 if(left & 1) /* upper nibble untouched */
483 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
485 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
486 do_rop_8(ptr++, byte_and, byte_xor);
488 if(right & 1) /* lower nibble untouched */
489 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
492 else
494 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
496 unsigned int byte_len = (right - ((left + 1) & ~1)) / 2;
498 ptr = start;
499 if(left & 1) /* upper nibble untouched */
500 do_rop_8(ptr++, 0xf0, byte_xor & 0x0f);
502 memset( ptr, byte_xor, byte_len );
504 if(right & 1) /* lower nibble untouched */
505 do_rop_8(ptr + byte_len, 0x0f, byte_xor & 0xf0);
511 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
513 BYTE *ptr, *start;
514 int x, y, i;
515 BYTE byte_and = (and & 1) ? 0xff : 0;
516 BYTE byte_xor = (xor & 1) ? 0xff : 0;
518 for(i = 0; i < num; i++, rc++)
520 int left = dib->rect.left + rc->left;
521 int right = dib->rect.left + rc->right;
523 assert( !IsRectEmpty( rc ));
525 start = get_pixel_ptr_1(dib, rc->left, rc->top);
527 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
529 BYTE mask = edge_masks_1[left & 7] & ~edge_masks_1[right & 7];
531 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
533 do_rop_8(start, byte_and | ~mask, byte_xor & mask);
536 else if (and)
538 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
540 ptr = start;
542 if(left & 7)
543 do_rop_8(ptr++, byte_and | ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
545 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
546 do_rop_8(ptr++, byte_and, byte_xor);
548 if(right & 7)
549 /* this is inverted wrt start mask */
550 do_rop_8(ptr, byte_and | edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
553 else
555 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
557 unsigned int byte_len = (right - ((left + 7) & ~7)) / 8;
559 ptr = start;
561 if(left & 7)
562 do_rop_8(ptr++, ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
564 memset( ptr, byte_xor, byte_len );
566 if(right & 7)
567 do_rop_8(ptr + byte_len, edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
573 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
575 return;
578 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
579 DWORD and, DWORD xor)
581 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
582 int len = params->length, err = params->err_start;
583 int major_inc, minor_inc;
585 if (params->x_major)
587 major_inc = params->x_inc;
588 minor_inc = (dib->stride * params->y_inc) / 4;
590 else
592 major_inc = (dib->stride * params->y_inc) / 4;
593 minor_inc = params->x_inc;
596 while (len--)
598 do_rop_32( ptr, and, xor );
599 if (err + params->bias > 0)
601 ptr += minor_inc;
602 err += params->err_add_1;
604 else err += params->err_add_2;
605 ptr += major_inc;
609 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
610 DWORD and, DWORD xor)
612 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
613 int len = params->length, err = params->err_start;
614 int major_inc, minor_inc;
616 if (params->x_major)
618 major_inc = params->x_inc * 3;
619 minor_inc = dib->stride * params->y_inc;
621 else
623 major_inc = dib->stride * params->y_inc;
624 minor_inc = params->x_inc * 3;
627 while (len--)
629 do_rop_8( ptr, and, xor );
630 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
631 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
632 if (err + params->bias > 0)
634 ptr += minor_inc;
635 err += params->err_add_1;
637 else err += params->err_add_2;
638 ptr += major_inc;
642 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
643 DWORD and, DWORD xor)
645 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
646 int len = params->length, err = params->err_start;
647 int major_inc, minor_inc;
649 if (params->x_major)
651 major_inc = params->x_inc;
652 minor_inc = (dib->stride * params->y_inc) / 2;
654 else
656 major_inc = (dib->stride * params->y_inc) / 2;
657 minor_inc = params->x_inc;
660 while (len--)
662 do_rop_16( ptr, and, xor );
663 if (err + params->bias > 0)
665 ptr += minor_inc;
666 err += params->err_add_1;
668 else err += params->err_add_2;
669 ptr += major_inc;
673 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
674 DWORD and, DWORD xor)
676 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
677 int len = params->length, err = params->err_start;
678 int major_inc, minor_inc;
680 if (params->x_major)
682 major_inc = params->x_inc;
683 minor_inc = dib->stride * params->y_inc;
685 else
687 major_inc = dib->stride * params->y_inc;
688 minor_inc = params->x_inc;
691 while (len--)
693 do_rop_8( ptr, and, xor );
694 if (err + params->bias > 0)
696 ptr += minor_inc;
697 err += params->err_add_1;
699 else err += params->err_add_2;
700 ptr += major_inc;
704 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
705 DWORD and, DWORD xor)
707 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
708 int len = params->length, err = params->err_start;
709 int x = dib->rect.left + start->x;
711 and = (and & 0x0f) | ((and << 4) & 0xf0);
712 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
714 if (params->x_major)
716 while (len--)
718 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
719 if (err + params->bias > 0)
721 ptr += dib->stride * params->y_inc;
722 err += params->err_add_1;
724 else err += params->err_add_2;
725 if ((x / 2) != ((x + params->x_inc) / 2))
726 ptr += params->x_inc;
727 x += params->x_inc;
730 else
732 while (len--)
734 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
735 if (err + params->bias > 0)
737 if ((x / 2) != ((x + params->x_inc) / 2))
738 ptr += params->x_inc;
739 x += params->x_inc;
740 err += params->err_add_1;
742 else err += params->err_add_2;
743 ptr += dib->stride * params->y_inc;
748 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
749 DWORD and, DWORD xor)
751 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
752 int len = params->length, err = params->err_start;
753 int x = dib->rect.left + start->x;
755 and = (and & 0x1) ? 0xff : 0;
756 xor = (xor & 0x1) ? 0xff : 0;
758 if (params->x_major)
760 while (len--)
762 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
763 if (err + params->bias > 0)
765 ptr += dib->stride * params->y_inc;
766 err += params->err_add_1;
768 else err += params->err_add_2;
769 if ((x / 8) != ((x + params->x_inc) / 8))
770 ptr += params->x_inc;
771 x += params->x_inc;
774 else
776 while (len--)
778 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
779 if (err + params->bias > 0)
781 if ((x / 8) != ((x + params->x_inc) / 8))
782 ptr += params->x_inc;
783 x += params->x_inc;
784 err += params->err_add_1;
786 else err += params->err_add_2;
787 ptr += dib->stride * params->y_inc;
792 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
793 DWORD and, DWORD xor)
795 return;
798 static inline INT calc_offset(INT edge, INT size, INT origin)
800 INT offset;
802 if(edge - origin >= 0)
803 offset = (edge - origin) % size;
804 else
806 offset = (origin - edge) % size;
807 if(offset) offset = size - offset;
809 return offset;
812 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
814 POINT offset;
816 offset.x = calc_offset(rc->left, brush->width, origin->x);
817 offset.y = calc_offset(rc->top, brush->height, origin->y);
819 return offset;
822 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
823 const dib_info *brush, const rop_mask_bits *bits)
825 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
826 int x, y, i, len, brush_x;
827 POINT offset;
829 for(i = 0; i < num; i++, rc++)
831 offset = calc_brush_offset(rc, brush, origin);
832 start = get_pixel_ptr_32(dib, rc->left, rc->top);
833 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
835 if (bits->and)
837 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
839 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
841 and_ptr = start_and + offset.x;
842 xor_ptr = start_xor + offset.x;
844 for(x = rc->left, ptr = start; x < rc->right; x++)
846 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
847 if(and_ptr == start_and + brush->width)
849 and_ptr = start_and;
850 xor_ptr = start_xor;
854 offset.y++;
855 if(offset.y == brush->height)
857 start_and = bits->and;
858 start_xor = bits->xor;
859 offset.y = 0;
861 else
863 start_and += brush->stride / 4;
864 start_xor += brush->stride / 4;
868 else
870 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
872 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
874 len = min( rc->right - x, brush->width - brush_x );
875 memcpy( start + x - rc->left, start_xor + brush_x, len * 4 );
876 brush_x = 0;
879 start_xor += brush->stride / 4;
880 offset.y++;
881 if(offset.y == brush->height)
883 start_xor = bits->xor;
884 offset.y = 0;
891 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
892 const dib_info *brush, const rop_mask_bits *bits)
894 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
895 int x, y, i, len, brush_x;
896 POINT offset;
898 for(i = 0; i < num; i++, rc++)
900 offset = calc_brush_offset(rc, brush, origin);
902 start = get_pixel_ptr_24(dib, rc->left, rc->top);
903 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
905 if (bits->and)
907 start_and = (BYTE*)bits->and + offset.y * brush->stride;
908 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
910 and_ptr = start_and + offset.x * 3;
911 xor_ptr = start_xor + offset.x * 3;
913 for(x = rc->left, ptr = start; x < rc->right; x++)
915 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
916 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
917 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
918 if(and_ptr == start_and + brush->width * 3)
920 and_ptr = start_and;
921 xor_ptr = start_xor;
925 offset.y++;
926 if(offset.y == brush->height)
928 start_and = bits->and;
929 start_xor = bits->xor;
930 offset.y = 0;
932 else
934 start_and += brush->stride;
935 start_xor += brush->stride;
939 else
941 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
943 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
945 len = min( rc->right - x, brush->width - brush_x );
946 memcpy( start + (x - rc->left) * 3, start_xor + brush_x * 3, len * 3 );
947 brush_x = 0;
950 start_xor += brush->stride;
951 offset.y++;
952 if(offset.y == brush->height)
954 start_xor = bits->xor;
955 offset.y = 0;
962 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
963 const dib_info *brush, const rop_mask_bits *bits)
965 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
966 int x, y, i, len, brush_x;
967 POINT offset;
969 for(i = 0; i < num; i++, rc++)
971 offset = calc_brush_offset(rc, brush, origin);
973 start = get_pixel_ptr_16(dib, rc->left, rc->top);
974 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
976 if (bits->and)
978 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
979 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
981 and_ptr = start_and + offset.x;
982 xor_ptr = start_xor + offset.x;
984 for(x = rc->left, ptr = start; x < rc->right; x++)
986 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
987 if(and_ptr == start_and + brush->width)
989 and_ptr = start_and;
990 xor_ptr = start_xor;
994 offset.y++;
995 if(offset.y == brush->height)
997 start_and = bits->and;
998 start_xor = bits->xor;
999 offset.y = 0;
1001 else
1003 start_and += brush->stride / 2;
1004 start_xor += brush->stride / 2;
1008 else
1010 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
1012 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1014 len = min( rc->right - x, brush->width - brush_x );
1015 memcpy( start + x - rc->left, start_xor + brush_x, len * 2 );
1016 brush_x = 0;
1019 start_xor += brush->stride / 2;
1020 offset.y++;
1021 if(offset.y == brush->height)
1023 start_xor = bits->xor;
1024 offset.y = 0;
1031 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1032 const dib_info *brush, const rop_mask_bits *bits)
1034 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1035 int x, y, i, len, brush_x;
1036 POINT offset;
1038 for(i = 0; i < num; i++, rc++)
1040 offset = calc_brush_offset(rc, brush, origin);
1042 start = get_pixel_ptr_8(dib, rc->left, rc->top);
1043 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1045 if (bits->and)
1047 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1048 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1050 and_ptr = start_and + offset.x;
1051 xor_ptr = start_xor + offset.x;
1053 for(x = rc->left, ptr = start; x < rc->right; x++)
1055 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1056 if(and_ptr == start_and + brush->width)
1058 and_ptr = start_and;
1059 xor_ptr = start_xor;
1063 offset.y++;
1064 if(offset.y == brush->height)
1066 start_and = bits->and;
1067 start_xor = bits->xor;
1068 offset.y = 0;
1070 else
1072 start_and += brush->stride;
1073 start_xor += brush->stride;
1077 else
1079 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1081 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1083 len = min( rc->right - x, brush->width - brush_x );
1084 memcpy( start + x - rc->left, start_xor + brush_x, len );
1085 brush_x = 0;
1088 start_xor += brush->stride;
1089 offset.y++;
1090 if(offset.y == brush->height)
1092 start_xor = bits->xor;
1093 offset.y = 0;
1100 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1101 const dib_info *brush, const rop_mask_bits *bits)
1103 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1104 int x, y, i, left, right;
1105 POINT offset;
1107 for(i = 0; i < num; i++, rc++)
1109 offset = calc_brush_offset(rc, brush, origin);
1110 left = dib->rect.left + rc->left;
1111 right = dib->rect.left + rc->right;
1113 start = get_pixel_ptr_4(dib, rc->left, rc->top);
1114 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1116 if (bits->and)
1118 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1119 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1121 INT brush_x = offset.x;
1122 BYTE byte_and, byte_xor;
1124 and_ptr = start_and + brush_x / 2;
1125 xor_ptr = start_xor + brush_x / 2;
1127 for(x = left, ptr = start; x < right; x++)
1129 /* FIXME: Two pixels at a time */
1130 if(x & 1) /* lower dst nibble */
1132 if(brush_x & 1) /* lower pat nibble */
1134 byte_and = *and_ptr++ | 0xf0;
1135 byte_xor = *xor_ptr++ & 0x0f;
1137 else /* upper pat nibble */
1139 byte_and = (*and_ptr >> 4) | 0xf0;
1140 byte_xor = (*xor_ptr >> 4) & 0x0f;
1143 else /* upper dst nibble */
1145 if(brush_x & 1) /* lower pat nibble */
1147 byte_and = (*and_ptr++ << 4) | 0x0f;
1148 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1150 else /* upper pat nibble */
1152 byte_and = *and_ptr | 0x0f;
1153 byte_xor = *xor_ptr & 0xf0;
1156 do_rop_8(ptr, byte_and, byte_xor);
1158 if(x & 1) ptr++;
1160 if(++brush_x == brush->width)
1162 brush_x = 0;
1163 and_ptr = start_and;
1164 xor_ptr = start_xor;
1168 offset.y++;
1169 if(offset.y == brush->height)
1171 start_and = bits->and;
1172 start_xor = bits->xor;
1173 offset.y = 0;
1175 else
1177 start_and += brush->stride;
1178 start_xor += brush->stride;
1182 else
1184 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1186 INT brush_x = offset.x;
1187 BYTE byte_xor;
1189 xor_ptr = start_xor + brush_x / 2;
1191 for(x = left, ptr = start; x < right; x++)
1193 /* FIXME: Two pixels at a time */
1194 if(x & 1) /* lower dst nibble */
1196 if(brush_x & 1) /* lower pat nibble */
1197 byte_xor = *xor_ptr++ & 0x0f;
1198 else /* upper pat nibble */
1199 byte_xor = (*xor_ptr >> 4) & 0x0f;
1200 do_rop_8(ptr, 0xf0, byte_xor);
1202 else /* upper dst nibble */
1204 if(brush_x & 1) /* lower pat nibble */
1205 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1206 else /* upper pat nibble */
1207 byte_xor = *xor_ptr & 0xf0;
1208 do_rop_8(ptr, 0x0f, byte_xor);
1211 if(x & 1) ptr++;
1213 if(++brush_x == brush->width)
1215 brush_x = 0;
1216 xor_ptr = start_xor;
1220 start_xor += brush->stride;
1221 offset.y++;
1222 if(offset.y == brush->height)
1224 start_xor = bits->xor;
1225 offset.y = 0;
1232 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1233 const dib_info *brush, const rop_mask_bits *bits)
1235 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1236 int x, y, i, left, right;
1237 POINT offset;
1239 for(i = 0; i < num; i++, rc++)
1241 offset = calc_brush_offset(rc, brush, origin);
1242 left = dib->rect.left + rc->left;
1243 right = dib->rect.left + rc->right;
1245 start = get_pixel_ptr_1(dib, rc->left, rc->top);
1246 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1248 if (bits->and)
1250 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1251 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1253 INT brush_x = offset.x;
1254 BYTE byte_and, byte_xor;
1256 and_ptr = start_and + brush_x / 8;
1257 xor_ptr = start_xor + brush_x / 8;
1259 for(x = left, ptr = start; x < right; x++)
1261 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1262 byte_and |= ~pixel_masks_1[x % 8];
1263 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1264 byte_xor &= pixel_masks_1[x % 8];
1266 do_rop_8(ptr, byte_and, byte_xor);
1268 if((x & 7) == 7) ptr++;
1270 if((brush_x & 7) == 7)
1272 and_ptr++;
1273 xor_ptr++;
1276 if(++brush_x == brush->width)
1278 brush_x = 0;
1279 and_ptr = start_and;
1280 xor_ptr = start_xor;
1284 offset.y++;
1285 if(offset.y == brush->height)
1287 start_and = bits->and;
1288 start_xor = bits->xor;
1289 offset.y = 0;
1291 else
1293 start_and += brush->stride;
1294 start_xor += brush->stride;
1298 else
1300 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1302 INT brush_x = offset.x;
1304 xor_ptr = start_xor + brush_x / 8;
1306 for(x = left, ptr = start; x < right; x++)
1308 BYTE byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1309 byte_xor &= pixel_masks_1[x % 8];
1311 do_rop_8(ptr, ~pixel_masks_1[x % 8], byte_xor);
1313 if((x & 7) == 7) ptr++;
1314 if((brush_x & 7) == 7) xor_ptr++;
1316 if(++brush_x == brush->width)
1318 brush_x = 0;
1319 xor_ptr = start_xor;
1323 start_xor += brush->stride;
1324 offset.y++;
1325 if(offset.y == brush->height)
1327 start_xor = bits->xor;
1328 offset.y = 0;
1335 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1336 const dib_info *brush, const rop_mask_bits *bits)
1338 return;
1341 static inline void copy_rect_bits_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1342 int dst_stride, int src_stride, int rop2 )
1344 const DWORD *src;
1345 DWORD *dst;
1346 int x, y;
1348 #define LOOP( op ) \
1349 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1350 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src++, dst++) \
1353 switch (rop2)
1355 ROPS_WITHOUT_COPY( dst[0], src[0] )
1357 #undef LOOP
1360 static inline void copy_rect_bits_rev_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1361 int dst_stride, int src_stride, int rop2 )
1363 const DWORD *src;
1364 DWORD *dst;
1365 int x, y;
1367 src_start += size->cx - 1;
1368 dst_start += size->cx - 1;
1370 #define LOOP( op ) \
1371 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1372 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src--, dst--) \
1375 switch (rop2)
1377 ROPS_WITHOUT_COPY( dst[0], src[0] )
1379 #undef LOOP
1382 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1383 const dib_info *src, const POINT *origin, int rop2, int overlap)
1385 DWORD *dst_start, *src_start;
1386 int y, dst_stride, src_stride;
1387 SIZE size;
1389 if (overlap & OVERLAP_BELOW)
1391 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1392 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1393 dst_stride = -dst->stride / 4;
1394 src_stride = -src->stride / 4;
1396 else
1398 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1399 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1400 dst_stride = dst->stride / 4;
1401 src_stride = src->stride / 4;
1404 if (rop2 == R2_COPYPEN)
1406 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1407 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1408 return;
1411 size.cx = rc->right - rc->left;
1412 size.cy = rc->bottom - rc->top;
1414 if (overlap & OVERLAP_RIGHT)
1415 copy_rect_bits_rev_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1416 else
1417 copy_rect_bits_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1420 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1421 const dib_info *src, const POINT *origin, int rop2, int overlap)
1423 BYTE *dst_start, *src_start;
1424 int y, dst_stride, src_stride;
1425 struct rop_codes codes;
1427 if (overlap & OVERLAP_BELOW)
1429 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1430 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1431 dst_stride = -dst->stride;
1432 src_stride = -src->stride;
1434 else
1436 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1437 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1438 dst_stride = dst->stride;
1439 src_stride = src->stride;
1442 if (rop2 == R2_COPYPEN)
1444 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1445 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1446 return;
1449 get_rop_codes( rop2, &codes );
1450 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1452 if (overlap & OVERLAP_RIGHT)
1453 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1454 else
1455 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1459 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1460 const dib_info *src, const POINT *origin, int rop2, int overlap)
1462 WORD *dst_start, *src_start;
1463 int y, dst_stride, src_stride;
1464 struct rop_codes codes;
1466 if (overlap & OVERLAP_BELOW)
1468 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1469 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1470 dst_stride = -dst->stride / 2;
1471 src_stride = -src->stride / 2;
1473 else
1475 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1476 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1477 dst_stride = dst->stride / 2;
1478 src_stride = src->stride / 2;
1481 if (rop2 == R2_COPYPEN)
1483 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1484 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1485 return;
1488 get_rop_codes( rop2, &codes );
1489 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1491 if (overlap & OVERLAP_RIGHT)
1492 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1493 else
1494 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1498 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1499 const dib_info *src, const POINT *origin, int rop2, int overlap)
1501 BYTE *dst_start, *src_start;
1502 int y, dst_stride, src_stride;
1503 struct rop_codes codes;
1505 if (overlap & OVERLAP_BELOW)
1507 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1508 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1509 dst_stride = -dst->stride;
1510 src_stride = -src->stride;
1512 else
1514 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1515 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1516 dst_stride = dst->stride;
1517 src_stride = src->stride;
1520 if (rop2 == R2_COPYPEN)
1522 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1523 memmove( dst_start, src_start, (rc->right - rc->left) );
1524 return;
1527 get_rop_codes( rop2, &codes );
1528 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1530 if (overlap & OVERLAP_RIGHT)
1531 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1532 else
1533 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1537 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1538 const dib_info *src, const POINT *origin, int rop2, int overlap)
1540 BYTE *dst_start, *src_start;
1541 int y, dst_stride, src_stride;
1542 struct rop_codes codes;
1543 int left = dst->rect.left + rc->left;
1544 int right = dst->rect.left + rc->right;
1545 int org_x = src->rect.left + origin->x;
1547 if (overlap & OVERLAP_BELOW)
1549 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1550 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1551 dst_stride = -dst->stride;
1552 src_stride = -src->stride;
1554 else
1556 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1557 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1558 dst_stride = dst->stride;
1559 src_stride = src->stride;
1562 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1564 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1565 memmove( dst_start, src_start, (right - left) / 2 );
1566 return;
1569 get_rop_codes( rop2, &codes );
1570 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1572 if (overlap & OVERLAP_RIGHT)
1573 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1574 else
1575 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1579 static inline void copy_rect_bits_partial_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1580 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1582 const BYTE *src;
1583 BYTE *dst, src_val, mask;
1584 int dst_end = dst_x + size->cx, y;
1585 int off = (src_x & 7) - (dst_x & 7);
1586 struct rop_codes codes;
1588 get_rop_codes( rop2, &codes );
1590 src_start += src_x / 8;
1591 dst_start += dst_x / 8;
1593 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1595 dst = dst_start;
1596 src = src_start;
1597 if (off == 0)
1598 src_val = src[0];
1599 else if (off > 0)
1601 src_val = src[0] << off;
1602 if ((dst_end & 7) + off > 8)
1603 src_val |= (src[1] >> (8 - off));
1605 else
1606 src_val = src[0] >> -off;
1608 mask = edge_masks_1[dst_x & 7];
1609 if (dst_end & 7)
1610 mask &= ~edge_masks_1[dst_end & 7];
1611 do_rop_codes_mask_8( dst, src_val, &codes, mask );
1615 static inline void copy_rect_bits_align_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1616 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1618 const BYTE *src;
1619 BYTE *dst, mask;
1620 int y, i, full_bytes, dst_end = dst_x + size->cx;
1621 struct rop_codes codes;
1623 get_rop_codes( rop2, &codes );
1625 src_start += src_x / 8;
1626 dst_start += dst_x / 8;
1627 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1629 switch( rop2 )
1631 case R2_COPYPEN:
1632 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1634 dst = dst_start;
1635 src = src_start;
1636 if (dst_x & 7)
1638 mask = edge_masks_1[dst_x & 7];
1639 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1640 src++;
1641 dst++;
1643 memmove( dst, src, full_bytes );
1644 src += full_bytes;
1645 dst += full_bytes;
1646 if (dst_end & 7)
1648 mask = ~edge_masks_1[dst_end & 7];
1649 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1652 break;
1654 #define LOOP( op ) \
1655 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1657 dst = dst_start; \
1658 src = src_start; \
1659 if (dst_x & 7) \
1661 mask = edge_masks_1[dst_x & 7]; \
1662 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1663 src++; \
1664 dst++; \
1666 for (i = 0; i < full_bytes; i++, src++, dst++) \
1667 op; \
1668 if (dst_end & 7) \
1670 mask = ~edge_masks_1[dst_end & 7]; \
1671 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1675 ROPS_WITHOUT_COPY( dst[0], src[0] );
1677 #undef LOOP
1680 static inline void copy_rect_bits_shl_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1681 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1683 const BYTE *src;
1684 BYTE *dst, mask, src_val;
1685 int y, i, full_bytes, dst_end = dst_x + size->cx;
1686 int off = (src_x & 7) - (dst_x & 7);
1687 struct rop_codes codes;
1689 get_rop_codes( rop2, &codes );
1691 src_start += src_x / 8;
1692 dst_start += dst_x / 8;
1693 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1695 #define LOOP( op ) \
1696 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1698 dst = dst_start; \
1699 src = src_start; \
1700 if (dst_x & 7) \
1702 src_val = (src[0] << off) | (src[1] >> (8 - off)); \
1703 mask = edge_masks_1[dst_x & 7]; \
1704 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1705 src++; \
1706 dst++; \
1708 for (i = 0; i < full_bytes; i++, src++, dst++) \
1709 op; \
1710 if (dst_end & 7) \
1712 src_val = src[0] << off; \
1713 if ((dst_end & 7) + off > 8) \
1714 src_val |= (src[1] >> (8 - off)); \
1715 mask = ~edge_masks_1[dst_end & 7]; \
1716 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1720 switch( rop2 )
1722 ROPS_ALL( dst[0], ((src[0] << off) | (src[1] >> (8 - off))) );
1724 #undef LOOP
1727 static inline void copy_rect_bits_shr_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1728 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1730 const BYTE *src;
1731 BYTE *dst, mask, src_val, last_src;
1732 int y, i, full_bytes, dst_end = dst_x + size->cx;
1733 int off = (src_x & 7) - (dst_x & 7);
1734 struct rop_codes codes;
1736 get_rop_codes( rop2, &codes );
1738 src_start += src_x / 8;
1739 dst_start += dst_x / 8;
1740 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1742 #define LOOP( op ) \
1743 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1745 dst = dst_start; \
1746 src = src_start; \
1747 last_src = 0; \
1748 if (dst_x & 7) \
1750 last_src = src[0]; \
1751 mask = edge_masks_1[dst_x & 7]; \
1752 do_rop_codes_mask_8( dst, src[0] >> -off, &codes, mask ); \
1753 src++; \
1754 dst++; \
1756 for (i = 0; i < full_bytes; i++, src++, dst++) \
1758 src_val = (last_src << (8 + off)) | (src[0] >> -off); \
1759 last_src = src[0]; \
1760 op; \
1762 if (dst_end & 7) \
1764 src_val = last_src << (8 + off); \
1765 if ((dst_end & 7) + off > 0) \
1766 src_val |= (src[0] >> -off); \
1767 mask = ~edge_masks_1[dst_end & 7]; \
1768 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1772 switch( rop2 )
1774 ROPS_ALL( dst[0], src_val )
1776 #undef LOOP
1779 static inline void copy_rect_bits_rev_align_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1780 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1782 const BYTE *src;
1783 BYTE *dst, mask;
1784 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1785 struct rop_codes codes;
1787 get_rop_codes( rop2, &codes );
1789 src_start += (src_end - 1) / 8;
1790 dst_start += (dst_end - 1) / 8;
1791 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1793 switch( rop2 )
1795 case R2_COPYPEN:
1796 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1798 dst = dst_start;
1799 src = src_start;
1800 if (dst_end & 7)
1802 mask = ~edge_masks_1[dst_end & 7];
1803 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1804 src--;
1805 dst--;
1807 memmove( dst, src, full_bytes );
1808 src -= full_bytes;
1809 dst -= full_bytes;
1810 if (dst_x & 7)
1812 mask = edge_masks_1[dst_x & 7];
1813 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1816 break;
1818 #define LOOP( op ) \
1819 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1821 dst = dst_start; \
1822 src = src_start; \
1823 if (dst_end & 7) \
1825 mask = ~edge_masks_1[dst_end & 7]; \
1826 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1827 src--; \
1828 dst--; \
1830 for (i = 0; i < full_bytes; i++, src--, dst--) \
1831 op; \
1832 if (dst_x & 7) \
1834 mask = edge_masks_1[dst_x & 7]; \
1835 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1839 ROPS_WITHOUT_COPY( dst[0], src[0] );
1841 #undef LOOP
1844 static inline void copy_rect_bits_rev_shl_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1845 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1847 const BYTE *src;
1848 BYTE *dst, mask, src_val, last_src;
1849 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1850 int off = ((src_end - 1) & 7) - ((dst_end - 1) & 7);
1851 struct rop_codes codes;
1853 get_rop_codes( rop2, &codes );
1855 src_start += (src_end - 1) / 8;
1856 dst_start += (dst_end - 1) / 8;
1857 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1859 #define LOOP( op ) \
1860 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1862 dst = dst_start; \
1863 src = src_start; \
1864 last_src = 0; \
1865 if (dst_end & 7) \
1867 last_src = src[0]; \
1868 mask = ~edge_masks_1[dst_end & 7]; \
1869 do_rop_codes_mask_8( dst, src[0] << off, &codes, mask ); \
1870 src--; \
1871 dst--; \
1873 for (i = 0; i < full_bytes; i++, src--, dst--) \
1875 src_val = (src[0] << off) | (last_src >> (8 - off)); \
1876 last_src = src[0]; \
1877 op; \
1879 if (dst_x & 7) \
1881 src_val = last_src >> (8 - off); \
1882 if ((dst_x & 7) + off < 8) \
1883 src_val |= (src[0] << off); \
1884 mask = edge_masks_1[dst_x & 7]; \
1885 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1889 switch( rop2 )
1891 ROPS_ALL( dst[0], src_val );
1893 #undef LOOP
1896 static inline void copy_rect_bits_rev_shr_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1897 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1899 const BYTE *src;
1900 BYTE *dst, mask, src_val;
1901 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1902 int off = ((src_end - 1) & 7) - ((dst_end - 1) & 7);
1903 struct rop_codes codes;
1905 get_rop_codes( rop2, &codes );
1907 src_start += (src_end - 1) / 8;
1908 dst_start += (dst_end - 1) / 8;
1909 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1911 #define LOOP( op ) \
1912 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1914 dst = dst_start; \
1915 src = src_start; \
1916 if (dst_end & 7) \
1918 mask = edge_masks_1[dst_x & 7]; \
1919 do_rop_codes_mask_8( dst, (src[-1] << (8 + off)) | (src[0] >> -off), &codes, mask ); \
1920 src--; \
1921 dst--; \
1923 for (i = 0; i < full_bytes; i++, src--, dst--) \
1924 op; \
1925 if (dst_x & 7) \
1927 src_val = src[0] >> -off; \
1928 if ((dst_x & 7) + off < 0) \
1929 src_val |= (src[-1] << (8 + off)); \
1930 mask = edge_masks_1[dst_x & 7]; \
1931 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1935 switch( rop2 )
1937 ROPS_ALL( dst[0], (src[-1] << (8 + off)) | (src[0] >> -off) );
1939 #undef LOOP
1942 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1943 const dib_info *src, const POINT *origin, int rop2, int overlap)
1945 BYTE *dst_start, *src_start;
1946 int y, dst_stride, src_stride;
1947 int left = dst->rect.left + rc->left;
1948 int right = dst->rect.left + rc->right;
1949 int org_x = src->rect.left + origin->x;
1950 SIZE size;
1952 if (overlap & OVERLAP_BELOW)
1954 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1955 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1956 dst_stride = -dst->stride;
1957 src_stride = -src->stride;
1959 else
1961 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1962 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1963 dst_stride = dst->stride;
1964 src_stride = src->stride;
1967 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1969 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1970 memmove( dst_start, src_start, (right - left) / 8 );
1971 return;
1974 size.cx = right - left;
1975 size.cy = rc->bottom - rc->top;
1977 /* Special case starting and finishing in same byte, neither on byte boundary */
1978 if ((left & 7) && (right & 7) && (left & ~7) == (right & ~7))
1979 copy_rect_bits_partial_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1980 else if (overlap & OVERLAP_RIGHT)
1982 int off = ((org_x + right - left - 1) & 7) - ((right - 1) & 7);
1984 if (off == 0)
1985 copy_rect_bits_rev_align_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1986 else if (off > 0)
1987 copy_rect_bits_rev_shl_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1988 else
1989 copy_rect_bits_rev_shr_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1991 else
1993 int off = (org_x & 7) - (left & 7);
1995 if (off == 0)
1996 copy_rect_bits_align_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1997 else if (off > 0)
1998 copy_rect_bits_shl_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1999 else
2000 copy_rect_bits_shr_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
2004 static void copy_rect_null(const dib_info *dst, const RECT *rc,
2005 const dib_info *src, const POINT *origin, int rop2, int overlap)
2007 return;
2010 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
2012 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
2013 return *ptr;
2016 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
2018 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
2019 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
2022 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
2024 WORD *ptr = get_pixel_ptr_16( dib, x, y );
2025 return *ptr;
2028 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
2030 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
2031 return *ptr;
2034 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
2036 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
2038 if ((dib->rect.left + x) & 1)
2039 return *ptr & 0x0f;
2040 else
2041 return (*ptr >> 4) & 0x0f;
2044 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
2046 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
2047 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
2050 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
2052 return 0;
2055 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
2057 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
2060 static const DWORD field_masks[33] =
2062 0x00, /* should never happen */
2063 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
2064 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2065 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2066 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2069 static inline DWORD get_field(DWORD field, int shift, int len)
2071 shift = shift - (8 - len);
2072 if (shift < 0)
2073 field <<= -shift;
2074 else
2075 field >>= shift;
2076 field &= field_masks[len];
2077 field |= field >> len;
2078 return field;
2081 static inline DWORD put_field(DWORD field, int shift, int len)
2083 shift = shift - (8 - len);
2084 field &= field_masks[len];
2085 if (shift < 0)
2086 field >>= -shift;
2087 else
2088 field <<= shift;
2089 return field;
2092 static DWORD rgb_to_pixel_masks(const dib_info *dib, DWORD r, DWORD g, DWORD b)
2094 return put_field(r, dib->red_shift, dib->red_len) |
2095 put_field(g, dib->green_shift, dib->green_len) |
2096 put_field(b, dib->blue_shift, dib->blue_len);
2099 static DWORD rgbquad_to_pixel_masks(const dib_info *dib, RGBQUAD rgb)
2101 return rgb_to_pixel_masks(dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2104 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
2106 return rgb_to_pixel_masks(dib, GetRValue(colour), GetGValue(colour), GetBValue(colour));
2109 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
2111 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
2114 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
2116 const RGBQUAD *color_table = get_dib_color_table( dib );
2117 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
2118 int i, best_index = 0;
2119 DWORD diff, best_diff = 0xffffffff;
2121 for(i = 0; i < size; i++)
2123 const RGBQUAD *cur = color_table + i;
2124 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
2125 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
2126 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
2128 if(diff == 0)
2130 best_index = i;
2131 break;
2134 if(diff < best_diff)
2136 best_diff = diff;
2137 best_index = i;
2140 return best_index;
2143 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y,
2144 DWORD src_pixel, DWORD bg_pixel, BYTE r, BYTE g, BYTE b)
2146 DWORD ret;
2148 if (dib->color_table_size != 1)
2150 if (dither)
2152 if (((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255) r = g = b = 255;
2153 else r = g = b = 0;
2155 ret = rgb_to_pixel_colortable( dib, r, g, b );
2157 else ret = (src_pixel == bg_pixel); /* only match raw pixel value */
2159 return ret ? 0xff : 0;
2162 static DWORD rgbquad_to_pixel_colortable(const dib_info *dib, RGBQUAD rgb)
2164 return rgb_to_pixel_colortable( dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue );
2167 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
2169 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
2172 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
2174 return 0;
2177 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
2179 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
2182 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
2184 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
2185 get_field( pixel, dib->green_shift, dib->green_len ),
2186 get_field( pixel, dib->blue_shift, dib->blue_len ) );
2189 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
2191 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
2192 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
2193 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
2196 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
2198 const RGBQUAD *color_table = get_dib_color_table( dib );
2200 if (!dib->color_table || pixel < dib->color_table_size)
2202 RGBQUAD quad = color_table[pixel];
2203 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
2205 return 0;
2208 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
2210 return 0;
2213 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
2215 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
2217 return d1->red_mask == d2->red_mask &&
2218 d1->green_mask == d2->green_mask &&
2219 d1->blue_mask == d2->blue_mask;
2222 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2224 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2225 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2227 switch(src->bit_count)
2229 case 32:
2231 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2232 if(src->funcs == &funcs_8888)
2234 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2235 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2236 else
2238 for(y = src_rect->top; y < src_rect->bottom; y++)
2240 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2241 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2242 dst_start += dst->stride / 4;
2243 src_start += src->stride / 4;
2247 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2249 for(y = src_rect->top; y < src_rect->bottom; y++)
2251 dst_pixel = dst_start;
2252 src_pixel = src_start;
2253 for(x = src_rect->left; x < src_rect->right; x++)
2255 src_val = *src_pixel++;
2256 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
2257 (((src_val >> src->green_shift) & 0xff) << 8) |
2258 ((src_val >> src->blue_shift) & 0xff);
2260 if(pad_size) memset(dst_pixel, 0, pad_size);
2261 dst_start += dst->stride / 4;
2262 src_start += src->stride / 4;
2265 else
2267 for(y = src_rect->top; y < src_rect->bottom; y++)
2269 dst_pixel = dst_start;
2270 src_pixel = src_start;
2271 for(x = src_rect->left; x < src_rect->right; x++)
2273 src_val = *src_pixel++;
2274 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2275 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2276 get_field( src_val, src->blue_shift, src->blue_len ));
2278 if(pad_size) memset(dst_pixel, 0, pad_size);
2279 dst_start += dst->stride / 4;
2280 src_start += src->stride / 4;
2283 break;
2286 case 24:
2288 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2290 for(y = src_rect->top; y < src_rect->bottom; y++)
2292 dst_pixel = dst_start;
2293 src_pixel = src_start;
2294 for(x = src_rect->left; x < src_rect->right; x++)
2296 RGBQUAD rgb;
2297 rgb.rgbBlue = *src_pixel++;
2298 rgb.rgbGreen = *src_pixel++;
2299 rgb.rgbRed = *src_pixel++;
2301 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
2303 if(pad_size) memset(dst_pixel, 0, pad_size);
2304 dst_start += dst->stride / 4;
2305 src_start += src->stride;
2307 break;
2310 case 16:
2312 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2313 if(src->funcs == &funcs_555)
2315 for(y = src_rect->top; y < src_rect->bottom; y++)
2317 dst_pixel = dst_start;
2318 src_pixel = src_start;
2319 for(x = src_rect->left; x < src_rect->right; x++)
2321 src_val = *src_pixel++;
2322 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
2323 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
2324 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
2326 if(pad_size) memset(dst_pixel, 0, pad_size);
2327 dst_start += dst->stride / 4;
2328 src_start += src->stride / 2;
2331 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2333 for(y = src_rect->top; y < src_rect->bottom; y++)
2335 dst_pixel = dst_start;
2336 src_pixel = src_start;
2337 for(x = src_rect->left; x < src_rect->right; x++)
2339 src_val = *src_pixel++;
2340 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2341 (((src_val >> src->red_shift) << 14) & 0x070000) |
2342 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2343 (((src_val >> src->green_shift) << 6) & 0x000700) |
2344 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2345 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2347 if(pad_size) memset(dst_pixel, 0, pad_size);
2348 dst_start += dst->stride / 4;
2349 src_start += src->stride / 2;
2352 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2354 for(y = src_rect->top; y < src_rect->bottom; y++)
2356 dst_pixel = dst_start;
2357 src_pixel = src_start;
2358 for(x = src_rect->left; x < src_rect->right; x++)
2360 src_val = *src_pixel++;
2361 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2362 (((src_val >> src->red_shift) << 14) & 0x070000) |
2363 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2364 (((src_val >> src->green_shift) << 4) & 0x000300) |
2365 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2366 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2368 if(pad_size) memset(dst_pixel, 0, pad_size);
2369 dst_start += dst->stride / 4;
2370 src_start += src->stride / 2;
2373 else
2375 for(y = src_rect->top; y < src_rect->bottom; y++)
2377 dst_pixel = dst_start;
2378 src_pixel = src_start;
2379 for(x = src_rect->left; x < src_rect->right; x++)
2381 src_val = *src_pixel++;
2382 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2383 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2384 get_field( src_val, src->blue_shift, src->blue_len ));
2386 if(pad_size) memset(dst_pixel, 0, pad_size);
2387 dst_start += dst->stride / 4;
2388 src_start += src->stride / 2;
2391 break;
2394 case 8:
2396 const RGBQUAD *color_table = get_dib_color_table( src );
2397 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2398 DWORD dst_colors[256], i;
2400 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2401 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2402 color_table[i].rgbBlue;
2404 for(y = src_rect->top; y < src_rect->bottom; y++)
2406 dst_pixel = dst_start;
2407 src_pixel = src_start;
2408 for(x = src_rect->left; x < src_rect->right; x++)
2409 *dst_pixel++ = dst_colors[*src_pixel++];
2411 if(pad_size) memset(dst_pixel, 0, pad_size);
2412 dst_start += dst->stride / 4;
2413 src_start += src->stride;
2415 break;
2418 case 4:
2420 const RGBQUAD *color_table = get_dib_color_table( src );
2421 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2422 DWORD dst_colors[16], i;
2424 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2425 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2426 color_table[i].rgbBlue;
2428 for(y = src_rect->top; y < src_rect->bottom; y++)
2430 int pos = (src->rect.left + src_rect->left) & 1;
2431 src_pixel = src_start;
2432 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2434 if (pos & 1)
2435 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2436 else
2437 dst_start[x] = dst_colors[*src_pixel >> 4];
2439 if(pad_size) memset(dst_start + x, 0, pad_size);
2440 dst_start += dst->stride / 4;
2441 src_start += src->stride;
2443 break;
2446 case 1:
2448 const RGBQUAD *color_table = get_dib_color_table( src );
2449 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2450 DWORD dst_colors[2], i;
2452 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2453 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2454 color_table[i].rgbBlue;
2456 for(y = src_rect->top; y < src_rect->bottom; y++)
2458 int pos = (src->rect.left + src_rect->left) & 7;
2459 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2461 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2462 dst_start[x] = dst_colors[src_val];
2464 if(pad_size) memset(dst_start + x, 0, pad_size);
2465 dst_start += dst->stride / 4;
2466 src_start += src->stride;
2468 break;
2473 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2475 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2476 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2478 switch(src->bit_count)
2480 case 32:
2482 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2484 if(src->funcs == &funcs_8888)
2486 for(y = src_rect->top; y < src_rect->bottom; y++)
2488 dst_pixel = dst_start;
2489 src_pixel = src_start;
2490 for(x = src_rect->left; x < src_rect->right; x++)
2492 src_val = *src_pixel++;
2493 *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val);
2495 if(pad_size) memset(dst_pixel, 0, pad_size);
2496 dst_start += dst->stride / 4;
2497 src_start += src->stride / 4;
2500 else if(bit_fields_match(src, dst))
2502 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2503 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2504 else
2506 for(y = src_rect->top; y < src_rect->bottom; y++)
2508 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2509 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2510 dst_start += dst->stride / 4;
2511 src_start += src->stride / 4;
2515 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
2516 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
2518 for(y = src_rect->top; y < src_rect->bottom; y++)
2520 dst_pixel = dst_start;
2521 src_pixel = src_start;
2522 for(x = src_rect->left; x < src_rect->right; x++)
2524 src_val = *src_pixel++;
2525 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
2526 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
2527 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
2529 if(pad_size) memset(dst_pixel, 0, pad_size);
2530 dst_start += dst->stride / 4;
2531 src_start += src->stride / 4;
2534 else
2536 for(y = src_rect->top; y < src_rect->bottom; y++)
2538 dst_pixel = dst_start;
2539 src_pixel = src_start;
2540 for(x = src_rect->left; x < src_rect->right; x++)
2542 src_val = *src_pixel++;
2543 *dst_pixel++ = rgb_to_pixel_masks(dst,
2544 get_field(src_val, src->red_shift, src->red_len),
2545 get_field(src_val, src->green_shift, src->green_len),
2546 get_field(src_val, src->blue_shift, src->blue_len));
2548 if(pad_size) memset(dst_pixel, 0, pad_size);
2549 dst_start += dst->stride / 4;
2550 src_start += src->stride / 4;
2553 break;
2556 case 24:
2558 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2560 for(y = src_rect->top; y < src_rect->bottom; y++)
2562 dst_pixel = dst_start;
2563 src_pixel = src_start;
2564 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2565 *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2566 if(pad_size) memset(dst_pixel, 0, pad_size);
2567 dst_start += dst->stride / 4;
2568 src_start += src->stride;
2570 break;
2573 case 16:
2575 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2576 if(src->funcs == &funcs_555)
2578 for(y = src_rect->top; y < src_rect->bottom; y++)
2580 dst_pixel = dst_start;
2581 src_pixel = src_start;
2582 for(x = src_rect->left; x < src_rect->right; x++)
2584 src_val = *src_pixel++;
2585 *dst_pixel++ = rgb_to_pixel_masks(dst,
2586 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2587 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2588 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
2590 if(pad_size) memset(dst_pixel, 0, pad_size);
2591 dst_start += dst->stride / 4;
2592 src_start += src->stride / 2;
2595 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2597 for(y = src_rect->top; y < src_rect->bottom; y++)
2599 dst_pixel = dst_start;
2600 src_pixel = src_start;
2601 for(x = src_rect->left; x < src_rect->right; x++)
2603 src_val = *src_pixel++;
2604 *dst_pixel++ = rgb_to_pixel_masks(dst,
2605 (((src_val >> src->red_shift) << 3) & 0xf8) |
2606 (((src_val >> src->red_shift) >> 2) & 0x07),
2607 (((src_val >> src->green_shift) << 3) & 0xf8) |
2608 (((src_val >> src->green_shift) >> 2) & 0x07),
2609 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2610 (((src_val >> src->blue_shift) >> 2) & 0x07));
2612 if(pad_size) memset(dst_pixel, 0, pad_size);
2613 dst_start += dst->stride / 4;
2614 src_start += src->stride / 2;
2617 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2619 for(y = src_rect->top; y < src_rect->bottom; y++)
2621 dst_pixel = dst_start;
2622 src_pixel = src_start;
2623 for(x = src_rect->left; x < src_rect->right; x++)
2625 src_val = *src_pixel++;
2626 *dst_pixel++ = rgb_to_pixel_masks(dst,
2627 (((src_val >> src->red_shift) << 3) & 0xf8) |
2628 (((src_val >> src->red_shift) >> 2) & 0x07),
2629 (((src_val >> src->green_shift) << 2) & 0xfc) |
2630 (((src_val >> src->green_shift) >> 4) & 0x03),
2631 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2632 (((src_val >> src->blue_shift) >> 2) & 0x07));
2634 if(pad_size) memset(dst_pixel, 0, pad_size);
2635 dst_start += dst->stride / 4;
2636 src_start += src->stride / 2;
2639 else
2641 for(y = src_rect->top; y < src_rect->bottom; y++)
2643 dst_pixel = dst_start;
2644 src_pixel = src_start;
2645 for(x = src_rect->left; x < src_rect->right; x++)
2647 src_val = *src_pixel++;
2648 *dst_pixel++ = rgb_to_pixel_masks(dst,
2649 get_field(src_val, src->red_shift, src->red_len),
2650 get_field(src_val, src->green_shift, src->green_len),
2651 get_field(src_val, src->blue_shift, src->blue_len));
2653 if(pad_size) memset(dst_pixel, 0, pad_size);
2654 dst_start += dst->stride / 4;
2655 src_start += src->stride / 2;
2658 break;
2661 case 8:
2663 const RGBQUAD *color_table = get_dib_color_table( src );
2664 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2665 DWORD dst_colors[256], i;
2667 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2668 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2670 for(y = src_rect->top; y < src_rect->bottom; y++)
2672 dst_pixel = dst_start;
2673 src_pixel = src_start;
2674 for(x = src_rect->left; x < src_rect->right; x++)
2675 *dst_pixel++ = dst_colors[*src_pixel++];
2677 if(pad_size) memset(dst_pixel, 0, pad_size);
2678 dst_start += dst->stride / 4;
2679 src_start += src->stride;
2681 break;
2684 case 4:
2686 const RGBQUAD *color_table = get_dib_color_table( src );
2687 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2688 DWORD dst_colors[16], i;
2690 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2691 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2693 for(y = src_rect->top; y < src_rect->bottom; y++)
2695 int pos = (src->rect.left + src_rect->left) & 1;
2696 src_pixel = src_start;
2697 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2699 if (pos & 1)
2700 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2701 else
2702 dst_start[x] = dst_colors[*src_pixel >> 4];
2704 if(pad_size) memset(dst_start + x, 0, pad_size);
2705 dst_start += dst->stride / 4;
2706 src_start += src->stride;
2708 break;
2711 case 1:
2713 const RGBQUAD *color_table = get_dib_color_table( src );
2714 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2715 DWORD dst_colors[2], i;
2717 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2718 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2720 for(y = src_rect->top; y < src_rect->bottom; y++)
2722 int pos = (src->rect.left + src_rect->left) & 7;
2723 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2725 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2726 dst_start[x] = dst_colors[src_val];
2728 if(pad_size) memset(dst_start + x, 0, pad_size);
2729 dst_start += dst->stride / 4;
2730 src_start += src->stride;
2732 break;
2737 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2739 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2740 DWORD src_val;
2741 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2743 switch(src->bit_count)
2745 case 32:
2747 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2748 if(src->funcs == &funcs_8888)
2750 for(y = src_rect->top; y < src_rect->bottom; y++)
2752 dst_pixel = dst_start;
2753 src_pixel = src_start;
2754 for(x = src_rect->left; x < src_rect->right; x++)
2756 src_val = *src_pixel++;
2757 *dst_pixel++ = src_val & 0xff;
2758 *dst_pixel++ = (src_val >> 8) & 0xff;
2759 *dst_pixel++ = (src_val >> 16) & 0xff;
2761 if(pad_size) memset(dst_pixel, 0, pad_size);
2762 dst_start += dst->stride;
2763 src_start += src->stride / 4;
2766 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2768 for(y = src_rect->top; y < src_rect->bottom; y++)
2770 dst_pixel = dst_start;
2771 src_pixel = src_start;
2772 for(x = src_rect->left; x < src_rect->right; x++)
2774 src_val = *src_pixel++;
2775 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2776 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2777 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2779 if(pad_size) memset(dst_pixel, 0, pad_size);
2780 dst_start += dst->stride;
2781 src_start += src->stride / 4;
2784 else
2786 for(y = src_rect->top; y < src_rect->bottom; y++)
2788 dst_pixel = dst_start;
2789 src_pixel = src_start;
2790 for(x = src_rect->left; x < src_rect->right; x++)
2792 src_val = *src_pixel++;
2793 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2794 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2795 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2797 if(pad_size) memset(dst_pixel, 0, pad_size);
2798 dst_start += dst->stride;
2799 src_start += src->stride / 4;
2802 break;
2805 case 24:
2807 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2809 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2810 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2811 else
2813 for(y = src_rect->top; y < src_rect->bottom; y++)
2815 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2816 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2817 dst_start += dst->stride;
2818 src_start += src->stride;
2821 break;
2824 case 16:
2826 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2827 if(src->funcs == &funcs_555)
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++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2837 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2838 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2840 if(pad_size) memset(dst_pixel, 0, pad_size);
2841 dst_start += dst->stride;
2842 src_start += src->stride / 2;
2845 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
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++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2855 (((src_val >> src->blue_shift) >> 2) & 0x07);
2856 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2857 (((src_val >> src->green_shift) >> 2) & 0x07);
2858 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2859 (((src_val >> src->red_shift) >> 2) & 0x07);
2861 if(pad_size) memset(dst_pixel, 0, pad_size);
2862 dst_start += dst->stride;
2863 src_start += src->stride / 2;
2866 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2868 for(y = src_rect->top; y < src_rect->bottom; y++)
2870 dst_pixel = dst_start;
2871 src_pixel = src_start;
2872 for(x = src_rect->left; x < src_rect->right; x++)
2874 src_val = *src_pixel++;
2875 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2876 (((src_val >> src->blue_shift) >> 2) & 0x07);
2877 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2878 (((src_val >> src->green_shift) >> 4) & 0x03);
2879 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2880 (((src_val >> src->red_shift) >> 2) & 0x07);
2882 if(pad_size) memset(dst_pixel, 0, pad_size);
2883 dst_start += dst->stride;
2884 src_start += src->stride / 2;
2887 else
2889 for(y = src_rect->top; y < src_rect->bottom; y++)
2891 dst_pixel = dst_start;
2892 src_pixel = src_start;
2893 for(x = src_rect->left; x < src_rect->right; x++)
2895 src_val = *src_pixel++;
2896 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2897 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2898 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2900 if(pad_size) memset(dst_pixel, 0, pad_size);
2901 dst_start += dst->stride;
2902 src_start += src->stride / 2;
2905 break;
2908 case 8:
2910 const RGBQUAD *color_table = get_dib_color_table( src );
2911 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2912 for(y = src_rect->top; y < src_rect->bottom; y++)
2914 dst_pixel = dst_start;
2915 src_pixel = src_start;
2916 for(x = src_rect->left; x < src_rect->right; x++)
2918 RGBQUAD rgb = color_table[*src_pixel++];
2919 *dst_pixel++ = rgb.rgbBlue;
2920 *dst_pixel++ = rgb.rgbGreen;
2921 *dst_pixel++ = rgb.rgbRed;
2923 if(pad_size) memset(dst_pixel, 0, pad_size);
2924 dst_start += dst->stride;
2925 src_start += src->stride;
2927 break;
2930 case 4:
2932 const RGBQUAD *color_table = get_dib_color_table( src );
2933 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2934 for(y = src_rect->top; y < src_rect->bottom; y++)
2936 int pos = (src->rect.left + src_rect->left) & 1;
2937 src_pixel = src_start;
2938 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2940 RGBQUAD rgb;
2941 if (pos & 1)
2942 rgb = color_table[*src_pixel++ & 0xf];
2943 else
2944 rgb = color_table[*src_pixel >> 4];
2945 dst_start[x * 3] = rgb.rgbBlue;
2946 dst_start[x * 3 + 1] = rgb.rgbGreen;
2947 dst_start[x * 3 + 2] = rgb.rgbRed;
2949 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2950 dst_start += dst->stride;
2951 src_start += src->stride;
2953 break;
2956 case 1:
2958 const RGBQUAD *color_table = get_dib_color_table( src );
2959 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2960 for(y = src_rect->top; y < src_rect->bottom; y++)
2962 int pos = (src->rect.left + src_rect->left) & 7;
2963 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2965 RGBQUAD rgb;
2966 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2967 rgb = color_table[src_val];
2968 dst_start[x * 3] = rgb.rgbBlue;
2969 dst_start[x * 3 + 1] = rgb.rgbGreen;
2970 dst_start[x * 3 + 2] = rgb.rgbRed;
2972 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2973 dst_start += dst->stride;
2974 src_start += src->stride;
2976 break;
2981 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2983 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2984 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2985 DWORD src_val;
2987 switch(src->bit_count)
2989 case 32:
2991 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2993 if(src->funcs == &funcs_8888)
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 src_val = *src_pixel++;
3002 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
3003 ((src_val >> 6) & 0x03e0) |
3004 ((src_val >> 3) & 0x001f);
3006 if(pad_size) memset(dst_pixel, 0, pad_size);
3007 dst_start += dst->stride / 2;
3008 src_start += src->stride / 4;
3011 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3013 for(y = src_rect->top; y < src_rect->bottom; y++)
3015 dst_pixel = dst_start;
3016 src_pixel = src_start;
3017 for(x = src_rect->left; x < src_rect->right; x++)
3019 src_val = *src_pixel++;
3020 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
3021 (((src_val >> src->green_shift) << 2) & 0x03e0) |
3022 (((src_val >> src->blue_shift) >> 3) & 0x001f);
3024 if(pad_size) memset(dst_pixel, 0, pad_size);
3025 dst_start += dst->stride / 2;
3026 src_start += src->stride / 4;
3029 else
3031 for(y = src_rect->top; y < src_rect->bottom; y++)
3033 dst_pixel = dst_start;
3034 src_pixel = src_start;
3035 for(x = src_rect->left; x < src_rect->right; x++)
3037 src_val = *src_pixel++;
3038 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
3039 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
3040 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
3042 if(pad_size) memset(dst_pixel, 0, pad_size);
3043 dst_start += dst->stride / 2;
3044 src_start += src->stride / 4;
3047 break;
3050 case 24:
3052 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3054 for(y = src_rect->top; y < src_rect->bottom; y++)
3056 dst_pixel = dst_start;
3057 src_pixel = src_start;
3058 for(x = src_rect->left; x < src_rect->right; x++)
3060 RGBQUAD rgb;
3061 rgb.rgbBlue = *src_pixel++;
3062 rgb.rgbGreen = *src_pixel++;
3063 rgb.rgbRed = *src_pixel++;
3065 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
3066 ((rgb.rgbGreen << 2) & 0x03e0) |
3067 ((rgb.rgbBlue >> 3) & 0x001f);
3069 if(pad_size) memset(dst_pixel, 0, pad_size);
3070 dst_start += dst->stride / 2;
3071 src_start += src->stride;
3073 break;
3076 case 16:
3078 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3079 if(src->funcs == &funcs_555)
3081 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3082 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3083 else
3085 for(y = src_rect->top; y < src_rect->bottom; y++)
3087 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
3088 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3089 dst_start += dst->stride / 2;
3090 src_start += src->stride / 2;
3094 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3096 for(y = src_rect->top; y < src_rect->bottom; y++)
3098 dst_pixel = dst_start;
3099 src_pixel = src_start;
3100 for(x = src_rect->left; x < src_rect->right; x++)
3102 src_val = *src_pixel++;
3103 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
3104 (((src_val >> src->green_shift) << 5) & 0x03e0) |
3105 ( (src_val >> src->blue_shift) & 0x001f);
3107 if(pad_size) memset(dst_pixel, 0, pad_size);
3108 dst_start += dst->stride / 2;
3109 src_start += src->stride / 2;
3112 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3114 for(y = src_rect->top; y < src_rect->bottom; y++)
3116 dst_pixel = dst_start;
3117 src_pixel = src_start;
3118 for(x = src_rect->left; x < src_rect->right; x++)
3120 src_val = *src_pixel++;
3121 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
3122 (((src_val >> src->green_shift) << 4) & 0x03e0) |
3123 ( (src_val >> src->blue_shift) & 0x001f);
3125 if(pad_size) memset(dst_pixel, 0, pad_size);
3126 dst_start += dst->stride / 2;
3127 src_start += src->stride / 2;
3130 else
3132 for(y = src_rect->top; y < src_rect->bottom; y++)
3134 dst_pixel = dst_start;
3135 src_pixel = src_start;
3136 for(x = src_rect->left; x < src_rect->right; x++)
3138 src_val = *src_pixel++;
3139 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
3140 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
3141 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
3143 if(pad_size) memset(dst_pixel, 0, pad_size);
3144 dst_start += dst->stride / 2;
3145 src_start += src->stride / 2;
3148 break;
3151 case 8:
3153 const RGBQUAD *color_table = get_dib_color_table( src );
3154 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3155 WORD dst_colors[256];
3156 int i;
3158 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3159 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3160 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3161 ((color_table[i].rgbBlue >> 3) & 0x001f);
3163 for(y = src_rect->top; y < src_rect->bottom; y++)
3165 dst_pixel = dst_start;
3166 src_pixel = src_start;
3167 for(x = src_rect->left; x < src_rect->right; x++)
3168 *dst_pixel++ = dst_colors[*src_pixel++];
3170 if(pad_size) memset(dst_pixel, 0, pad_size);
3171 dst_start += dst->stride / 2;
3172 src_start += src->stride;
3174 break;
3177 case 4:
3179 const RGBQUAD *color_table = get_dib_color_table( src );
3180 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3181 WORD dst_colors[16];
3182 int i;
3184 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3185 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3186 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3187 ((color_table[i].rgbBlue >> 3) & 0x001f);
3189 for(y = src_rect->top; y < src_rect->bottom; y++)
3191 int pos = (src->rect.left + src_rect->left) & 1;
3192 src_pixel = src_start;
3193 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3195 if (pos & 1)
3196 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3197 else
3198 dst_start[x] = dst_colors[*src_pixel >> 4];
3200 if(pad_size) memset(dst_start + x, 0, pad_size);
3201 dst_start += dst->stride / 2;
3202 src_start += src->stride;
3204 break;
3207 case 1:
3209 const RGBQUAD *color_table = get_dib_color_table( src );
3210 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3211 WORD dst_colors[2];
3212 int i;
3214 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3215 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3216 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3217 ((color_table[i].rgbBlue >> 3) & 0x001f);
3219 for(y = src_rect->top; y < src_rect->bottom; y++)
3221 int pos = (src->rect.left + src_rect->left) & 7;
3222 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3224 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3225 dst_start[x] = dst_colors[src_val];
3227 if(pad_size) memset(dst_start + x, 0, pad_size);
3228 dst_start += dst->stride / 2;
3229 src_start += src->stride;
3231 break;
3236 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3238 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
3239 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
3240 DWORD src_val;
3242 switch(src->bit_count)
3244 case 32:
3246 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3248 if(src->funcs == &funcs_8888)
3250 for(y = src_rect->top; y < src_rect->bottom; y++)
3252 dst_pixel = dst_start;
3253 src_pixel = src_start;
3254 for(x = src_rect->left; x < src_rect->right; x++)
3256 src_val = *src_pixel++;
3257 *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val);
3259 if(pad_size) memset(dst_pixel, 0, pad_size);
3260 dst_start += dst->stride / 2;
3261 src_start += src->stride / 4;
3264 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3266 for(y = src_rect->top; y < src_rect->bottom; y++)
3268 dst_pixel = dst_start;
3269 src_pixel = src_start;
3270 for(x = src_rect->left; x < src_rect->right; x++)
3272 src_val = *src_pixel++;
3273 *dst_pixel++ = rgb_to_pixel_masks(dst,
3274 src_val >> src->red_shift,
3275 src_val >> src->green_shift,
3276 src_val >> src->blue_shift);
3278 if(pad_size) memset(dst_pixel, 0, pad_size);
3279 dst_start += dst->stride / 2;
3280 src_start += src->stride / 4;
3283 else
3285 for(y = src_rect->top; y < src_rect->bottom; y++)
3287 dst_pixel = dst_start;
3288 src_pixel = src_start;
3289 for(x = src_rect->left; x < src_rect->right; x++)
3291 src_val = *src_pixel++;
3292 *dst_pixel++ = rgb_to_pixel_masks(dst,
3293 get_field(src_val, src->red_shift, src->red_len),
3294 get_field(src_val, src->green_shift, src->green_len),
3295 get_field(src_val, src->blue_shift, src->blue_len ));
3297 if(pad_size) memset(dst_pixel, 0, pad_size);
3298 dst_start += dst->stride / 2;
3299 src_start += src->stride / 4;
3302 break;
3305 case 24:
3307 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3309 for(y = src_rect->top; y < src_rect->bottom; y++)
3311 dst_pixel = dst_start;
3312 src_pixel = src_start;
3313 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3314 *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3315 if(pad_size) memset(dst_pixel, 0, pad_size);
3316 dst_start += dst->stride / 2;
3317 src_start += src->stride;
3319 break;
3322 case 16:
3324 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3325 if(src->funcs == &funcs_555)
3327 for(y = src_rect->top; y < src_rect->bottom; y++)
3329 dst_pixel = dst_start;
3330 src_pixel = src_start;
3331 for(x = src_rect->left; x < src_rect->right; x++)
3333 src_val = *src_pixel++;
3334 *dst_pixel++ = rgb_to_pixel_masks(dst,
3335 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3336 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3337 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3339 if(pad_size) memset(dst_pixel, 0, pad_size);
3340 dst_start += dst->stride / 2;
3341 src_start += src->stride / 2;
3344 else if(bit_fields_match(src, dst))
3346 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3347 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3348 else
3350 for(y = src_rect->top; y < src_rect->bottom; y++)
3352 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
3353 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3354 dst_start += dst->stride / 2;
3355 src_start += src->stride / 2;
3359 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3361 for(y = src_rect->top; y < src_rect->bottom; y++)
3363 dst_pixel = dst_start;
3364 src_pixel = src_start;
3365 for(x = src_rect->left; x < src_rect->right; x++)
3367 src_val = *src_pixel++;
3368 *dst_pixel++ = rgb_to_pixel_masks(dst,
3369 (((src_val >> src->red_shift) << 3) & 0xf8) |
3370 (((src_val >> src->red_shift) >> 2) & 0x07),
3371 (((src_val >> src->green_shift) << 3) & 0xf8) |
3372 (((src_val >> src->green_shift) >> 2) & 0x07),
3373 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3374 (((src_val >> src->blue_shift) >> 2) & 0x07));
3376 if(pad_size) memset(dst_pixel, 0, pad_size);
3377 dst_start += dst->stride / 2;
3378 src_start += src->stride / 2;
3381 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3383 for(y = src_rect->top; y < src_rect->bottom; y++)
3385 dst_pixel = dst_start;
3386 src_pixel = src_start;
3387 for(x = src_rect->left; x < src_rect->right; x++)
3389 src_val = *src_pixel++;
3390 *dst_pixel++ = rgb_to_pixel_masks(dst,
3391 (((src_val >> src->red_shift) << 3) & 0xf8) |
3392 (((src_val >> src->red_shift) >> 2) & 0x07),
3393 (((src_val >> src->green_shift) << 2) & 0xfc) |
3394 (((src_val >> src->green_shift) >> 4) & 0x03),
3395 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3396 (((src_val >> src->blue_shift) >> 2) & 0x07));
3398 if(pad_size) memset(dst_pixel, 0, pad_size);
3399 dst_start += dst->stride / 2;
3400 src_start += src->stride / 2;
3403 else
3405 for(y = src_rect->top; y < src_rect->bottom; y++)
3407 dst_pixel = dst_start;
3408 src_pixel = src_start;
3409 for(x = src_rect->left; x < src_rect->right; x++)
3411 src_val = *src_pixel++;
3412 *dst_pixel++ = rgb_to_pixel_masks(dst,
3413 get_field(src_val, src->red_shift, src->red_len),
3414 get_field(src_val, src->green_shift, src->green_len),
3415 get_field(src_val, src->blue_shift, src->blue_len));
3417 if(pad_size) memset(dst_pixel, 0, pad_size);
3418 dst_start += dst->stride / 2;
3419 src_start += src->stride / 2;
3422 break;
3425 case 8:
3427 const RGBQUAD *color_table = get_dib_color_table( src );
3428 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3429 WORD dst_colors[256];
3430 int i;
3432 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3433 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3435 for(y = src_rect->top; y < src_rect->bottom; y++)
3437 dst_pixel = dst_start;
3438 src_pixel = src_start;
3439 for(x = src_rect->left; x < src_rect->right; x++)
3440 *dst_pixel++ = dst_colors[*src_pixel++];
3442 if(pad_size) memset(dst_pixel, 0, pad_size);
3443 dst_start += dst->stride / 2;
3444 src_start += src->stride;
3446 break;
3449 case 4:
3451 const RGBQUAD *color_table = get_dib_color_table( src );
3452 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3453 WORD dst_colors[16];
3454 int i;
3456 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3457 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3459 for(y = src_rect->top; y < src_rect->bottom; y++)
3461 int pos = (src->rect.left + src_rect->left) & 1;
3462 src_pixel = src_start;
3463 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3465 if (pos & 1)
3466 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3467 else
3468 dst_start[x] = dst_colors[*src_pixel >> 4];
3470 if(pad_size) memset(dst_start + x, 0, pad_size);
3471 dst_start += dst->stride / 2;
3472 src_start += src->stride;
3474 break;
3477 case 1:
3479 const RGBQUAD *color_table = get_dib_color_table( src );
3480 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3481 WORD dst_colors[2];
3482 int i;
3484 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3485 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3487 for(y = src_rect->top; y < src_rect->bottom; y++)
3489 int pos = (src->rect.left + src_rect->left) & 7;
3490 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3492 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3493 dst_start[x] = dst_colors[src_val];
3495 if(pad_size) memset(dst_start + x, 0, pad_size);
3496 dst_start += dst->stride / 2;
3497 src_start += src->stride;
3499 break;
3504 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
3506 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
3507 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
3511 * To translate an RGB value into a colour table index Windows uses the 5 msbs of each component.
3512 * We thus create a lookup table with 32^3 entries.
3514 struct rgb_lookup_colortable_ctx
3516 const dib_info *dib;
3517 BYTE map[32 * 32 * 32];
3518 BYTE valid[32 * 32 * 32 / 8];
3521 static void rgb_lookup_colortable_init(const dib_info *dib, struct rgb_lookup_colortable_ctx *ctx)
3523 ctx->dib = dib;
3524 memset(ctx->valid, 0, sizeof(ctx->valid));
3527 static inline BYTE rgb_lookup_colortable(struct rgb_lookup_colortable_ctx *ctx, DWORD r, DWORD g, DWORD b)
3529 DWORD pos = ((r & 0xf8) >> 3) | ((g & 0xf8) << 2) | ((b & 0xf8) << 7);
3531 if (!(ctx->valid[pos / 8] & pixel_masks_1[pos & 7]))
3533 ctx->valid[pos / 8] |= pixel_masks_1[pos & 7];
3534 ctx->map[pos] = rgb_to_pixel_colortable(ctx->dib, (r & 0xf8) | 4, (g & 0xf8) | 4, (b & 0xf8) | 4);
3536 return ctx->map[pos];
3539 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3541 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
3542 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
3543 struct rgb_lookup_colortable_ctx lookup_ctx;
3544 DWORD src_val;
3546 switch(src->bit_count)
3548 case 32:
3550 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3552 rgb_lookup_colortable_init(dst, &lookup_ctx);
3553 if(src->funcs == &funcs_8888)
3555 for(y = src_rect->top; y < src_rect->bottom; y++)
3557 dst_pixel = dst_start;
3558 src_pixel = src_start;
3559 for(x = src_rect->left; x < src_rect->right; x++)
3561 src_val = *src_pixel++;
3562 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx, src_val >> 16, src_val >> 8, src_val );
3564 if(pad_size) memset(dst_pixel, 0, pad_size);
3565 dst_start += dst->stride;
3566 src_start += src->stride / 4;
3569 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3571 for(y = src_rect->top; y < src_rect->bottom; y++)
3573 dst_pixel = dst_start;
3574 src_pixel = src_start;
3575 for(x = src_rect->left; x < src_rect->right; x++)
3577 src_val = *src_pixel++;
3578 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx,
3579 src_val >> src->red_shift,
3580 src_val >> src->green_shift,
3581 src_val >> src->blue_shift );
3583 if(pad_size) memset(dst_pixel, 0, pad_size);
3584 dst_start += dst->stride;
3585 src_start += src->stride / 4;
3588 else
3590 for(y = src_rect->top; y < src_rect->bottom; y++)
3592 dst_pixel = dst_start;
3593 src_pixel = src_start;
3594 for(x = src_rect->left; x < src_rect->right; x++)
3596 src_val = *src_pixel++;
3597 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx,
3598 get_field(src_val, src->red_shift, src->red_len),
3599 get_field(src_val, src->green_shift, src->green_len),
3600 get_field(src_val, src->blue_shift, src->blue_len));
3602 if(pad_size) memset(dst_pixel, 0, pad_size);
3603 dst_start += dst->stride;
3604 src_start += src->stride / 4;
3607 break;
3610 case 24:
3612 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3614 rgb_lookup_colortable_init(dst, &lookup_ctx);
3615 for(y = src_rect->top; y < src_rect->bottom; y++)
3617 dst_pixel = dst_start;
3618 src_pixel = src_start;
3619 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3621 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx, src_pixel[2], src_pixel[1], src_pixel[0] );
3623 if(pad_size) memset(dst_pixel, 0, pad_size);
3624 dst_start += dst->stride;
3625 src_start += src->stride;
3627 break;
3630 case 16:
3632 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3633 rgb_lookup_colortable_init(dst, &lookup_ctx);
3634 if(src->funcs == &funcs_555)
3636 for(y = src_rect->top; y < src_rect->bottom; y++)
3638 dst_pixel = dst_start;
3639 src_pixel = src_start;
3640 for(x = src_rect->left; x < src_rect->right; x++)
3642 src_val = *src_pixel++;
3643 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx,
3644 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3645 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3646 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3648 if(pad_size) memset(dst_pixel, 0, pad_size);
3649 dst_start += dst->stride;
3650 src_start += src->stride / 2;
3653 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3655 for(y = src_rect->top; y < src_rect->bottom; y++)
3657 dst_pixel = dst_start;
3658 src_pixel = src_start;
3659 for(x = src_rect->left; x < src_rect->right; x++)
3661 src_val = *src_pixel++;
3662 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx,
3663 (((src_val >> src->red_shift) << 3) & 0xf8) |
3664 (((src_val >> src->red_shift) >> 2) & 0x07),
3665 (((src_val >> src->green_shift) << 3) & 0xf8) |
3666 (((src_val >> src->green_shift) >> 2) & 0x07),
3667 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3668 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3670 if(pad_size) memset(dst_pixel, 0, pad_size);
3671 dst_start += dst->stride;
3672 src_start += src->stride / 2;
3675 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3677 for(y = src_rect->top; y < src_rect->bottom; y++)
3679 dst_pixel = dst_start;
3680 src_pixel = src_start;
3681 for(x = src_rect->left; x < src_rect->right; x++)
3683 src_val = *src_pixel++;
3684 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx,
3685 (((src_val >> src->red_shift) << 3) & 0xf8) |
3686 (((src_val >> src->red_shift) >> 2) & 0x07),
3687 (((src_val >> src->green_shift) << 2) & 0xfc) |
3688 (((src_val >> src->green_shift) >> 4) & 0x03),
3689 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3690 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3692 if(pad_size) memset(dst_pixel, 0, pad_size);
3693 dst_start += dst->stride;
3694 src_start += src->stride / 2;
3697 else
3699 for(y = src_rect->top; y < src_rect->bottom; y++)
3701 dst_pixel = dst_start;
3702 src_pixel = src_start;
3703 for(x = src_rect->left; x < src_rect->right; x++)
3705 src_val = *src_pixel++;
3706 *dst_pixel++ = rgb_lookup_colortable(&lookup_ctx,
3707 get_field(src_val, src->red_shift, src->red_len),
3708 get_field(src_val, src->green_shift, src->green_len),
3709 get_field(src_val, src->blue_shift, src->blue_len));
3711 if(pad_size) memset(dst_pixel, 0, pad_size);
3712 dst_start += dst->stride;
3713 src_start += src->stride / 2;
3716 break;
3719 case 8:
3721 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3723 if(color_tables_match(dst, src))
3725 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3726 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3727 else
3729 for(y = src_rect->top; y < src_rect->bottom; y++)
3731 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
3732 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3733 dst_start += dst->stride;
3734 src_start += src->stride;
3738 else
3740 const RGBQUAD *color_table = get_dib_color_table( src );
3741 BYTE dst_colors[256];
3742 int i;
3744 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3745 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
3747 for(y = src_rect->top; y < src_rect->bottom; y++)
3749 dst_pixel = dst_start;
3750 src_pixel = src_start;
3751 for(x = src_rect->left; x < src_rect->right; x++)
3752 *dst_pixel++ = dst_colors[*src_pixel++];
3754 if(pad_size) memset(dst_pixel, 0, pad_size);
3755 dst_start += dst->stride;
3756 src_start += src->stride;
3759 break;
3762 case 4:
3764 const RGBQUAD *color_table = get_dib_color_table( src );
3765 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3766 BYTE dst_colors[16];
3767 int i;
3769 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3770 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
3772 for(y = src_rect->top; y < src_rect->bottom; y++)
3774 int pos = (src->rect.left + src_rect->left) & 1;
3775 src_pixel = src_start;
3776 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3778 if (pos & 1)
3779 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3780 else
3781 dst_start[x] = dst_colors[*src_pixel >> 4];
3783 if(pad_size) memset(dst_start + x, 0, pad_size);
3784 dst_start += dst->stride;
3785 src_start += src->stride;
3787 break;
3790 case 1:
3792 const RGBQUAD *color_table = get_dib_color_table( src );
3793 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3794 BYTE dst_colors[2];
3795 int i;
3797 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3798 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
3800 for(y = src_rect->top; y < src_rect->bottom; y++)
3802 int pos = (src->rect.left + src_rect->left) & 7;
3803 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3805 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3806 dst_start[x] = dst_colors[src_val];
3808 if(pad_size) memset(dst_start + x, 0, pad_size);
3809 dst_start += dst->stride;
3810 src_start += src->stride;
3812 break;
3817 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3819 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3820 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3821 DWORD src_val;
3823 switch(src->bit_count)
3825 case 32:
3827 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3829 if(src->funcs == &funcs_8888)
3831 for(y = src_rect->top; y < src_rect->bottom; y++)
3833 dst_pixel = dst_start;
3834 src_pixel = src_start;
3835 for(x = src_rect->left; x < src_rect->right; x++)
3837 src_val = *src_pixel++;
3838 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3839 if((x - src_rect->left) & 1)
3841 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3842 dst_pixel++;
3844 else
3845 *dst_pixel = (dst_val << 4) & 0xf0;
3847 if(pad_size)
3849 if((x - src_rect->left) & 1) dst_pixel++;
3850 memset(dst_pixel, 0, pad_size);
3852 dst_start += dst->stride;
3853 src_start += src->stride / 4;
3856 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3858 for(y = src_rect->top; y < src_rect->bottom; y++)
3860 dst_pixel = dst_start;
3861 src_pixel = src_start;
3862 for(x = src_rect->left; x < src_rect->right; x++)
3864 src_val = *src_pixel++;
3865 dst_val = rgb_to_pixel_colortable(dst,
3866 src_val >> src->red_shift,
3867 src_val >> src->green_shift,
3868 src_val >> src->blue_shift);
3869 if((x - src_rect->left) & 1)
3871 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3872 dst_pixel++;
3874 else
3875 *dst_pixel = (dst_val << 4) & 0xf0;
3877 if(pad_size)
3879 if((x - src_rect->left) & 1) dst_pixel++;
3880 memset(dst_pixel, 0, pad_size);
3882 dst_start += dst->stride;
3883 src_start += src->stride / 4;
3886 else
3888 for(y = src_rect->top; y < src_rect->bottom; y++)
3890 dst_pixel = dst_start;
3891 src_pixel = src_start;
3892 for(x = src_rect->left; x < src_rect->right; x++)
3894 src_val = *src_pixel++;
3895 dst_val = rgb_to_pixel_colortable(dst,
3896 get_field(src_val, src->red_shift, src->red_len),
3897 get_field(src_val, src->green_shift, src->green_len),
3898 get_field(src_val, src->blue_shift, src->blue_len));
3899 if((x - src_rect->left) & 1)
3901 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3902 dst_pixel++;
3904 else
3905 *dst_pixel = (dst_val << 4) & 0xf0;
3907 if(pad_size)
3909 if((x - src_rect->left) & 1) dst_pixel++;
3910 memset(dst_pixel, 0, pad_size);
3912 dst_start += dst->stride;
3913 src_start += src->stride / 4;
3916 break;
3919 case 24:
3921 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3923 for(y = src_rect->top; y < src_rect->bottom; y++)
3925 dst_pixel = dst_start;
3926 src_pixel = src_start;
3927 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3929 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3931 if((x - src_rect->left) & 1)
3933 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3934 dst_pixel++;
3936 else
3937 *dst_pixel = (dst_val << 4) & 0xf0;
3939 if(pad_size)
3941 if((x - src_rect->left) & 1) dst_pixel++;
3942 memset(dst_pixel, 0, pad_size);
3944 dst_start += dst->stride;
3945 src_start += src->stride;
3947 break;
3950 case 16:
3952 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3953 if(src->funcs == &funcs_555)
3955 for(y = src_rect->top; y < src_rect->bottom; y++)
3957 dst_pixel = dst_start;
3958 src_pixel = src_start;
3959 for(x = src_rect->left; x < src_rect->right; x++)
3961 src_val = *src_pixel++;
3962 dst_val = rgb_to_pixel_colortable(dst,
3963 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3964 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3965 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3966 if((x - src_rect->left) & 1)
3968 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3969 dst_pixel++;
3971 else
3972 *dst_pixel = (dst_val << 4) & 0xf0;
3974 if(pad_size)
3976 if((x - src_rect->left) & 1) dst_pixel++;
3977 memset(dst_pixel, 0, pad_size);
3979 dst_start += dst->stride;
3980 src_start += src->stride / 2;
3983 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3985 for(y = src_rect->top; y < src_rect->bottom; y++)
3987 dst_pixel = dst_start;
3988 src_pixel = src_start;
3989 for(x = src_rect->left; x < src_rect->right; x++)
3991 src_val = *src_pixel++;
3992 dst_val = rgb_to_pixel_colortable(dst,
3993 (((src_val >> src->red_shift) << 3) & 0xf8) |
3994 (((src_val >> src->red_shift) >> 2) & 0x07),
3995 (((src_val >> src->green_shift) << 3) & 0xf8) |
3996 (((src_val >> src->green_shift) >> 2) & 0x07),
3997 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3998 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3999 if((x - src_rect->left) & 1)
4001 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4002 dst_pixel++;
4004 else
4005 *dst_pixel = (dst_val << 4) & 0xf0;
4007 if(pad_size)
4009 if((x - src_rect->left) & 1) dst_pixel++;
4010 memset(dst_pixel, 0, pad_size);
4012 dst_start += dst->stride;
4013 src_start += src->stride / 2;
4016 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
4018 for(y = src_rect->top; y < src_rect->bottom; y++)
4020 dst_pixel = dst_start;
4021 src_pixel = src_start;
4022 for(x = src_rect->left; x < src_rect->right; x++)
4024 src_val = *src_pixel++;
4025 dst_val = rgb_to_pixel_colortable(dst,
4026 (((src_val >> src->red_shift) << 3) & 0xf8) |
4027 (((src_val >> src->red_shift) >> 2) & 0x07),
4028 (((src_val >> src->green_shift) << 2) & 0xfc) |
4029 (((src_val >> src->green_shift) >> 4) & 0x03),
4030 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4031 (((src_val >> src->blue_shift) >> 2) & 0x07) );
4032 if((x - src_rect->left) & 1)
4034 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4035 dst_pixel++;
4037 else
4038 *dst_pixel = (dst_val << 4) & 0xf0;
4040 if(pad_size)
4042 if((x - src_rect->left) & 1) dst_pixel++;
4043 memset(dst_pixel, 0, pad_size);
4045 dst_start += dst->stride;
4046 src_start += src->stride / 2;
4049 else
4051 for(y = src_rect->top; y < src_rect->bottom; y++)
4053 dst_pixel = dst_start;
4054 src_pixel = src_start;
4055 for(x = src_rect->left; x < src_rect->right; x++)
4057 src_val = *src_pixel++;
4058 dst_val = rgb_to_pixel_colortable(dst,
4059 get_field(src_val, src->red_shift, src->red_len),
4060 get_field(src_val, src->green_shift, src->green_len),
4061 get_field(src_val, src->blue_shift, src->blue_len));
4062 if((x - src_rect->left) & 1)
4064 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4065 dst_pixel++;
4067 else
4068 *dst_pixel = (dst_val << 4) & 0xf0;
4070 if(pad_size)
4072 if((x - src_rect->left) & 1) dst_pixel++;
4073 memset(dst_pixel, 0, pad_size);
4075 dst_start += dst->stride;
4076 src_start += src->stride / 2;
4079 break;
4082 case 8:
4084 const RGBQUAD *color_table = get_dib_color_table( src );
4085 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4086 BYTE dst_colors[256];
4087 int i;
4089 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
4090 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
4092 for(y = src_rect->top; y < src_rect->bottom; y++)
4094 dst_pixel = dst_start;
4095 src_pixel = src_start;
4096 for(x = src_rect->left; x < src_rect->right; x++)
4098 dst_val = dst_colors[*src_pixel++];
4099 if((x - src_rect->left) & 1)
4101 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4102 dst_pixel++;
4104 else
4105 *dst_pixel = (dst_val << 4) & 0xf0;
4107 if(pad_size)
4109 if((x - src_rect->left) & 1) dst_pixel++;
4110 memset(dst_pixel, 0, pad_size);
4112 dst_start += dst->stride;
4113 src_start += src->stride;
4115 break;
4118 case 4:
4120 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4122 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
4124 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
4125 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
4126 else
4128 for(y = src_rect->top; y < src_rect->bottom; y++)
4130 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
4131 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
4132 dst_start += dst->stride;
4133 src_start += src->stride;
4137 else
4139 const RGBQUAD *color_table = get_dib_color_table( src );
4140 BYTE dst_colors[16];
4141 int i;
4143 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
4144 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
4146 for(y = src_rect->top; y < src_rect->bottom; y++)
4148 int pos = (src->rect.left + src_rect->left) & 1;
4149 dst_pixel = dst_start;
4150 src_pixel = src_start;
4151 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4153 if(pos & 1)
4154 dst_val = dst_colors[*src_pixel++ & 0xf];
4155 else
4156 dst_val = dst_colors[*src_pixel >> 4];
4157 if((x - src_rect->left) & 1)
4159 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4160 dst_pixel++;
4162 else
4163 *dst_pixel = (dst_val << 4) & 0xf0;
4165 if(pad_size)
4167 if((x - src_rect->left) & 1) dst_pixel++;
4168 memset(dst_pixel, 0, pad_size);
4170 dst_start += dst->stride;
4171 src_start += src->stride;
4174 break;
4177 case 1:
4179 const RGBQUAD *color_table = get_dib_color_table( src );
4180 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4181 BYTE dst_colors[2];
4182 int i;
4184 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
4185 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
4187 for(y = src_rect->top; y < src_rect->bottom; y++)
4189 int pos = (src->rect.left + src_rect->left) & 7;
4190 dst_pixel = dst_start;
4191 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4193 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4194 dst_val = dst_colors[src_val];
4195 if((x - src_rect->left) & 1)
4197 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4198 dst_pixel++;
4200 else
4201 *dst_pixel = (dst_val << 4) & 0xf0;
4203 if(pad_size)
4205 if((x - src_rect->left) & 1) dst_pixel++;
4206 memset(dst_pixel, 0, pad_size);
4208 dst_start += dst->stride;
4209 src_start += src->stride;
4211 break;
4216 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4218 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
4219 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
4220 RGBQUAD rgb, bg_entry = *get_dib_color_table( dst ); /* entry 0 is the background color */
4221 DWORD src_val;
4222 int bit_pos;
4224 switch(src->bit_count)
4226 case 32:
4228 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
4229 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
4231 if(src->funcs == &funcs_8888)
4233 for(y = src_rect->top; y < src_rect->bottom; y++)
4235 dst_pixel = dst_start;
4236 src_pixel = src_start;
4237 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4239 src_val = *src_pixel++;
4240 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4241 src_val >> 16, src_val >> 8, src_val);
4242 if(bit_pos == 0) *dst_pixel = 0;
4243 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4245 if(++bit_pos == 8)
4247 dst_pixel++;
4248 bit_pos = 0;
4251 if(pad_size)
4253 if(bit_pos != 0) dst_pixel++;
4254 memset(dst_pixel, 0, pad_size);
4256 dst_start += dst->stride;
4257 src_start += src->stride / 4;
4260 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
4262 for(y = src_rect->top; y < src_rect->bottom; y++)
4264 dst_pixel = dst_start;
4265 src_pixel = src_start;
4266 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4268 src_val = *src_pixel++;
4269 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4270 src_val >> src->red_shift,
4271 src_val >> src->green_shift,
4272 src_val >> src->blue_shift);
4274 if(bit_pos == 0) *dst_pixel = 0;
4275 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4277 if(++bit_pos == 8)
4279 dst_pixel++;
4280 bit_pos = 0;
4283 if(pad_size)
4285 if(bit_pos != 0) dst_pixel++;
4286 memset(dst_pixel, 0, pad_size);
4288 dst_start += dst->stride;
4289 src_start += src->stride / 4;
4292 else
4294 for(y = src_rect->top; y < src_rect->bottom; y++)
4296 dst_pixel = dst_start;
4297 src_pixel = src_start;
4298 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4300 src_val = *src_pixel++;
4301 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4302 get_field(src_val, src->red_shift, src->red_len),
4303 get_field(src_val, src->green_shift, src->green_len),
4304 get_field(src_val, src->blue_shift, src->blue_len));
4306 if(bit_pos == 0) *dst_pixel = 0;
4307 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4309 if(++bit_pos == 8)
4311 dst_pixel++;
4312 bit_pos = 0;
4315 if(pad_size)
4317 if(bit_pos != 0) dst_pixel++;
4318 memset(dst_pixel, 0, pad_size);
4320 dst_start += dst->stride;
4321 src_start += src->stride / 4;
4324 break;
4327 case 24:
4329 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
4330 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, RGB(bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue));
4332 for(y = src_rect->top; y < src_rect->bottom; y++)
4334 dst_pixel = dst_start;
4335 src_pixel = src_start;
4336 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
4338 dst_val = rgb_to_pixel_mono(dst, dither, x, y, RGB(src_pixel[2], src_pixel[1], src_pixel[0]),
4339 bg_pixel, src_pixel[2], src_pixel[1], src_pixel[0]);
4341 if(bit_pos == 0) *dst_pixel = 0;
4342 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4344 if(++bit_pos == 8)
4346 dst_pixel++;
4347 bit_pos = 0;
4350 if(pad_size)
4352 if(bit_pos != 0) dst_pixel++;
4353 memset(dst_pixel, 0, pad_size);
4355 dst_start += dst->stride;
4356 src_start += src->stride;
4358 break;
4361 case 16:
4363 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
4364 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
4366 if(src->funcs == &funcs_555)
4368 for(y = src_rect->top; y < src_rect->bottom; y++)
4370 dst_pixel = dst_start;
4371 src_pixel = src_start;
4372 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4374 src_val = *src_pixel++;
4375 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4376 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
4377 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
4378 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
4380 if(bit_pos == 0) *dst_pixel = 0;
4381 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4383 if(++bit_pos == 8)
4385 dst_pixel++;
4386 bit_pos = 0;
4389 if(pad_size)
4391 if(bit_pos != 0) dst_pixel++;
4392 memset(dst_pixel, 0, pad_size);
4394 dst_start += dst->stride;
4395 src_start += src->stride / 2;
4398 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
4400 for(y = src_rect->top; y < src_rect->bottom; y++)
4402 dst_pixel = dst_start;
4403 src_pixel = src_start;
4404 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4406 src_val = *src_pixel++;
4407 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4408 (((src_val >> src->red_shift) << 3) & 0xf8) |
4409 (((src_val >> src->red_shift) >> 2) & 0x07),
4410 (((src_val >> src->green_shift) << 3) & 0xf8) |
4411 (((src_val >> src->green_shift) >> 2) & 0x07),
4412 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4413 (((src_val >> src->blue_shift) >> 2) & 0x07));
4414 if(bit_pos == 0) *dst_pixel = 0;
4415 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4417 if(++bit_pos == 8)
4419 dst_pixel++;
4420 bit_pos = 0;
4423 if(pad_size)
4425 if(bit_pos != 0) dst_pixel++;
4426 memset(dst_pixel, 0, pad_size);
4428 dst_start += dst->stride;
4429 src_start += src->stride / 2;
4432 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
4434 for(y = src_rect->top; y < src_rect->bottom; y++)
4436 dst_pixel = dst_start;
4437 src_pixel = src_start;
4438 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4440 src_val = *src_pixel++;
4441 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4442 (((src_val >> src->red_shift) << 3) & 0xf8) |
4443 (((src_val >> src->red_shift) >> 2) & 0x07),
4444 (((src_val >> src->green_shift) << 2) & 0xfc) |
4445 (((src_val >> src->green_shift) >> 4) & 0x03),
4446 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4447 (((src_val >> src->blue_shift) >> 2) & 0x07));
4448 if(bit_pos == 0) *dst_pixel = 0;
4449 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4451 if(++bit_pos == 8)
4453 dst_pixel++;
4454 bit_pos = 0;
4457 if(pad_size)
4459 if(bit_pos != 0) dst_pixel++;
4460 memset(dst_pixel, 0, pad_size);
4462 dst_start += dst->stride;
4463 src_start += src->stride / 2;
4466 else
4468 for(y = src_rect->top; y < src_rect->bottom; y++)
4470 dst_pixel = dst_start;
4471 src_pixel = src_start;
4472 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4474 src_val = *src_pixel++;
4475 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4476 get_field(src_val, src->red_shift, src->red_len),
4477 get_field(src_val, src->green_shift, src->green_len),
4478 get_field(src_val, src->blue_shift, src->blue_len));
4479 if(bit_pos == 0) *dst_pixel = 0;
4480 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4482 if(++bit_pos == 8)
4484 dst_pixel++;
4485 bit_pos = 0;
4488 if(pad_size)
4490 if(bit_pos != 0) dst_pixel++;
4491 memset(dst_pixel, 0, pad_size);
4493 dst_start += dst->stride;
4494 src_start += src->stride / 2;
4497 break;
4500 case 8:
4502 const RGBQUAD *color_table = get_dib_color_table( src );
4503 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4504 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4506 for(y = src_rect->top; y < src_rect->bottom; y++)
4508 dst_pixel = dst_start;
4509 src_pixel = src_start;
4510 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4512 BYTE src_val = *src_pixel++;
4513 rgb = color_table[src_val];
4514 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4515 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4517 if(bit_pos == 0) *dst_pixel = 0;
4518 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4520 if(++bit_pos == 8)
4522 dst_pixel++;
4523 bit_pos = 0;
4526 if(pad_size)
4528 if(bit_pos != 0) dst_pixel++;
4529 memset(dst_pixel, 0, pad_size);
4531 dst_start += dst->stride;
4532 src_start += src->stride;
4534 break;
4537 case 4:
4539 const RGBQUAD *color_table = get_dib_color_table( src );
4540 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4541 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4543 for(y = src_rect->top; y < src_rect->bottom; y++)
4545 int pos = (src->rect.left + src_rect->left) & 1;
4546 dst_pixel = dst_start;
4547 src_pixel = src_start;
4548 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4550 src_val = (pos & 1) ? *src_pixel++ & 0xf : *src_pixel >> 4;
4551 rgb = color_table[src_val];
4552 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4553 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4555 if(bit_pos == 0) *dst_pixel = 0;
4556 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4558 if(++bit_pos == 8)
4560 dst_pixel++;
4561 bit_pos = 0;
4564 if(pad_size)
4566 if(bit_pos != 0) dst_pixel++;
4567 memset(dst_pixel, 0, pad_size);
4569 dst_start += dst->stride;
4570 src_start += src->stride;
4572 break;
4575 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
4576 uses text/bkgnd colours instead of the dib's colour table, this
4577 doesn't appear to be the case for a dc backed by a
4578 dibsection. */
4580 case 1:
4582 const RGBQUAD *color_table = get_dib_color_table( src );
4583 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4584 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4586 for(y = src_rect->top; y < src_rect->bottom; y++)
4588 int pos = (src->rect.left + src_rect->left) & 7;
4589 dst_pixel = dst_start;
4590 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4592 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4593 rgb = color_table[src_val];
4594 dst_val = FILTER_DIBINDEX(rgb, rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4595 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
4596 if(bit_pos == 0) *dst_pixel = 0;
4597 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4599 if(++bit_pos == 8)
4601 dst_pixel++;
4602 bit_pos = 0;
4605 if(pad_size)
4607 if(bit_pos != 0) dst_pixel++;
4608 memset(dst_pixel, 0, pad_size);
4610 dst_start += dst->stride;
4611 src_start += src->stride;
4613 break;
4618 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4622 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
4624 return (src * alpha + dst * (255 - alpha) + 127) / 255;
4627 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
4629 return (blend_color( dst, src, alpha ) |
4630 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4631 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4632 blend_color( dst >> 24, src >> 24, alpha ) << 24);
4635 static inline DWORD blend_argb_no_src_alpha( DWORD dst, DWORD src, DWORD alpha )
4637 return (blend_color( dst, src, alpha ) |
4638 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4639 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4640 blend_color( dst >> 24, 255, alpha ) << 24);
4643 static inline DWORD blend_argb( DWORD dst, DWORD src )
4645 BYTE b = (BYTE)src;
4646 BYTE g = (BYTE)(src >> 8);
4647 BYTE r = (BYTE)(src >> 16);
4648 DWORD alpha = (BYTE)(src >> 24);
4649 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4650 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4651 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4652 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4655 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
4657 BYTE b = ((BYTE)src * alpha + 127) / 255;
4658 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4659 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4660 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4661 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4662 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4663 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4664 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4667 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
4669 if (blend.AlphaFormat & AC_SRC_ALPHA)
4671 DWORD alpha = blend.SourceConstantAlpha;
4672 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
4673 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4674 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4675 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4676 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
4677 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
4678 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
4680 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
4681 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
4682 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
4685 static void blend_rects_8888(const dib_info *dst, int num, const RECT *rc,
4686 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4688 int i, x, y;
4690 for (i = 0; i < num; i++, rc++)
4692 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4693 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4695 if (blend.AlphaFormat & AC_SRC_ALPHA)
4697 if (blend.SourceConstantAlpha == 255)
4698 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4699 for (x = 0; x < rc->right - rc->left; x++)
4700 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
4701 else
4702 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4703 for (x = 0; x < rc->right - rc->left; x++)
4704 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4706 else if (src->compression == BI_RGB)
4707 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4708 for (x = 0; x < rc->right - rc->left; x++)
4709 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4710 else
4711 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4712 for (x = 0; x < rc->right - rc->left; x++)
4713 dst_ptr[x] = blend_argb_no_src_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4717 static void blend_rects_32(const dib_info *dst, int num, const RECT *rc,
4718 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4720 int i, x, y;
4722 for (i = 0; i < num; i++, rc++)
4724 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4725 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4727 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
4729 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4731 for (x = 0; x < rc->right - rc->left; x++)
4733 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
4734 dst_ptr[x] >> dst->green_shift,
4735 dst_ptr[x] >> dst->blue_shift,
4736 src_ptr[x], blend );
4737 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
4738 (((val >> 8) & 0xff) << dst->green_shift) |
4739 (((val >> 16) & 0xff) << dst->red_shift));
4743 else
4745 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4747 for (x = 0; x < rc->right - rc->left; x++)
4749 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4750 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4751 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4752 src_ptr[x], blend );
4753 dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val );
4760 static void blend_rects_24(const dib_info *dst, int num, const RECT *rc,
4761 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4763 int i, x, y;
4765 for (i = 0; i < num; i++, rc++)
4767 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4768 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
4770 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4772 for (x = 0; x < rc->right - rc->left; x++)
4774 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4775 src_ptr[x], blend );
4776 dst_ptr[x * 3] = val;
4777 dst_ptr[x * 3 + 1] = val >> 8;
4778 dst_ptr[x * 3 + 2] = val >> 16;
4784 static void blend_rects_555(const dib_info *dst, int num, const RECT *rc,
4785 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4787 int i, x, y;
4789 for (i = 0; i < num; i++, rc++)
4791 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4792 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4794 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4796 for (x = 0; x < rc->right - rc->left; x++)
4798 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4799 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4800 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4801 src_ptr[x], blend );
4802 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4808 static void blend_rects_16(const dib_info *dst, int num, const RECT *rc,
4809 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4811 int i, x, y;
4813 for (i = 0; i < num; i++, rc++)
4815 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4816 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4818 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4820 for (x = 0; x < rc->right - rc->left; x++)
4822 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4823 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4824 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4825 src_ptr[x], blend );
4826 dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val );
4832 static void blend_rects_8(const dib_info *dst, int num, const RECT *rc,
4833 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4835 const RGBQUAD *color_table = get_dib_color_table( dst );
4836 struct rgb_lookup_colortable_ctx lookup_ctx;
4837 int i, x, y;
4839 rgb_lookup_colortable_init( dst, &lookup_ctx );
4840 for (i = 0; i < num; i++, rc++)
4842 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4843 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4845 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4847 for (x = 0; x < rc->right - rc->left; x++)
4849 RGBQUAD rgb = color_table[dst_ptr[x]];
4850 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4851 dst_ptr[x] = rgb_lookup_colortable( &lookup_ctx, val >> 16, val >> 8, val );
4857 static void blend_rects_4(const dib_info *dst, int num, const RECT *rc,
4858 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4860 const RGBQUAD *color_table = get_dib_color_table( dst );
4861 struct rgb_lookup_colortable_ctx lookup_ctx;
4862 int i, j, x, y;
4864 rgb_lookup_colortable_init( dst, &lookup_ctx );
4865 for (i = 0; i < num; i++, rc++)
4867 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4868 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4870 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4872 for (j = 0, x = (dst->rect.left + rc->left) & 1; j < rc->right - rc->left; j++, x++)
4874 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4875 RGBQUAD rgb = color_table[val];
4876 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[j], blend );
4877 val = rgb_lookup_colortable( &lookup_ctx, val >> 16, val >> 8, val );
4878 if (x & 1)
4879 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4880 else
4881 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4887 static void blend_rects_1(const dib_info *dst, int num, const RECT *rc,
4888 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4890 const RGBQUAD *color_table = get_dib_color_table( dst );
4891 int i, j, x, y;
4893 for (i = 0; i < num; i++, rc++)
4895 DWORD *src_ptr = get_pixel_ptr_32( src, rc->left + offset->x, rc->top + offset->y );
4896 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4898 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4900 for (j = 0, x = (dst->rect.left + rc->left) & 7; j < rc->right - rc->left; j++, x++)
4902 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4903 RGBQUAD rgb = color_table[val];
4904 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[j], blend );
4905 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4906 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4912 static void blend_rects_null(const dib_info *dst, int num, const RECT *rc,
4913 const dib_info *src, const POINT *offset, BLENDFUNCTION blend)
4917 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4919 BYTE r, g, b, a;
4920 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4921 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4922 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4923 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4924 return a << 24 | r << 16 | g << 8 | b;
4927 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4929 BYTE r, g, b;
4930 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4931 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4932 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4933 return r << 16 | g << 8 | b;
4936 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4937 unsigned int x, unsigned int y )
4939 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4940 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4941 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4942 r = min( 31, max( 0, r / 16 ));
4943 g = min( 31, max( 0, g / 16 ));
4944 b = min( 31, max( 0, b / 16 ));
4945 return (r << 10) | (g << 5) | b;
4948 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4949 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4951 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4952 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4953 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4954 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4957 /* compute the left/right triangle limit for row y */
4958 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4960 int x1, x2;
4962 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4963 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4965 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4967 *left = max( rc->left, min( x1, x2 ) );
4968 *right = min( rc->right, max( x1, x2 ) );
4971 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4972 static inline int triangle_det( const TRIVERTEX *v )
4974 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);
4977 /* compute the barycentric weights for a given point inside the triangle */
4978 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4980 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4981 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4984 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4986 INT64 l1, l2;
4987 BYTE r, g, b, a;
4989 triangle_weights( v, x, y, &l1, &l2 );
4990 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4991 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4992 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4993 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4994 return a << 24 | r << 16 | g << 8 | b;
4997 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4999 INT64 l1, l2;
5000 BYTE r, g, b;
5002 triangle_weights( v, x, y, &l1, &l2 );
5003 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
5004 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
5005 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
5006 return r << 16 | g << 8 | b;
5009 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
5011 INT64 l1, l2;
5012 int r, g, b;
5014 triangle_weights( v, x, y, &l1, &l2 );
5015 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
5016 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
5017 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
5018 r = min( 31, max( 0, r / 16 ));
5019 g = min( 31, max( 0, g / 16 ));
5020 b = min( 31, max( 0, b / 16 ));
5021 return (r << 10) | (g << 5) | b;
5024 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
5026 INT64 l1, l2;
5027 BYTE r, g, b;
5029 triangle_weights( v, x, y, &l1, &l2 );
5030 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
5031 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
5032 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
5033 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
5036 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5038 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
5039 int x, y, left, right, det;
5041 switch (mode)
5043 case GRADIENT_FILL_RECT_H:
5044 for (x = 0; x < rc->right - rc->left; x++)
5045 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5047 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
5048 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
5049 break;
5051 case GRADIENT_FILL_RECT_V:
5052 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5054 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
5055 memset_32( ptr, val, rc->right - rc->left );
5057 break;
5059 case GRADIENT_FILL_TRIANGLE:
5060 if (!(det = triangle_det( v ))) return FALSE;
5061 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5063 triangle_coords( v, rc, y, &left, &right );
5064 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
5066 break;
5068 return TRUE;
5071 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5073 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
5074 int x, y, left, right, det;
5076 switch (mode)
5078 case GRADIENT_FILL_RECT_H:
5079 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5081 for (x = 0; x < rc->right - rc->left; x++)
5083 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5084 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
5085 (((val >> 8) & 0xff) << dib->green_shift) |
5086 (((val >> 16) & 0xff) << dib->red_shift));
5089 else
5091 for (x = 0; x < rc->right - rc->left; x++)
5093 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5094 ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5098 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
5099 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
5100 break;
5102 case GRADIENT_FILL_RECT_V:
5103 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5105 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
5106 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5107 val = ((( val & 0xff) << dib->blue_shift) |
5108 (((val >> 8) & 0xff) << dib->green_shift) |
5109 (((val >> 16) & 0xff) << dib->red_shift));
5110 else
5111 val = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5113 memset_32( ptr, val, rc->right - rc->left );
5115 break;
5117 case GRADIENT_FILL_TRIANGLE:
5118 if (!(det = triangle_det( v ))) return FALSE;
5119 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5121 triangle_coords( v, rc, y, &left, &right );
5123 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5124 for (x = left; x < right; x++)
5126 DWORD val = gradient_triangle_24( v, x, y, det );
5127 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
5128 (((val >> 8) & 0xff) << dib->green_shift) |
5129 (((val >> 16) & 0xff) << dib->red_shift));
5131 else
5132 for (x = left; x < right; x++)
5134 DWORD val = gradient_triangle_24( v, x, y, det );
5135 ptr[x - rc->left] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5138 break;
5140 return TRUE;
5143 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5145 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
5146 int x, y, left, right, det;
5148 switch (mode)
5150 case GRADIENT_FILL_RECT_H:
5151 for (x = 0; x < rc->right - rc->left; x++)
5153 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5154 ptr[x * 3] = val;
5155 ptr[x * 3 + 1] = val >> 8;
5156 ptr[x * 3 + 2] = val >> 16;
5159 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
5160 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
5161 break;
5163 case GRADIENT_FILL_RECT_V:
5164 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5166 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
5167 for (x = 0; x < rc->right - rc->left; x++)
5169 ptr[x * 3] = val;
5170 ptr[x * 3 + 1] = val >> 8;
5171 ptr[x * 3 + 2] = val >> 16;
5174 break;
5176 case GRADIENT_FILL_TRIANGLE:
5177 if (!(det = triangle_det( v ))) return FALSE;
5178 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5180 triangle_coords( v, rc, y, &left, &right );
5181 for (x = left; x < right; x++)
5183 DWORD val = gradient_triangle_24( v, x, y, det );
5184 ptr[(x - rc->left) * 3] = val;
5185 ptr[(x - rc->left) * 3 + 1] = val >> 8;
5186 ptr[(x - rc->left) * 3 + 2] = val >> 16;
5189 break;
5191 return TRUE;
5194 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5196 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5197 int x, y, left, right, det;
5199 switch (mode)
5201 case GRADIENT_FILL_RECT_H:
5202 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5203 for (x = rc->left; x < rc->right; x++)
5204 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5205 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5206 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5207 break;
5209 case GRADIENT_FILL_RECT_V:
5210 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5212 WORD values[4];
5213 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5214 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5216 break;
5218 case GRADIENT_FILL_TRIANGLE:
5219 if (!(det = triangle_det( v ))) return FALSE;
5220 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5222 triangle_coords( v, rc, y, &left, &right );
5223 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
5225 break;
5227 return TRUE;
5230 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5232 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5233 int x, y, left, right, det;
5235 switch (mode)
5237 case GRADIENT_FILL_RECT_H:
5238 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5239 for (x = rc->left; x < rc->right; x++)
5241 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5242 ptr[x - rc->left] = rgb_to_pixel_masks( dib,
5243 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5244 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5245 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5247 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5248 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5249 break;
5251 case GRADIENT_FILL_RECT_V:
5252 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5254 WORD values[4];
5255 for (x = 0; x < 4; x++)
5257 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5258 values[x] = rgb_to_pixel_masks( dib,
5259 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5260 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5261 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5263 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5265 break;
5267 case GRADIENT_FILL_TRIANGLE:
5268 if (!(det = triangle_det( v ))) return FALSE;
5269 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5271 triangle_coords( v, rc, y, &left, &right );
5272 for (x = left; x < right; x++)
5274 WORD val = gradient_triangle_555( v, x, y, det );
5275 ptr[x - rc->left] = rgb_to_pixel_masks( dib,
5276 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5277 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5278 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5281 break;
5283 return TRUE;
5286 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5288 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
5289 int x, y, left, right, det;
5291 switch (mode)
5293 case GRADIENT_FILL_RECT_H:
5294 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5295 for (x = rc->left; x < rc->right; x++)
5296 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5297 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5298 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
5299 break;
5301 case GRADIENT_FILL_RECT_V:
5302 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5304 BYTE values[16];
5305 for (x = 0; x < 16; x++)
5306 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5307 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
5309 break;
5311 case GRADIENT_FILL_TRIANGLE:
5312 if (!(det = triangle_det( v ))) return FALSE;
5313 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5315 triangle_coords( v, rc, y, &left, &right );
5316 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
5318 break;
5320 return TRUE;
5323 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5325 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
5326 int x, y, left, right, det, pos;
5328 switch (mode)
5330 case GRADIENT_FILL_RECT_H:
5331 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5333 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5335 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5336 if (pos & 1)
5337 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5338 else
5339 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5342 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5344 x = rc->left;
5345 pos = (dib->rect.left + rc->left) & 1;
5346 if (pos)
5348 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
5349 pos++;
5350 x++;
5352 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
5353 if (x < rc->right)
5354 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
5356 break;
5358 case GRADIENT_FILL_RECT_V:
5359 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5361 BYTE values[16];
5362 for (x = 0; x < 16; x++)
5363 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5364 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5365 if (pos & 1)
5366 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
5367 else
5368 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
5370 break;
5372 case GRADIENT_FILL_TRIANGLE:
5373 if (!(det = triangle_det( v ))) return FALSE;
5374 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5376 triangle_coords( v, rc, y, &left, &right );
5377 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
5379 BYTE val = gradient_triangle_8( dib, v, x, y, det );
5380 if (pos & 1)
5381 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5382 else
5383 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5386 break;
5388 return TRUE;
5391 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5393 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
5394 int x, y, left, right, det, pos;
5396 switch (mode)
5398 case GRADIENT_FILL_RECT_H:
5399 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5401 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5403 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
5404 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5407 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5408 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5409 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5410 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
5411 break;
5413 case GRADIENT_FILL_RECT_V:
5414 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5416 BYTE values[16];
5417 for (x = 0; x < 16; x++)
5418 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
5419 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5420 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5421 (values[x % 16] & pixel_masks_1[pos % 8]);
5423 break;
5425 case GRADIENT_FILL_TRIANGLE:
5426 if (!(det = triangle_det( v ))) return FALSE;
5427 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5429 triangle_coords( v, rc, y, &left, &right );
5430 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
5432 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
5433 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5436 break;
5438 return TRUE;
5441 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5443 return TRUE;
5446 static void mask_rect_32( const dib_info *dst, const RECT *rc,
5447 const dib_info *src, const POINT *origin, int rop2 )
5449 DWORD *dst_start = get_pixel_ptr_32(dst, rc->left, rc->top), dst_colors[256];
5450 DWORD src_val, bit_val, i, full, pos;
5451 int x, y, origin_end = origin->x + rc->right - rc->left;
5452 const RGBQUAD *color_table = get_dib_color_table( src );
5453 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5455 if (dst->funcs == &funcs_8888)
5456 for (i = 0; i < 2; i++)
5457 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
5458 color_table[i].rgbBlue;
5459 else
5460 for (i = 0; i < 2; i++)
5461 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
5463 /* Creating a BYTE-sized table so we don't need to mask the lsb of bit_val */
5464 for (i = 2; i < ARRAY_SIZE(dst_colors); i++)
5465 dst_colors[i] = dst_colors[i & 1];
5467 /* Special case starting and finishing in same byte, neither on byte boundary */
5468 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5470 struct rop_codes codes;
5472 get_rop_codes( rop2, &codes );
5474 for (y = rc->top; y < rc->bottom; y++)
5476 pos = origin->x & 7;
5477 for (x = 0; x < rc->right - rc->left; x++, pos++)
5479 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5480 do_rop_codes_32( dst_start + x, dst_colors[bit_val], &codes );
5482 dst_start += dst->stride / 4;
5483 src_start += src->stride;
5485 return;
5488 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5490 #define LOOP( op ) \
5491 for (y = rc->top; y < rc->bottom; y++) \
5493 pos = origin->x & 7; \
5494 src_val = src_start[pos / 8]; \
5495 x = 0; \
5496 switch (pos & 7) \
5498 case 1: bit_val = src_val >> 6; op; x++; \
5499 /* fall through */ \
5500 case 2: bit_val = src_val >> 5; op; x++; \
5501 /* fall through */ \
5502 case 3: bit_val = src_val >> 4; op; x++; \
5503 /* fall through */ \
5504 case 4: bit_val = src_val >> 3; op; x++; \
5505 /* fall through */ \
5506 case 5: bit_val = src_val >> 2; op; x++; \
5507 /* fall through */ \
5508 case 6: bit_val = src_val >> 1; op; x++; \
5509 /* fall through */ \
5510 case 7: bit_val = src_val; op; x++; \
5511 pos = (pos + 7) & ~7; \
5513 for (i = 0; i < full; i++, pos += 8) \
5515 src_val = src_start[pos / 8]; \
5516 bit_val = src_val >> 7; op; x++; \
5517 bit_val = src_val >> 6; op; x++; \
5518 bit_val = src_val >> 5; op; x++; \
5519 bit_val = src_val >> 4; op; x++; \
5520 bit_val = src_val >> 3; op; x++; \
5521 bit_val = src_val >> 2; op; x++; \
5522 bit_val = src_val >> 1; op; x++; \
5523 bit_val = src_val; op; x++; \
5525 if (origin_end & 7) \
5527 src_val = src_start[pos / 8]; \
5528 x += (origin_end & 7) - 1; \
5529 switch (origin_end & 7) \
5531 case 7: bit_val = src_val >> 1; op; x--; \
5532 /* fall through */ \
5533 case 6: bit_val = src_val >> 2; op; x--; \
5534 /* fall through */ \
5535 case 5: bit_val = src_val >> 3; op; x--; \
5536 /* fall through */ \
5537 case 4: bit_val = src_val >> 4; op; x--; \
5538 /* fall through */ \
5539 case 3: bit_val = src_val >> 5; op; x--; \
5540 /* fall through */ \
5541 case 2: bit_val = src_val >> 6; op; x--; \
5542 /* fall through */ \
5543 case 1: bit_val = src_val >> 7; op; \
5546 dst_start += dst->stride / 4; \
5547 src_start += src->stride; \
5550 switch (rop2)
5552 ROPS_ALL( dst_start[x], dst_colors[bit_val] )
5554 #undef LOOP
5557 static void mask_rect_24( const dib_info *dst, const RECT *rc,
5558 const dib_info *src, const POINT *origin, int rop2 )
5560 BYTE *dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
5561 DWORD src_val, bit_val, i, full, pos;
5562 struct rop_codes codes;
5563 int x, y, origin_end = origin->x + rc->right - rc->left;
5564 const RGBQUAD *color_table = get_dib_color_table( src );
5565 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5566 RGBQUAD rgb;
5568 get_rop_codes( rop2, &codes );
5570 /* Special case starting and finishing in same byte, neither on byte boundary */
5571 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5573 for (y = rc->top; y < rc->bottom; y++)
5575 pos = origin->x & 7;
5576 for (x = 0; x < rc->right - rc->left; x++, pos++)
5578 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5579 rgb = color_table[bit_val];
5580 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5581 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5582 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5584 dst_start += dst->stride;
5585 src_start += src->stride;
5587 return;
5590 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5592 for (y = rc->top; y < rc->bottom; y++)
5594 pos = origin->x & 7;
5595 src_val = src_start[pos / 8];
5596 x = 0;
5598 switch (pos & 7)
5600 case 1:
5601 bit_val = (src_val >> 6) & 1;
5602 rgb = color_table[bit_val];
5603 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5604 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5605 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5606 x++;
5607 /* fall through */
5608 case 2:
5609 bit_val = (src_val >> 5) & 1;
5610 rgb = color_table[bit_val];
5611 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5612 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5613 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5614 x++;
5615 /* fall through */
5616 case 3:
5617 bit_val = (src_val >> 4) & 1;
5618 rgb = color_table[bit_val];
5619 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5620 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5621 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5622 x++;
5623 /* fall through */
5624 case 4:
5625 bit_val = (src_val >> 3) & 1;
5626 rgb = color_table[bit_val];
5627 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5628 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5629 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5630 x++;
5631 /* fall through */
5632 case 5:
5633 bit_val = (src_val >> 2) & 1;
5634 rgb = color_table[bit_val];
5635 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5636 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5637 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5638 x++;
5639 /* fall through */
5640 case 6:
5641 bit_val = (src_val >> 1) & 1;
5642 rgb = color_table[bit_val];
5643 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5644 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5645 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5646 x++;
5647 /* fall through */
5648 case 7:
5649 bit_val = src_val & 1;
5650 rgb = color_table[bit_val];
5651 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5652 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5653 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5654 x++;
5655 pos = (pos + 7) & ~7;
5658 for (i = 0; i < full; i++, pos += 8)
5660 src_val = src_start[pos / 8];
5662 bit_val = (src_val >> 7) & 1;
5663 rgb = color_table[bit_val];
5664 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5665 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5666 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5667 x++;
5669 bit_val = (src_val >> 6) & 1;
5670 rgb = color_table[bit_val];
5671 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5672 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5673 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5674 x++;
5676 bit_val = (src_val >> 5) & 1;
5677 rgb = color_table[bit_val];
5678 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5679 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5680 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5681 x++;
5683 bit_val = (src_val >> 4) & 1;
5684 rgb = color_table[bit_val];
5685 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5686 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5687 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5688 x++;
5690 bit_val = (src_val >> 3) & 1;
5691 rgb = color_table[bit_val];
5692 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5693 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5694 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5695 x++;
5697 bit_val = (src_val >> 2) & 1;
5698 rgb = color_table[bit_val];
5699 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5700 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5701 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5702 x++;
5704 bit_val = (src_val >> 1) & 1;
5705 rgb = color_table[bit_val];
5706 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5707 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5708 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5709 x++;
5711 bit_val = src_val & 1;
5712 rgb = color_table[bit_val];
5713 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5714 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5715 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5716 x++;
5719 if (origin_end & 7)
5721 src_val = src_start[pos / 8];
5722 x += (origin_end & 7) - 1;
5724 switch (origin_end & 7)
5726 case 7:
5727 bit_val = (src_val >> 1) & 1;
5728 rgb = color_table[bit_val];
5729 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5730 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5731 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5732 x--;
5733 /* fall through */
5734 case 6:
5735 bit_val = (src_val >> 2) & 1;
5736 rgb = color_table[bit_val];
5737 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5738 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5739 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5740 x--;
5741 /* fall through */
5742 case 5:
5743 bit_val = (src_val >> 3) & 1;
5744 rgb = color_table[bit_val];
5745 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5746 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5747 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5748 x--;
5749 /* fall through */
5750 case 4:
5751 bit_val = (src_val >> 4) & 1;
5752 rgb = color_table[bit_val];
5753 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5754 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5755 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5756 x--;
5757 /* fall through */
5758 case 3:
5759 bit_val = (src_val >> 5) & 1;
5760 rgb = color_table[bit_val];
5761 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5762 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5763 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5764 x--;
5765 /* fall through */
5766 case 2:
5767 bit_val = (src_val >> 6) & 1;
5768 rgb = color_table[bit_val];
5769 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5770 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5771 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5772 x--;
5773 /* fall through */
5774 case 1:
5775 bit_val = (src_val >> 7) & 1;
5776 rgb = color_table[bit_val];
5777 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5778 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5779 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5783 dst_start += dst->stride;
5784 src_start += src->stride;
5788 static void mask_rect_16( const dib_info *dst, const RECT *rc,
5789 const dib_info *src, const POINT *origin, int rop2 )
5791 WORD *dst_start = get_pixel_ptr_16(dst, rc->left, rc->top), dst_colors[2];
5792 DWORD src_val, bit_val, i, full, pos;
5793 struct rop_codes codes;
5794 int x, y, origin_end = origin->x + rc->right - rc->left;
5795 const RGBQUAD *color_table = get_dib_color_table( src );
5796 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5798 get_rop_codes( rop2, &codes );
5800 if (dst->funcs == &funcs_555)
5801 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
5802 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
5803 ((color_table[i].rgbGreen << 2) & 0x03e0) |
5804 ((color_table[i].rgbBlue >> 3) & 0x001f);
5805 else
5806 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
5807 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
5809 /* Special case starting and finishing in same byte, neither on byte boundary */
5810 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5812 for (y = rc->top; y < rc->bottom; y++)
5814 pos = origin->x & 7;
5815 for (x = 0; x < rc->right - rc->left; x++, pos++)
5817 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5818 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5820 dst_start += dst->stride / 2;
5821 src_start += src->stride;
5823 return;
5826 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5828 for (y = rc->top; y < rc->bottom; y++)
5830 pos = origin->x & 7;
5831 src_val = src_start[pos / 8];
5832 x = 0;
5834 switch (pos & 7)
5836 case 1:
5837 bit_val = (src_val >> 6) & 1;
5838 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5839 /* fall through */
5840 case 2:
5841 bit_val = (src_val >> 5) & 1;
5842 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5843 /* fall through */
5844 case 3:
5845 bit_val = (src_val >> 4) & 1;
5846 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5847 /* fall through */
5848 case 4:
5849 bit_val = (src_val >> 3) & 1;
5850 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5851 /* fall through */
5852 case 5:
5853 bit_val = (src_val >> 2) & 1;
5854 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5855 /* fall through */
5856 case 6:
5857 bit_val = (src_val >> 1) & 1;
5858 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5859 /* fall through */
5860 case 7:
5861 bit_val = src_val & 1;
5862 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5863 pos = (pos + 7) & ~7;
5866 for (i = 0; i < full; i++, pos += 8)
5868 src_val = src_start[pos / 8];
5870 bit_val = (src_val >> 7) & 1;
5871 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5872 bit_val = (src_val >> 6) & 1;
5873 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5874 bit_val = (src_val >> 5) & 1;
5875 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5876 bit_val = (src_val >> 4) & 1;
5877 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5878 bit_val = (src_val >> 3) & 1;
5879 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5880 bit_val = (src_val >> 2) & 1;
5881 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5882 bit_val = (src_val >> 1) & 1;
5883 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5884 bit_val = src_val & 1;
5885 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5888 if (origin_end & 7)
5890 src_val = src_start[pos / 8];
5891 x += (origin_end & 7) - 1;
5893 switch (origin_end & 7)
5895 case 7:
5896 bit_val = (src_val >> 1) & 1;
5897 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5898 /* fall through */
5899 case 6:
5900 bit_val = (src_val >> 2) & 1;
5901 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5902 /* fall through */
5903 case 5:
5904 bit_val = (src_val >> 3) & 1;
5905 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5906 /* fall through */
5907 case 4:
5908 bit_val = (src_val >> 4) & 1;
5909 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5910 /* fall through */
5911 case 3:
5912 bit_val = (src_val >> 5) & 1;
5913 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5914 /* fall through */
5915 case 2:
5916 bit_val = (src_val >> 6) & 1;
5917 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5918 /* fall through */
5919 case 1:
5920 bit_val = (src_val >> 7) & 1;
5921 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5925 dst_start += dst->stride / 2;
5926 src_start += src->stride;
5930 static void mask_rect_8( const dib_info *dst, const RECT *rc,
5931 const dib_info *src, const POINT *origin, int rop2 )
5933 BYTE *dst_start = get_pixel_ptr_8(dst, rc->left, rc->top), dst_colors[2];
5934 DWORD src_val, bit_val, i, full, pos;
5935 struct rop_codes codes;
5936 int x, y, origin_end = origin->x + rc->right - rc->left;
5937 const RGBQUAD *color_table = get_dib_color_table( src );
5938 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5940 get_rop_codes( rop2, &codes );
5942 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
5943 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
5945 /* Special case starting and finishing in same byte, neither on byte boundary */
5946 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5948 for (y = rc->top; y < rc->bottom; y++)
5950 pos = origin->x & 7;
5951 for (x = 0; x < rc->right - rc->left; x++, pos++)
5953 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5954 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
5956 dst_start += dst->stride;
5957 src_start += src->stride;
5959 return;
5962 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5964 for (y = rc->top; y < rc->bottom; y++)
5966 pos = origin->x & 7;
5967 src_val = src_start[pos / 8];
5968 x = 0;
5970 switch (pos & 7)
5972 case 1:
5973 bit_val = (src_val >> 6) & 1;
5974 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5975 /* fall through */
5976 case 2:
5977 bit_val = (src_val >> 5) & 1;
5978 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5979 /* fall through */
5980 case 3:
5981 bit_val = (src_val >> 4) & 1;
5982 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5983 /* fall through */
5984 case 4:
5985 bit_val = (src_val >> 3) & 1;
5986 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5987 /* fall through */
5988 case 5:
5989 bit_val = (src_val >> 2) & 1;
5990 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5991 /* fall through */
5992 case 6:
5993 bit_val = (src_val >> 1) & 1;
5994 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5995 /* fall through */
5996 case 7:
5997 bit_val = src_val & 1;
5998 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5999 pos = (pos + 7) & ~7;
6002 for (i = 0; i < full; i++, pos += 8)
6004 src_val = src_start[pos / 8];
6006 bit_val = (src_val >> 7) & 1;
6007 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6008 bit_val = (src_val >> 6) & 1;
6009 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6010 bit_val = (src_val >> 5) & 1;
6011 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6012 bit_val = (src_val >> 4) & 1;
6013 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6014 bit_val = (src_val >> 3) & 1;
6015 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6016 bit_val = (src_val >> 2) & 1;
6017 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6018 bit_val = (src_val >> 1) & 1;
6019 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6020 bit_val = src_val & 1;
6021 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
6024 if (origin_end & 7)
6026 src_val = src_start[pos / 8];
6027 x += (origin_end & 7) - 1;
6029 switch (origin_end & 7)
6031 case 7:
6032 bit_val = (src_val >> 1) & 1;
6033 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
6034 /* fall through */
6035 case 6:
6036 bit_val = (src_val >> 2) & 1;
6037 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
6038 /* fall through */
6039 case 5:
6040 bit_val = (src_val >> 3) & 1;
6041 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
6042 /* fall through */
6043 case 4:
6044 bit_val = (src_val >> 4) & 1;
6045 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
6046 /* fall through */
6047 case 3:
6048 bit_val = (src_val >> 5) & 1;
6049 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
6050 /* fall through */
6051 case 2:
6052 bit_val = (src_val >> 6) & 1;
6053 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
6054 /* fall through */
6055 case 1:
6056 bit_val = (src_val >> 7) & 1;
6057 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
6061 dst_start += dst->stride;
6062 src_start += src->stride;
6066 static void mask_rect_4( const dib_info *dst, const RECT *rc,
6067 const dib_info *src, const POINT *origin, int rop2 )
6069 BYTE *dst_start = get_pixel_ptr_4(dst, rc->left, rc->top), dst_colors[2], *dst_ptr;
6070 DWORD bit_val, i, pos;
6071 struct rop_codes codes;
6072 int x, y;
6073 int left = dst->rect.left + rc->left;
6074 int right = dst->rect.left + rc->right;
6075 const RGBQUAD *color_table = get_dib_color_table( src );
6076 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
6078 get_rop_codes( rop2, &codes );
6080 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
6082 dst_colors[i] = FILTER_DIBINDEX(color_table[i],rgbquad_to_pixel_colortable(dst, color_table[i]));
6083 /* Set high nibble to match so we don't need to shift it later. */
6084 dst_colors[i] |= dst_colors[i] << 4;
6087 for (y = rc->top; y < rc->bottom; y++)
6089 pos = origin->x & 7;
6091 for (x = left, dst_ptr = dst_start; x < right; x++, pos++)
6093 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
6094 if (x & 1)
6095 do_rop_codes_mask_8( dst_ptr++, dst_colors[bit_val], &codes, 0x0f );
6096 else
6097 do_rop_codes_mask_8( dst_ptr, dst_colors[bit_val], &codes, 0xf0 );
6099 dst_start += dst->stride;
6100 src_start += src->stride;
6104 static void mask_rect_null( const dib_info *dst, const RECT *rc,
6105 const dib_info *src, const POINT *origin, int rop2 )
6109 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
6111 if (dst == text) return dst;
6113 if (dst > text)
6115 DWORD diff = dst - text;
6116 DWORD range = max_comp - text;
6117 dst = text + (diff * range ) / (0xff - text);
6118 return dst;
6120 else
6122 DWORD diff = text - dst;
6123 DWORD range = text - min_comp;
6124 dst = text - (diff * range) / text;
6125 return dst;
6129 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
6131 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
6132 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
6133 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
6136 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6137 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6139 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6140 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6141 int x, y;
6143 for (y = rect->top; y < rect->bottom; y++)
6145 for (x = 0; x < rect->right - rect->left; x++)
6147 if (glyph_ptr[x] <= 1) continue;
6148 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6149 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
6151 dst_ptr += dib->stride / 4;
6152 glyph_ptr += glyph->stride;
6156 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6157 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6159 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6160 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6161 int x, y;
6162 DWORD text, val;
6164 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6165 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6166 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6168 for (y = rect->top; y < rect->bottom; y++)
6170 for (x = 0; x < rect->right - rect->left; x++)
6172 if (glyph_ptr[x] <= 1) continue;
6173 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6174 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6175 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6176 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6177 text, ranges + glyph_ptr[x] );
6178 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6180 dst_ptr += dib->stride / 4;
6181 glyph_ptr += glyph->stride;
6185 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6186 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6188 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6189 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6190 int x, y;
6191 DWORD val;
6193 for (y = rect->top; y < rect->bottom; y++)
6195 for (x = 0; x < rect->right - rect->left; x++)
6197 if (glyph_ptr[x] <= 1) continue;
6198 if (glyph_ptr[x] >= 16)
6199 val = text_pixel;
6200 else
6201 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6202 text_pixel, ranges + glyph_ptr[x] );
6203 dst_ptr[x * 3] = val;
6204 dst_ptr[x * 3 + 1] = val >> 8;
6205 dst_ptr[x * 3 + 2] = val >> 16;
6207 dst_ptr += dib->stride;
6208 glyph_ptr += glyph->stride;
6212 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6213 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6215 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6216 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6217 int x, y;
6218 DWORD text, val;
6220 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6221 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6222 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6224 for (y = rect->top; y < rect->bottom; y++)
6226 for (x = 0; x < rect->right - rect->left; x++)
6228 if (glyph_ptr[x] <= 1) continue;
6229 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6230 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6231 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6232 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6233 text, ranges + glyph_ptr[x] );
6234 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6236 dst_ptr += dib->stride / 2;
6237 glyph_ptr += glyph->stride;
6241 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6242 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6244 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6245 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6246 int x, y;
6247 DWORD text, val;
6249 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6250 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6251 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6253 for (y = rect->top; y < rect->bottom; y++)
6255 for (x = 0; x < rect->right - rect->left; x++)
6257 if (glyph_ptr[x] <= 1) continue;
6258 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6259 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6260 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6261 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6262 text, ranges + glyph_ptr[x] );
6263 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6265 dst_ptr += dib->stride / 2;
6266 glyph_ptr += glyph->stride;
6270 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6271 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6273 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
6274 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6275 int x, y;
6277 for (y = rect->top; y < rect->bottom; y++)
6279 for (x = 0; x < rect->right - rect->left; x++)
6281 /* no antialiasing, glyph should only contain 0 or 16. */
6282 if (glyph_ptr[x] >= 16)
6283 dst_ptr[x] = text_pixel;
6285 dst_ptr += dib->stride;
6286 glyph_ptr += glyph->stride;
6290 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6291 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6293 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
6294 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6295 int x, y, pos;
6297 for (y = rect->top; y < rect->bottom; y++)
6299 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
6301 /* no antialiasing, glyph should only contain 0 or 16. */
6302 if (glyph_ptr[x] >= 16)
6304 if (pos & 1)
6305 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
6306 else
6307 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
6310 dst_ptr += dib->stride;
6311 glyph_ptr += glyph->stride;
6315 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6316 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6318 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
6319 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6320 int x, y, pos;
6321 BYTE text = (text_pixel & 1) ? 0xff : 0;
6323 for (y = rect->top; y < rect->bottom; y++)
6325 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
6327 /* no antialiasing, glyph should only contain 0 or 16. */
6328 if (glyph_ptr[x] >= 16)
6329 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
6330 (text & pixel_masks_1[pos % 8]);
6332 dst_ptr += dib->stride;
6333 glyph_ptr += glyph->stride;
6337 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6338 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6340 return;
6342 static inline BYTE blend_color_gamma( BYTE dst, BYTE text, BYTE alpha,
6343 const struct font_gamma_ramp *gamma_ramp )
6345 if (alpha == 0) return dst;
6346 if (alpha == 255) return text;
6347 if (dst == text) return dst;
6349 return gamma_ramp->encode[ blend_color( gamma_ramp->decode[dst],
6350 gamma_ramp->decode[text],
6351 alpha ) ];
6354 static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha,
6355 const struct font_gamma_ramp *gamma_ramp )
6357 if (gamma_ramp != NULL && gamma_ramp->gamma != 1000)
6359 return blend_color_gamma( r, text >> 16, (BYTE)(alpha >> 16), gamma_ramp ) << 16 |
6360 blend_color_gamma( g, text >> 8, (BYTE)(alpha >> 8), gamma_ramp ) << 8 |
6361 blend_color_gamma( b, text, (BYTE) alpha, gamma_ramp );
6363 return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 |
6364 blend_color( g, text >> 8, (BYTE)(alpha >> 8) ) << 8 |
6365 blend_color( b, text, (BYTE) alpha );
6368 static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6369 const POINT *origin, DWORD text_pixel,
6370 const struct font_gamma_ramp *gamma_ramp )
6372 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6373 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6374 int x, y;
6376 for (y = rect->top; y < rect->bottom; y++)
6378 for (x = 0; x < rect->right - rect->left; x++)
6380 if (glyph_ptr[x] == 0) continue;
6381 dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x],
6382 text_pixel, glyph_ptr[x], gamma_ramp );
6384 dst_ptr += dib->stride / 4;
6385 glyph_ptr += glyph->stride / 4;
6389 static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6390 const POINT *origin, DWORD text_pixel,
6391 const struct font_gamma_ramp *gamma_ramp )
6393 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6394 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6395 int x, y;
6396 DWORD text, val;
6398 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6399 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6400 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6402 for (y = rect->top; y < rect->bottom; y++)
6404 for (x = 0; x < rect->right - rect->left; x++)
6406 if (glyph_ptr[x] == 0) continue;
6407 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6408 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6409 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6410 text, glyph_ptr[x], gamma_ramp );
6411 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6413 dst_ptr += dib->stride / 4;
6414 glyph_ptr += glyph->stride / 4;
6418 static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6419 const POINT *origin, DWORD text_pixel,
6420 const struct font_gamma_ramp *gamma_ramp )
6422 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6423 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6424 int x, y;
6425 DWORD val;
6427 for (y = rect->top; y < rect->bottom; y++)
6429 for (x = 0; x < rect->right - rect->left; x++)
6431 if (glyph_ptr[x] == 0) continue;
6432 val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6433 text_pixel, glyph_ptr[x], gamma_ramp );
6434 dst_ptr[x * 3] = val;
6435 dst_ptr[x * 3 + 1] = val >> 8;
6436 dst_ptr[x * 3 + 2] = val >> 16;
6438 dst_ptr += dib->stride;
6439 glyph_ptr += glyph->stride / 4;
6443 static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6444 const POINT *origin, DWORD text_pixel,
6445 const struct font_gamma_ramp *gamma_ramp )
6447 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6448 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6449 int x, y;
6450 DWORD text, val;
6452 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6453 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6454 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6456 for (y = rect->top; y < rect->bottom; y++)
6458 for (x = 0; x < rect->right - rect->left; x++)
6460 if (glyph_ptr[x] == 0) continue;
6461 val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6462 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6463 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6464 text, glyph_ptr[x], NULL );
6465 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6467 dst_ptr += dib->stride / 2;
6468 glyph_ptr += glyph->stride / 4;
6472 static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6473 const POINT *origin, DWORD text_pixel,
6474 const struct font_gamma_ramp *gamma_ramp )
6476 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6477 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6478 int x, y;
6479 DWORD text, val;
6481 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6482 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6483 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6485 for (y = rect->top; y < rect->bottom; y++)
6487 for (x = 0; x < rect->right - rect->left; x++)
6489 if (glyph_ptr[x] == 0) continue;
6490 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6491 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6492 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6493 text, glyph_ptr[x], NULL );
6494 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6496 dst_ptr += dib->stride / 2;
6497 glyph_ptr += glyph->stride / 4;
6501 static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6502 const POINT *origin, DWORD text_pixel,
6503 const struct font_gamma_ramp *gamma_ramp )
6505 return;
6508 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
6509 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6511 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
6512 int x, y;
6514 /* masks are always 8x8 */
6515 assert( dib->width == 8 );
6516 assert( dib->height == 8 );
6518 for(y = 0; y < 8; y++, hatch_ptr++)
6520 for(x = 0; x < 8; x++)
6522 if(*hatch_ptr & pixel_masks_1[x])
6524 and_bits[x] = fg->and;
6525 xor_bits[x] = fg->xor;
6527 else
6529 and_bits[x] = bg->and;
6530 xor_bits[x] = bg->xor;
6533 and_bits += dib->stride / 4;
6534 xor_bits += dib->stride / 4;
6538 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
6539 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6541 DWORD mask_start = 0, mask_offset;
6542 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6543 int x, y;
6545 /* masks are always 8x8 */
6546 assert( dib->width == 8 );
6547 assert( dib->height == 8 );
6549 for(y = 0; y < 8; y++, hatch_ptr++)
6551 mask_offset = mask_start;
6552 for(x = 0; x < 8; x++)
6554 if(*hatch_ptr & pixel_masks_1[x])
6556 and_bits[mask_offset] = fg->and & 0xff;
6557 xor_bits[mask_offset++] = fg->xor & 0xff;
6558 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
6559 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
6560 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
6561 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
6563 else
6565 and_bits[mask_offset] = bg->and & 0xff;
6566 xor_bits[mask_offset++] = bg->xor & 0xff;
6567 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
6568 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
6569 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
6570 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
6573 mask_start += dib->stride;
6577 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
6578 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6580 WORD *and_bits = bits->and, *xor_bits = bits->xor;
6581 int x, y;
6583 /* masks are always 8x8 */
6584 assert( dib->width == 8 );
6585 assert( dib->height == 8 );
6587 for(y = 0; y < 8; y++, hatch_ptr++)
6589 for(x = 0; x < 8; x++)
6591 if(*hatch_ptr & pixel_masks_1[x])
6593 and_bits[x] = fg->and;
6594 xor_bits[x] = fg->xor;
6596 else
6598 and_bits[x] = bg->and;
6599 xor_bits[x] = bg->xor;
6602 and_bits += dib->stride / 2;
6603 xor_bits += dib->stride / 2;
6607 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
6608 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6610 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6611 int x, y;
6613 /* masks are always 8x8 */
6614 assert( dib->width == 8 );
6615 assert( dib->height == 8 );
6617 for(y = 0; y < 8; y++, hatch_ptr++)
6619 for(x = 0; x < 8; x++)
6621 if(*hatch_ptr & pixel_masks_1[x])
6623 and_bits[x] = fg->and;
6624 xor_bits[x] = fg->xor;
6626 else
6628 and_bits[x] = bg->and;
6629 xor_bits[x] = bg->xor;
6632 and_bits += dib->stride;
6633 xor_bits += dib->stride;
6637 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
6638 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6640 DWORD mask_offset;
6641 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6642 const rop_mask *rop_mask;
6643 int x, y;
6645 /* masks are always 8x8 */
6646 assert( dib->width == 8 );
6647 assert( dib->height == 8 );
6649 for(y = 0; y < 8; y++, hatch_ptr++)
6651 for(x = mask_offset = 0; x < 8; x++)
6653 if(*hatch_ptr & pixel_masks_1[x])
6654 rop_mask = fg;
6655 else
6656 rop_mask = bg;
6658 if(x & 1)
6660 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
6661 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
6662 mask_offset++;
6664 else
6666 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
6667 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
6670 and_bits += dib->stride;
6671 xor_bits += dib->stride;
6675 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
6676 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6678 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6679 rop_mask rop_mask;
6680 int x, y;
6682 /* masks are always 8x8 */
6683 assert( dib->width == 8 );
6684 assert( dib->height == 8 );
6686 for(y = 0; y < 8; y++, hatch_ptr++)
6688 *and_bits = *xor_bits = 0;
6689 for(x = 0; x < 8; x++)
6691 if(*hatch_ptr & pixel_masks_1[x])
6693 rop_mask.and = (fg->and & 1) ? 0xff : 0;
6694 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
6696 else
6698 rop_mask.and = (bg->and & 1) ? 0xff : 0;
6699 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
6701 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6702 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6704 and_bits += dib->stride;
6705 xor_bits += dib->stride;
6709 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
6710 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6714 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6716 /* mapping between RGB triples and the default color table */
6717 static const BYTE mapping[27] =
6719 0, /* 000000 -> 000000 */
6720 4, /* 00007f -> 000080 */
6721 252, /* 0000ff -> 0000ff */
6722 2, /* 007f00 -> 008000 */
6723 6, /* 007f7f -> 008080 */
6724 224, /* 007fff -> 0080c0 */
6725 250, /* 00ff00 -> 00ff00 */
6726 184, /* 00ff7f -> 00e080 */
6727 254, /* 00ffff -> 00ffff */
6728 1, /* 7f0000 -> 800000 */
6729 5, /* 7f007f -> 800080 */
6730 196, /* 7f00ff -> 8000c0 */
6731 3, /* 7f7f00 -> 808000 */
6732 248, /* 7f7f7f -> 808080 */
6733 228, /* 7f7fff -> 8080c0 */
6734 60, /* 7fff00 -> 80e000 */
6735 188, /* 7fff7f -> 80e080 */
6736 244, /* 7fffff -> 80c0c0 */
6737 249, /* ff0000 -> ff0000 */
6738 135, /* ff007f -> e00080 */
6739 253, /* ff00ff -> ff00ff */
6740 39, /* ff7f00 -> e08000 */
6741 167, /* ff7f7f -> e08080 */
6742 231, /* ff7fff -> e080c0 */
6743 251, /* ffff00 -> ffff00 */
6744 191, /* ffff7f -> e0e080 */
6745 255 /* ffffff -> ffffff */
6748 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6749 struct rop_codes codes;
6750 int x, y;
6752 /* masks are always 8x8 */
6753 assert( dib->width == 8 );
6754 assert( dib->height == 8 );
6756 get_rop_codes( rop2, &codes );
6758 for (y = 0; y < 8; y++)
6760 for (x = 0; x < 8; x++)
6762 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6763 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6764 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6765 DWORD pixel = mapping[r * 9 + g * 3 + b];
6766 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
6767 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
6769 and_bits += dib->stride;
6770 xor_bits += dib->stride;
6774 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6776 /* mapping between RGB triples and the default color table */
6777 static const BYTE mapping[27] =
6779 0, /* 000000 -> 000000 */
6780 4, /* 00007f -> 000080 */
6781 12, /* 0000ff -> 0000ff */
6782 2, /* 007f00 -> 008000 */
6783 6, /* 007f7f -> 008080 */
6784 6, /* 007fff -> 008080 */
6785 10, /* 00ff00 -> 00ff00 */
6786 6, /* 00ff7f -> 008080 */
6787 14, /* 00ffff -> 00ffff */
6788 1, /* 7f0000 -> 800000 */
6789 5, /* 7f007f -> 800080 */
6790 5, /* 7f00ff -> 800080 */
6791 3, /* 7f7f00 -> 808000 */
6792 7, /* 7f7f7f -> 808080 */
6793 8, /* 7f7fff -> c0c0c0 */
6794 3, /* 7fff00 -> 808000 */
6795 8, /* 7fff7f -> c0c0c0 */
6796 8, /* 7fffff -> c0c0c0 */
6797 9, /* ff0000 -> ff0000 */
6798 5, /* ff007f -> 800080 */
6799 13, /* ff00ff -> ff00ff */
6800 3, /* ff7f00 -> 808000 */
6801 8, /* ff7f7f -> c0c0c0 */
6802 8, /* ff7fff -> c0c0c0 */
6803 11, /* ffff00 -> ffff00 */
6804 8, /* ffff7f -> c0c0c0 */
6805 15 /* ffffff -> ffffff */
6808 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6809 struct rop_codes codes;
6810 int x, y;
6812 /* masks are always 8x8 */
6813 assert( dib->width == 8 );
6814 assert( dib->height == 8 );
6816 get_rop_codes( rop2, &codes );
6818 for (y = 0; y < 8; y++)
6820 for (x = 0; x < 8; x++)
6822 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6823 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6824 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6825 DWORD pixel = mapping[r * 9 + g * 3 + b];
6826 if (x & 1)
6828 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
6829 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
6831 else
6833 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
6834 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
6837 and_bits += dib->stride;
6838 xor_bits += dib->stride;
6842 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6844 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6845 struct rop_codes codes;
6846 rop_mask rop_mask;
6847 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
6849 /* masks are always 8x8 */
6850 assert( dib->width == 8 );
6851 assert( dib->height == 8 );
6853 get_rop_codes( rop2, &codes );
6855 for (y = 0; y < 8; y++)
6857 *and_bits = *xor_bits = 0;
6858 for (x = 0; x < 8; x++)
6860 if (grey + bayer_8x8[y][x] > 63)
6862 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
6863 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
6865 else
6867 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
6868 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
6870 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6871 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6873 and_bits += dib->stride;
6874 xor_bits += dib->stride;
6878 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6882 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
6884 switch (mode)
6886 default:
6887 case STRETCH_DELETESCANS:
6888 get_rop_codes( R2_COPYPEN, codes );
6889 break;
6890 case STRETCH_ORSCANS:
6891 get_rop_codes( R2_MERGEPEN, codes );
6892 break;
6893 case STRETCH_ANDSCANS:
6894 get_rop_codes( R2_MASKPEN, codes );
6895 break;
6897 return;
6900 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
6901 const dib_info *src_dib, const POINT *src_start,
6902 const struct stretch_params *params, int mode,
6903 BOOL keep_dst)
6905 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
6906 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
6907 int err = params->err_start;
6908 int width;
6910 if (mode == STRETCH_DELETESCANS || !keep_dst)
6912 for (width = params->length; width; width--)
6914 *dst_ptr = *src_ptr;
6915 dst_ptr += params->dst_inc;
6916 if (err > 0)
6918 src_ptr += params->src_inc;
6919 err += params->err_add_1;
6921 else err += params->err_add_2;
6924 else
6926 struct rop_codes codes;
6928 rop_codes_from_stretch_mode( mode, &codes );
6929 for (width = params->length; width; width--)
6931 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
6932 dst_ptr += params->dst_inc;
6933 if (err > 0)
6935 src_ptr += params->src_inc;
6936 err += params->err_add_1;
6938 else err += params->err_add_2;
6943 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
6944 const dib_info *src_dib, const POINT *src_start,
6945 const struct stretch_params *params, int mode,
6946 BOOL keep_dst)
6948 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
6949 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
6950 int err = params->err_start;
6951 int width;
6953 if (mode == STRETCH_DELETESCANS || !keep_dst)
6955 for (width = params->length; width; width--)
6957 dst_ptr[0] = src_ptr[0];
6958 dst_ptr[1] = src_ptr[1];
6959 dst_ptr[2] = src_ptr[2];
6960 dst_ptr += 3 * params->dst_inc;
6961 if (err > 0)
6963 src_ptr += 3 * params->src_inc;
6964 err += params->err_add_1;
6966 else err += params->err_add_2;
6969 else
6971 struct rop_codes codes;
6973 rop_codes_from_stretch_mode( mode, &codes );
6974 for (width = params->length; width; width--)
6976 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6977 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
6978 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
6979 dst_ptr += 3 * params->dst_inc;
6980 if (err > 0)
6982 src_ptr += 3 * params->src_inc;
6983 err += params->err_add_1;
6985 else err += params->err_add_2;
6990 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
6991 const dib_info *src_dib, const POINT *src_start,
6992 const struct stretch_params *params, int mode,
6993 BOOL keep_dst)
6995 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
6996 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
6997 int err = params->err_start;
6998 int width;
7000 if (mode == STRETCH_DELETESCANS || !keep_dst)
7002 for (width = params->length; width; width--)
7004 *dst_ptr = *src_ptr;
7005 dst_ptr += params->dst_inc;
7006 if (err > 0)
7008 src_ptr += params->src_inc;
7009 err += params->err_add_1;
7011 else err += params->err_add_2;
7014 else
7016 struct rop_codes codes;
7018 rop_codes_from_stretch_mode( mode, &codes );
7019 for (width = params->length; width; width--)
7021 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
7022 dst_ptr += params->dst_inc;
7023 if (err > 0)
7025 src_ptr += params->src_inc;
7026 err += params->err_add_1;
7028 else err += params->err_add_2;
7033 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
7034 const dib_info *src_dib, const POINT *src_start,
7035 const struct stretch_params *params, int mode,
7036 BOOL keep_dst)
7038 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
7039 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
7040 int err = params->err_start;
7041 int width;
7043 if (mode == STRETCH_DELETESCANS || !keep_dst)
7045 for (width = params->length; width; width--)
7047 *dst_ptr = *src_ptr;
7048 dst_ptr += params->dst_inc;
7049 if (err > 0)
7051 src_ptr += params->src_inc;
7052 err += params->err_add_1;
7054 else err += params->err_add_2;
7057 else
7059 struct rop_codes codes;
7061 rop_codes_from_stretch_mode( mode, &codes );
7062 for (width = params->length; width; width--)
7064 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7065 dst_ptr += params->dst_inc;
7066 if (err > 0)
7068 src_ptr += params->src_inc;
7069 err += params->err_add_1;
7071 else err += params->err_add_2;
7076 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
7077 const dib_info *src_dib, const POINT *src_start,
7078 const struct stretch_params *params, int mode,
7079 BOOL keep_dst)
7081 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
7082 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
7083 int err = params->err_start;
7084 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7085 struct rop_codes codes;
7086 BYTE src_val;
7088 if (!keep_dst) mode = STRETCH_DELETESCANS;
7089 rop_codes_from_stretch_mode( mode, &codes );
7090 for (width = params->length; width; width--)
7092 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
7093 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
7095 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
7097 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
7098 dst_ptr += params->dst_inc;
7099 dst_x += params->dst_inc;
7101 if (err > 0)
7103 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
7104 src_ptr += params->src_inc;
7105 src_x += params->src_inc;
7106 err += params->err_add_1;
7108 else err += params->err_add_2;
7112 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
7113 const dib_info *src_dib, const POINT *src_start,
7114 const struct stretch_params *params, int mode,
7115 BOOL keep_dst)
7117 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
7118 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
7119 int err = params->err_start;
7120 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7121 struct rop_codes codes;
7122 BYTE src_val;
7124 if (!keep_dst) mode = STRETCH_DELETESCANS;
7125 rop_codes_from_stretch_mode( mode, &codes );
7126 for (width = params->length; width; width--)
7128 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
7129 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
7131 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
7132 dst_ptr += params->dst_inc;
7133 dst_x += params->dst_inc;
7135 if (err > 0)
7137 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
7138 src_ptr += params->src_inc;
7139 src_x += params->src_inc;
7140 err += params->err_add_1;
7142 else err += params->err_add_2;
7146 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
7147 const dib_info *src_dib, const POINT *src_start,
7148 const struct stretch_params *params, int mode,
7149 BOOL keep_dst)
7151 FIXME("bit count %d\n", dst_dib->bit_count);
7152 return;
7155 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
7156 const dib_info *src_dib, const POINT *src_start,
7157 const struct stretch_params *params, int mode,
7158 BOOL keep_dst)
7160 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
7161 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
7162 int err = params->err_start;
7163 int width;
7165 if (mode == STRETCH_DELETESCANS)
7167 for (width = params->length; width; width--)
7169 *dst_ptr = *src_ptr;
7170 src_ptr += params->src_inc;
7171 if (err > 0)
7173 dst_ptr += params->dst_inc;
7174 err += params->err_add_1;
7176 else err += params->err_add_2;
7179 else
7181 struct rop_codes codes;
7182 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
7183 BOOL new_pix = TRUE;
7185 rop_codes_from_stretch_mode( mode, &codes );
7186 for (width = params->length; width; width--)
7188 if (new_pix && !keep_dst) *dst_ptr = init_val;
7189 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
7190 new_pix = FALSE;
7191 src_ptr += params->src_inc;
7192 if (err > 0)
7194 dst_ptr += params->dst_inc;
7195 new_pix = TRUE;
7196 err += params->err_add_1;
7198 else err += params->err_add_2;
7203 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
7204 const dib_info *src_dib, const POINT *src_start,
7205 const struct stretch_params *params, int mode,
7206 BOOL keep_dst)
7208 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
7209 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
7210 int err = params->err_start;
7211 int width;
7213 if (mode == STRETCH_DELETESCANS)
7215 for (width = params->length; width; width--)
7217 dst_ptr[0] = src_ptr[0];
7218 dst_ptr[1] = src_ptr[1];
7219 dst_ptr[2] = src_ptr[2];
7220 src_ptr += 3 * params->src_inc;
7221 if (err > 0)
7223 dst_ptr += 3 * params->dst_inc;
7224 err += params->err_add_1;
7226 else err += params->err_add_2;
7229 else
7231 struct rop_codes codes;
7232 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7233 BOOL new_pix = TRUE;
7235 rop_codes_from_stretch_mode( mode, &codes );
7236 for (width = params->length; width; width--)
7238 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
7239 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7240 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
7241 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
7242 new_pix = FALSE;
7243 src_ptr += 3 * params->src_inc;
7244 if (err > 0)
7246 dst_ptr += 3 * params->dst_inc;
7247 new_pix = TRUE;
7248 err += params->err_add_1;
7250 else err += params->err_add_2;
7255 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
7256 const dib_info *src_dib, const POINT *src_start,
7257 const struct stretch_params *params, int mode,
7258 BOOL keep_dst)
7260 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
7261 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
7262 int err = params->err_start;
7263 int width;
7265 if (mode == STRETCH_DELETESCANS)
7267 for (width = params->length; width; width--)
7269 *dst_ptr = *src_ptr;
7270 src_ptr += params->src_inc;
7271 if (err > 0)
7273 dst_ptr += params->dst_inc;
7274 err += params->err_add_1;
7276 else err += params->err_add_2;
7279 else
7281 struct rop_codes codes;
7282 WORD init_val = (mode == STRETCH_ANDSCANS) ? 0xffff : 0;
7283 BOOL new_pix = TRUE;
7285 rop_codes_from_stretch_mode( mode, &codes );
7286 for (width = params->length; width; width--)
7288 if (new_pix && !keep_dst) *dst_ptr = init_val;
7289 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
7290 new_pix = FALSE;
7291 src_ptr += params->src_inc;
7292 if (err > 0)
7294 dst_ptr += params->dst_inc;
7295 new_pix = TRUE;
7296 err += params->err_add_1;
7298 else err += params->err_add_2;
7303 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
7304 const dib_info *src_dib, const POINT *src_start,
7305 const struct stretch_params *params, int mode,
7306 BOOL keep_dst)
7308 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
7309 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
7310 int err = params->err_start;
7311 int width;
7313 if (mode == STRETCH_DELETESCANS)
7315 for (width = params->length; width; width--)
7317 *dst_ptr = *src_ptr;
7318 src_ptr += params->src_inc;
7319 if (err > 0)
7321 dst_ptr += params->dst_inc;
7322 err += params->err_add_1;
7324 else err += params->err_add_2;
7327 else
7329 struct rop_codes codes;
7330 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7331 BOOL new_pix = TRUE;
7333 rop_codes_from_stretch_mode( mode, &codes );
7334 for (width = params->length; width; width--)
7336 if (new_pix && !keep_dst) *dst_ptr = init_val;
7337 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7338 new_pix = FALSE;
7339 src_ptr += params->src_inc;
7340 if (err > 0)
7342 dst_ptr += params->dst_inc;
7343 new_pix = TRUE;
7344 err += params->err_add_1;
7346 else err += params->err_add_2;
7351 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
7352 const dib_info *src_dib, const POINT *src_start,
7353 const struct stretch_params *params, int mode,
7354 BOOL keep_dst)
7356 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
7357 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
7358 int err = params->err_start;
7359 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7360 struct rop_codes codes;
7361 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7362 BOOL new_pix = TRUE;
7364 rop_codes_from_stretch_mode( mode, &codes );
7365 for (width = params->length; width; width--)
7367 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
7369 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
7370 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
7372 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
7373 new_pix = FALSE;
7375 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
7376 src_ptr += params->src_inc;
7377 src_x += params->src_inc;
7379 if (err > 0)
7381 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
7382 dst_ptr += params->dst_inc;
7383 dst_x += params->dst_inc;
7384 new_pix = TRUE;
7385 err += params->err_add_1;
7387 else err += params->err_add_2;
7391 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
7392 const dib_info *src_dib, const POINT *src_start,
7393 const struct stretch_params *params, int mode,
7394 BOOL keep_dst)
7396 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
7397 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
7398 int err = params->err_start;
7399 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7400 struct rop_codes codes;
7401 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7402 BOOL new_pix = TRUE;
7404 rop_codes_from_stretch_mode( mode, &codes );
7405 for (width = params->length; width; width--)
7407 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
7408 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
7409 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
7410 new_pix = FALSE;
7412 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
7413 src_ptr += params->src_inc;
7414 src_x += params->src_inc;
7416 if (err > 0)
7418 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
7419 dst_ptr += params->dst_inc;
7420 dst_x += params->dst_inc;
7421 new_pix = TRUE;
7422 err += params->err_add_1;
7424 else err += params->err_add_2;
7428 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
7429 const dib_info *src_dib, const POINT *src_start,
7430 const struct stretch_params *params, int mode,
7431 BOOL keep_dst)
7433 FIXME("bit count %d\n", dst_dib->bit_count);
7434 return;
7437 static float clampf( float value, float min, float max )
7439 return max( min, min( value, max ) );
7442 static int clamp( int value, int min, int max )
7444 return max( min, min( value, max ) );
7447 static BYTE linear_interpolate( BYTE start, BYTE end, float delta )
7449 return start + (end - start) * delta + 0.5f;
7452 static BYTE bilinear_interpolate( BYTE c00, BYTE c01, BYTE c10, BYTE c11, float dx, float dy )
7454 return linear_interpolate( linear_interpolate( c00, c01, dx ),
7455 linear_interpolate( c10, c11, dx ), dy );
7458 static void calc_halftone_params( const struct bitblt_coords *dst, const struct bitblt_coords *src,
7459 RECT *dst_rect, RECT *src_rect, int *src_start_x,
7460 int *src_start_y, float *src_inc_x, float *src_inc_y )
7462 int src_width, src_height, dst_width, dst_height;
7463 BOOL mirrored_x, mirrored_y;
7465 get_bounding_rect( src_rect, src->x, src->y, src->width, src->height );
7466 get_bounding_rect( dst_rect, dst->x, dst->y, dst->width, dst->height );
7467 intersect_rect( src_rect, &src->visrect, src_rect );
7468 intersect_rect( dst_rect, &dst->visrect, dst_rect );
7469 OffsetRect( dst_rect, -dst_rect->left, -dst_rect->top );
7471 src_width = src_rect->right - src_rect->left;
7472 src_height = src_rect->bottom - src_rect->top;
7473 dst_width = dst_rect->right - dst_rect->left;
7474 dst_height = dst_rect->bottom - dst_rect->top;
7476 mirrored_x = (dst->width < 0) != (src->width < 0);
7477 mirrored_y = (dst->height < 0) != (src->height < 0);
7478 *src_start_x = mirrored_x ? src_rect->right - 1 : src_rect->left;
7479 *src_start_y = mirrored_y ? src_rect->bottom - 1 : src_rect->top;
7480 *src_inc_x = mirrored_x ? -(float)src_width / dst_width : (float)src_width / dst_width;
7481 *src_inc_y = mirrored_y ? -(float)src_height / dst_height : (float)src_height / dst_height;
7484 static void halftone_888( const dib_info *dst_dib, const struct bitblt_coords *dst,
7485 const dib_info *src_dib, const struct bitblt_coords *src )
7487 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
7488 DWORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7489 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7490 BYTE c00_r, c01_r, c10_r, c11_r;
7491 BYTE c00_g, c01_g, c10_g, c11_g;
7492 BYTE c00_b, c01_b, c10_b, c11_b;
7493 RECT dst_rect, src_rect;
7494 BYTE r, g, b;
7496 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7497 &src_inc_y );
7499 float_y = src_start_y;
7500 dst_ptr = get_pixel_ptr_32( dst_dib, dst_rect.left, dst_rect.top );
7501 for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
7503 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7504 y0 = float_y;
7505 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7506 dy = float_y - y0;
7508 float_x = src_start_x;
7509 src_ptr = get_pixel_ptr_32( src_dib, 0, y0 );
7510 src_ptr_dy = (y1 - y0) * src_dib->stride / 4;
7511 for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
7513 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7514 x0 = float_x;
7515 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7516 dx = float_x - x0;
7518 c00_ptr = src_ptr + x0;
7519 c01_ptr = src_ptr + x1;
7520 c10_ptr = c00_ptr + src_ptr_dy;
7521 c11_ptr = c01_ptr + src_ptr_dy;
7522 c00_r = (*c00_ptr >> 16) & 0xff;
7523 c01_r = (*c01_ptr >> 16) & 0xff;
7524 c10_r = (*c10_ptr >> 16) & 0xff;
7525 c11_r = (*c11_ptr >> 16) & 0xff;
7526 c00_g = (*c00_ptr >> 8) & 0xff;
7527 c01_g = (*c01_ptr >> 8) & 0xff;
7528 c10_g = (*c10_ptr >> 8) & 0xff;
7529 c11_g = (*c11_ptr >> 8) & 0xff;
7530 c00_b = *c00_ptr & 0xff;
7531 c01_b = *c01_ptr & 0xff;
7532 c10_b = *c10_ptr & 0xff;
7533 c11_b = *c11_ptr & 0xff;
7534 r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
7535 g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
7536 b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
7537 dst_ptr[dst_x] = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0x0000ff);
7539 float_x += src_inc_x;
7542 dst_ptr += dst_dib->stride / 4;
7543 float_y += src_inc_y;
7547 static void halftone_32( const dib_info *dst_dib, const struct bitblt_coords *dst,
7548 const dib_info *src_dib, const struct bitblt_coords *src )
7550 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
7551 DWORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7552 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7553 BYTE c00_r, c01_r, c10_r, c11_r;
7554 BYTE c00_g, c01_g, c10_g, c11_g;
7555 BYTE c00_b, c01_b, c10_b, c11_b;
7556 RECT dst_rect, src_rect;
7557 BYTE r, g, b;
7559 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7560 &src_inc_y );
7562 float_y = src_start_y;
7563 dst_ptr = get_pixel_ptr_32( dst_dib, dst_rect.left, dst_rect.top );
7564 for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
7566 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7567 y0 = float_y;
7568 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7569 dy = float_y - y0;
7571 float_x = src_start_x;
7572 src_ptr = get_pixel_ptr_32( src_dib, 0, y0 );
7573 src_ptr_dy = (y1 - y0) * src_dib->stride / 4;
7574 for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
7576 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7577 x0 = float_x;
7578 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7579 dx = float_x - x0;
7581 c00_ptr = src_ptr + x0;
7582 c01_ptr = src_ptr + x1;
7583 c10_ptr = c00_ptr + src_ptr_dy;
7584 c11_ptr = c01_ptr + src_ptr_dy;
7585 c00_r = get_field( *c00_ptr, src_dib->red_shift, src_dib->red_len );
7586 c01_r = get_field( *c01_ptr, src_dib->red_shift, src_dib->red_len );
7587 c10_r = get_field( *c10_ptr, src_dib->red_shift, src_dib->red_len );
7588 c11_r = get_field( *c11_ptr, src_dib->red_shift, src_dib->red_len );
7589 c00_g = get_field( *c00_ptr, src_dib->green_shift, src_dib->green_len );
7590 c01_g = get_field( *c01_ptr, src_dib->green_shift, src_dib->green_len );
7591 c10_g = get_field( *c10_ptr, src_dib->green_shift, src_dib->green_len );
7592 c11_g = get_field( *c11_ptr, src_dib->green_shift, src_dib->green_len );
7593 c00_b = get_field( *c00_ptr, src_dib->blue_shift, src_dib->blue_len );
7594 c01_b = get_field( *c01_ptr, src_dib->blue_shift, src_dib->blue_len );
7595 c10_b = get_field( *c10_ptr, src_dib->blue_shift, src_dib->blue_len );
7596 c11_b = get_field( *c11_ptr, src_dib->blue_shift, src_dib->blue_len );
7597 r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
7598 g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
7599 b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
7600 dst_ptr[dst_x] = rgb_to_pixel_masks( dst_dib, r, g, b );
7602 float_x += src_inc_x;
7605 dst_ptr += dst_dib->stride / 4;
7606 float_y += src_inc_y;
7610 static void halftone_24( const dib_info *dst_dib, const struct bitblt_coords *dst,
7611 const dib_info *src_dib, const struct bitblt_coords *src )
7613 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
7614 BYTE *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7615 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7616 BYTE c00_r, c01_r, c10_r, c11_r;
7617 BYTE c00_g, c01_g, c10_g, c11_g;
7618 BYTE c00_b, c01_b, c10_b, c11_b;
7619 RECT dst_rect, src_rect;
7620 BYTE r, g, b;
7622 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7623 &src_inc_y );
7625 float_y = src_start_y;
7626 dst_ptr = get_pixel_ptr_24( dst_dib, dst_rect.left, dst_rect.top );
7627 for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
7629 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7630 y0 = float_y;
7631 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7632 dy = float_y - y0;
7634 float_x = src_start_x;
7635 src_ptr = get_pixel_ptr_24( src_dib, 0, y0 );
7636 src_ptr_dy = (y1 - y0) * src_dib->stride;
7637 for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
7639 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7640 x0 = float_x;
7641 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7642 dx = float_x - x0;
7644 c00_ptr = src_ptr + x0 * 3;
7645 c01_ptr = src_ptr + x1 * 3;
7646 c10_ptr = c00_ptr + src_ptr_dy;
7647 c11_ptr = c01_ptr + src_ptr_dy;
7648 c00_b = c00_ptr[0];
7649 c01_b = c01_ptr[0];
7650 c10_b = c10_ptr[0];
7651 c11_b = c11_ptr[0];
7652 c00_g = c00_ptr[1];
7653 c01_g = c01_ptr[1];
7654 c10_g = c10_ptr[1];
7655 c11_g = c11_ptr[1];
7656 c00_r = c00_ptr[2];
7657 c01_r = c01_ptr[2];
7658 c10_r = c10_ptr[2];
7659 c11_r = c11_ptr[2];
7660 r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
7661 g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
7662 b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
7663 dst_ptr[dst_x * 3] = b;
7664 dst_ptr[dst_x * 3 + 1] = g;
7665 dst_ptr[dst_x * 3 + 2] = r;
7667 float_x += src_inc_x;
7670 dst_ptr += dst_dib->stride;
7671 float_y += src_inc_y;
7675 static void halftone_555( const dib_info *dst_dib, const struct bitblt_coords *dst,
7676 const dib_info *src_dib, const struct bitblt_coords *src )
7678 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
7679 WORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7680 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7681 BYTE c00_r, c01_r, c10_r, c11_r;
7682 BYTE c00_g, c01_g, c10_g, c11_g;
7683 BYTE c00_b, c01_b, c10_b, c11_b;
7684 RECT dst_rect, src_rect;
7685 BYTE r, g, b;
7687 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7688 &src_inc_y );
7690 float_y = src_start_y;
7691 dst_ptr = get_pixel_ptr_16( dst_dib, dst_rect.left, dst_rect.top );
7692 for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
7694 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7695 y0 = float_y;
7696 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7697 dy = float_y - y0;
7699 float_x = src_start_x;
7700 src_ptr = get_pixel_ptr_16( src_dib, 0, y0 );
7701 src_ptr_dy = (y1 - y0) * src_dib->stride / 2;
7702 for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
7704 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7705 x0 = float_x;
7706 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7707 dx = float_x - x0;
7709 c00_ptr = src_ptr + x0;
7710 c01_ptr = src_ptr + x1;
7711 c10_ptr = c00_ptr + src_ptr_dy;
7712 c11_ptr = c01_ptr + src_ptr_dy;
7713 c00_r = ((*c00_ptr >> 7) & 0xf8) | ((*c00_ptr >> 12) & 0x07);
7714 c01_r = ((*c01_ptr >> 7) & 0xf8) | ((*c01_ptr >> 12) & 0x07);
7715 c10_r = ((*c10_ptr >> 7) & 0xf8) | ((*c10_ptr >> 12) & 0x07);
7716 c11_r = ((*c11_ptr >> 7) & 0xf8) | ((*c11_ptr >> 12) & 0x07);
7717 c00_g = ((*c00_ptr >> 2) & 0xf8) | ((*c00_ptr >> 7) & 0x07);
7718 c01_g = ((*c01_ptr >> 2) & 0xf8) | ((*c01_ptr >> 7) & 0x07);
7719 c10_g = ((*c10_ptr >> 2) & 0xf8) | ((*c10_ptr >> 7) & 0x07);
7720 c11_g = ((*c11_ptr >> 2) & 0xf8) | ((*c11_ptr >> 7) & 0x07);
7721 c00_b = ((*c00_ptr << 3) & 0xf8) | ((*c00_ptr >> 2) & 0x07);
7722 c01_b = ((*c01_ptr << 3) & 0xf8) | ((*c01_ptr >> 2) & 0x07);
7723 c10_b = ((*c10_ptr << 3) & 0xf8) | ((*c10_ptr >> 2) & 0x07);
7724 c11_b = ((*c11_ptr << 3) & 0xf8) | ((*c11_ptr >> 2) & 0x07);
7725 r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
7726 g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
7727 b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
7728 dst_ptr[dst_x] = ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f);
7730 float_x += src_inc_x;
7733 dst_ptr += dst_dib->stride / 2;
7734 float_y += src_inc_y;
7738 static void halftone_16( const dib_info *dst_dib, const struct bitblt_coords *dst,
7739 const dib_info *src_dib, const struct bitblt_coords *src )
7741 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
7742 WORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7743 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7744 BYTE c00_r, c01_r, c10_r, c11_r;
7745 BYTE c00_g, c01_g, c10_g, c11_g;
7746 BYTE c00_b, c01_b, c10_b, c11_b;
7747 RECT dst_rect, src_rect;
7748 BYTE r, g, b;
7750 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7751 &src_inc_y );
7753 float_y = src_start_y;
7754 dst_ptr = get_pixel_ptr_16( dst_dib, dst_rect.left, dst_rect.top );
7755 for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
7757 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7758 y0 = float_y;
7759 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7760 dy = float_y - y0;
7762 float_x = src_start_x;
7763 src_ptr = get_pixel_ptr_16( src_dib, 0, y0 );
7764 src_ptr_dy = (y1 - y0) * src_dib->stride / 2;
7765 for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
7767 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7768 x0 = float_x;
7769 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7770 dx = float_x - x0;
7772 c00_ptr = src_ptr + x0;
7773 c01_ptr = src_ptr + x1;
7774 c10_ptr = c00_ptr + src_ptr_dy;
7775 c11_ptr = c01_ptr + src_ptr_dy;
7776 c00_r = get_field( *c00_ptr, src_dib->red_shift, src_dib->red_len );
7777 c01_r = get_field( *c01_ptr, src_dib->red_shift, src_dib->red_len );
7778 c10_r = get_field( *c10_ptr, src_dib->red_shift, src_dib->red_len );
7779 c11_r = get_field( *c11_ptr, src_dib->red_shift, src_dib->red_len );
7780 c00_g = get_field( *c00_ptr, src_dib->green_shift, src_dib->green_len );
7781 c01_g = get_field( *c01_ptr, src_dib->green_shift, src_dib->green_len );
7782 c10_g = get_field( *c10_ptr, src_dib->green_shift, src_dib->green_len );
7783 c11_g = get_field( *c11_ptr, src_dib->green_shift, src_dib->green_len );
7784 c00_b = get_field( *c00_ptr, src_dib->blue_shift, src_dib->blue_len );
7785 c01_b = get_field( *c01_ptr, src_dib->blue_shift, src_dib->blue_len );
7786 c10_b = get_field( *c10_ptr, src_dib->blue_shift, src_dib->blue_len );
7787 c11_b = get_field( *c11_ptr, src_dib->blue_shift, src_dib->blue_len );
7788 r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
7789 g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
7790 b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
7791 dst_ptr[dst_x] = rgb_to_pixel_masks( dst_dib, r, g, b );
7793 float_x += src_inc_x;
7796 dst_ptr += dst_dib->stride / 2;
7797 float_y += src_inc_y;
7801 static void halftone_8( const dib_info *dst_dib, const struct bitblt_coords *dst,
7802 const dib_info *src_dib, const struct bitblt_coords *src )
7804 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
7805 BYTE *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7806 RGBQUAD c00_rgb, c01_rgb, c10_rgb, c11_rgb, zero_rgb = {0};
7807 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7808 const RGBQUAD *src_clr_table;
7809 RECT dst_rect, src_rect;
7810 BYTE r, g, b;
7812 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7813 &src_inc_y );
7815 float_y = src_start_y;
7816 src_clr_table = get_dib_color_table( src_dib );
7817 dst_ptr = get_pixel_ptr_8( dst_dib, dst_rect.left, dst_rect.top );
7818 for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
7820 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7821 y0 = float_y;
7822 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7823 dy = float_y - y0;
7825 float_x = src_start_x;
7826 src_ptr = get_pixel_ptr_8( src_dib, 0, y0 );
7827 src_ptr_dy = (y1 - y0) * src_dib->stride;
7828 for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
7830 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7831 x0 = float_x;
7832 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7833 dx = float_x - x0;
7835 c00_ptr = src_ptr + x0;
7836 c01_ptr = src_ptr + x1;
7837 c10_ptr = c00_ptr + src_ptr_dy;
7838 c11_ptr = c01_ptr + src_ptr_dy;
7839 if (src_clr_table)
7841 c00_rgb = *c00_ptr < src_dib->color_table_size ? src_clr_table[*c00_ptr] : zero_rgb;
7842 c01_rgb = *c01_ptr < src_dib->color_table_size ? src_clr_table[*c01_ptr] : zero_rgb;
7843 c10_rgb = *c10_ptr < src_dib->color_table_size ? src_clr_table[*c10_ptr] : zero_rgb;
7844 c11_rgb = *c11_ptr < src_dib->color_table_size ? src_clr_table[*c11_ptr] : zero_rgb;
7845 r = bilinear_interpolate( c00_rgb.rgbRed, c01_rgb.rgbRed, c10_rgb.rgbRed, c11_rgb.rgbRed, dx, dy );
7846 g = bilinear_interpolate( c00_rgb.rgbGreen, c01_rgb.rgbGreen, c10_rgb.rgbGreen, c11_rgb.rgbGreen, dx, dy );
7847 b = bilinear_interpolate( c00_rgb.rgbBlue, c01_rgb.rgbBlue, c10_rgb.rgbBlue, c11_rgb.rgbBlue, dx, dy );
7849 else
7851 r = 0;
7852 g = 0;
7853 b = 0;
7855 dst_ptr[dst_x] = rgb_to_pixel_colortable( dst_dib, r, g, b );
7857 float_x += src_inc_x;
7860 dst_ptr += dst_dib->stride;
7861 float_y += src_inc_y;
7865 static void halftone_4( const dib_info *dst_dib, const struct bitblt_coords *dst,
7866 const dib_info *src_dib, const struct bitblt_coords *src )
7868 BYTE *dst_col_ptr, *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7869 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
7870 RGBQUAD c00_rgb, c01_rgb, c10_rgb, c11_rgb, zero_rgb = {0};
7871 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7872 BYTE r, g, b, val, c00, c01, c10, c11;
7873 const RGBQUAD *src_clr_table;
7874 RECT dst_rect, src_rect;
7876 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7877 &src_inc_y );
7879 float_y = src_start_y;
7880 src_clr_table = get_dib_color_table( src_dib );
7881 dst_col_ptr = (BYTE *)dst_dib->bits.ptr + (dst_dib->rect.top + dst_rect.top) * dst_dib->stride;
7882 for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
7884 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7885 y0 = float_y;
7886 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7887 dy = float_y - y0;
7889 float_x = src_start_x;
7890 src_ptr = (BYTE *)src_dib->bits.ptr + (src_dib->rect.top + y0) * src_dib->stride;
7891 src_ptr_dy = (y1 - y0) * src_dib->stride;
7892 for (dst_x = dst_rect.left; dst_x < dst_rect.right; ++dst_x)
7894 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7895 x0 = float_x;
7896 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7897 dx = float_x - x0;
7899 c00_ptr = src_ptr + (src_dib->rect.left + x0) / 2;
7900 c01_ptr = src_ptr + (src_dib->rect.left + x1) / 2;
7901 c10_ptr = c00_ptr + src_ptr_dy;
7902 c11_ptr = c01_ptr + src_ptr_dy;
7903 if ((src_dib->rect.left + x0) & 1)
7905 c00 = *c00_ptr & 0x0f;
7906 c10 = *c10_ptr & 0x0f;
7908 else
7910 c00 = (*c00_ptr >> 4) & 0x0f;
7911 c10 = (*c10_ptr >> 4) & 0x0f;
7913 if ((src_dib->rect.left + x1) & 1)
7915 c01 = *c01_ptr & 0x0f;
7916 c11 = *c11_ptr & 0x0f;
7918 else
7920 c01 = (*c01_ptr >> 4) & 0x0f;
7921 c11 = (*c11_ptr >> 4) & 0x0f;
7924 if (src_clr_table)
7926 c00_rgb = c00 < src_dib->color_table_size ? src_clr_table[c00] : zero_rgb;
7927 c01_rgb = c01 < src_dib->color_table_size ? src_clr_table[c01] : zero_rgb;
7928 c10_rgb = c10 < src_dib->color_table_size ? src_clr_table[c10] : zero_rgb;
7929 c11_rgb = c11 < src_dib->color_table_size ? src_clr_table[c11] : zero_rgb;
7930 r = bilinear_interpolate( c00_rgb.rgbRed, c01_rgb.rgbRed, c10_rgb.rgbRed, c11_rgb.rgbRed, dx, dy );
7931 g = bilinear_interpolate( c00_rgb.rgbGreen, c01_rgb.rgbGreen, c10_rgb.rgbGreen, c11_rgb.rgbGreen, dx, dy );
7932 b = bilinear_interpolate( c00_rgb.rgbBlue, c01_rgb.rgbBlue, c10_rgb.rgbBlue, c11_rgb.rgbBlue, dx, dy );
7934 else
7936 r = 0;
7937 g = 0;
7938 b = 0;
7941 dst_ptr = dst_col_ptr + (dst_dib->rect.left + dst_x) / 2;
7942 val = rgb_to_pixel_colortable( dst_dib, r, g, b );
7943 if ((dst_x + dst_dib->rect.left) & 1)
7944 *dst_ptr = (val & 0x0f) | (*dst_ptr & 0xf0);
7945 else
7946 *dst_ptr = (val << 4) & 0xf0;
7948 float_x += src_inc_x;
7951 dst_col_ptr += dst_dib->stride;
7952 float_y += src_inc_y;
7956 static void halftone_1( const dib_info *dst_dib, const struct bitblt_coords *dst,
7957 const dib_info *src_dib, const struct bitblt_coords *src )
7959 int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1, bit_pos;
7960 BYTE *dst_col_ptr, *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
7961 RGBQUAD c00_rgb, c01_rgb, c10_rgb, c11_rgb, zero_rgb = {0};
7962 float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
7963 BYTE r, g, b, val, c00, c01, c10, c11;
7964 const RGBQUAD *src_clr_table;
7965 RECT dst_rect, src_rect;
7966 RGBQUAD bg_entry;
7967 DWORD bg_pixel;
7969 calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
7970 &src_inc_y );
7972 float_y = src_start_y;
7973 bg_entry = *get_dib_color_table( dst_dib );
7974 src_clr_table = get_dib_color_table( src_dib );
7975 dst_col_ptr = (BYTE *)dst_dib->bits.ptr + (dst_dib->rect.top + dst_rect.top) * dst_dib->stride;
7976 for (dst_y = dst_rect.top; dst_y < dst_rect.bottom; ++dst_y)
7978 float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
7979 y0 = float_y;
7980 y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
7981 dy = float_y - y0;
7983 float_x = src_start_x;
7984 src_ptr = (BYTE *)src_dib->bits.ptr + (src_dib->rect.top + y0) * src_dib->stride;
7985 src_ptr_dy = (y1 - y0) * src_dib->stride;
7986 for (dst_x = dst_rect.left; dst_x < dst_rect.right; ++dst_x)
7988 float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
7989 x0 = float_x;
7990 x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
7991 dx = float_x - x0;
7993 c00_ptr = src_ptr + (src_dib->rect.left + x0) / 8;
7994 c01_ptr = src_ptr + (src_dib->rect.left + x1) / 8;
7995 c10_ptr = c00_ptr + src_ptr_dy;
7996 c11_ptr = c01_ptr + src_ptr_dy;
7997 c00 = (*c00_ptr & pixel_masks_1[(src_dib->rect.left + x0) & 7]) ? 1 : 0;
7998 c01 = (*c01_ptr & pixel_masks_1[(src_dib->rect.left + x1) & 7]) ? 1 : 0;
7999 c10 = (*c10_ptr & pixel_masks_1[(src_dib->rect.left + x0) & 7]) ? 1 : 0;
8000 c11 = (*c11_ptr & pixel_masks_1[(src_dib->rect.left + x1) & 7]) ? 1 : 0;
8002 if (src_clr_table)
8004 c00_rgb = c00 < src_dib->color_table_size ? src_clr_table[c00] : zero_rgb;
8005 c01_rgb = c01 < src_dib->color_table_size ? src_clr_table[c01] : zero_rgb;
8006 c10_rgb = c10 < src_dib->color_table_size ? src_clr_table[c10] : zero_rgb;
8007 c11_rgb = c11 < src_dib->color_table_size ? src_clr_table[c11] : zero_rgb;
8008 r = bilinear_interpolate( c00_rgb.rgbRed, c01_rgb.rgbRed, c10_rgb.rgbRed, c11_rgb.rgbRed, dx, dy );
8009 g = bilinear_interpolate( c00_rgb.rgbGreen, c01_rgb.rgbGreen, c10_rgb.rgbGreen, c11_rgb.rgbGreen, dx, dy );
8010 b = bilinear_interpolate( c00_rgb.rgbBlue, c01_rgb.rgbBlue, c10_rgb.rgbBlue, c11_rgb.rgbBlue, dx, dy );
8012 else
8014 r = 0;
8015 g = 0;
8016 b = 0;
8019 dst_ptr = dst_col_ptr + (dst_dib->rect.left + dst_x) / 8;
8020 bit_pos = (dst_x + dst_dib->rect.left) & 7;
8021 bg_pixel = FILTER_DIBINDEX(bg_entry, RGB(bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue));
8022 val = rgb_to_pixel_mono( dst_dib, FALSE, dst_x, dst_y, RGB(r, g, b), bg_pixel, r, g, b );
8023 if (bit_pos == 0)
8024 *dst_ptr = 0;
8025 *dst_ptr = (*dst_ptr & ~pixel_masks_1[bit_pos]) | (val & pixel_masks_1[bit_pos]);
8027 float_x += src_inc_x;
8030 dst_col_ptr += dst_dib->stride;
8031 float_y += src_inc_y;
8035 static void halftone_null( const dib_info *dst_dib, const struct bitblt_coords *dst,
8036 const dib_info *src_dib, const struct bitblt_coords *src )
8039 const primitive_funcs funcs_8888 =
8041 solid_rects_32,
8042 solid_line_32,
8043 pattern_rects_32,
8044 copy_rect_32,
8045 blend_rects_8888,
8046 gradient_rect_8888,
8047 mask_rect_32,
8048 draw_glyph_8888,
8049 draw_subpixel_glyph_8888,
8050 get_pixel_32,
8051 colorref_to_pixel_888,
8052 pixel_to_colorref_888,
8053 convert_to_8888,
8054 create_rop_masks_32,
8055 create_dither_masks_null,
8056 stretch_row_32,
8057 shrink_row_32,
8058 halftone_888
8061 const primitive_funcs funcs_32 =
8063 solid_rects_32,
8064 solid_line_32,
8065 pattern_rects_32,
8066 copy_rect_32,
8067 blend_rects_32,
8068 gradient_rect_32,
8069 mask_rect_32,
8070 draw_glyph_32,
8071 draw_subpixel_glyph_32,
8072 get_pixel_32,
8073 colorref_to_pixel_masks,
8074 pixel_to_colorref_masks,
8075 convert_to_32,
8076 create_rop_masks_32,
8077 create_dither_masks_null,
8078 stretch_row_32,
8079 shrink_row_32,
8080 halftone_32
8083 const primitive_funcs funcs_24 =
8085 solid_rects_24,
8086 solid_line_24,
8087 pattern_rects_24,
8088 copy_rect_24,
8089 blend_rects_24,
8090 gradient_rect_24,
8091 mask_rect_24,
8092 draw_glyph_24,
8093 draw_subpixel_glyph_24,
8094 get_pixel_24,
8095 colorref_to_pixel_888,
8096 pixel_to_colorref_888,
8097 convert_to_24,
8098 create_rop_masks_24,
8099 create_dither_masks_null,
8100 stretch_row_24,
8101 shrink_row_24,
8102 halftone_24
8105 const primitive_funcs funcs_555 =
8107 solid_rects_16,
8108 solid_line_16,
8109 pattern_rects_16,
8110 copy_rect_16,
8111 blend_rects_555,
8112 gradient_rect_555,
8113 mask_rect_16,
8114 draw_glyph_555,
8115 draw_subpixel_glyph_555,
8116 get_pixel_16,
8117 colorref_to_pixel_555,
8118 pixel_to_colorref_555,
8119 convert_to_555,
8120 create_rop_masks_16,
8121 create_dither_masks_null,
8122 stretch_row_16,
8123 shrink_row_16,
8124 halftone_555
8127 const primitive_funcs funcs_16 =
8129 solid_rects_16,
8130 solid_line_16,
8131 pattern_rects_16,
8132 copy_rect_16,
8133 blend_rects_16,
8134 gradient_rect_16,
8135 mask_rect_16,
8136 draw_glyph_16,
8137 draw_subpixel_glyph_16,
8138 get_pixel_16,
8139 colorref_to_pixel_masks,
8140 pixel_to_colorref_masks,
8141 convert_to_16,
8142 create_rop_masks_16,
8143 create_dither_masks_null,
8144 stretch_row_16,
8145 shrink_row_16,
8146 halftone_16
8149 const primitive_funcs funcs_8 =
8151 solid_rects_8,
8152 solid_line_8,
8153 pattern_rects_8,
8154 copy_rect_8,
8155 blend_rects_8,
8156 gradient_rect_8,
8157 mask_rect_8,
8158 draw_glyph_8,
8159 draw_subpixel_glyph_null,
8160 get_pixel_8,
8161 colorref_to_pixel_colortable,
8162 pixel_to_colorref_colortable,
8163 convert_to_8,
8164 create_rop_masks_8,
8165 create_dither_masks_8,
8166 stretch_row_8,
8167 shrink_row_8,
8168 halftone_8
8171 const primitive_funcs funcs_4 =
8173 solid_rects_4,
8174 solid_line_4,
8175 pattern_rects_4,
8176 copy_rect_4,
8177 blend_rects_4,
8178 gradient_rect_4,
8179 mask_rect_4,
8180 draw_glyph_4,
8181 draw_subpixel_glyph_null,
8182 get_pixel_4,
8183 colorref_to_pixel_colortable,
8184 pixel_to_colorref_colortable,
8185 convert_to_4,
8186 create_rop_masks_4,
8187 create_dither_masks_4,
8188 stretch_row_4,
8189 shrink_row_4,
8190 halftone_4
8193 const primitive_funcs funcs_1 =
8195 solid_rects_1,
8196 solid_line_1,
8197 pattern_rects_1,
8198 copy_rect_1,
8199 blend_rects_1,
8200 gradient_rect_1,
8201 mask_rect_null,
8202 draw_glyph_1,
8203 draw_subpixel_glyph_null,
8204 get_pixel_1,
8205 colorref_to_pixel_colortable,
8206 pixel_to_colorref_colortable,
8207 convert_to_1,
8208 create_rop_masks_1,
8209 create_dither_masks_1,
8210 stretch_row_1,
8211 shrink_row_1,
8212 halftone_1
8215 const primitive_funcs funcs_null =
8217 solid_rects_null,
8218 solid_line_null,
8219 pattern_rects_null,
8220 copy_rect_null,
8221 blend_rects_null,
8222 gradient_rect_null,
8223 mask_rect_null,
8224 draw_glyph_null,
8225 draw_subpixel_glyph_null,
8226 get_pixel_null,
8227 colorref_to_pixel_null,
8228 pixel_to_colorref_null,
8229 convert_to_null,
8230 create_rop_masks_null,
8231 create_dither_masks_null,
8232 stretch_row_null,
8233 shrink_row_null,
8234 halftone_null