server: Use server_get_file_info for all info classes not implemented on client side.
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blob01a1c7c1d835204c2ab3d5846cdbee0a567c1211
1 /*
2 * DIB driver primitives.
4 * Copyright 2011 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
23 #include "gdi_private.h"
24 #include "dibdrv.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dib);
30 /* Bayer matrices for dithering */
32 static const BYTE bayer_4x4[4][4] =
34 { 0, 8, 2, 10 },
35 { 12, 4, 14, 6 },
36 { 3, 11, 1, 9 },
37 { 15, 7, 13, 5 }
40 static const BYTE bayer_8x8[8][8] =
42 { 0, 32, 8, 40, 2, 34, 10, 42 },
43 { 48, 16, 56, 24, 50, 18, 58, 26 },
44 { 12, 44, 4, 36, 14, 46, 6, 38 },
45 { 60, 28, 52, 20, 62, 30, 54, 22 },
46 { 3, 35, 11, 43, 1, 33, 9, 41 },
47 { 51, 19, 59, 27, 49, 17, 57, 25 },
48 { 15, 47, 7, 39, 13, 45, 5, 37 },
49 { 63, 31, 55, 23, 61, 29, 53, 21 }
52 static const BYTE bayer_16x16[16][16] =
54 { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170 },
55 { 192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106 },
56 { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154 },
57 { 240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90 },
58 { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166 },
59 { 204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102 },
60 { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150 },
61 { 252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86 },
62 { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169 },
63 { 195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105 },
64 { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153 },
65 { 243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89 },
66 { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165 },
67 { 207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101 },
68 { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149 },
69 { 255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85 },
72 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
74 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 4);
77 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
79 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride) + (dib->rect.left + x) * 3 / 4;
82 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
84 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 3;
87 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
89 return (WORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 2);
92 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
94 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + dib->rect.left + x;
97 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
99 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 2;
102 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
104 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 8;
107 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
108 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
109 static const BYTE edge_masks_1[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
111 #define FILTER_DIBINDEX(rgbquad,other_val) \
112 (HIWORD( *(DWORD *)(&rgbquad) ) == 0x10ff ? LOWORD( *(DWORD *)(&rgbquad) ) : (other_val))
114 #define ROPS_WITHOUT_COPY( _d, _s ) \
115 case R2_BLACK: LOOP( (_d) = 0 ) break; \
116 case R2_NOTMERGEPEN: LOOP( (_d) = ~((_d) | (_s)) ) break; \
117 case R2_MASKNOTPEN: LOOP( (_d) &= ~(_s) ) break; \
118 case R2_NOTCOPYPEN: LOOP( (_d) = ~(_s) ) break; \
119 case R2_MASKPENNOT: LOOP( (_d) = (~(_d) & (_s)) ) break; \
120 case R2_NOT: LOOP( (_d) = ~(_d) ) break; \
121 case R2_XORPEN: LOOP( (_d) ^= (_s) ) break; \
122 case R2_NOTMASKPEN: LOOP( (_d) = ~((_d) & (_s)) ) break; \
123 case R2_MASKPEN: LOOP( (_d) &= (_s) ) break; \
124 case R2_NOTXORPEN: LOOP( (_d) = ~((_d) ^ (_s)) ) break; \
125 case R2_NOP: break; \
126 case R2_MERGENOTPEN: LOOP( (_d) = ((_d) | ~(_s)) ) break; \
127 case R2_MERGEPENNOT: LOOP( (_d) = (~(_d) | (_s)) ) break; \
128 case R2_MERGEPEN: LOOP( (_d) |= (_s) ) break; \
129 case R2_WHITE: LOOP( (_d) = ~0 ) break;
131 #define ROPS_ALL( _d, _s ) \
132 case R2_COPYPEN: LOOP( (_d) = (_s) ) break; \
133 ROPS_WITHOUT_COPY( (_d), (_s) )
135 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
137 *ptr = (*ptr & and) ^ xor;
140 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
142 *ptr = (*ptr & and) ^ xor;
145 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
147 *ptr = (*ptr & and) ^ xor;
150 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
152 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
155 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
157 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
160 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
162 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
165 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
167 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
170 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
172 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
175 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
177 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
180 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
182 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
183 do_rop_codes_16( dst, *src, codes );
186 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
188 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
191 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
193 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
194 do_rop_codes_8( dst, *src, codes );
197 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
198 struct rop_codes *codes, int len)
200 BYTE src_val;
202 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
204 if (dst_x & 1)
206 if (src_x & 1) src_val = *src++;
207 else src_val = *src >> 4;
208 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
210 else
212 if (src_x & 1) src_val = *src++ << 4;
213 else src_val = *src;
214 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
219 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
220 struct rop_codes *codes, int len)
222 BYTE src_val;
224 src_x += len - 1;
225 dst_x += len - 1;
226 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
228 if (dst_x & 1)
230 if (src_x & 1) src_val = *src;
231 else src_val = *src-- >> 4;
232 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
234 else
236 if (src_x & 1) src_val = *src << 4;
237 else src_val = *src--;
238 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
243 static inline void memset_32( DWORD *start, DWORD val, DWORD size )
245 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
246 DWORD dummy;
247 __asm__ __volatile__( "cld; rep; stosl"
248 : "=c" (dummy), "=D" (dummy)
249 : "a" (val), "0" (size), "1" (start) );
250 #else
251 while (size--) *start++ = val;
252 #endif
255 static inline void memset_16( WORD *start, WORD val, DWORD size )
257 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
258 DWORD dummy;
259 __asm__ __volatile__( "cld; rep; stosw"
260 : "=c" (dummy), "=D" (dummy)
261 : "a" (val), "0" (size), "1" (start) );
262 #else
263 while (size--) *start++ = val;
264 #endif
267 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
269 DWORD *ptr, *start;
270 int x, y, i;
272 for(i = 0; i < num; i++, rc++)
274 assert( !is_rect_empty( rc ));
276 start = get_pixel_ptr_32(dib, rc->left, rc->top);
277 if (and)
278 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
279 for(x = rc->left, ptr = start; x < rc->right; x++)
280 do_rop_32(ptr++, and, xor);
281 else
282 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
283 memset_32( start, xor, rc->right - rc->left );
287 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
289 DWORD *ptr, *start;
290 BYTE *byte_ptr, *byte_start;
291 int x, y, i;
292 DWORD and_masks[3], xor_masks[3];
294 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
295 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
296 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
297 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
298 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
299 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
301 for(i = 0; i < num; i++, rc++)
303 int left = dib->rect.left + rc->left;
304 int right = dib->rect.left + rc->right;
306 assert( !is_rect_empty( rc ));
308 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
310 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
311 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
313 for(x = left, byte_ptr = byte_start; x < right; x++)
315 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
316 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
317 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
321 else if (and)
323 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
324 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
326 ptr = start;
328 switch(left & 3)
330 case 1:
331 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
332 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
333 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
334 break;
335 case 2:
336 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
337 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
338 break;
339 case 3:
340 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
341 break;
344 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
346 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
347 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
348 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
351 switch(right & 3)
353 case 1:
354 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
355 break;
356 case 2:
357 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
358 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
359 break;
360 case 3:
361 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
362 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
363 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
364 break;
368 else
370 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
371 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
373 ptr = start;
375 switch(left & 3)
377 case 1:
378 do_rop_32(ptr++, 0x00ffffff, xor_masks[0] & 0xff000000);
379 *ptr++ = xor_masks[1];
380 *ptr++ = xor_masks[2];
381 break;
382 case 2:
383 do_rop_32(ptr++, 0x0000ffff, xor_masks[1] & 0xffff0000);
384 *ptr++ = xor_masks[2];
385 break;
386 case 3:
387 do_rop_32(ptr++, 0x000000ff, xor_masks[2] & 0xffffff00);
388 break;
391 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
393 *ptr++ = xor_masks[0];
394 *ptr++ = xor_masks[1];
395 *ptr++ = xor_masks[2];
398 switch(right & 3)
400 case 1:
401 do_rop_32(ptr, 0xff000000, xor_masks[0] & 0x00ffffff);
402 break;
403 case 2:
404 *ptr++ = xor_masks[0];
405 do_rop_32(ptr, 0xffff0000, xor_masks[1] & 0x0000ffff);
406 break;
407 case 3:
408 *ptr++ = xor_masks[0];
409 *ptr++ = xor_masks[1];
410 do_rop_32(ptr, 0xffffff00, xor_masks[2] & 0x000000ff);
411 break;
418 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
420 WORD *ptr, *start;
421 int x, y, i;
423 for(i = 0; i < num; i++, rc++)
425 assert( !is_rect_empty( rc ));
427 start = get_pixel_ptr_16(dib, rc->left, rc->top);
428 if (and)
429 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
430 for(x = rc->left, ptr = start; x < rc->right; x++)
431 do_rop_16(ptr++, and, xor);
432 else
433 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
434 memset_16( start, xor, rc->right - rc->left );
438 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
440 BYTE *ptr, *start;
441 int x, y, i;
443 for(i = 0; i < num; i++, rc++)
445 assert( !is_rect_empty( rc ));
447 start = get_pixel_ptr_8(dib, rc->left, rc->top);
448 if (and)
449 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
450 for(x = rc->left, ptr = start; x < rc->right; x++)
451 do_rop_8(ptr++, and, xor);
452 else
453 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
454 memset( start, xor, rc->right - rc->left );
458 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
460 BYTE *ptr, *start;
461 int x, y, i;
462 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
463 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
465 for(i = 0; i < num; i++, rc++)
467 int left = dib->rect.left + rc->left;
468 int right = dib->rect.left + rc->right;
470 assert( !is_rect_empty( rc ));
472 start = get_pixel_ptr_4(dib, rc->left, rc->top);
473 if (and)
475 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
477 ptr = start;
478 if(left & 1) /* upper nibble untouched */
479 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
481 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
482 do_rop_8(ptr++, byte_and, byte_xor);
484 if(right & 1) /* lower nibble untouched */
485 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
488 else
490 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
492 unsigned int byte_len = (right - ((left + 1) & ~1)) / 2;
494 ptr = start;
495 if(left & 1) /* upper nibble untouched */
496 do_rop_8(ptr++, 0xf0, byte_xor & 0x0f);
498 memset( ptr, byte_xor, byte_len );
500 if(right & 1) /* lower nibble untouched */
501 do_rop_8(ptr + byte_len, 0x0f, byte_xor & 0xf0);
507 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
509 BYTE *ptr, *start;
510 int x, y, i;
511 BYTE byte_and = (and & 1) ? 0xff : 0;
512 BYTE byte_xor = (xor & 1) ? 0xff : 0;
514 for(i = 0; i < num; i++, rc++)
516 int left = dib->rect.left + rc->left;
517 int right = dib->rect.left + rc->right;
519 assert( !is_rect_empty( rc ));
521 start = get_pixel_ptr_1(dib, rc->left, rc->top);
523 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
525 BYTE mask = edge_masks_1[left & 7] & ~edge_masks_1[right & 7];
527 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
529 do_rop_8(start, byte_and | ~mask, byte_xor & mask);
532 else if (and)
534 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
536 ptr = start;
538 if(left & 7)
539 do_rop_8(ptr++, byte_and | ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
541 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
542 do_rop_8(ptr++, byte_and, byte_xor);
544 if(right & 7)
545 /* this is inverted wrt start mask */
546 do_rop_8(ptr, byte_and | edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
549 else
551 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
553 unsigned int byte_len = (right - ((left + 7) & ~7)) / 8;
555 ptr = start;
557 if(left & 7)
558 do_rop_8(ptr++, ~edge_masks_1[left & 7], byte_xor & edge_masks_1[left & 7]);
560 memset( ptr, byte_xor, byte_len );
562 if(right & 7)
563 do_rop_8(ptr + byte_len, edge_masks_1[right & 7], byte_xor & ~edge_masks_1[right & 7]);
569 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
571 return;
574 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
575 DWORD and, DWORD xor)
577 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
578 int len = params->length, err = params->err_start;
579 int major_inc, minor_inc;
581 if (params->x_major)
583 major_inc = params->x_inc;
584 minor_inc = (dib->stride * params->y_inc) / 4;
586 else
588 major_inc = (dib->stride * params->y_inc) / 4;
589 minor_inc = params->x_inc;
592 while (len--)
594 do_rop_32( ptr, and, xor );
595 if (err + params->bias > 0)
597 ptr += minor_inc;
598 err += params->err_add_1;
600 else err += params->err_add_2;
601 ptr += major_inc;
605 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
606 DWORD and, DWORD xor)
608 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
609 int len = params->length, err = params->err_start;
610 int major_inc, minor_inc;
612 if (params->x_major)
614 major_inc = params->x_inc * 3;
615 minor_inc = dib->stride * params->y_inc;
617 else
619 major_inc = dib->stride * params->y_inc;
620 minor_inc = params->x_inc * 3;
623 while (len--)
625 do_rop_8( ptr, and, xor );
626 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
627 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
628 if (err + params->bias > 0)
630 ptr += minor_inc;
631 err += params->err_add_1;
633 else err += params->err_add_2;
634 ptr += major_inc;
638 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
639 DWORD and, DWORD xor)
641 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
642 int len = params->length, err = params->err_start;
643 int major_inc, minor_inc;
645 if (params->x_major)
647 major_inc = params->x_inc;
648 minor_inc = (dib->stride * params->y_inc) / 2;
650 else
652 major_inc = (dib->stride * params->y_inc) / 2;
653 minor_inc = params->x_inc;
656 while (len--)
658 do_rop_16( ptr, and, xor );
659 if (err + params->bias > 0)
661 ptr += minor_inc;
662 err += params->err_add_1;
664 else err += params->err_add_2;
665 ptr += major_inc;
669 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
670 DWORD and, DWORD xor)
672 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
673 int len = params->length, err = params->err_start;
674 int major_inc, minor_inc;
676 if (params->x_major)
678 major_inc = params->x_inc;
679 minor_inc = dib->stride * params->y_inc;
681 else
683 major_inc = dib->stride * params->y_inc;
684 minor_inc = params->x_inc;
687 while (len--)
689 do_rop_8( ptr, and, xor );
690 if (err + params->bias > 0)
692 ptr += minor_inc;
693 err += params->err_add_1;
695 else err += params->err_add_2;
696 ptr += major_inc;
700 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
701 DWORD and, DWORD xor)
703 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
704 int len = params->length, err = params->err_start;
705 int x = dib->rect.left + start->x;
707 and = (and & 0x0f) | ((and << 4) & 0xf0);
708 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
710 if (params->x_major)
712 while (len--)
714 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
715 if (err + params->bias > 0)
717 ptr += dib->stride * params->y_inc;
718 err += params->err_add_1;
720 else err += params->err_add_2;
721 if ((x / 2) != ((x + params->x_inc) / 2))
722 ptr += params->x_inc;
723 x += params->x_inc;
726 else
728 while (len--)
730 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
731 if (err + params->bias > 0)
733 if ((x / 2) != ((x + params->x_inc) / 2))
734 ptr += params->x_inc;
735 x += params->x_inc;
736 err += params->err_add_1;
738 else err += params->err_add_2;
739 ptr += dib->stride * params->y_inc;
744 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
745 DWORD and, DWORD xor)
747 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
748 int len = params->length, err = params->err_start;
749 int x = dib->rect.left + start->x;
751 and = (and & 0x1) ? 0xff : 0;
752 xor = (xor & 0x1) ? 0xff : 0;
754 if (params->x_major)
756 while (len--)
758 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
759 if (err + params->bias > 0)
761 ptr += dib->stride * params->y_inc;
762 err += params->err_add_1;
764 else err += params->err_add_2;
765 if ((x / 8) != ((x + params->x_inc) / 8))
766 ptr += params->x_inc;
767 x += params->x_inc;
770 else
772 while (len--)
774 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
775 if (err + params->bias > 0)
777 if ((x / 8) != ((x + params->x_inc) / 8))
778 ptr += params->x_inc;
779 x += params->x_inc;
780 err += params->err_add_1;
782 else err += params->err_add_2;
783 ptr += dib->stride * params->y_inc;
788 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
789 DWORD and, DWORD xor)
791 return;
794 static inline INT calc_offset(INT edge, INT size, INT origin)
796 INT offset;
798 if(edge - origin >= 0)
799 offset = (edge - origin) % size;
800 else
802 offset = (origin - edge) % size;
803 if(offset) offset = size - offset;
805 return offset;
808 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
810 POINT offset;
812 offset.x = calc_offset(rc->left, brush->width, origin->x);
813 offset.y = calc_offset(rc->top, brush->height, origin->y);
815 return offset;
818 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
819 const dib_info *brush, const rop_mask_bits *bits)
821 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
822 int x, y, i, len, brush_x;
823 POINT offset;
825 for(i = 0; i < num; i++, rc++)
827 offset = calc_brush_offset(rc, brush, origin);
828 start = get_pixel_ptr_32(dib, rc->left, rc->top);
829 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
831 if (bits->and)
833 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
835 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
837 and_ptr = start_and + offset.x;
838 xor_ptr = start_xor + offset.x;
840 for(x = rc->left, ptr = start; x < rc->right; x++)
842 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
843 if(and_ptr == start_and + brush->width)
845 and_ptr = start_and;
846 xor_ptr = start_xor;
850 offset.y++;
851 if(offset.y == brush->height)
853 start_and = bits->and;
854 start_xor = bits->xor;
855 offset.y = 0;
857 else
859 start_and += brush->stride / 4;
860 start_xor += brush->stride / 4;
864 else
866 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
868 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
870 len = min( rc->right - x, brush->width - brush_x );
871 memcpy( start + x - rc->left, start_xor + brush_x, len * 4 );
872 brush_x = 0;
875 start_xor += brush->stride / 4;
876 offset.y++;
877 if(offset.y == brush->height)
879 start_xor = bits->xor;
880 offset.y = 0;
887 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
888 const dib_info *brush, const rop_mask_bits *bits)
890 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
891 int x, y, i, len, brush_x;
892 POINT offset;
894 for(i = 0; i < num; i++, rc++)
896 offset = calc_brush_offset(rc, brush, origin);
898 start = get_pixel_ptr_24(dib, rc->left, rc->top);
899 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
901 if (bits->and)
903 start_and = (BYTE*)bits->and + offset.y * brush->stride;
904 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
906 and_ptr = start_and + offset.x * 3;
907 xor_ptr = start_xor + offset.x * 3;
909 for(x = rc->left, ptr = start; x < rc->right; x++)
911 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
912 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
913 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
914 if(and_ptr == start_and + brush->width * 3)
916 and_ptr = start_and;
917 xor_ptr = start_xor;
921 offset.y++;
922 if(offset.y == brush->height)
924 start_and = bits->and;
925 start_xor = bits->xor;
926 offset.y = 0;
928 else
930 start_and += brush->stride;
931 start_xor += brush->stride;
935 else
937 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
939 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
941 len = min( rc->right - x, brush->width - brush_x );
942 memcpy( start + (x - rc->left) * 3, start_xor + brush_x * 3, len * 3 );
943 brush_x = 0;
946 start_xor += brush->stride;
947 offset.y++;
948 if(offset.y == brush->height)
950 start_xor = bits->xor;
951 offset.y = 0;
958 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
959 const dib_info *brush, const rop_mask_bits *bits)
961 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
962 int x, y, i, len, brush_x;
963 POINT offset;
965 for(i = 0; i < num; i++, rc++)
967 offset = calc_brush_offset(rc, brush, origin);
969 start = get_pixel_ptr_16(dib, rc->left, rc->top);
970 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
972 if (bits->and)
974 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
975 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
977 and_ptr = start_and + offset.x;
978 xor_ptr = start_xor + offset.x;
980 for(x = rc->left, ptr = start; x < rc->right; x++)
982 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
983 if(and_ptr == start_and + brush->width)
985 and_ptr = start_and;
986 xor_ptr = start_xor;
990 offset.y++;
991 if(offset.y == brush->height)
993 start_and = bits->and;
994 start_xor = bits->xor;
995 offset.y = 0;
997 else
999 start_and += brush->stride / 2;
1000 start_xor += brush->stride / 2;
1004 else
1006 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
1008 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1010 len = min( rc->right - x, brush->width - brush_x );
1011 memcpy( start + x - rc->left, start_xor + brush_x, len * 2 );
1012 brush_x = 0;
1015 start_xor += brush->stride / 2;
1016 offset.y++;
1017 if(offset.y == brush->height)
1019 start_xor = bits->xor;
1020 offset.y = 0;
1027 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1028 const dib_info *brush, const rop_mask_bits *bits)
1030 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1031 int x, y, i, len, brush_x;
1032 POINT offset;
1034 for(i = 0; i < num; i++, rc++)
1036 offset = calc_brush_offset(rc, brush, origin);
1038 start = get_pixel_ptr_8(dib, rc->left, rc->top);
1039 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1041 if (bits->and)
1043 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1044 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1046 and_ptr = start_and + offset.x;
1047 xor_ptr = start_xor + offset.x;
1049 for(x = rc->left, ptr = start; x < rc->right; x++)
1051 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
1052 if(and_ptr == start_and + brush->width)
1054 and_ptr = start_and;
1055 xor_ptr = start_xor;
1059 offset.y++;
1060 if(offset.y == brush->height)
1062 start_and = bits->and;
1063 start_xor = bits->xor;
1064 offset.y = 0;
1066 else
1068 start_and += brush->stride;
1069 start_xor += brush->stride;
1073 else
1075 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1077 for (x = rc->left, brush_x = offset.x; x < rc->right; x += len)
1079 len = min( rc->right - x, brush->width - brush_x );
1080 memcpy( start + x - rc->left, start_xor + brush_x, len );
1081 brush_x = 0;
1084 start_xor += brush->stride;
1085 offset.y++;
1086 if(offset.y == brush->height)
1088 start_xor = bits->xor;
1089 offset.y = 0;
1096 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1097 const dib_info *brush, const rop_mask_bits *bits)
1099 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1100 int x, y, i, left, right;
1101 POINT offset;
1103 for(i = 0; i < num; i++, rc++)
1105 offset = calc_brush_offset(rc, brush, origin);
1106 left = dib->rect.left + rc->left;
1107 right = dib->rect.left + rc->right;
1109 start = get_pixel_ptr_4(dib, rc->left, rc->top);
1110 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1112 if (bits->and)
1114 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1115 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1117 INT brush_x = offset.x;
1118 BYTE byte_and, byte_xor;
1120 and_ptr = start_and + brush_x / 2;
1121 xor_ptr = start_xor + brush_x / 2;
1123 for(x = left, ptr = start; x < right; x++)
1125 /* FIXME: Two pixels at a time */
1126 if(x & 1) /* lower dst nibble */
1128 if(brush_x & 1) /* lower pat nibble */
1130 byte_and = *and_ptr++ | 0xf0;
1131 byte_xor = *xor_ptr++ & 0x0f;
1133 else /* upper pat nibble */
1135 byte_and = (*and_ptr >> 4) | 0xf0;
1136 byte_xor = (*xor_ptr >> 4) & 0x0f;
1139 else /* upper dst nibble */
1141 if(brush_x & 1) /* lower pat nibble */
1143 byte_and = (*and_ptr++ << 4) | 0x0f;
1144 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1146 else /* upper pat nibble */
1148 byte_and = *and_ptr | 0x0f;
1149 byte_xor = *xor_ptr & 0xf0;
1152 do_rop_8(ptr, byte_and, byte_xor);
1154 if(x & 1) ptr++;
1156 if(++brush_x == brush->width)
1158 brush_x = 0;
1159 and_ptr = start_and;
1160 xor_ptr = start_xor;
1164 offset.y++;
1165 if(offset.y == brush->height)
1167 start_and = bits->and;
1168 start_xor = bits->xor;
1169 offset.y = 0;
1171 else
1173 start_and += brush->stride;
1174 start_xor += brush->stride;
1178 else
1180 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1182 INT brush_x = offset.x;
1183 BYTE byte_xor;
1185 xor_ptr = start_xor + brush_x / 2;
1187 for(x = left, ptr = start; x < right; x++)
1189 /* FIXME: Two pixels at a time */
1190 if(x & 1) /* lower dst nibble */
1192 if(brush_x & 1) /* lower pat nibble */
1193 byte_xor = *xor_ptr++ & 0x0f;
1194 else /* upper pat nibble */
1195 byte_xor = (*xor_ptr >> 4) & 0x0f;
1196 do_rop_8(ptr, 0xf0, byte_xor);
1198 else /* upper dst nibble */
1200 if(brush_x & 1) /* lower pat nibble */
1201 byte_xor = (*xor_ptr++ << 4) & 0xf0;
1202 else /* upper pat nibble */
1203 byte_xor = *xor_ptr & 0xf0;
1204 do_rop_8(ptr, 0x0f, byte_xor);
1207 if(x & 1) ptr++;
1209 if(++brush_x == brush->width)
1211 brush_x = 0;
1212 xor_ptr = start_xor;
1216 start_xor += brush->stride;
1217 offset.y++;
1218 if(offset.y == brush->height)
1220 start_xor = bits->xor;
1221 offset.y = 0;
1228 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1229 const dib_info *brush, const rop_mask_bits *bits)
1231 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
1232 int x, y, i, left, right;
1233 POINT offset;
1235 for(i = 0; i < num; i++, rc++)
1237 offset = calc_brush_offset(rc, brush, origin);
1238 left = dib->rect.left + rc->left;
1239 right = dib->rect.left + rc->right;
1241 start = get_pixel_ptr_1(dib, rc->left, rc->top);
1242 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1244 if (bits->and)
1246 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1247 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1249 INT brush_x = offset.x;
1250 BYTE byte_and, byte_xor;
1252 and_ptr = start_and + brush_x / 8;
1253 xor_ptr = start_xor + brush_x / 8;
1255 for(x = left, ptr = start; x < right; x++)
1257 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1258 byte_and |= ~pixel_masks_1[x % 8];
1259 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1260 byte_xor &= pixel_masks_1[x % 8];
1262 do_rop_8(ptr, byte_and, byte_xor);
1264 if((x & 7) == 7) ptr++;
1266 if((brush_x & 7) == 7)
1268 and_ptr++;
1269 xor_ptr++;
1272 if(++brush_x == brush->width)
1274 brush_x = 0;
1275 and_ptr = start_and;
1276 xor_ptr = start_xor;
1280 offset.y++;
1281 if(offset.y == brush->height)
1283 start_and = bits->and;
1284 start_xor = bits->xor;
1285 offset.y = 0;
1287 else
1289 start_and += brush->stride;
1290 start_xor += brush->stride;
1294 else
1296 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1298 INT brush_x = offset.x;
1300 xor_ptr = start_xor + brush_x / 8;
1302 for(x = left, ptr = start; x < right; x++)
1304 BYTE byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1305 byte_xor &= pixel_masks_1[x % 8];
1307 do_rop_8(ptr, ~pixel_masks_1[x % 8], byte_xor);
1309 if((x & 7) == 7) ptr++;
1310 if((brush_x & 7) == 7) xor_ptr++;
1312 if(++brush_x == brush->width)
1314 brush_x = 0;
1315 xor_ptr = start_xor;
1319 start_xor += brush->stride;
1320 offset.y++;
1321 if(offset.y == brush->height)
1323 start_xor = bits->xor;
1324 offset.y = 0;
1331 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1332 const dib_info *brush, const rop_mask_bits *bits)
1334 return;
1337 static inline void copy_rect_bits_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1338 int dst_stride, int src_stride, int rop2 )
1340 const DWORD *src;
1341 DWORD *dst;
1342 int x, y;
1344 #define LOOP( op ) \
1345 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1346 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src++, dst++) \
1349 switch (rop2)
1351 ROPS_WITHOUT_COPY( dst[0], src[0] )
1353 #undef LOOP
1356 static inline void copy_rect_bits_rev_32( DWORD *dst_start, const DWORD *src_start, const SIZE *size,
1357 int dst_stride, int src_stride, int rop2 )
1359 const DWORD *src;
1360 DWORD *dst;
1361 int x, y;
1363 src_start += size->cx - 1;
1364 dst_start += size->cx - 1;
1366 #define LOOP( op ) \
1367 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1368 for (x = 0, src = src_start, dst = dst_start; x < size->cx; x++, src--, dst--) \
1371 switch (rop2)
1373 ROPS_WITHOUT_COPY( dst[0], src[0] )
1375 #undef LOOP
1378 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1379 const dib_info *src, const POINT *origin, int rop2, int overlap)
1381 DWORD *dst_start, *src_start;
1382 int y, dst_stride, src_stride;
1383 SIZE size;
1385 if (overlap & OVERLAP_BELOW)
1387 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1388 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1389 dst_stride = -dst->stride / 4;
1390 src_stride = -src->stride / 4;
1392 else
1394 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1395 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1396 dst_stride = dst->stride / 4;
1397 src_stride = src->stride / 4;
1400 if (rop2 == R2_COPYPEN)
1402 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1403 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1404 return;
1407 size.cx = rc->right - rc->left;
1408 size.cy = rc->bottom - rc->top;
1410 if (overlap & OVERLAP_RIGHT)
1411 copy_rect_bits_rev_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1412 else
1413 copy_rect_bits_32( dst_start, src_start, &size, dst_stride, src_stride, rop2 );
1416 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1417 const dib_info *src, const POINT *origin, int rop2, int overlap)
1419 BYTE *dst_start, *src_start;
1420 int y, dst_stride, src_stride;
1421 struct rop_codes codes;
1423 if (overlap & OVERLAP_BELOW)
1425 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1426 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1427 dst_stride = -dst->stride;
1428 src_stride = -src->stride;
1430 else
1432 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1433 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1434 dst_stride = dst->stride;
1435 src_stride = src->stride;
1438 if (rop2 == R2_COPYPEN)
1440 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1441 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1442 return;
1445 get_rop_codes( rop2, &codes );
1446 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1448 if (overlap & OVERLAP_RIGHT)
1449 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1450 else
1451 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1455 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1456 const dib_info *src, const POINT *origin, int rop2, int overlap)
1458 WORD *dst_start, *src_start;
1459 int y, dst_stride, src_stride;
1460 struct rop_codes codes;
1462 if (overlap & OVERLAP_BELOW)
1464 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1465 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1466 dst_stride = -dst->stride / 2;
1467 src_stride = -src->stride / 2;
1469 else
1471 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1472 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1473 dst_stride = dst->stride / 2;
1474 src_stride = src->stride / 2;
1477 if (rop2 == R2_COPYPEN)
1479 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1480 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1481 return;
1484 get_rop_codes( rop2, &codes );
1485 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1487 if (overlap & OVERLAP_RIGHT)
1488 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1489 else
1490 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1494 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1495 const dib_info *src, const POINT *origin, int rop2, int overlap)
1497 BYTE *dst_start, *src_start;
1498 int y, dst_stride, src_stride;
1499 struct rop_codes codes;
1501 if (overlap & OVERLAP_BELOW)
1503 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1504 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1505 dst_stride = -dst->stride;
1506 src_stride = -src->stride;
1508 else
1510 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1511 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1512 dst_stride = dst->stride;
1513 src_stride = src->stride;
1516 if (rop2 == R2_COPYPEN)
1518 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1519 memmove( dst_start, src_start, (rc->right - rc->left) );
1520 return;
1523 get_rop_codes( rop2, &codes );
1524 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1526 if (overlap & OVERLAP_RIGHT)
1527 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1528 else
1529 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1533 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1534 const dib_info *src, const POINT *origin, int rop2, int overlap)
1536 BYTE *dst_start, *src_start;
1537 int y, dst_stride, src_stride;
1538 struct rop_codes codes;
1539 int left = dst->rect.left + rc->left;
1540 int right = dst->rect.left + rc->right;
1541 int org_x = src->rect.left + origin->x;
1543 if (overlap & OVERLAP_BELOW)
1545 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1546 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1547 dst_stride = -dst->stride;
1548 src_stride = -src->stride;
1550 else
1552 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1553 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1554 dst_stride = dst->stride;
1555 src_stride = src->stride;
1558 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1560 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1561 memmove( dst_start, src_start, (right - left) / 2 );
1562 return;
1565 get_rop_codes( rop2, &codes );
1566 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1568 if (overlap & OVERLAP_RIGHT)
1569 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1570 else
1571 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1575 static inline void copy_rect_bits_partial_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1576 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1578 const BYTE *src;
1579 BYTE *dst, src_val, mask;
1580 int dst_end = dst_x + size->cx, y;
1581 int off = (src_x & 7) - (dst_x & 7);
1582 struct rop_codes codes;
1584 get_rop_codes( rop2, &codes );
1586 src_start += src_x / 8;
1587 dst_start += dst_x / 8;
1589 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1591 dst = dst_start;
1592 src = src_start;
1593 if (off == 0)
1594 src_val = src[0];
1595 else if (off > 0)
1597 src_val = src[0] << off;
1598 if ((dst_end & 7) + off > 8)
1599 src_val |= (src[1] >> (8 - off));
1601 else
1602 src_val = src[0] >> -off;
1604 mask = edge_masks_1[dst_x & 7];
1605 if (dst_end & 7)
1606 mask &= ~edge_masks_1[dst_end & 7];
1607 do_rop_codes_mask_8( dst, src_val, &codes, mask );
1611 static inline void copy_rect_bits_align_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1612 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1614 const BYTE *src;
1615 BYTE *dst, mask;
1616 int y, i, full_bytes, dst_end = dst_x + size->cx;
1617 struct rop_codes codes;
1619 get_rop_codes( rop2, &codes );
1621 src_start += src_x / 8;
1622 dst_start += dst_x / 8;
1623 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1625 switch( rop2 )
1627 case R2_COPYPEN:
1628 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1630 dst = dst_start;
1631 src = src_start;
1632 if (dst_x & 7)
1634 mask = edge_masks_1[dst_x & 7];
1635 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1636 src++;
1637 dst++;
1639 memmove( dst, src, full_bytes );
1640 src += full_bytes;
1641 dst += full_bytes;
1642 if (dst_end & 7)
1644 mask = ~edge_masks_1[dst_end & 7];
1645 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1648 break;
1650 #define LOOP( op ) \
1651 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1653 dst = dst_start; \
1654 src = src_start; \
1655 if (dst_x & 7) \
1657 mask = edge_masks_1[dst_x & 7]; \
1658 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1659 src++; \
1660 dst++; \
1662 for (i = 0; i < full_bytes; i++, src++, dst++) \
1663 op; \
1664 if (dst_end & 7) \
1666 mask = ~edge_masks_1[dst_end & 7]; \
1667 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1671 ROPS_WITHOUT_COPY( dst[0], src[0] );
1673 #undef LOOP
1676 static inline void copy_rect_bits_shl_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1677 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1679 const BYTE *src;
1680 BYTE *dst, mask, src_val;
1681 int y, i, full_bytes, dst_end = dst_x + size->cx;
1682 int off = (src_x & 7) - (dst_x & 7);
1683 struct rop_codes codes;
1685 get_rop_codes( rop2, &codes );
1687 src_start += src_x / 8;
1688 dst_start += dst_x / 8;
1689 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1691 #define LOOP( op ) \
1692 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1694 dst = dst_start; \
1695 src = src_start; \
1696 if (dst_x & 7) \
1698 src_val = (src[0] << off) | (src[1] >> (8 - off)); \
1699 mask = edge_masks_1[dst_x & 7]; \
1700 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1701 src++; \
1702 dst++; \
1704 for (i = 0; i < full_bytes; i++, src++, dst++) \
1705 op; \
1706 if (dst_end & 7) \
1708 src_val = src[0] << off; \
1709 if ((dst_end & 7) + off > 8) \
1710 src_val |= (src[1] >> (8 - off)); \
1711 mask = ~edge_masks_1[dst_end & 7]; \
1712 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1716 switch( rop2 )
1718 ROPS_ALL( dst[0], ((src[0] << off) | (src[1] >> (8 - off))) );
1720 #undef LOOP
1723 static inline void copy_rect_bits_shr_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1724 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1726 const BYTE *src;
1727 BYTE *dst, mask, src_val, last_src;
1728 int y, i, full_bytes, dst_end = dst_x + size->cx;
1729 int off = (src_x & 7) - (dst_x & 7);
1730 struct rop_codes codes;
1732 get_rop_codes( rop2, &codes );
1734 src_start += src_x / 8;
1735 dst_start += dst_x / 8;
1736 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1738 #define LOOP( op ) \
1739 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1741 dst = dst_start; \
1742 src = src_start; \
1743 last_src = 0; \
1744 if (dst_x & 7) \
1746 last_src = src[0]; \
1747 mask = edge_masks_1[dst_x & 7]; \
1748 do_rop_codes_mask_8( dst, src[0] >> -off, &codes, mask ); \
1749 src++; \
1750 dst++; \
1752 for (i = 0; i < full_bytes; i++, src++, dst++) \
1754 src_val = (last_src << (8 + off)) | (src[0] >> -off); \
1755 last_src = src[0]; \
1756 op; \
1758 if (dst_end & 7) \
1760 src_val = last_src << (8 + off); \
1761 if ((dst_end & 7) + off > 0) \
1762 src_val |= (src[0] >> -off); \
1763 mask = ~edge_masks_1[dst_end & 7]; \
1764 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1768 switch( rop2 )
1770 ROPS_ALL( dst[0], src_val )
1772 #undef LOOP
1775 static inline void copy_rect_bits_rev_align_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1776 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1778 const BYTE *src;
1779 BYTE *dst, mask;
1780 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1781 struct rop_codes codes;
1783 get_rop_codes( rop2, &codes );
1785 src_start += (src_end - 1) / 8;
1786 dst_start += (dst_end - 1) / 8;
1787 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1789 switch( rop2 )
1791 case R2_COPYPEN:
1792 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride)
1794 dst = dst_start;
1795 src = src_start;
1796 if (dst_end & 7)
1798 mask = ~edge_masks_1[dst_end & 7];
1799 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1800 src--;
1801 dst--;
1803 memmove( dst, src, full_bytes );
1804 src -= full_bytes;
1805 dst -= full_bytes;
1806 if (dst_x & 7)
1808 mask = edge_masks_1[dst_x & 7];
1809 do_rop_codes_mask_8( dst, src[0], &codes, mask );
1812 break;
1814 #define LOOP( op ) \
1815 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1817 dst = dst_start; \
1818 src = src_start; \
1819 if (dst_end & 7) \
1821 mask = ~edge_masks_1[dst_end & 7]; \
1822 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1823 src--; \
1824 dst--; \
1826 for (i = 0; i < full_bytes; i++, src--, dst--) \
1827 op; \
1828 if (dst_x & 7) \
1830 mask = edge_masks_1[dst_x & 7]; \
1831 do_rop_codes_mask_8( dst, src[0], &codes, mask ); \
1835 ROPS_WITHOUT_COPY( dst[0], src[0] );
1837 #undef LOOP
1840 static inline void copy_rect_bits_rev_shl_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1841 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1843 const BYTE *src;
1844 BYTE *dst, mask, src_val, last_src;
1845 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1846 int off = ((src_end - 1) & 7) - ((dst_end - 1) & 7);
1847 struct rop_codes codes;
1849 get_rop_codes( rop2, &codes );
1851 src_start += (src_end - 1) / 8;
1852 dst_start += (dst_end - 1) / 8;
1853 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1855 #define LOOP( op ) \
1856 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1858 dst = dst_start; \
1859 src = src_start; \
1860 last_src = 0; \
1861 if (dst_end & 7) \
1863 last_src = src[0]; \
1864 mask = ~edge_masks_1[dst_end & 7]; \
1865 do_rop_codes_mask_8( dst, src[0] << off, &codes, mask ); \
1866 src--; \
1867 dst--; \
1869 for (i = 0; i < full_bytes; i++, src--, dst--) \
1871 src_val = (src[0] << off) | (last_src >> (8 - off)); \
1872 last_src = src[0]; \
1873 op; \
1875 if (dst_x & 7) \
1877 src_val = last_src >> (8 - off); \
1878 if ((dst_x & 7) + off < 8) \
1879 src_val |= (src[0] << off); \
1880 mask = edge_masks_1[dst_x & 7]; \
1881 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1885 switch( rop2 )
1887 ROPS_ALL( dst[0], src_val );
1889 #undef LOOP
1892 static inline void copy_rect_bits_rev_shr_1( BYTE *dst_start, int dst_x, const BYTE *src_start, int src_x,
1893 const SIZE *size, int dst_stride, int src_stride, int rop2 )
1895 const BYTE *src;
1896 BYTE *dst, mask, src_val;
1897 int y, i, full_bytes, dst_end = dst_x + size->cx, src_end = src_x + size->cx;
1898 int off = ((src_end - 1) & 7) - ((dst_end - 1) & 7);
1899 struct rop_codes codes;
1901 get_rop_codes( rop2, &codes );
1903 src_start += (src_end - 1) / 8;
1904 dst_start += (dst_end - 1) / 8;
1905 full_bytes = (dst_end - ((dst_x + 7) & ~7)) / 8;
1907 #define LOOP( op ) \
1908 for (y = 0; y < size->cy; y++, dst_start += dst_stride, src_start += src_stride) \
1910 dst = dst_start; \
1911 src = src_start; \
1912 if (dst_end & 7) \
1914 mask = edge_masks_1[dst_x & 7]; \
1915 do_rop_codes_mask_8( dst, (src[-1] << (8 + off)) | (src[0] >> -off), &codes, mask ); \
1916 src--; \
1917 dst--; \
1919 for (i = 0; i < full_bytes; i++, src--, dst--) \
1920 op; \
1921 if (dst_x & 7) \
1923 src_val = src[0] >> -off; \
1924 if ((dst_x & 7) + off < 0) \
1925 src_val |= (src[-1] << (8 + off)); \
1926 mask = edge_masks_1[dst_x & 7]; \
1927 do_rop_codes_mask_8( dst, src_val, &codes, mask ); \
1931 switch( rop2 )
1933 ROPS_ALL( dst[0], (src[-1] << (8 + off)) | (src[0] >> -off) );
1935 #undef LOOP
1938 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1939 const dib_info *src, const POINT *origin, int rop2, int overlap)
1941 BYTE *dst_start, *src_start;
1942 int y, dst_stride, src_stride;
1943 int left = dst->rect.left + rc->left;
1944 int right = dst->rect.left + rc->right;
1945 int org_x = src->rect.left + origin->x;
1946 SIZE size;
1948 if (overlap & OVERLAP_BELOW)
1950 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1951 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1952 dst_stride = -dst->stride;
1953 src_stride = -src->stride;
1955 else
1957 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1958 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1959 dst_stride = dst->stride;
1960 src_stride = src->stride;
1963 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1965 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1966 memmove( dst_start, src_start, (right - left) / 8 );
1967 return;
1970 size.cx = right - left;
1971 size.cy = rc->bottom - rc->top;
1973 /* Special case starting and finishing in same byte, neither on byte boundary */
1974 if ((left & 7) && (right & 7) && (left & ~7) == (right & ~7))
1975 copy_rect_bits_partial_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1976 else if (overlap & OVERLAP_RIGHT)
1978 int off = ((org_x + right - left - 1) & 7) - ((right - 1) & 7);
1980 if (off == 0)
1981 copy_rect_bits_rev_align_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1982 else if (off > 0)
1983 copy_rect_bits_rev_shl_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1984 else
1985 copy_rect_bits_rev_shr_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1987 else
1989 int off = (org_x & 7) - (left & 7);
1991 if (off == 0)
1992 copy_rect_bits_align_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1993 else if (off > 0)
1994 copy_rect_bits_shl_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
1995 else
1996 copy_rect_bits_shr_1( dst_start, left & 7, src_start, org_x & 7, &size, dst_stride, src_stride, rop2 );
2000 static void copy_rect_null(const dib_info *dst, const RECT *rc,
2001 const dib_info *src, const POINT *origin, int rop2, int overlap)
2003 return;
2006 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
2008 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
2009 return *ptr;
2012 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
2014 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
2015 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
2018 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
2020 WORD *ptr = get_pixel_ptr_16( dib, x, y );
2021 return *ptr;
2024 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
2026 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
2027 return *ptr;
2030 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
2032 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
2034 if ((dib->rect.left + x) & 1)
2035 return *ptr & 0x0f;
2036 else
2037 return (*ptr >> 4) & 0x0f;
2040 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
2042 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
2043 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
2046 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
2048 return 0;
2051 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
2053 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
2056 static const DWORD field_masks[33] =
2058 0x00, /* should never happen */
2059 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
2060 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2061 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2062 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2065 static inline DWORD get_field(DWORD field, int shift, int len)
2067 shift = shift - (8 - len);
2068 if (shift < 0)
2069 field <<= -shift;
2070 else
2071 field >>= shift;
2072 field &= field_masks[len];
2073 field |= field >> len;
2074 return field;
2077 static inline DWORD put_field(DWORD field, int shift, int len)
2079 shift = shift - (8 - len);
2080 field &= field_masks[len];
2081 if (shift < 0)
2082 field >>= -shift;
2083 else
2084 field <<= shift;
2085 return field;
2088 static DWORD rgb_to_pixel_masks(const dib_info *dib, DWORD r, DWORD g, DWORD b)
2090 return put_field(r, dib->red_shift, dib->red_len) |
2091 put_field(g, dib->green_shift, dib->green_len) |
2092 put_field(b, dib->blue_shift, dib->blue_len);
2095 static DWORD rgbquad_to_pixel_masks(const dib_info *dib, RGBQUAD rgb)
2097 return rgb_to_pixel_masks(dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2100 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
2102 return rgb_to_pixel_masks(dib, GetRValue(colour), GetGValue(colour), GetBValue(colour));
2105 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
2107 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
2110 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
2112 const RGBQUAD *color_table = get_dib_color_table( dib );
2113 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
2114 int i, best_index = 0;
2115 DWORD diff, best_diff = 0xffffffff;
2117 for(i = 0; i < size; i++)
2119 const RGBQUAD *cur = color_table + i;
2120 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
2121 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
2122 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
2124 if(diff == 0)
2126 best_index = i;
2127 break;
2130 if(diff < best_diff)
2132 best_diff = diff;
2133 best_index = i;
2136 return best_index;
2139 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y,
2140 DWORD src_pixel, DWORD bg_pixel, BYTE r, BYTE g, BYTE b)
2142 DWORD ret;
2144 if (dib->color_table_size != 1)
2146 if (dither)
2148 if (((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255) r = g = b = 255;
2149 else r = g = b = 0;
2151 ret = rgb_to_pixel_colortable( dib, r, g, b );
2153 else ret = (src_pixel == bg_pixel); /* only match raw pixel value */
2155 return ret ? 0xff : 0;
2158 static DWORD rgbquad_to_pixel_colortable(const dib_info *dib, RGBQUAD rgb)
2160 return rgb_to_pixel_colortable( dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue );
2163 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
2165 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
2168 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
2170 return 0;
2173 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
2175 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
2178 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
2180 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
2181 get_field( pixel, dib->green_shift, dib->green_len ),
2182 get_field( pixel, dib->blue_shift, dib->blue_len ) );
2185 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
2187 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
2188 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
2189 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
2192 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
2194 const RGBQUAD *color_table = get_dib_color_table( dib );
2196 if (!dib->color_table || pixel < dib->color_table_size)
2198 RGBQUAD quad = color_table[pixel];
2199 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
2201 return 0;
2204 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
2206 return 0;
2209 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
2211 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
2213 return d1->red_mask == d2->red_mask &&
2214 d1->green_mask == d2->green_mask &&
2215 d1->blue_mask == d2->blue_mask;
2218 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2220 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2221 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2223 switch(src->bit_count)
2225 case 32:
2227 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2228 if(src->funcs == &funcs_8888)
2230 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2231 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2232 else
2234 for(y = src_rect->top; y < src_rect->bottom; y++)
2236 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2237 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2238 dst_start += dst->stride / 4;
2239 src_start += src->stride / 4;
2243 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2245 for(y = src_rect->top; y < src_rect->bottom; y++)
2247 dst_pixel = dst_start;
2248 src_pixel = src_start;
2249 for(x = src_rect->left; x < src_rect->right; x++)
2251 src_val = *src_pixel++;
2252 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
2253 (((src_val >> src->green_shift) & 0xff) << 8) |
2254 ((src_val >> src->blue_shift) & 0xff);
2256 if(pad_size) memset(dst_pixel, 0, pad_size);
2257 dst_start += dst->stride / 4;
2258 src_start += src->stride / 4;
2261 else
2263 for(y = src_rect->top; y < src_rect->bottom; y++)
2265 dst_pixel = dst_start;
2266 src_pixel = src_start;
2267 for(x = src_rect->left; x < src_rect->right; x++)
2269 src_val = *src_pixel++;
2270 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2271 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2272 get_field( src_val, src->blue_shift, src->blue_len ));
2274 if(pad_size) memset(dst_pixel, 0, pad_size);
2275 dst_start += dst->stride / 4;
2276 src_start += src->stride / 4;
2279 break;
2282 case 24:
2284 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2286 for(y = src_rect->top; y < src_rect->bottom; y++)
2288 dst_pixel = dst_start;
2289 src_pixel = src_start;
2290 for(x = src_rect->left; x < src_rect->right; x++)
2292 RGBQUAD rgb;
2293 rgb.rgbBlue = *src_pixel++;
2294 rgb.rgbGreen = *src_pixel++;
2295 rgb.rgbRed = *src_pixel++;
2297 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
2299 if(pad_size) memset(dst_pixel, 0, pad_size);
2300 dst_start += dst->stride / 4;
2301 src_start += src->stride;
2303 break;
2306 case 16:
2308 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2309 if(src->funcs == &funcs_555)
2311 for(y = src_rect->top; y < src_rect->bottom; y++)
2313 dst_pixel = dst_start;
2314 src_pixel = src_start;
2315 for(x = src_rect->left; x < src_rect->right; x++)
2317 src_val = *src_pixel++;
2318 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
2319 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
2320 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
2322 if(pad_size) memset(dst_pixel, 0, pad_size);
2323 dst_start += dst->stride / 4;
2324 src_start += src->stride / 2;
2327 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2329 for(y = src_rect->top; y < src_rect->bottom; y++)
2331 dst_pixel = dst_start;
2332 src_pixel = src_start;
2333 for(x = src_rect->left; x < src_rect->right; x++)
2335 src_val = *src_pixel++;
2336 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2337 (((src_val >> src->red_shift) << 14) & 0x070000) |
2338 (((src_val >> src->green_shift) << 11) & 0x00f800) |
2339 (((src_val >> src->green_shift) << 6) & 0x000700) |
2340 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2341 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2343 if(pad_size) memset(dst_pixel, 0, pad_size);
2344 dst_start += dst->stride / 4;
2345 src_start += src->stride / 2;
2348 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2350 for(y = src_rect->top; y < src_rect->bottom; y++)
2352 dst_pixel = dst_start;
2353 src_pixel = src_start;
2354 for(x = src_rect->left; x < src_rect->right; x++)
2356 src_val = *src_pixel++;
2357 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
2358 (((src_val >> src->red_shift) << 14) & 0x070000) |
2359 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
2360 (((src_val >> src->green_shift) << 4) & 0x000300) |
2361 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
2362 (((src_val >> src->blue_shift) >> 2) & 0x000007);
2364 if(pad_size) memset(dst_pixel, 0, pad_size);
2365 dst_start += dst->stride / 4;
2366 src_start += src->stride / 2;
2369 else
2371 for(y = src_rect->top; y < src_rect->bottom; y++)
2373 dst_pixel = dst_start;
2374 src_pixel = src_start;
2375 for(x = src_rect->left; x < src_rect->right; x++)
2377 src_val = *src_pixel++;
2378 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
2379 get_field( src_val, src->green_shift, src->green_len ) << 8 |
2380 get_field( src_val, src->blue_shift, src->blue_len ));
2382 if(pad_size) memset(dst_pixel, 0, pad_size);
2383 dst_start += dst->stride / 4;
2384 src_start += src->stride / 2;
2387 break;
2390 case 8:
2392 const RGBQUAD *color_table = get_dib_color_table( src );
2393 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2394 DWORD dst_colors[256], i;
2396 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2397 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2398 color_table[i].rgbBlue;
2400 for(y = src_rect->top; y < src_rect->bottom; y++)
2402 dst_pixel = dst_start;
2403 src_pixel = src_start;
2404 for(x = src_rect->left; x < src_rect->right; x++)
2405 *dst_pixel++ = dst_colors[*src_pixel++];
2407 if(pad_size) memset(dst_pixel, 0, pad_size);
2408 dst_start += dst->stride / 4;
2409 src_start += src->stride;
2411 break;
2414 case 4:
2416 const RGBQUAD *color_table = get_dib_color_table( src );
2417 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2418 DWORD dst_colors[16], i;
2420 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2421 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2422 color_table[i].rgbBlue;
2424 for(y = src_rect->top; y < src_rect->bottom; y++)
2426 int pos = (src->rect.left + src_rect->left) & 1;
2427 src_pixel = src_start;
2428 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2430 if (pos & 1)
2431 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2432 else
2433 dst_start[x] = dst_colors[*src_pixel >> 4];
2435 if(pad_size) memset(dst_start + x, 0, pad_size);
2436 dst_start += dst->stride / 4;
2437 src_start += src->stride;
2439 break;
2442 case 1:
2444 const RGBQUAD *color_table = get_dib_color_table( src );
2445 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2446 DWORD dst_colors[2], i;
2448 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2449 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
2450 color_table[i].rgbBlue;
2452 for(y = src_rect->top; y < src_rect->bottom; y++)
2454 int pos = (src->rect.left + src_rect->left) & 7;
2455 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2457 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2458 dst_start[x] = dst_colors[src_val];
2460 if(pad_size) memset(dst_start + x, 0, pad_size);
2461 dst_start += dst->stride / 4;
2462 src_start += src->stride;
2464 break;
2469 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2471 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
2472 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
2474 switch(src->bit_count)
2476 case 32:
2478 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2480 if(src->funcs == &funcs_8888)
2482 for(y = src_rect->top; y < src_rect->bottom; y++)
2484 dst_pixel = dst_start;
2485 src_pixel = src_start;
2486 for(x = src_rect->left; x < src_rect->right; x++)
2488 src_val = *src_pixel++;
2489 *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val);
2491 if(pad_size) memset(dst_pixel, 0, pad_size);
2492 dst_start += dst->stride / 4;
2493 src_start += src->stride / 4;
2496 else if(bit_fields_match(src, dst))
2498 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2499 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2500 else
2502 for(y = src_rect->top; y < src_rect->bottom; y++)
2504 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
2505 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2506 dst_start += dst->stride / 4;
2507 src_start += src->stride / 4;
2511 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
2512 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
2514 for(y = src_rect->top; y < src_rect->bottom; y++)
2516 dst_pixel = dst_start;
2517 src_pixel = src_start;
2518 for(x = src_rect->left; x < src_rect->right; x++)
2520 src_val = *src_pixel++;
2521 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
2522 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
2523 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
2525 if(pad_size) memset(dst_pixel, 0, pad_size);
2526 dst_start += dst->stride / 4;
2527 src_start += src->stride / 4;
2530 else
2532 for(y = src_rect->top; y < src_rect->bottom; y++)
2534 dst_pixel = dst_start;
2535 src_pixel = src_start;
2536 for(x = src_rect->left; x < src_rect->right; x++)
2538 src_val = *src_pixel++;
2539 *dst_pixel++ = rgb_to_pixel_masks(dst,
2540 get_field(src_val, src->red_shift, src->red_len),
2541 get_field(src_val, src->green_shift, src->green_len),
2542 get_field(src_val, src->blue_shift, src->blue_len));
2544 if(pad_size) memset(dst_pixel, 0, pad_size);
2545 dst_start += dst->stride / 4;
2546 src_start += src->stride / 4;
2549 break;
2552 case 24:
2554 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2556 for(y = src_rect->top; y < src_rect->bottom; y++)
2558 dst_pixel = dst_start;
2559 src_pixel = src_start;
2560 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2561 *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2562 if(pad_size) memset(dst_pixel, 0, pad_size);
2563 dst_start += dst->stride / 4;
2564 src_start += src->stride;
2566 break;
2569 case 16:
2571 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2572 if(src->funcs == &funcs_555)
2574 for(y = src_rect->top; y < src_rect->bottom; y++)
2576 dst_pixel = dst_start;
2577 src_pixel = src_start;
2578 for(x = src_rect->left; x < src_rect->right; x++)
2580 src_val = *src_pixel++;
2581 *dst_pixel++ = rgb_to_pixel_masks(dst,
2582 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2583 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2584 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
2586 if(pad_size) memset(dst_pixel, 0, pad_size);
2587 dst_start += dst->stride / 4;
2588 src_start += src->stride / 2;
2591 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2593 for(y = src_rect->top; y < src_rect->bottom; y++)
2595 dst_pixel = dst_start;
2596 src_pixel = src_start;
2597 for(x = src_rect->left; x < src_rect->right; x++)
2599 src_val = *src_pixel++;
2600 *dst_pixel++ = rgb_to_pixel_masks(dst,
2601 (((src_val >> src->red_shift) << 3) & 0xf8) |
2602 (((src_val >> src->red_shift) >> 2) & 0x07),
2603 (((src_val >> src->green_shift) << 3) & 0xf8) |
2604 (((src_val >> src->green_shift) >> 2) & 0x07),
2605 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2606 (((src_val >> src->blue_shift) >> 2) & 0x07));
2608 if(pad_size) memset(dst_pixel, 0, pad_size);
2609 dst_start += dst->stride / 4;
2610 src_start += src->stride / 2;
2613 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2615 for(y = src_rect->top; y < src_rect->bottom; y++)
2617 dst_pixel = dst_start;
2618 src_pixel = src_start;
2619 for(x = src_rect->left; x < src_rect->right; x++)
2621 src_val = *src_pixel++;
2622 *dst_pixel++ = rgb_to_pixel_masks(dst,
2623 (((src_val >> src->red_shift) << 3) & 0xf8) |
2624 (((src_val >> src->red_shift) >> 2) & 0x07),
2625 (((src_val >> src->green_shift) << 2) & 0xfc) |
2626 (((src_val >> src->green_shift) >> 4) & 0x03),
2627 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2628 (((src_val >> src->blue_shift) >> 2) & 0x07));
2630 if(pad_size) memset(dst_pixel, 0, pad_size);
2631 dst_start += dst->stride / 4;
2632 src_start += src->stride / 2;
2635 else
2637 for(y = src_rect->top; y < src_rect->bottom; y++)
2639 dst_pixel = dst_start;
2640 src_pixel = src_start;
2641 for(x = src_rect->left; x < src_rect->right; x++)
2643 src_val = *src_pixel++;
2644 *dst_pixel++ = rgb_to_pixel_masks(dst,
2645 get_field(src_val, src->red_shift, src->red_len),
2646 get_field(src_val, src->green_shift, src->green_len),
2647 get_field(src_val, src->blue_shift, src->blue_len));
2649 if(pad_size) memset(dst_pixel, 0, pad_size);
2650 dst_start += dst->stride / 4;
2651 src_start += src->stride / 2;
2654 break;
2657 case 8:
2659 const RGBQUAD *color_table = get_dib_color_table( src );
2660 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2661 DWORD dst_colors[256], i;
2663 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2664 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2666 for(y = src_rect->top; y < src_rect->bottom; y++)
2668 dst_pixel = dst_start;
2669 src_pixel = src_start;
2670 for(x = src_rect->left; x < src_rect->right; x++)
2671 *dst_pixel++ = dst_colors[*src_pixel++];
2673 if(pad_size) memset(dst_pixel, 0, pad_size);
2674 dst_start += dst->stride / 4;
2675 src_start += src->stride;
2677 break;
2680 case 4:
2682 const RGBQUAD *color_table = get_dib_color_table( src );
2683 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2684 DWORD dst_colors[16], i;
2686 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2687 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2689 for(y = src_rect->top; y < src_rect->bottom; y++)
2691 int pos = (src->rect.left + src_rect->left) & 1;
2692 src_pixel = src_start;
2693 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2695 if (pos & 1)
2696 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
2697 else
2698 dst_start[x] = dst_colors[*src_pixel >> 4];
2700 if(pad_size) memset(dst_start + x, 0, pad_size);
2701 dst_start += dst->stride / 4;
2702 src_start += src->stride;
2704 break;
2707 case 1:
2709 const RGBQUAD *color_table = get_dib_color_table( src );
2710 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2711 DWORD dst_colors[2], i;
2713 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
2714 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
2716 for(y = src_rect->top; y < src_rect->bottom; y++)
2718 int pos = (src->rect.left + src_rect->left) & 7;
2719 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2721 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2722 dst_start[x] = dst_colors[src_val];
2724 if(pad_size) memset(dst_start + x, 0, pad_size);
2725 dst_start += dst->stride / 4;
2726 src_start += src->stride;
2728 break;
2733 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2735 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2736 DWORD src_val;
2737 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2739 switch(src->bit_count)
2741 case 32:
2743 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2744 if(src->funcs == &funcs_8888)
2746 for(y = src_rect->top; y < src_rect->bottom; y++)
2748 dst_pixel = dst_start;
2749 src_pixel = src_start;
2750 for(x = src_rect->left; x < src_rect->right; x++)
2752 src_val = *src_pixel++;
2753 *dst_pixel++ = src_val & 0xff;
2754 *dst_pixel++ = (src_val >> 8) & 0xff;
2755 *dst_pixel++ = (src_val >> 16) & 0xff;
2757 if(pad_size) memset(dst_pixel, 0, pad_size);
2758 dst_start += dst->stride;
2759 src_start += src->stride / 4;
2762 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2764 for(y = src_rect->top; y < src_rect->bottom; y++)
2766 dst_pixel = dst_start;
2767 src_pixel = src_start;
2768 for(x = src_rect->left; x < src_rect->right; x++)
2770 src_val = *src_pixel++;
2771 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2772 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2773 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2775 if(pad_size) memset(dst_pixel, 0, pad_size);
2776 dst_start += dst->stride;
2777 src_start += src->stride / 4;
2780 else
2782 for(y = src_rect->top; y < src_rect->bottom; y++)
2784 dst_pixel = dst_start;
2785 src_pixel = src_start;
2786 for(x = src_rect->left; x < src_rect->right; x++)
2788 src_val = *src_pixel++;
2789 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2790 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2791 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2793 if(pad_size) memset(dst_pixel, 0, pad_size);
2794 dst_start += dst->stride;
2795 src_start += src->stride / 4;
2798 break;
2801 case 24:
2803 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2805 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2806 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2807 else
2809 for(y = src_rect->top; y < src_rect->bottom; y++)
2811 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2812 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2813 dst_start += dst->stride;
2814 src_start += src->stride;
2817 break;
2820 case 16:
2822 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2823 if(src->funcs == &funcs_555)
2825 for(y = src_rect->top; y < src_rect->bottom; y++)
2827 dst_pixel = dst_start;
2828 src_pixel = src_start;
2829 for(x = src_rect->left; x < src_rect->right; x++)
2831 src_val = *src_pixel++;
2832 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2833 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2834 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2836 if(pad_size) memset(dst_pixel, 0, pad_size);
2837 dst_start += dst->stride;
2838 src_start += src->stride / 2;
2841 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2843 for(y = src_rect->top; y < src_rect->bottom; y++)
2845 dst_pixel = dst_start;
2846 src_pixel = src_start;
2847 for(x = src_rect->left; x < src_rect->right; x++)
2849 src_val = *src_pixel++;
2850 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2851 (((src_val >> src->blue_shift) >> 2) & 0x07);
2852 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2853 (((src_val >> src->green_shift) >> 2) & 0x07);
2854 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2855 (((src_val >> src->red_shift) >> 2) & 0x07);
2857 if(pad_size) memset(dst_pixel, 0, pad_size);
2858 dst_start += dst->stride;
2859 src_start += src->stride / 2;
2862 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2864 for(y = src_rect->top; y < src_rect->bottom; y++)
2866 dst_pixel = dst_start;
2867 src_pixel = src_start;
2868 for(x = src_rect->left; x < src_rect->right; x++)
2870 src_val = *src_pixel++;
2871 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2872 (((src_val >> src->blue_shift) >> 2) & 0x07);
2873 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2874 (((src_val >> src->green_shift) >> 4) & 0x03);
2875 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2876 (((src_val >> src->red_shift) >> 2) & 0x07);
2878 if(pad_size) memset(dst_pixel, 0, pad_size);
2879 dst_start += dst->stride;
2880 src_start += src->stride / 2;
2883 else
2885 for(y = src_rect->top; y < src_rect->bottom; y++)
2887 dst_pixel = dst_start;
2888 src_pixel = src_start;
2889 for(x = src_rect->left; x < src_rect->right; x++)
2891 src_val = *src_pixel++;
2892 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2893 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2894 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2896 if(pad_size) memset(dst_pixel, 0, pad_size);
2897 dst_start += dst->stride;
2898 src_start += src->stride / 2;
2901 break;
2904 case 8:
2906 const RGBQUAD *color_table = get_dib_color_table( src );
2907 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2908 for(y = src_rect->top; y < src_rect->bottom; y++)
2910 dst_pixel = dst_start;
2911 src_pixel = src_start;
2912 for(x = src_rect->left; x < src_rect->right; x++)
2914 RGBQUAD rgb = color_table[*src_pixel++];
2915 *dst_pixel++ = rgb.rgbBlue;
2916 *dst_pixel++ = rgb.rgbGreen;
2917 *dst_pixel++ = rgb.rgbRed;
2919 if(pad_size) memset(dst_pixel, 0, pad_size);
2920 dst_start += dst->stride;
2921 src_start += src->stride;
2923 break;
2926 case 4:
2928 const RGBQUAD *color_table = get_dib_color_table( src );
2929 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2930 for(y = src_rect->top; y < src_rect->bottom; y++)
2932 int pos = (src->rect.left + src_rect->left) & 1;
2933 src_pixel = src_start;
2934 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2936 RGBQUAD rgb;
2937 if (pos & 1)
2938 rgb = color_table[*src_pixel++ & 0xf];
2939 else
2940 rgb = color_table[*src_pixel >> 4];
2941 dst_start[x * 3] = rgb.rgbBlue;
2942 dst_start[x * 3 + 1] = rgb.rgbGreen;
2943 dst_start[x * 3 + 2] = rgb.rgbRed;
2945 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2946 dst_start += dst->stride;
2947 src_start += src->stride;
2949 break;
2952 case 1:
2954 const RGBQUAD *color_table = get_dib_color_table( src );
2955 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2956 for(y = src_rect->top; y < src_rect->bottom; y++)
2958 int pos = (src->rect.left + src_rect->left) & 7;
2959 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2961 RGBQUAD rgb;
2962 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2963 rgb = color_table[src_val];
2964 dst_start[x * 3] = rgb.rgbBlue;
2965 dst_start[x * 3 + 1] = rgb.rgbGreen;
2966 dst_start[x * 3 + 2] = rgb.rgbRed;
2968 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2969 dst_start += dst->stride;
2970 src_start += src->stride;
2972 break;
2977 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2979 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2980 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2981 DWORD src_val;
2983 switch(src->bit_count)
2985 case 32:
2987 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2989 if(src->funcs == &funcs_8888)
2991 for(y = src_rect->top; y < src_rect->bottom; y++)
2993 dst_pixel = dst_start;
2994 src_pixel = src_start;
2995 for(x = src_rect->left; x < src_rect->right; x++)
2997 src_val = *src_pixel++;
2998 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2999 ((src_val >> 6) & 0x03e0) |
3000 ((src_val >> 3) & 0x001f);
3002 if(pad_size) memset(dst_pixel, 0, pad_size);
3003 dst_start += dst->stride / 2;
3004 src_start += src->stride / 4;
3007 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3009 for(y = src_rect->top; y < src_rect->bottom; y++)
3011 dst_pixel = dst_start;
3012 src_pixel = src_start;
3013 for(x = src_rect->left; x < src_rect->right; x++)
3015 src_val = *src_pixel++;
3016 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
3017 (((src_val >> src->green_shift) << 2) & 0x03e0) |
3018 (((src_val >> src->blue_shift) >> 3) & 0x001f);
3020 if(pad_size) memset(dst_pixel, 0, pad_size);
3021 dst_start += dst->stride / 2;
3022 src_start += src->stride / 4;
3025 else
3027 for(y = src_rect->top; y < src_rect->bottom; y++)
3029 dst_pixel = dst_start;
3030 src_pixel = src_start;
3031 for(x = src_rect->left; x < src_rect->right; x++)
3033 src_val = *src_pixel++;
3034 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
3035 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
3036 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
3038 if(pad_size) memset(dst_pixel, 0, pad_size);
3039 dst_start += dst->stride / 2;
3040 src_start += src->stride / 4;
3043 break;
3046 case 24:
3048 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3050 for(y = src_rect->top; y < src_rect->bottom; y++)
3052 dst_pixel = dst_start;
3053 src_pixel = src_start;
3054 for(x = src_rect->left; x < src_rect->right; x++)
3056 RGBQUAD rgb;
3057 rgb.rgbBlue = *src_pixel++;
3058 rgb.rgbGreen = *src_pixel++;
3059 rgb.rgbRed = *src_pixel++;
3061 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
3062 ((rgb.rgbGreen << 2) & 0x03e0) |
3063 ((rgb.rgbBlue >> 3) & 0x001f);
3065 if(pad_size) memset(dst_pixel, 0, pad_size);
3066 dst_start += dst->stride / 2;
3067 src_start += src->stride;
3069 break;
3072 case 16:
3074 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3075 if(src->funcs == &funcs_555)
3077 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3078 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3079 else
3081 for(y = src_rect->top; y < src_rect->bottom; y++)
3083 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
3084 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3085 dst_start += dst->stride / 2;
3086 src_start += src->stride / 2;
3090 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3092 for(y = src_rect->top; y < src_rect->bottom; y++)
3094 dst_pixel = dst_start;
3095 src_pixel = src_start;
3096 for(x = src_rect->left; x < src_rect->right; x++)
3098 src_val = *src_pixel++;
3099 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
3100 (((src_val >> src->green_shift) << 5) & 0x03e0) |
3101 ( (src_val >> src->blue_shift) & 0x001f);
3103 if(pad_size) memset(dst_pixel, 0, pad_size);
3104 dst_start += dst->stride / 2;
3105 src_start += src->stride / 2;
3108 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3110 for(y = src_rect->top; y < src_rect->bottom; y++)
3112 dst_pixel = dst_start;
3113 src_pixel = src_start;
3114 for(x = src_rect->left; x < src_rect->right; x++)
3116 src_val = *src_pixel++;
3117 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
3118 (((src_val >> src->green_shift) << 4) & 0x03e0) |
3119 ( (src_val >> src->blue_shift) & 0x001f);
3121 if(pad_size) memset(dst_pixel, 0, pad_size);
3122 dst_start += dst->stride / 2;
3123 src_start += src->stride / 2;
3126 else
3128 for(y = src_rect->top; y < src_rect->bottom; y++)
3130 dst_pixel = dst_start;
3131 src_pixel = src_start;
3132 for(x = src_rect->left; x < src_rect->right; x++)
3134 src_val = *src_pixel++;
3135 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
3136 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
3137 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
3139 if(pad_size) memset(dst_pixel, 0, pad_size);
3140 dst_start += dst->stride / 2;
3141 src_start += src->stride / 2;
3144 break;
3147 case 8:
3149 const RGBQUAD *color_table = get_dib_color_table( src );
3150 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3151 WORD dst_colors[256];
3152 int i;
3154 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3155 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3156 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3157 ((color_table[i].rgbBlue >> 3) & 0x001f);
3159 for(y = src_rect->top; y < src_rect->bottom; y++)
3161 dst_pixel = dst_start;
3162 src_pixel = src_start;
3163 for(x = src_rect->left; x < src_rect->right; x++)
3164 *dst_pixel++ = dst_colors[*src_pixel++];
3166 if(pad_size) memset(dst_pixel, 0, pad_size);
3167 dst_start += dst->stride / 2;
3168 src_start += src->stride;
3170 break;
3173 case 4:
3175 const RGBQUAD *color_table = get_dib_color_table( src );
3176 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3177 WORD dst_colors[16];
3178 int i;
3180 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3181 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3182 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3183 ((color_table[i].rgbBlue >> 3) & 0x001f);
3185 for(y = src_rect->top; y < src_rect->bottom; y++)
3187 int pos = (src->rect.left + src_rect->left) & 1;
3188 src_pixel = src_start;
3189 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3191 if (pos & 1)
3192 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3193 else
3194 dst_start[x] = dst_colors[*src_pixel >> 4];
3196 if(pad_size) memset(dst_start + x, 0, pad_size);
3197 dst_start += dst->stride / 2;
3198 src_start += src->stride;
3200 break;
3203 case 1:
3205 const RGBQUAD *color_table = get_dib_color_table( src );
3206 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3207 WORD dst_colors[2];
3208 int i;
3210 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3211 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
3212 ((color_table[i].rgbGreen << 2) & 0x03e0) |
3213 ((color_table[i].rgbBlue >> 3) & 0x001f);
3215 for(y = src_rect->top; y < src_rect->bottom; y++)
3217 int pos = (src->rect.left + src_rect->left) & 7;
3218 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3220 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3221 dst_start[x] = dst_colors[src_val];
3223 if(pad_size) memset(dst_start + x, 0, pad_size);
3224 dst_start += dst->stride / 2;
3225 src_start += src->stride;
3227 break;
3232 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3234 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
3235 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
3236 DWORD src_val;
3238 switch(src->bit_count)
3240 case 32:
3242 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3244 if(src->funcs == &funcs_8888)
3246 for(y = src_rect->top; y < src_rect->bottom; y++)
3248 dst_pixel = dst_start;
3249 src_pixel = src_start;
3250 for(x = src_rect->left; x < src_rect->right; x++)
3252 src_val = *src_pixel++;
3253 *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val);
3255 if(pad_size) memset(dst_pixel, 0, pad_size);
3256 dst_start += dst->stride / 2;
3257 src_start += src->stride / 4;
3260 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3262 for(y = src_rect->top; y < src_rect->bottom; y++)
3264 dst_pixel = dst_start;
3265 src_pixel = src_start;
3266 for(x = src_rect->left; x < src_rect->right; x++)
3268 src_val = *src_pixel++;
3269 *dst_pixel++ = rgb_to_pixel_masks(dst,
3270 src_val >> src->red_shift,
3271 src_val >> src->green_shift,
3272 src_val >> src->blue_shift);
3274 if(pad_size) memset(dst_pixel, 0, pad_size);
3275 dst_start += dst->stride / 2;
3276 src_start += src->stride / 4;
3279 else
3281 for(y = src_rect->top; y < src_rect->bottom; y++)
3283 dst_pixel = dst_start;
3284 src_pixel = src_start;
3285 for(x = src_rect->left; x < src_rect->right; x++)
3287 src_val = *src_pixel++;
3288 *dst_pixel++ = rgb_to_pixel_masks(dst,
3289 get_field(src_val, src->red_shift, src->red_len),
3290 get_field(src_val, src->green_shift, src->green_len),
3291 get_field(src_val, src->blue_shift, src->blue_len ));
3293 if(pad_size) memset(dst_pixel, 0, pad_size);
3294 dst_start += dst->stride / 2;
3295 src_start += src->stride / 4;
3298 break;
3301 case 24:
3303 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3305 for(y = src_rect->top; y < src_rect->bottom; y++)
3307 dst_pixel = dst_start;
3308 src_pixel = src_start;
3309 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3310 *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3311 if(pad_size) memset(dst_pixel, 0, pad_size);
3312 dst_start += dst->stride / 2;
3313 src_start += src->stride;
3315 break;
3318 case 16:
3320 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3321 if(src->funcs == &funcs_555)
3323 for(y = src_rect->top; y < src_rect->bottom; y++)
3325 dst_pixel = dst_start;
3326 src_pixel = src_start;
3327 for(x = src_rect->left; x < src_rect->right; x++)
3329 src_val = *src_pixel++;
3330 *dst_pixel++ = rgb_to_pixel_masks(dst,
3331 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3332 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3333 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3335 if(pad_size) memset(dst_pixel, 0, pad_size);
3336 dst_start += dst->stride / 2;
3337 src_start += src->stride / 2;
3340 else if(bit_fields_match(src, dst))
3342 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3343 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3344 else
3346 for(y = src_rect->top; y < src_rect->bottom; y++)
3348 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
3349 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3350 dst_start += dst->stride / 2;
3351 src_start += src->stride / 2;
3355 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3357 for(y = src_rect->top; y < src_rect->bottom; y++)
3359 dst_pixel = dst_start;
3360 src_pixel = src_start;
3361 for(x = src_rect->left; x < src_rect->right; x++)
3363 src_val = *src_pixel++;
3364 *dst_pixel++ = rgb_to_pixel_masks(dst,
3365 (((src_val >> src->red_shift) << 3) & 0xf8) |
3366 (((src_val >> src->red_shift) >> 2) & 0x07),
3367 (((src_val >> src->green_shift) << 3) & 0xf8) |
3368 (((src_val >> src->green_shift) >> 2) & 0x07),
3369 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3370 (((src_val >> src->blue_shift) >> 2) & 0x07));
3372 if(pad_size) memset(dst_pixel, 0, pad_size);
3373 dst_start += dst->stride / 2;
3374 src_start += src->stride / 2;
3377 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3379 for(y = src_rect->top; y < src_rect->bottom; y++)
3381 dst_pixel = dst_start;
3382 src_pixel = src_start;
3383 for(x = src_rect->left; x < src_rect->right; x++)
3385 src_val = *src_pixel++;
3386 *dst_pixel++ = rgb_to_pixel_masks(dst,
3387 (((src_val >> src->red_shift) << 3) & 0xf8) |
3388 (((src_val >> src->red_shift) >> 2) & 0x07),
3389 (((src_val >> src->green_shift) << 2) & 0xfc) |
3390 (((src_val >> src->green_shift) >> 4) & 0x03),
3391 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3392 (((src_val >> src->blue_shift) >> 2) & 0x07));
3394 if(pad_size) memset(dst_pixel, 0, pad_size);
3395 dst_start += dst->stride / 2;
3396 src_start += src->stride / 2;
3399 else
3401 for(y = src_rect->top; y < src_rect->bottom; y++)
3403 dst_pixel = dst_start;
3404 src_pixel = src_start;
3405 for(x = src_rect->left; x < src_rect->right; x++)
3407 src_val = *src_pixel++;
3408 *dst_pixel++ = rgb_to_pixel_masks(dst,
3409 get_field(src_val, src->red_shift, src->red_len),
3410 get_field(src_val, src->green_shift, src->green_len),
3411 get_field(src_val, src->blue_shift, src->blue_len));
3413 if(pad_size) memset(dst_pixel, 0, pad_size);
3414 dst_start += dst->stride / 2;
3415 src_start += src->stride / 2;
3418 break;
3421 case 8:
3423 const RGBQUAD *color_table = get_dib_color_table( src );
3424 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3425 WORD dst_colors[256];
3426 int i;
3428 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3429 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3431 for(y = src_rect->top; y < src_rect->bottom; y++)
3433 dst_pixel = dst_start;
3434 src_pixel = src_start;
3435 for(x = src_rect->left; x < src_rect->right; x++)
3436 *dst_pixel++ = dst_colors[*src_pixel++];
3438 if(pad_size) memset(dst_pixel, 0, pad_size);
3439 dst_start += dst->stride / 2;
3440 src_start += src->stride;
3442 break;
3445 case 4:
3447 const RGBQUAD *color_table = get_dib_color_table( src );
3448 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3449 WORD dst_colors[16];
3450 int i;
3452 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3453 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3455 for(y = src_rect->top; y < src_rect->bottom; y++)
3457 int pos = (src->rect.left + src_rect->left) & 1;
3458 src_pixel = src_start;
3459 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3461 if (pos & 1)
3462 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3463 else
3464 dst_start[x] = dst_colors[*src_pixel >> 4];
3466 if(pad_size) memset(dst_start + x, 0, pad_size);
3467 dst_start += dst->stride / 2;
3468 src_start += src->stride;
3470 break;
3473 case 1:
3475 const RGBQUAD *color_table = get_dib_color_table( src );
3476 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3477 WORD dst_colors[2];
3478 int i;
3480 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3481 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
3483 for(y = src_rect->top; y < src_rect->bottom; y++)
3485 int pos = (src->rect.left + src_rect->left) & 7;
3486 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3488 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3489 dst_start[x] = dst_colors[src_val];
3491 if(pad_size) memset(dst_start + x, 0, pad_size);
3492 dst_start += dst->stride / 2;
3493 src_start += src->stride;
3495 break;
3500 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
3502 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
3503 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
3506 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
3508 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
3509 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
3512 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3514 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
3515 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
3516 DWORD src_val;
3518 switch(src->bit_count)
3520 case 32:
3522 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3524 if(src->funcs == &funcs_8888)
3526 for(y = src_rect->top; y < src_rect->bottom; y++)
3528 dst_pixel = dst_start;
3529 src_pixel = src_start;
3530 for(x = src_rect->left; x < src_rect->right; x++)
3532 src_val = *src_pixel++;
3533 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
3535 if(pad_size) memset(dst_pixel, 0, pad_size);
3536 dst_start += dst->stride;
3537 src_start += src->stride / 4;
3540 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3542 for(y = src_rect->top; y < src_rect->bottom; y++)
3544 dst_pixel = dst_start;
3545 src_pixel = src_start;
3546 for(x = src_rect->left; x < src_rect->right; x++)
3548 src_val = *src_pixel++;
3549 *dst_pixel++ = rgb_lookup_colortable(dst,
3550 src_val >> src->red_shift,
3551 src_val >> src->green_shift,
3552 src_val >> src->blue_shift );
3554 if(pad_size) memset(dst_pixel, 0, pad_size);
3555 dst_start += dst->stride;
3556 src_start += src->stride / 4;
3559 else
3561 for(y = src_rect->top; y < src_rect->bottom; y++)
3563 dst_pixel = dst_start;
3564 src_pixel = src_start;
3565 for(x = src_rect->left; x < src_rect->right; x++)
3567 src_val = *src_pixel++;
3568 *dst_pixel++ = rgb_lookup_colortable(dst,
3569 get_field(src_val, src->red_shift, src->red_len),
3570 get_field(src_val, src->green_shift, src->green_len),
3571 get_field(src_val, src->blue_shift, src->blue_len));
3573 if(pad_size) memset(dst_pixel, 0, pad_size);
3574 dst_start += dst->stride;
3575 src_start += src->stride / 4;
3578 break;
3581 case 24:
3583 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3585 for(y = src_rect->top; y < src_rect->bottom; y++)
3587 dst_pixel = dst_start;
3588 src_pixel = src_start;
3589 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3591 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
3593 if(pad_size) memset(dst_pixel, 0, pad_size);
3594 dst_start += dst->stride;
3595 src_start += src->stride;
3597 break;
3600 case 16:
3602 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3603 if(src->funcs == &funcs_555)
3605 for(y = src_rect->top; y < src_rect->bottom; y++)
3607 dst_pixel = dst_start;
3608 src_pixel = src_start;
3609 for(x = src_rect->left; x < src_rect->right; x++)
3611 src_val = *src_pixel++;
3612 *dst_pixel++ = rgb_lookup_colortable(dst,
3613 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3614 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3615 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3617 if(pad_size) memset(dst_pixel, 0, pad_size);
3618 dst_start += dst->stride;
3619 src_start += src->stride / 2;
3622 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3624 for(y = src_rect->top; y < src_rect->bottom; y++)
3626 dst_pixel = dst_start;
3627 src_pixel = src_start;
3628 for(x = src_rect->left; x < src_rect->right; x++)
3630 src_val = *src_pixel++;
3631 *dst_pixel++ = rgb_lookup_colortable(dst,
3632 (((src_val >> src->red_shift) << 3) & 0xf8) |
3633 (((src_val >> src->red_shift) >> 2) & 0x07),
3634 (((src_val >> src->green_shift) << 3) & 0xf8) |
3635 (((src_val >> src->green_shift) >> 2) & 0x07),
3636 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3637 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3639 if(pad_size) memset(dst_pixel, 0, pad_size);
3640 dst_start += dst->stride;
3641 src_start += src->stride / 2;
3644 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3646 for(y = src_rect->top; y < src_rect->bottom; y++)
3648 dst_pixel = dst_start;
3649 src_pixel = src_start;
3650 for(x = src_rect->left; x < src_rect->right; x++)
3652 src_val = *src_pixel++;
3653 *dst_pixel++ = rgb_lookup_colortable(dst,
3654 (((src_val >> src->red_shift) << 3) & 0xf8) |
3655 (((src_val >> src->red_shift) >> 2) & 0x07),
3656 (((src_val >> src->green_shift) << 2) & 0xfc) |
3657 (((src_val >> src->green_shift) >> 4) & 0x03),
3658 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3659 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3661 if(pad_size) memset(dst_pixel, 0, pad_size);
3662 dst_start += dst->stride;
3663 src_start += src->stride / 2;
3666 else
3668 for(y = src_rect->top; y < src_rect->bottom; y++)
3670 dst_pixel = dst_start;
3671 src_pixel = src_start;
3672 for(x = src_rect->left; x < src_rect->right; x++)
3674 src_val = *src_pixel++;
3675 *dst_pixel++ = rgb_lookup_colortable(dst,
3676 get_field(src_val, src->red_shift, src->red_len),
3677 get_field(src_val, src->green_shift, src->green_len),
3678 get_field(src_val, src->blue_shift, src->blue_len));
3680 if(pad_size) memset(dst_pixel, 0, pad_size);
3681 dst_start += dst->stride;
3682 src_start += src->stride / 2;
3685 break;
3688 case 8:
3690 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3692 if(color_tables_match(dst, src))
3694 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3695 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3696 else
3698 for(y = src_rect->top; y < src_rect->bottom; y++)
3700 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
3701 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
3702 dst_start += dst->stride;
3703 src_start += src->stride;
3707 else
3709 const RGBQUAD *color_table = get_dib_color_table( src );
3710 BYTE dst_colors[256];
3711 int i;
3713 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3714 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
3716 for(y = src_rect->top; y < src_rect->bottom; y++)
3718 dst_pixel = dst_start;
3719 src_pixel = src_start;
3720 for(x = src_rect->left; x < src_rect->right; x++)
3721 *dst_pixel++ = dst_colors[*src_pixel++];
3723 if(pad_size) memset(dst_pixel, 0, pad_size);
3724 dst_start += dst->stride;
3725 src_start += src->stride;
3728 break;
3731 case 4:
3733 const RGBQUAD *color_table = get_dib_color_table( src );
3734 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3735 BYTE dst_colors[16];
3736 int i;
3738 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3739 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
3741 for(y = src_rect->top; y < src_rect->bottom; y++)
3743 int pos = (src->rect.left + src_rect->left) & 1;
3744 src_pixel = src_start;
3745 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3747 if (pos & 1)
3748 dst_start[x] = dst_colors[*src_pixel++ & 0xf];
3749 else
3750 dst_start[x] = dst_colors[*src_pixel >> 4];
3752 if(pad_size) memset(dst_start + x, 0, pad_size);
3753 dst_start += dst->stride;
3754 src_start += src->stride;
3756 break;
3759 case 1:
3761 const RGBQUAD *color_table = get_dib_color_table( src );
3762 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3763 BYTE dst_colors[2];
3764 int i;
3766 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
3767 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
3769 for(y = src_rect->top; y < src_rect->bottom; y++)
3771 int pos = (src->rect.left + src_rect->left) & 7;
3772 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3774 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3775 dst_start[x] = dst_colors[src_val];
3777 if(pad_size) memset(dst_start + x, 0, pad_size);
3778 dst_start += dst->stride;
3779 src_start += src->stride;
3781 break;
3786 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3788 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3789 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3790 DWORD src_val;
3792 switch(src->bit_count)
3794 case 32:
3796 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3798 if(src->funcs == &funcs_8888)
3800 for(y = src_rect->top; y < src_rect->bottom; y++)
3802 dst_pixel = dst_start;
3803 src_pixel = src_start;
3804 for(x = src_rect->left; x < src_rect->right; x++)
3806 src_val = *src_pixel++;
3807 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3808 if((x - src_rect->left) & 1)
3810 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3811 dst_pixel++;
3813 else
3814 *dst_pixel = (dst_val << 4) & 0xf0;
3816 if(pad_size)
3818 if((x - src_rect->left) & 1) dst_pixel++;
3819 memset(dst_pixel, 0, pad_size);
3821 dst_start += dst->stride;
3822 src_start += src->stride / 4;
3825 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3827 for(y = src_rect->top; y < src_rect->bottom; y++)
3829 dst_pixel = dst_start;
3830 src_pixel = src_start;
3831 for(x = src_rect->left; x < src_rect->right; x++)
3833 src_val = *src_pixel++;
3834 dst_val = rgb_to_pixel_colortable(dst,
3835 src_val >> src->red_shift,
3836 src_val >> src->green_shift,
3837 src_val >> src->blue_shift);
3838 if((x - src_rect->left) & 1)
3840 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3841 dst_pixel++;
3843 else
3844 *dst_pixel = (dst_val << 4) & 0xf0;
3846 if(pad_size)
3848 if((x - src_rect->left) & 1) dst_pixel++;
3849 memset(dst_pixel, 0, pad_size);
3851 dst_start += dst->stride;
3852 src_start += src->stride / 4;
3855 else
3857 for(y = src_rect->top; y < src_rect->bottom; y++)
3859 dst_pixel = dst_start;
3860 src_pixel = src_start;
3861 for(x = src_rect->left; x < src_rect->right; x++)
3863 src_val = *src_pixel++;
3864 dst_val = rgb_to_pixel_colortable(dst,
3865 get_field(src_val, src->red_shift, src->red_len),
3866 get_field(src_val, src->green_shift, src->green_len),
3867 get_field(src_val, src->blue_shift, src->blue_len));
3868 if((x - src_rect->left) & 1)
3870 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3871 dst_pixel++;
3873 else
3874 *dst_pixel = (dst_val << 4) & 0xf0;
3876 if(pad_size)
3878 if((x - src_rect->left) & 1) dst_pixel++;
3879 memset(dst_pixel, 0, pad_size);
3881 dst_start += dst->stride;
3882 src_start += src->stride / 4;
3885 break;
3888 case 24:
3890 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3892 for(y = src_rect->top; y < src_rect->bottom; y++)
3894 dst_pixel = dst_start;
3895 src_pixel = src_start;
3896 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3898 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3900 if((x - src_rect->left) & 1)
3902 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3903 dst_pixel++;
3905 else
3906 *dst_pixel = (dst_val << 4) & 0xf0;
3908 if(pad_size)
3910 if((x - src_rect->left) & 1) dst_pixel++;
3911 memset(dst_pixel, 0, pad_size);
3913 dst_start += dst->stride;
3914 src_start += src->stride;
3916 break;
3919 case 16:
3921 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3922 if(src->funcs == &funcs_555)
3924 for(y = src_rect->top; y < src_rect->bottom; y++)
3926 dst_pixel = dst_start;
3927 src_pixel = src_start;
3928 for(x = src_rect->left; x < src_rect->right; x++)
3930 src_val = *src_pixel++;
3931 dst_val = rgb_to_pixel_colortable(dst,
3932 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3933 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3934 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3935 if((x - src_rect->left) & 1)
3937 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3938 dst_pixel++;
3940 else
3941 *dst_pixel = (dst_val << 4) & 0xf0;
3943 if(pad_size)
3945 if((x - src_rect->left) & 1) dst_pixel++;
3946 memset(dst_pixel, 0, pad_size);
3948 dst_start += dst->stride;
3949 src_start += src->stride / 2;
3952 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3954 for(y = src_rect->top; y < src_rect->bottom; y++)
3956 dst_pixel = dst_start;
3957 src_pixel = src_start;
3958 for(x = src_rect->left; x < src_rect->right; x++)
3960 src_val = *src_pixel++;
3961 dst_val = rgb_to_pixel_colortable(dst,
3962 (((src_val >> src->red_shift) << 3) & 0xf8) |
3963 (((src_val >> src->red_shift) >> 2) & 0x07),
3964 (((src_val >> src->green_shift) << 3) & 0xf8) |
3965 (((src_val >> src->green_shift) >> 2) & 0x07),
3966 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3967 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3968 if((x - src_rect->left) & 1)
3970 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3971 dst_pixel++;
3973 else
3974 *dst_pixel = (dst_val << 4) & 0xf0;
3976 if(pad_size)
3978 if((x - src_rect->left) & 1) dst_pixel++;
3979 memset(dst_pixel, 0, pad_size);
3981 dst_start += dst->stride;
3982 src_start += src->stride / 2;
3985 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3987 for(y = src_rect->top; y < src_rect->bottom; y++)
3989 dst_pixel = dst_start;
3990 src_pixel = src_start;
3991 for(x = src_rect->left; x < src_rect->right; x++)
3993 src_val = *src_pixel++;
3994 dst_val = rgb_to_pixel_colortable(dst,
3995 (((src_val >> src->red_shift) << 3) & 0xf8) |
3996 (((src_val >> src->red_shift) >> 2) & 0x07),
3997 (((src_val >> src->green_shift) << 2) & 0xfc) |
3998 (((src_val >> src->green_shift) >> 4) & 0x03),
3999 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4000 (((src_val >> src->blue_shift) >> 2) & 0x07) );
4001 if((x - src_rect->left) & 1)
4003 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4004 dst_pixel++;
4006 else
4007 *dst_pixel = (dst_val << 4) & 0xf0;
4009 if(pad_size)
4011 if((x - src_rect->left) & 1) dst_pixel++;
4012 memset(dst_pixel, 0, pad_size);
4014 dst_start += dst->stride;
4015 src_start += src->stride / 2;
4018 else
4020 for(y = src_rect->top; y < src_rect->bottom; y++)
4022 dst_pixel = dst_start;
4023 src_pixel = src_start;
4024 for(x = src_rect->left; x < src_rect->right; x++)
4026 src_val = *src_pixel++;
4027 dst_val = rgb_to_pixel_colortable(dst,
4028 get_field(src_val, src->red_shift, src->red_len),
4029 get_field(src_val, src->green_shift, src->green_len),
4030 get_field(src_val, src->blue_shift, src->blue_len));
4031 if((x - src_rect->left) & 1)
4033 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4034 dst_pixel++;
4036 else
4037 *dst_pixel = (dst_val << 4) & 0xf0;
4039 if(pad_size)
4041 if((x - src_rect->left) & 1) dst_pixel++;
4042 memset(dst_pixel, 0, pad_size);
4044 dst_start += dst->stride;
4045 src_start += src->stride / 2;
4048 break;
4051 case 8:
4053 const RGBQUAD *color_table = get_dib_color_table( src );
4054 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4055 BYTE dst_colors[256];
4056 int i;
4058 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
4059 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
4061 for(y = src_rect->top; y < src_rect->bottom; y++)
4063 dst_pixel = dst_start;
4064 src_pixel = src_start;
4065 for(x = src_rect->left; x < src_rect->right; x++)
4067 dst_val = dst_colors[*src_pixel++];
4068 if((x - src_rect->left) & 1)
4070 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4071 dst_pixel++;
4073 else
4074 *dst_pixel = (dst_val << 4) & 0xf0;
4076 if(pad_size)
4078 if((x - src_rect->left) & 1) dst_pixel++;
4079 memset(dst_pixel, 0, pad_size);
4081 dst_start += dst->stride;
4082 src_start += src->stride;
4084 break;
4087 case 4:
4089 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4091 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
4093 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
4094 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
4095 else
4097 for(y = src_rect->top; y < src_rect->bottom; y++)
4099 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
4100 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
4101 dst_start += dst->stride;
4102 src_start += src->stride;
4106 else
4108 const RGBQUAD *color_table = get_dib_color_table( src );
4109 BYTE dst_colors[16];
4110 int i;
4112 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
4113 dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
4115 for(y = src_rect->top; y < src_rect->bottom; y++)
4117 int pos = (src->rect.left + src_rect->left) & 1;
4118 dst_pixel = dst_start;
4119 src_pixel = src_start;
4120 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4122 if(pos & 1)
4123 dst_val = dst_colors[*src_pixel++ & 0xf];
4124 else
4125 dst_val = dst_colors[*src_pixel >> 4];
4126 if((x - src_rect->left) & 1)
4128 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4129 dst_pixel++;
4131 else
4132 *dst_pixel = (dst_val << 4) & 0xf0;
4134 if(pad_size)
4136 if((x - src_rect->left) & 1) dst_pixel++;
4137 memset(dst_pixel, 0, pad_size);
4139 dst_start += dst->stride;
4140 src_start += src->stride;
4143 break;
4146 case 1:
4148 const RGBQUAD *color_table = get_dib_color_table( src );
4149 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4150 BYTE dst_colors[2];
4151 int i;
4153 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
4154 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
4156 for(y = src_rect->top; y < src_rect->bottom; y++)
4158 int pos = (src->rect.left + src_rect->left) & 7;
4159 dst_pixel = dst_start;
4160 for(x = src_rect->left; x < src_rect->right; x++, pos++)
4162 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4163 dst_val = dst_colors[src_val];
4164 if((x - src_rect->left) & 1)
4166 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
4167 dst_pixel++;
4169 else
4170 *dst_pixel = (dst_val << 4) & 0xf0;
4172 if(pad_size)
4174 if((x - src_rect->left) & 1) dst_pixel++;
4175 memset(dst_pixel, 0, pad_size);
4177 dst_start += dst->stride;
4178 src_start += src->stride;
4180 break;
4185 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4187 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
4188 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
4189 RGBQUAD rgb, bg_entry = *get_dib_color_table( dst ); /* entry 0 is the background color */
4190 DWORD src_val;
4191 int bit_pos;
4193 switch(src->bit_count)
4195 case 32:
4197 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
4198 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
4200 if(src->funcs == &funcs_8888)
4202 for(y = src_rect->top; y < src_rect->bottom; y++)
4204 dst_pixel = dst_start;
4205 src_pixel = src_start;
4206 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4208 src_val = *src_pixel++;
4209 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4210 src_val >> 16, src_val >> 8, src_val);
4211 if(bit_pos == 0) *dst_pixel = 0;
4212 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4214 if(++bit_pos == 8)
4216 dst_pixel++;
4217 bit_pos = 0;
4220 if(pad_size)
4222 if(bit_pos != 0) dst_pixel++;
4223 memset(dst_pixel, 0, pad_size);
4225 dst_start += dst->stride;
4226 src_start += src->stride / 4;
4229 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
4231 for(y = src_rect->top; y < src_rect->bottom; y++)
4233 dst_pixel = dst_start;
4234 src_pixel = src_start;
4235 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4237 src_val = *src_pixel++;
4238 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4239 src_val >> src->red_shift,
4240 src_val >> src->green_shift,
4241 src_val >> src->blue_shift);
4243 if(bit_pos == 0) *dst_pixel = 0;
4244 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4246 if(++bit_pos == 8)
4248 dst_pixel++;
4249 bit_pos = 0;
4252 if(pad_size)
4254 if(bit_pos != 0) dst_pixel++;
4255 memset(dst_pixel, 0, pad_size);
4257 dst_start += dst->stride;
4258 src_start += src->stride / 4;
4261 else
4263 for(y = src_rect->top; y < src_rect->bottom; y++)
4265 dst_pixel = dst_start;
4266 src_pixel = src_start;
4267 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4269 src_val = *src_pixel++;
4270 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4271 get_field(src_val, src->red_shift, src->red_len),
4272 get_field(src_val, src->green_shift, src->green_len),
4273 get_field(src_val, src->blue_shift, src->blue_len));
4275 if(bit_pos == 0) *dst_pixel = 0;
4276 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4278 if(++bit_pos == 8)
4280 dst_pixel++;
4281 bit_pos = 0;
4284 if(pad_size)
4286 if(bit_pos != 0) dst_pixel++;
4287 memset(dst_pixel, 0, pad_size);
4289 dst_start += dst->stride;
4290 src_start += src->stride / 4;
4293 break;
4296 case 24:
4298 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
4299 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, RGB(bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue));
4301 for(y = src_rect->top; y < src_rect->bottom; y++)
4303 dst_pixel = dst_start;
4304 src_pixel = src_start;
4305 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
4307 dst_val = rgb_to_pixel_mono(dst, dither, x, y, RGB(src_pixel[2], src_pixel[1], src_pixel[0]),
4308 bg_pixel, src_pixel[2], src_pixel[1], src_pixel[0]);
4310 if(bit_pos == 0) *dst_pixel = 0;
4311 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4313 if(++bit_pos == 8)
4315 dst_pixel++;
4316 bit_pos = 0;
4319 if(pad_size)
4321 if(bit_pos != 0) dst_pixel++;
4322 memset(dst_pixel, 0, pad_size);
4324 dst_start += dst->stride;
4325 src_start += src->stride;
4327 break;
4330 case 16:
4332 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
4333 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
4335 if(src->funcs == &funcs_555)
4337 for(y = src_rect->top; y < src_rect->bottom; y++)
4339 dst_pixel = dst_start;
4340 src_pixel = src_start;
4341 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4343 src_val = *src_pixel++;
4344 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4345 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
4346 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
4347 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
4349 if(bit_pos == 0) *dst_pixel = 0;
4350 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4352 if(++bit_pos == 8)
4354 dst_pixel++;
4355 bit_pos = 0;
4358 if(pad_size)
4360 if(bit_pos != 0) dst_pixel++;
4361 memset(dst_pixel, 0, pad_size);
4363 dst_start += dst->stride;
4364 src_start += src->stride / 2;
4367 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
4369 for(y = src_rect->top; y < src_rect->bottom; y++)
4371 dst_pixel = dst_start;
4372 src_pixel = src_start;
4373 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4375 src_val = *src_pixel++;
4376 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4377 (((src_val >> src->red_shift) << 3) & 0xf8) |
4378 (((src_val >> src->red_shift) >> 2) & 0x07),
4379 (((src_val >> src->green_shift) << 3) & 0xf8) |
4380 (((src_val >> src->green_shift) >> 2) & 0x07),
4381 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4382 (((src_val >> src->blue_shift) >> 2) & 0x07));
4383 if(bit_pos == 0) *dst_pixel = 0;
4384 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4386 if(++bit_pos == 8)
4388 dst_pixel++;
4389 bit_pos = 0;
4392 if(pad_size)
4394 if(bit_pos != 0) dst_pixel++;
4395 memset(dst_pixel, 0, pad_size);
4397 dst_start += dst->stride;
4398 src_start += src->stride / 2;
4401 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
4403 for(y = src_rect->top; y < src_rect->bottom; y++)
4405 dst_pixel = dst_start;
4406 src_pixel = src_start;
4407 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4409 src_val = *src_pixel++;
4410 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4411 (((src_val >> src->red_shift) << 3) & 0xf8) |
4412 (((src_val >> src->red_shift) >> 2) & 0x07),
4413 (((src_val >> src->green_shift) << 2) & 0xfc) |
4414 (((src_val >> src->green_shift) >> 4) & 0x03),
4415 (((src_val >> src->blue_shift) << 3) & 0xf8) |
4416 (((src_val >> src->blue_shift) >> 2) & 0x07));
4417 if(bit_pos == 0) *dst_pixel = 0;
4418 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4420 if(++bit_pos == 8)
4422 dst_pixel++;
4423 bit_pos = 0;
4426 if(pad_size)
4428 if(bit_pos != 0) dst_pixel++;
4429 memset(dst_pixel, 0, pad_size);
4431 dst_start += dst->stride;
4432 src_start += src->stride / 2;
4435 else
4437 for(y = src_rect->top; y < src_rect->bottom; y++)
4439 dst_pixel = dst_start;
4440 src_pixel = src_start;
4441 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4443 src_val = *src_pixel++;
4444 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4445 get_field(src_val, src->red_shift, src->red_len),
4446 get_field(src_val, src->green_shift, src->green_len),
4447 get_field(src_val, src->blue_shift, src->blue_len));
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 break;
4469 case 8:
4471 const RGBQUAD *color_table = get_dib_color_table( src );
4472 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
4473 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4475 for(y = src_rect->top; y < src_rect->bottom; y++)
4477 dst_pixel = dst_start;
4478 src_pixel = src_start;
4479 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
4481 BYTE src_val = *src_pixel++;
4482 rgb = color_table[src_val];
4483 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4484 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4486 if(bit_pos == 0) *dst_pixel = 0;
4487 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4489 if(++bit_pos == 8)
4491 dst_pixel++;
4492 bit_pos = 0;
4495 if(pad_size)
4497 if(bit_pos != 0) dst_pixel++;
4498 memset(dst_pixel, 0, pad_size);
4500 dst_start += dst->stride;
4501 src_start += src->stride;
4503 break;
4506 case 4:
4508 const RGBQUAD *color_table = get_dib_color_table( src );
4509 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
4510 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4512 for(y = src_rect->top; y < src_rect->bottom; y++)
4514 int pos = (src->rect.left + src_rect->left) & 1;
4515 dst_pixel = dst_start;
4516 src_pixel = src_start;
4517 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4519 src_val = (pos & 1) ? *src_pixel++ & 0xf : *src_pixel >> 4;
4520 rgb = color_table[src_val];
4521 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4522 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
4524 if(bit_pos == 0) *dst_pixel = 0;
4525 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4527 if(++bit_pos == 8)
4529 dst_pixel++;
4530 bit_pos = 0;
4533 if(pad_size)
4535 if(bit_pos != 0) dst_pixel++;
4536 memset(dst_pixel, 0, pad_size);
4538 dst_start += dst->stride;
4539 src_start += src->stride;
4541 break;
4544 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
4545 uses text/bkgnd colours instead of the dib's colour table, this
4546 doesn't appear to be the case for a dc backed by a
4547 dibsection. */
4549 case 1:
4551 const RGBQUAD *color_table = get_dib_color_table( src );
4552 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
4553 DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
4555 for(y = src_rect->top; y < src_rect->bottom; y++)
4557 int pos = (src->rect.left + src_rect->left) & 7;
4558 dst_pixel = dst_start;
4559 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
4561 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
4562 rgb = color_table[src_val];
4563 dst_val = FILTER_DIBINDEX(rgb, rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
4564 rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
4565 if(bit_pos == 0) *dst_pixel = 0;
4566 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
4568 if(++bit_pos == 8)
4570 dst_pixel++;
4571 bit_pos = 0;
4574 if(pad_size)
4576 if(bit_pos != 0) dst_pixel++;
4577 memset(dst_pixel, 0, pad_size);
4579 dst_start += dst->stride;
4580 src_start += src->stride;
4582 break;
4587 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
4591 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
4593 return (src * alpha + dst * (255 - alpha) + 127) / 255;
4596 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
4598 return (blend_color( dst, src, alpha ) |
4599 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4600 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4601 blend_color( dst >> 24, src >> 24, alpha ) << 24);
4604 static inline DWORD blend_argb_no_src_alpha( DWORD dst, DWORD src, DWORD alpha )
4606 return (blend_color( dst, src, alpha ) |
4607 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
4608 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
4609 blend_color( dst >> 24, 255, alpha ) << 24);
4612 static inline DWORD blend_argb( DWORD dst, DWORD src )
4614 BYTE b = (BYTE)src;
4615 BYTE g = (BYTE)(src >> 8);
4616 BYTE r = (BYTE)(src >> 16);
4617 DWORD alpha = (BYTE)(src >> 24);
4618 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4619 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4620 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4621 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4624 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
4626 BYTE b = ((BYTE)src * alpha + 127) / 255;
4627 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4628 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4629 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4630 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
4631 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
4632 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
4633 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
4636 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
4638 if (blend.AlphaFormat & AC_SRC_ALPHA)
4640 DWORD alpha = blend.SourceConstantAlpha;
4641 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
4642 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
4643 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
4644 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
4645 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
4646 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
4647 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
4649 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
4650 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
4651 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
4654 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
4655 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4657 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4658 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4659 int x, y;
4661 if (blend.AlphaFormat & AC_SRC_ALPHA)
4663 if (blend.SourceConstantAlpha == 255)
4664 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4665 for (x = 0; x < rc->right - rc->left; x++)
4666 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
4667 else
4668 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4669 for (x = 0; x < rc->right - rc->left; x++)
4670 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4672 else if (src->compression == BI_RGB)
4673 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4674 for (x = 0; x < rc->right - rc->left; x++)
4675 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4676 else
4677 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4678 for (x = 0; x < rc->right - rc->left; x++)
4679 dst_ptr[x] = blend_argb_no_src_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
4682 static void blend_rect_32(const dib_info *dst, const RECT *rc,
4683 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4685 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4686 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
4687 int x, y;
4689 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
4691 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4693 for (x = 0; x < rc->right - rc->left; x++)
4695 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
4696 dst_ptr[x] >> dst->green_shift,
4697 dst_ptr[x] >> dst->blue_shift,
4698 src_ptr[x], blend );
4699 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
4700 (((val >> 8) & 0xff) << dst->green_shift) |
4701 (((val >> 16) & 0xff) << dst->red_shift));
4705 else
4707 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
4709 for (x = 0; x < rc->right - rc->left; x++)
4711 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4712 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4713 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4714 src_ptr[x], blend );
4715 dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val );
4721 static void blend_rect_24(const dib_info *dst, const RECT *rc,
4722 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4724 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4725 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
4726 int x, y;
4728 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4730 for (x = 0; x < rc->right - rc->left; x++)
4732 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4733 src_ptr[x], blend );
4734 dst_ptr[x * 3] = val;
4735 dst_ptr[x * 3 + 1] = val >> 8;
4736 dst_ptr[x * 3 + 2] = val >> 16;
4741 static void blend_rect_555(const dib_info *dst, const RECT *rc,
4742 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4744 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4745 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4746 int x, y;
4748 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4750 for (x = 0; x < rc->right - rc->left; x++)
4752 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4753 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4754 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4755 src_ptr[x], blend );
4756 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4761 static void blend_rect_16(const dib_info *dst, const RECT *rc,
4762 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4764 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4765 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4766 int x, y;
4768 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4770 for (x = 0; x < rc->right - rc->left; x++)
4772 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4773 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4774 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4775 src_ptr[x], blend );
4776 dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val );
4781 static void blend_rect_8(const dib_info *dst, const RECT *rc,
4782 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4784 const RGBQUAD *color_table = get_dib_color_table( dst );
4785 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4786 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4787 int x, y;
4789 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4791 for (x = 0; x < rc->right - rc->left; x++)
4793 RGBQUAD rgb = color_table[dst_ptr[x]];
4794 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4795 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4800 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4801 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4803 const RGBQUAD *color_table = get_dib_color_table( dst );
4804 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4805 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4806 int i, x, y;
4808 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4810 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4812 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4813 RGBQUAD rgb = color_table[val];
4814 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4815 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4816 if (x & 1)
4817 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4818 else
4819 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4824 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4825 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4827 const RGBQUAD *color_table = get_dib_color_table( dst );
4828 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4829 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4830 int i, x, y;
4832 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4834 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4836 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4837 RGBQUAD rgb = color_table[val];
4838 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4839 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4840 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4845 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4846 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4850 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4852 BYTE r, g, b, a;
4853 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4854 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4855 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4856 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4857 return a << 24 | r << 16 | g << 8 | b;
4860 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4862 BYTE r, g, b;
4863 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4864 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4865 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4866 return r << 16 | g << 8 | b;
4869 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4870 unsigned int x, unsigned int y )
4872 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4873 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4874 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4875 r = min( 31, max( 0, r / 16 ));
4876 g = min( 31, max( 0, g / 16 ));
4877 b = min( 31, max( 0, b / 16 ));
4878 return (r << 10) | (g << 5) | b;
4881 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4882 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4884 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4885 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4886 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4887 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4890 /* compute the left/right triangle limit for row y */
4891 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4893 int x1, x2;
4895 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4896 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4898 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4900 *left = max( rc->left, min( x1, x2 ) );
4901 *right = min( rc->right, max( x1, x2 ) );
4904 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4905 static inline int triangle_det( const TRIVERTEX *v )
4907 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);
4910 /* compute the barycentric weights for a given point inside the triangle */
4911 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4913 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4914 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4917 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4919 INT64 l1, l2;
4920 BYTE r, g, b, a;
4922 triangle_weights( v, x, y, &l1, &l2 );
4923 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4924 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4925 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4926 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4927 return a << 24 | r << 16 | g << 8 | b;
4930 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4932 INT64 l1, l2;
4933 BYTE r, g, b;
4935 triangle_weights( v, x, y, &l1, &l2 );
4936 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4937 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4938 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4939 return r << 16 | g << 8 | b;
4942 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4944 INT64 l1, l2;
4945 int r, g, b;
4947 triangle_weights( v, x, y, &l1, &l2 );
4948 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4949 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4950 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4951 r = min( 31, max( 0, r / 16 ));
4952 g = min( 31, max( 0, g / 16 ));
4953 b = min( 31, max( 0, b / 16 ));
4954 return (r << 10) | (g << 5) | b;
4957 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4959 INT64 l1, l2;
4960 BYTE r, g, b;
4962 triangle_weights( v, x, y, &l1, &l2 );
4963 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4964 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4965 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4966 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4969 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4971 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4972 int x, y, left, right, det;
4974 switch (mode)
4976 case GRADIENT_FILL_RECT_H:
4977 for (x = 0; x < rc->right - rc->left; x++)
4978 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4980 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4981 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4982 break;
4984 case GRADIENT_FILL_RECT_V:
4985 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4987 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4988 memset_32( ptr, val, rc->right - rc->left );
4990 break;
4992 case GRADIENT_FILL_TRIANGLE:
4993 if (!(det = triangle_det( v ))) return FALSE;
4994 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4996 triangle_coords( v, rc, y, &left, &right );
4997 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4999 break;
5001 return TRUE;
5004 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5006 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
5007 int x, y, left, right, det;
5009 switch (mode)
5011 case GRADIENT_FILL_RECT_H:
5012 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5014 for (x = 0; x < rc->right - rc->left; x++)
5016 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5017 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
5018 (((val >> 8) & 0xff) << dib->green_shift) |
5019 (((val >> 16) & 0xff) << dib->red_shift));
5022 else
5024 for (x = 0; x < rc->right - rc->left; x++)
5026 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5027 ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5031 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
5032 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
5033 break;
5035 case GRADIENT_FILL_RECT_V:
5036 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5038 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
5039 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5040 val = ((( val & 0xff) << dib->blue_shift) |
5041 (((val >> 8) & 0xff) << dib->green_shift) |
5042 (((val >> 16) & 0xff) << dib->red_shift));
5043 else
5044 val = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5046 memset_32( ptr, val, rc->right - rc->left );
5048 break;
5050 case GRADIENT_FILL_TRIANGLE:
5051 if (!(det = triangle_det( v ))) return FALSE;
5052 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
5054 triangle_coords( v, rc, y, &left, &right );
5056 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
5057 for (x = left; x < right; x++)
5059 DWORD val = gradient_triangle_24( v, x, y, det );
5060 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
5061 (((val >> 8) & 0xff) << dib->green_shift) |
5062 (((val >> 16) & 0xff) << dib->red_shift));
5064 else
5065 for (x = left; x < right; x++)
5067 DWORD val = gradient_triangle_24( v, x, y, det );
5068 ptr[x - rc->left] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
5071 break;
5073 return TRUE;
5076 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5078 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
5079 int x, y, left, right, det;
5081 switch (mode)
5083 case GRADIENT_FILL_RECT_H:
5084 for (x = 0; x < rc->right - rc->left; x++)
5086 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
5087 ptr[x * 3] = val;
5088 ptr[x * 3 + 1] = val >> 8;
5089 ptr[x * 3 + 2] = val >> 16;
5092 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
5093 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
5094 break;
5096 case GRADIENT_FILL_RECT_V:
5097 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5099 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
5100 for (x = 0; x < rc->right - rc->left; x++)
5102 ptr[x * 3] = val;
5103 ptr[x * 3 + 1] = val >> 8;
5104 ptr[x * 3 + 2] = val >> 16;
5107 break;
5109 case GRADIENT_FILL_TRIANGLE:
5110 if (!(det = triangle_det( v ))) return FALSE;
5111 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5113 triangle_coords( v, rc, y, &left, &right );
5114 for (x = left; x < right; x++)
5116 DWORD val = gradient_triangle_24( v, x, y, det );
5117 ptr[(x - rc->left) * 3] = val;
5118 ptr[(x - rc->left) * 3 + 1] = val >> 8;
5119 ptr[(x - rc->left) * 3 + 2] = val >> 16;
5122 break;
5124 return TRUE;
5127 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5129 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5130 int x, y, left, right, det;
5132 switch (mode)
5134 case GRADIENT_FILL_RECT_H:
5135 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5136 for (x = rc->left; x < rc->right; x++)
5137 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5138 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5139 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5140 break;
5142 case GRADIENT_FILL_RECT_V:
5143 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5145 WORD values[4];
5146 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5147 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5149 break;
5151 case GRADIENT_FILL_TRIANGLE:
5152 if (!(det = triangle_det( v ))) return FALSE;
5153 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5155 triangle_coords( v, rc, y, &left, &right );
5156 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
5158 break;
5160 return TRUE;
5163 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5165 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
5166 int x, y, left, right, det;
5168 switch (mode)
5170 case GRADIENT_FILL_RECT_H:
5171 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
5172 for (x = rc->left; x < rc->right; x++)
5174 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
5175 ptr[x - rc->left] = rgb_to_pixel_masks( dib,
5176 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5177 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5178 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5180 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
5181 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
5182 break;
5184 case GRADIENT_FILL_RECT_V:
5185 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5187 WORD values[4];
5188 for (x = 0; x < 4; x++)
5190 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
5191 values[x] = rgb_to_pixel_masks( dib,
5192 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5193 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5194 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5196 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
5198 break;
5200 case GRADIENT_FILL_TRIANGLE:
5201 if (!(det = triangle_det( v ))) return FALSE;
5202 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
5204 triangle_coords( v, rc, y, &left, &right );
5205 for (x = left; x < right; x++)
5207 WORD val = gradient_triangle_555( v, x, y, det );
5208 ptr[x - rc->left] = rgb_to_pixel_masks( dib,
5209 ((val >> 7) & 0xf8) | ((val >> 12) & 0x07),
5210 ((val >> 2) & 0xf8) | ((val >> 7) & 0x07),
5211 ((val << 3) & 0xf8) | ((val >> 2) & 0x07) );
5214 break;
5216 return TRUE;
5219 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5221 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
5222 int x, y, left, right, det;
5224 switch (mode)
5226 case GRADIENT_FILL_RECT_H:
5227 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5228 for (x = rc->left; x < rc->right; x++)
5229 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5230 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5231 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
5232 break;
5234 case GRADIENT_FILL_RECT_V:
5235 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5237 BYTE values[16];
5238 for (x = 0; x < 16; x++)
5239 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5240 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
5242 break;
5244 case GRADIENT_FILL_TRIANGLE:
5245 if (!(det = triangle_det( v ))) return FALSE;
5246 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5248 triangle_coords( v, rc, y, &left, &right );
5249 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
5251 break;
5253 return TRUE;
5256 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5258 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
5259 int x, y, left, right, det, pos;
5261 switch (mode)
5263 case GRADIENT_FILL_RECT_H:
5264 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5266 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5268 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
5269 if (pos & 1)
5270 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5271 else
5272 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5275 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5277 x = rc->left;
5278 pos = (dib->rect.left + rc->left) & 1;
5279 if (pos)
5281 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
5282 pos++;
5283 x++;
5285 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
5286 if (x < rc->right)
5287 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
5289 break;
5291 case GRADIENT_FILL_RECT_V:
5292 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5294 BYTE values[16];
5295 for (x = 0; x < 16; x++)
5296 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
5297 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
5298 if (pos & 1)
5299 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
5300 else
5301 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
5303 break;
5305 case GRADIENT_FILL_TRIANGLE:
5306 if (!(det = triangle_det( v ))) return FALSE;
5307 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5309 triangle_coords( v, rc, y, &left, &right );
5310 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
5312 BYTE val = gradient_triangle_8( dib, v, x, y, det );
5313 if (pos & 1)
5314 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
5315 else
5316 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
5319 break;
5321 return TRUE;
5324 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5326 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
5327 int x, y, left, right, det, pos;
5329 switch (mode)
5331 case GRADIENT_FILL_RECT_H:
5332 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
5334 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5336 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
5337 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5340 for ( ; y < rc->bottom; y++, ptr += dib->stride)
5341 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5342 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5343 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
5344 break;
5346 case GRADIENT_FILL_RECT_V:
5347 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5349 BYTE values[16];
5350 for (x = 0; x < 16; x++)
5351 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
5352 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
5353 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
5354 (values[x % 16] & pixel_masks_1[pos % 8]);
5356 break;
5358 case GRADIENT_FILL_TRIANGLE:
5359 if (!(det = triangle_det( v ))) return FALSE;
5360 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
5362 triangle_coords( v, rc, y, &left, &right );
5363 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
5365 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
5366 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
5369 break;
5371 return TRUE;
5374 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
5376 return TRUE;
5379 static void mask_rect_32( const dib_info *dst, const RECT *rc,
5380 const dib_info *src, const POINT *origin, int rop2 )
5382 DWORD *dst_start = get_pixel_ptr_32(dst, rc->left, rc->top), dst_colors[256];
5383 DWORD src_val, bit_val, i, full, pos;
5384 int x, y, origin_end = origin->x + rc->right - rc->left;
5385 const RGBQUAD *color_table = get_dib_color_table( src );
5386 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5388 if (dst->funcs == &funcs_8888)
5389 for (i = 0; i < 2; i++)
5390 dst_colors[i] = color_table[i].rgbRed << 16 | color_table[i].rgbGreen << 8 |
5391 color_table[i].rgbBlue;
5392 else
5393 for (i = 0; i < 2; i++)
5394 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
5396 /* Creating a BYTE-sized table so we don't need to mask the lsb of bit_val */
5397 for (i = 2; i < ARRAY_SIZE(dst_colors); i++)
5398 dst_colors[i] = dst_colors[i & 1];
5400 /* Special case starting and finishing in same byte, neither on byte boundary */
5401 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5403 struct rop_codes codes;
5405 get_rop_codes( rop2, &codes );
5407 for (y = rc->top; y < rc->bottom; y++)
5409 pos = origin->x & 7;
5410 for (x = 0; x < rc->right - rc->left; x++, pos++)
5412 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5413 do_rop_codes_32( dst_start + x, dst_colors[bit_val], &codes );
5415 dst_start += dst->stride / 4;
5416 src_start += src->stride;
5418 return;
5421 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5423 #define LOOP( op ) \
5424 for (y = rc->top; y < rc->bottom; y++) \
5426 pos = origin->x & 7; \
5427 src_val = src_start[pos / 8]; \
5428 x = 0; \
5429 switch (pos & 7) \
5431 case 1: bit_val = src_val >> 6; op; x++; \
5432 /* fall through */ \
5433 case 2: bit_val = src_val >> 5; op; x++; \
5434 /* fall through */ \
5435 case 3: bit_val = src_val >> 4; op; x++; \
5436 /* fall through */ \
5437 case 4: bit_val = src_val >> 3; op; x++; \
5438 /* fall through */ \
5439 case 5: bit_val = src_val >> 2; op; x++; \
5440 /* fall through */ \
5441 case 6: bit_val = src_val >> 1; op; x++; \
5442 /* fall through */ \
5443 case 7: bit_val = src_val; op; x++; \
5444 pos = (pos + 7) & ~7; \
5446 for (i = 0; i < full; i++, pos += 8) \
5448 src_val = src_start[pos / 8]; \
5449 bit_val = src_val >> 7; op; x++; \
5450 bit_val = src_val >> 6; op; x++; \
5451 bit_val = src_val >> 5; op; x++; \
5452 bit_val = src_val >> 4; op; x++; \
5453 bit_val = src_val >> 3; op; x++; \
5454 bit_val = src_val >> 2; op; x++; \
5455 bit_val = src_val >> 1; op; x++; \
5456 bit_val = src_val; op; x++; \
5458 if (origin_end & 7) \
5460 src_val = src_start[pos / 8]; \
5461 x += (origin_end & 7) - 1; \
5462 switch (origin_end & 7) \
5464 case 7: bit_val = src_val >> 1; op; x--; \
5465 /* fall through */ \
5466 case 6: bit_val = src_val >> 2; op; x--; \
5467 /* fall through */ \
5468 case 5: bit_val = src_val >> 3; op; x--; \
5469 /* fall through */ \
5470 case 4: bit_val = src_val >> 4; op; x--; \
5471 /* fall through */ \
5472 case 3: bit_val = src_val >> 5; op; x--; \
5473 /* fall through */ \
5474 case 2: bit_val = src_val >> 6; op; x--; \
5475 /* fall through */ \
5476 case 1: bit_val = src_val >> 7; op; \
5479 dst_start += dst->stride / 4; \
5480 src_start += src->stride; \
5483 switch (rop2)
5485 ROPS_ALL( dst_start[x], dst_colors[bit_val] )
5487 #undef LOOP
5490 static void mask_rect_24( const dib_info *dst, const RECT *rc,
5491 const dib_info *src, const POINT *origin, int rop2 )
5493 BYTE *dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
5494 DWORD src_val, bit_val, i, full, pos;
5495 struct rop_codes codes;
5496 int x, y, origin_end = origin->x + rc->right - rc->left;
5497 const RGBQUAD *color_table = get_dib_color_table( src );
5498 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5499 RGBQUAD rgb;
5501 get_rop_codes( rop2, &codes );
5503 /* Special case starting and finishing in same byte, neither on byte boundary */
5504 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5506 for (y = rc->top; y < rc->bottom; y++)
5508 pos = origin->x & 7;
5509 for (x = 0; x < rc->right - rc->left; x++, pos++)
5511 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5512 rgb = color_table[bit_val];
5513 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5514 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5515 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5517 dst_start += dst->stride;
5518 src_start += src->stride;
5520 return;
5523 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5525 for (y = rc->top; y < rc->bottom; y++)
5527 pos = origin->x & 7;
5528 src_val = src_start[pos / 8];
5529 x = 0;
5531 switch (pos & 7)
5533 case 1:
5534 bit_val = (src_val >> 6) & 1;
5535 rgb = color_table[bit_val];
5536 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5537 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5538 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5539 x++;
5540 /* fall through */
5541 case 2:
5542 bit_val = (src_val >> 5) & 1;
5543 rgb = color_table[bit_val];
5544 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5545 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5546 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5547 x++;
5548 /* fall through */
5549 case 3:
5550 bit_val = (src_val >> 4) & 1;
5551 rgb = color_table[bit_val];
5552 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5553 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5554 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5555 x++;
5556 /* fall through */
5557 case 4:
5558 bit_val = (src_val >> 3) & 1;
5559 rgb = color_table[bit_val];
5560 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5561 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5562 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5563 x++;
5564 /* fall through */
5565 case 5:
5566 bit_val = (src_val >> 2) & 1;
5567 rgb = color_table[bit_val];
5568 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5569 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5570 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5571 x++;
5572 /* fall through */
5573 case 6:
5574 bit_val = (src_val >> 1) & 1;
5575 rgb = color_table[bit_val];
5576 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5577 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5578 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5579 x++;
5580 /* fall through */
5581 case 7:
5582 bit_val = src_val & 1;
5583 rgb = color_table[bit_val];
5584 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5585 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5586 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5587 x++;
5588 pos = (pos + 7) & ~7;
5591 for (i = 0; i < full; i++, pos += 8)
5593 src_val = src_start[pos / 8];
5595 bit_val = (src_val >> 7) & 1;
5596 rgb = color_table[bit_val];
5597 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5598 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5599 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5600 x++;
5602 bit_val = (src_val >> 6) & 1;
5603 rgb = color_table[bit_val];
5604 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5605 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5606 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5607 x++;
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++;
5616 bit_val = (src_val >> 4) & 1;
5617 rgb = color_table[bit_val];
5618 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5619 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5620 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5621 x++;
5623 bit_val = (src_val >> 3) & 1;
5624 rgb = color_table[bit_val];
5625 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5626 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5627 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5628 x++;
5630 bit_val = (src_val >> 2) & 1;
5631 rgb = color_table[bit_val];
5632 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5633 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5634 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5635 x++;
5637 bit_val = (src_val >> 1) & 1;
5638 rgb = color_table[bit_val];
5639 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5640 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5641 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5642 x++;
5644 bit_val = src_val & 1;
5645 rgb = color_table[bit_val];
5646 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5647 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5648 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5649 x++;
5652 if (origin_end & 7)
5654 src_val = src_start[pos / 8];
5655 x += (origin_end & 7) - 1;
5657 switch (origin_end & 7)
5659 case 7:
5660 bit_val = (src_val >> 1) & 1;
5661 rgb = color_table[bit_val];
5662 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5663 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5664 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5665 x--;
5666 /* fall through */
5667 case 6:
5668 bit_val = (src_val >> 2) & 1;
5669 rgb = color_table[bit_val];
5670 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5671 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5672 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5673 x--;
5674 /* fall through */
5675 case 5:
5676 bit_val = (src_val >> 3) & 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--;
5682 /* fall through */
5683 case 4:
5684 bit_val = (src_val >> 4) & 1;
5685 rgb = color_table[bit_val];
5686 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5687 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5688 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5689 x--;
5690 /* fall through */
5691 case 3:
5692 bit_val = (src_val >> 5) & 1;
5693 rgb = color_table[bit_val];
5694 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5695 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5696 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5697 x--;
5698 /* fall through */
5699 case 2:
5700 bit_val = (src_val >> 6) & 1;
5701 rgb = color_table[bit_val];
5702 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5703 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5704 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5705 x--;
5706 /* fall through */
5707 case 1:
5708 bit_val = (src_val >> 7) & 1;
5709 rgb = color_table[bit_val];
5710 do_rop_codes_8( dst_start + x * 3, rgb.rgbBlue, &codes );
5711 do_rop_codes_8( dst_start + x * 3 + 1, rgb.rgbGreen, &codes );
5712 do_rop_codes_8( dst_start + x * 3 + 2, rgb.rgbRed, &codes );
5716 dst_start += dst->stride;
5717 src_start += src->stride;
5721 static void mask_rect_16( const dib_info *dst, const RECT *rc,
5722 const dib_info *src, const POINT *origin, int rop2 )
5724 WORD *dst_start = get_pixel_ptr_16(dst, rc->left, rc->top), dst_colors[2];
5725 DWORD src_val, bit_val, i, full, pos;
5726 struct rop_codes codes;
5727 int x, y, origin_end = origin->x + rc->right - rc->left;
5728 const RGBQUAD *color_table = get_dib_color_table( src );
5729 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5731 get_rop_codes( rop2, &codes );
5733 if (dst->funcs == &funcs_555)
5734 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
5735 dst_colors[i] = ((color_table[i].rgbRed << 7) & 0x7c00) |
5736 ((color_table[i].rgbGreen << 2) & 0x03e0) |
5737 ((color_table[i].rgbBlue >> 3) & 0x001f);
5738 else
5739 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
5740 dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]);
5742 /* Special case starting and finishing in same byte, neither on byte boundary */
5743 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5745 for (y = rc->top; y < rc->bottom; y++)
5747 pos = origin->x & 7;
5748 for (x = 0; x < rc->right - rc->left; x++, pos++)
5750 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5751 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5753 dst_start += dst->stride / 2;
5754 src_start += src->stride;
5756 return;
5759 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5761 for (y = rc->top; y < rc->bottom; y++)
5763 pos = origin->x & 7;
5764 src_val = src_start[pos / 8];
5765 x = 0;
5767 switch (pos & 7)
5769 case 1:
5770 bit_val = (src_val >> 6) & 1;
5771 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5772 /* fall through */
5773 case 2:
5774 bit_val = (src_val >> 5) & 1;
5775 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5776 /* fall through */
5777 case 3:
5778 bit_val = (src_val >> 4) & 1;
5779 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5780 /* fall through */
5781 case 4:
5782 bit_val = (src_val >> 3) & 1;
5783 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5784 /* fall through */
5785 case 5:
5786 bit_val = (src_val >> 2) & 1;
5787 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5788 /* fall through */
5789 case 6:
5790 bit_val = (src_val >> 1) & 1;
5791 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5792 /* fall through */
5793 case 7:
5794 bit_val = src_val & 1;
5795 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5796 pos = (pos + 7) & ~7;
5799 for (i = 0; i < full; i++, pos += 8)
5801 src_val = src_start[pos / 8];
5803 bit_val = (src_val >> 7) & 1;
5804 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5805 bit_val = (src_val >> 6) & 1;
5806 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5807 bit_val = (src_val >> 5) & 1;
5808 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5809 bit_val = (src_val >> 4) & 1;
5810 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5811 bit_val = (src_val >> 3) & 1;
5812 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5813 bit_val = (src_val >> 2) & 1;
5814 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5815 bit_val = (src_val >> 1) & 1;
5816 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5817 bit_val = src_val & 1;
5818 do_rop_codes_16( dst_start + x++, dst_colors[bit_val], &codes );
5821 if (origin_end & 7)
5823 src_val = src_start[pos / 8];
5824 x += (origin_end & 7) - 1;
5826 switch (origin_end & 7)
5828 case 7:
5829 bit_val = (src_val >> 1) & 1;
5830 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5831 /* fall through */
5832 case 6:
5833 bit_val = (src_val >> 2) & 1;
5834 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5835 /* fall through */
5836 case 5:
5837 bit_val = (src_val >> 3) & 1;
5838 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5839 /* fall through */
5840 case 4:
5841 bit_val = (src_val >> 4) & 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 >> 5) & 1;
5846 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5847 /* fall through */
5848 case 2:
5849 bit_val = (src_val >> 6) & 1;
5850 do_rop_codes_16( dst_start + x--, dst_colors[bit_val], &codes );
5851 /* fall through */
5852 case 1:
5853 bit_val = (src_val >> 7) & 1;
5854 do_rop_codes_16( dst_start + x, dst_colors[bit_val], &codes );
5858 dst_start += dst->stride / 2;
5859 src_start += src->stride;
5863 static void mask_rect_8( const dib_info *dst, const RECT *rc,
5864 const dib_info *src, const POINT *origin, int rop2 )
5866 BYTE *dst_start = get_pixel_ptr_8(dst, rc->left, rc->top), dst_colors[2];
5867 DWORD src_val, bit_val, i, full, pos;
5868 struct rop_codes codes;
5869 int x, y, origin_end = origin->x + rc->right - rc->left;
5870 const RGBQUAD *color_table = get_dib_color_table( src );
5871 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
5873 get_rop_codes( rop2, &codes );
5875 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
5876 dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
5878 /* Special case starting and finishing in same byte, neither on byte boundary */
5879 if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
5881 for (y = rc->top; y < rc->bottom; y++)
5883 pos = origin->x & 7;
5884 for (x = 0; x < rc->right - rc->left; x++, pos++)
5886 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
5887 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
5889 dst_start += dst->stride;
5890 src_start += src->stride;
5892 return;
5895 full = ((rc->right - rc->left) - ((8 - (origin->x & 7)) & 7)) / 8;
5897 for (y = rc->top; y < rc->bottom; y++)
5899 pos = origin->x & 7;
5900 src_val = src_start[pos / 8];
5901 x = 0;
5903 switch (pos & 7)
5905 case 1:
5906 bit_val = (src_val >> 6) & 1;
5907 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5908 /* fall through */
5909 case 2:
5910 bit_val = (src_val >> 5) & 1;
5911 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5912 /* fall through */
5913 case 3:
5914 bit_val = (src_val >> 4) & 1;
5915 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5916 /* fall through */
5917 case 4:
5918 bit_val = (src_val >> 3) & 1;
5919 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5920 /* fall through */
5921 case 5:
5922 bit_val = (src_val >> 2) & 1;
5923 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5924 /* fall through */
5925 case 6:
5926 bit_val = (src_val >> 1) & 1;
5927 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5928 /* fall through */
5929 case 7:
5930 bit_val = src_val & 1;
5931 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5932 pos = (pos + 7) & ~7;
5935 for (i = 0; i < full; i++, pos += 8)
5937 src_val = src_start[pos / 8];
5939 bit_val = (src_val >> 7) & 1;
5940 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5941 bit_val = (src_val >> 6) & 1;
5942 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5943 bit_val = (src_val >> 5) & 1;
5944 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5945 bit_val = (src_val >> 4) & 1;
5946 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5947 bit_val = (src_val >> 3) & 1;
5948 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5949 bit_val = (src_val >> 2) & 1;
5950 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5951 bit_val = (src_val >> 1) & 1;
5952 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5953 bit_val = src_val & 1;
5954 do_rop_codes_8( dst_start + x++, dst_colors[bit_val], &codes );
5957 if (origin_end & 7)
5959 src_val = src_start[pos / 8];
5960 x += (origin_end & 7) - 1;
5962 switch (origin_end & 7)
5964 case 7:
5965 bit_val = (src_val >> 1) & 1;
5966 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5967 /* fall through */
5968 case 6:
5969 bit_val = (src_val >> 2) & 1;
5970 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5971 /* fall through */
5972 case 5:
5973 bit_val = (src_val >> 3) & 1;
5974 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5975 /* fall through */
5976 case 4:
5977 bit_val = (src_val >> 4) & 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 >> 5) & 1;
5982 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5983 /* fall through */
5984 case 2:
5985 bit_val = (src_val >> 6) & 1;
5986 do_rop_codes_8( dst_start + x--, dst_colors[bit_val], &codes );
5987 /* fall through */
5988 case 1:
5989 bit_val = (src_val >> 7) & 1;
5990 do_rop_codes_8( dst_start + x, dst_colors[bit_val], &codes );
5994 dst_start += dst->stride;
5995 src_start += src->stride;
5999 static void mask_rect_4( const dib_info *dst, const RECT *rc,
6000 const dib_info *src, const POINT *origin, int rop2 )
6002 BYTE *dst_start = get_pixel_ptr_4(dst, rc->left, rc->top), dst_colors[2], *dst_ptr;
6003 DWORD bit_val, i, pos;
6004 struct rop_codes codes;
6005 int x, y;
6006 int left = dst->rect.left + rc->left;
6007 int right = dst->rect.left + rc->right;
6008 const RGBQUAD *color_table = get_dib_color_table( src );
6009 BYTE *src_start = get_pixel_ptr_1(src, origin->x, origin->y);
6011 get_rop_codes( rop2, &codes );
6013 for (i = 0; i < ARRAY_SIZE(dst_colors); i++)
6015 dst_colors[i] = FILTER_DIBINDEX(color_table[i],rgbquad_to_pixel_colortable(dst, color_table[i]));
6016 /* Set high nibble to match so we don't need to shift it later. */
6017 dst_colors[i] |= dst_colors[i] << 4;
6020 for (y = rc->top; y < rc->bottom; y++)
6022 pos = origin->x & 7;
6024 for (x = left, dst_ptr = dst_start; x < right; x++, pos++)
6026 bit_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
6027 if (x & 1)
6028 do_rop_codes_mask_8( dst_ptr++, dst_colors[bit_val], &codes, 0x0f );
6029 else
6030 do_rop_codes_mask_8( dst_ptr, dst_colors[bit_val], &codes, 0xf0 );
6032 dst_start += dst->stride;
6033 src_start += src->stride;
6037 static void mask_rect_null( const dib_info *dst, const RECT *rc,
6038 const dib_info *src, const POINT *origin, int rop2 )
6042 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
6044 if (dst == text) return dst;
6046 if (dst > text)
6048 DWORD diff = dst - text;
6049 DWORD range = max_comp - text;
6050 dst = text + (diff * range ) / (0xff - text);
6051 return dst;
6053 else
6055 DWORD diff = text - dst;
6056 DWORD range = text - min_comp;
6057 dst = text - (diff * range) / text;
6058 return dst;
6062 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
6064 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
6065 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
6066 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
6069 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6070 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6072 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6073 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6074 int x, y;
6076 for (y = rect->top; y < rect->bottom; y++)
6078 for (x = 0; x < rect->right - rect->left; x++)
6080 if (glyph_ptr[x] <= 1) continue;
6081 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6082 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
6084 dst_ptr += dib->stride / 4;
6085 glyph_ptr += glyph->stride;
6089 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6090 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6092 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6093 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6094 int x, y;
6095 DWORD text, val;
6097 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6098 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6099 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6101 for (y = rect->top; y < rect->bottom; y++)
6103 for (x = 0; x < rect->right - rect->left; x++)
6105 if (glyph_ptr[x] <= 1) continue;
6106 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6107 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6108 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6109 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6110 text, ranges + glyph_ptr[x] );
6111 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6113 dst_ptr += dib->stride / 4;
6114 glyph_ptr += glyph->stride;
6118 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6119 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6121 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6122 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6123 int x, y;
6124 DWORD val;
6126 for (y = rect->top; y < rect->bottom; y++)
6128 for (x = 0; x < rect->right - rect->left; x++)
6130 if (glyph_ptr[x] <= 1) continue;
6131 if (glyph_ptr[x] >= 16)
6132 val = text_pixel;
6133 else
6134 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6135 text_pixel, ranges + glyph_ptr[x] );
6136 dst_ptr[x * 3] = val;
6137 dst_ptr[x * 3 + 1] = val >> 8;
6138 dst_ptr[x * 3 + 2] = val >> 16;
6140 dst_ptr += dib->stride;
6141 glyph_ptr += glyph->stride;
6145 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6146 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6148 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6149 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6150 int x, y;
6151 DWORD text, val;
6153 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6154 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6155 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6157 for (y = rect->top; y < rect->bottom; y++)
6159 for (x = 0; x < rect->right - rect->left; x++)
6161 if (glyph_ptr[x] <= 1) continue;
6162 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6163 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6164 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6165 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6166 text, ranges + glyph_ptr[x] );
6167 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6169 dst_ptr += dib->stride / 2;
6170 glyph_ptr += glyph->stride;
6174 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6175 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6177 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6178 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6179 int x, y;
6180 DWORD text, val;
6182 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6183 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6184 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6186 for (y = rect->top; y < rect->bottom; y++)
6188 for (x = 0; x < rect->right - rect->left; x++)
6190 if (glyph_ptr[x] <= 1) continue;
6191 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
6192 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6193 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6194 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6195 text, ranges + glyph_ptr[x] );
6196 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6198 dst_ptr += dib->stride / 2;
6199 glyph_ptr += glyph->stride;
6203 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6204 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6206 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
6207 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6208 int x, y;
6210 for (y = rect->top; y < rect->bottom; y++)
6212 for (x = 0; x < rect->right - rect->left; x++)
6214 /* no antialiasing, glyph should only contain 0 or 16. */
6215 if (glyph_ptr[x] >= 16)
6216 dst_ptr[x] = text_pixel;
6218 dst_ptr += dib->stride;
6219 glyph_ptr += glyph->stride;
6223 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6224 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6226 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
6227 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6228 int x, y, pos;
6230 for (y = rect->top; y < rect->bottom; y++)
6232 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
6234 /* no antialiasing, glyph should only contain 0 or 16. */
6235 if (glyph_ptr[x] >= 16)
6237 if (pos & 1)
6238 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
6239 else
6240 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
6243 dst_ptr += dib->stride;
6244 glyph_ptr += glyph->stride;
6248 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6249 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6251 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
6252 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
6253 int x, y, pos;
6254 BYTE text = (text_pixel & 1) ? 0xff : 0;
6256 for (y = rect->top; y < rect->bottom; y++)
6258 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
6260 /* no antialiasing, glyph should only contain 0 or 16. */
6261 if (glyph_ptr[x] >= 16)
6262 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
6263 (text & pixel_masks_1[pos % 8]);
6265 dst_ptr += dib->stride;
6266 glyph_ptr += glyph->stride;
6270 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6271 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
6273 return;
6275 static inline BYTE blend_color_gamma( BYTE dst, BYTE text, BYTE alpha,
6276 const struct font_gamma_ramp *gamma_ramp )
6278 if (alpha == 0) return dst;
6279 if (alpha == 255) return text;
6280 if (dst == text) return dst;
6282 return gamma_ramp->encode[ blend_color( gamma_ramp->decode[dst],
6283 gamma_ramp->decode[text],
6284 alpha ) ];
6287 static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha,
6288 const struct font_gamma_ramp *gamma_ramp )
6290 if (gamma_ramp != NULL && gamma_ramp->gamma != 1000)
6292 return blend_color_gamma( r, text >> 16, (BYTE)(alpha >> 16), gamma_ramp ) << 16 |
6293 blend_color_gamma( g, text >> 8, (BYTE)(alpha >> 8), gamma_ramp ) << 8 |
6294 blend_color_gamma( b, text, (BYTE) alpha, gamma_ramp );
6296 return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 |
6297 blend_color( g, text >> 8, (BYTE)(alpha >> 8) ) << 8 |
6298 blend_color( b, text, (BYTE) alpha );
6301 static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6302 const POINT *origin, DWORD text_pixel,
6303 const struct font_gamma_ramp *gamma_ramp )
6305 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6306 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6307 int x, y;
6309 for (y = rect->top; y < rect->bottom; y++)
6311 for (x = 0; x < rect->right - rect->left; x++)
6313 if (glyph_ptr[x] == 0) continue;
6314 dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x],
6315 text_pixel, glyph_ptr[x], gamma_ramp );
6317 dst_ptr += dib->stride / 4;
6318 glyph_ptr += glyph->stride / 4;
6322 static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6323 const POINT *origin, DWORD text_pixel,
6324 const struct font_gamma_ramp *gamma_ramp )
6326 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
6327 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6328 int x, y;
6329 DWORD text, val;
6331 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6332 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6333 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6335 for (y = rect->top; y < rect->bottom; y++)
6337 for (x = 0; x < rect->right - rect->left; x++)
6339 if (glyph_ptr[x] == 0) continue;
6340 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6341 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6342 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6343 text, glyph_ptr[x], gamma_ramp );
6344 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6346 dst_ptr += dib->stride / 4;
6347 glyph_ptr += glyph->stride / 4;
6351 static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6352 const POINT *origin, DWORD text_pixel,
6353 const struct font_gamma_ramp *gamma_ramp )
6355 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
6356 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6357 int x, y;
6358 DWORD val;
6360 for (y = rect->top; y < rect->bottom; y++)
6362 for (x = 0; x < rect->right - rect->left; x++)
6364 if (glyph_ptr[x] == 0) continue;
6365 val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
6366 text_pixel, glyph_ptr[x], gamma_ramp );
6367 dst_ptr[x * 3] = val;
6368 dst_ptr[x * 3 + 1] = val >> 8;
6369 dst_ptr[x * 3 + 2] = val >> 16;
6371 dst_ptr += dib->stride;
6372 glyph_ptr += glyph->stride / 4;
6376 static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6377 const POINT *origin, DWORD text_pixel,
6378 const struct font_gamma_ramp *gamma_ramp )
6380 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6381 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6382 int x, y;
6383 DWORD text, val;
6385 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
6386 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
6387 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
6389 for (y = rect->top; y < rect->bottom; y++)
6391 for (x = 0; x < rect->right - rect->left; x++)
6393 if (glyph_ptr[x] == 0) continue;
6394 val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
6395 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
6396 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
6397 text, glyph_ptr[x], NULL );
6398 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
6400 dst_ptr += dib->stride / 2;
6401 glyph_ptr += glyph->stride / 4;
6405 static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6406 const POINT *origin, DWORD text_pixel,
6407 const struct font_gamma_ramp *gamma_ramp )
6409 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
6410 const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y );
6411 int x, y;
6412 DWORD text, val;
6414 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
6415 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
6416 get_field( text_pixel, dib->blue_shift, dib->blue_len );
6418 for (y = rect->top; y < rect->bottom; y++)
6420 for (x = 0; x < rect->right - rect->left; x++)
6422 if (glyph_ptr[x] == 0) continue;
6423 val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
6424 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
6425 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
6426 text, glyph_ptr[x], NULL );
6427 dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val );
6429 dst_ptr += dib->stride / 2;
6430 glyph_ptr += glyph->stride / 4;
6434 static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
6435 const POINT *origin, DWORD text_pixel,
6436 const struct font_gamma_ramp *gamma_ramp )
6438 return;
6441 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
6442 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6444 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
6445 int x, y;
6447 /* masks are always 8x8 */
6448 assert( dib->width == 8 );
6449 assert( dib->height == 8 );
6451 for(y = 0; y < 8; y++, hatch_ptr++)
6453 for(x = 0; x < 8; x++)
6455 if(*hatch_ptr & pixel_masks_1[x])
6457 and_bits[x] = fg->and;
6458 xor_bits[x] = fg->xor;
6460 else
6462 and_bits[x] = bg->and;
6463 xor_bits[x] = bg->xor;
6466 and_bits += dib->stride / 4;
6467 xor_bits += dib->stride / 4;
6471 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
6472 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6474 DWORD mask_start = 0, mask_offset;
6475 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6476 int x, y;
6478 /* masks are always 8x8 */
6479 assert( dib->width == 8 );
6480 assert( dib->height == 8 );
6482 for(y = 0; y < 8; y++, hatch_ptr++)
6484 mask_offset = mask_start;
6485 for(x = 0; x < 8; x++)
6487 if(*hatch_ptr & pixel_masks_1[x])
6489 and_bits[mask_offset] = fg->and & 0xff;
6490 xor_bits[mask_offset++] = fg->xor & 0xff;
6491 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
6492 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
6493 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
6494 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
6496 else
6498 and_bits[mask_offset] = bg->and & 0xff;
6499 xor_bits[mask_offset++] = bg->xor & 0xff;
6500 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
6501 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
6502 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
6503 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
6506 mask_start += dib->stride;
6510 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
6511 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6513 WORD *and_bits = bits->and, *xor_bits = bits->xor;
6514 int x, y;
6516 /* masks are always 8x8 */
6517 assert( dib->width == 8 );
6518 assert( dib->height == 8 );
6520 for(y = 0; y < 8; y++, hatch_ptr++)
6522 for(x = 0; x < 8; x++)
6524 if(*hatch_ptr & pixel_masks_1[x])
6526 and_bits[x] = fg->and;
6527 xor_bits[x] = fg->xor;
6529 else
6531 and_bits[x] = bg->and;
6532 xor_bits[x] = bg->xor;
6535 and_bits += dib->stride / 2;
6536 xor_bits += dib->stride / 2;
6540 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
6541 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6543 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6544 int x, y;
6546 /* masks are always 8x8 */
6547 assert( dib->width == 8 );
6548 assert( dib->height == 8 );
6550 for(y = 0; y < 8; y++, hatch_ptr++)
6552 for(x = 0; x < 8; x++)
6554 if(*hatch_ptr & pixel_masks_1[x])
6556 and_bits[x] = fg->and;
6557 xor_bits[x] = fg->xor;
6559 else
6561 and_bits[x] = bg->and;
6562 xor_bits[x] = bg->xor;
6565 and_bits += dib->stride;
6566 xor_bits += dib->stride;
6570 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
6571 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6573 DWORD mask_offset;
6574 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6575 const rop_mask *rop_mask;
6576 int x, y;
6578 /* masks are always 8x8 */
6579 assert( dib->width == 8 );
6580 assert( dib->height == 8 );
6582 for(y = 0; y < 8; y++, hatch_ptr++)
6584 for(x = mask_offset = 0; x < 8; x++)
6586 if(*hatch_ptr & pixel_masks_1[x])
6587 rop_mask = fg;
6588 else
6589 rop_mask = bg;
6591 if(x & 1)
6593 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
6594 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
6595 mask_offset++;
6597 else
6599 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
6600 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
6603 and_bits += dib->stride;
6604 xor_bits += dib->stride;
6608 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
6609 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6611 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6612 rop_mask rop_mask;
6613 int x, y;
6615 /* masks are always 8x8 */
6616 assert( dib->width == 8 );
6617 assert( dib->height == 8 );
6619 for(y = 0; y < 8; y++, hatch_ptr++)
6621 *and_bits = *xor_bits = 0;
6622 for(x = 0; x < 8; x++)
6624 if(*hatch_ptr & pixel_masks_1[x])
6626 rop_mask.and = (fg->and & 1) ? 0xff : 0;
6627 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
6629 else
6631 rop_mask.and = (bg->and & 1) ? 0xff : 0;
6632 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
6634 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6635 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6637 and_bits += dib->stride;
6638 xor_bits += dib->stride;
6642 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
6643 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
6647 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6649 /* mapping between RGB triples and the default color table */
6650 static const BYTE mapping[27] =
6652 0, /* 000000 -> 000000 */
6653 4, /* 00007f -> 000080 */
6654 252, /* 0000ff -> 0000ff */
6655 2, /* 007f00 -> 008000 */
6656 6, /* 007f7f -> 008080 */
6657 224, /* 007fff -> 0080c0 */
6658 250, /* 00ff00 -> 00ff00 */
6659 184, /* 00ff7f -> 00e080 */
6660 254, /* 00ffff -> 00ffff */
6661 1, /* 7f0000 -> 800000 */
6662 5, /* 7f007f -> 800080 */
6663 196, /* 7f00ff -> 8000c0 */
6664 3, /* 7f7f00 -> 808000 */
6665 248, /* 7f7f7f -> 808080 */
6666 228, /* 7f7fff -> 8080c0 */
6667 60, /* 7fff00 -> 80e000 */
6668 188, /* 7fff7f -> 80e080 */
6669 244, /* 7fffff -> 80c0c0 */
6670 249, /* ff0000 -> ff0000 */
6671 135, /* ff007f -> e00080 */
6672 253, /* ff00ff -> ff00ff */
6673 39, /* ff7f00 -> e08000 */
6674 167, /* ff7f7f -> e08080 */
6675 231, /* ff7fff -> e080c0 */
6676 251, /* ffff00 -> ffff00 */
6677 191, /* ffff7f -> e0e080 */
6678 255 /* ffffff -> ffffff */
6681 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6682 struct rop_codes codes;
6683 int x, y;
6685 /* masks are always 8x8 */
6686 assert( dib->width == 8 );
6687 assert( dib->height == 8 );
6689 get_rop_codes( rop2, &codes );
6691 for (y = 0; y < 8; y++)
6693 for (x = 0; x < 8; x++)
6695 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6696 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6697 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6698 DWORD pixel = mapping[r * 9 + g * 3 + b];
6699 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
6700 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
6702 and_bits += dib->stride;
6703 xor_bits += dib->stride;
6707 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6709 /* mapping between RGB triples and the default color table */
6710 static const BYTE mapping[27] =
6712 0, /* 000000 -> 000000 */
6713 4, /* 00007f -> 000080 */
6714 12, /* 0000ff -> 0000ff */
6715 2, /* 007f00 -> 008000 */
6716 6, /* 007f7f -> 008080 */
6717 6, /* 007fff -> 008080 */
6718 10, /* 00ff00 -> 00ff00 */
6719 6, /* 00ff7f -> 008080 */
6720 14, /* 00ffff -> 00ffff */
6721 1, /* 7f0000 -> 800000 */
6722 5, /* 7f007f -> 800080 */
6723 5, /* 7f00ff -> 800080 */
6724 3, /* 7f7f00 -> 808000 */
6725 7, /* 7f7f7f -> 808080 */
6726 8, /* 7f7fff -> c0c0c0 */
6727 3, /* 7fff00 -> 808000 */
6728 8, /* 7fff7f -> c0c0c0 */
6729 8, /* 7fffff -> c0c0c0 */
6730 9, /* ff0000 -> ff0000 */
6731 5, /* ff007f -> 800080 */
6732 13, /* ff00ff -> ff00ff */
6733 3, /* ff7f00 -> 808000 */
6734 8, /* ff7f7f -> c0c0c0 */
6735 8, /* ff7fff -> c0c0c0 */
6736 11, /* ffff00 -> ffff00 */
6737 8, /* ffff7f -> c0c0c0 */
6738 15 /* ffffff -> ffffff */
6741 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6742 struct rop_codes codes;
6743 int x, y;
6745 /* masks are always 8x8 */
6746 assert( dib->width == 8 );
6747 assert( dib->height == 8 );
6749 get_rop_codes( rop2, &codes );
6751 for (y = 0; y < 8; y++)
6753 for (x = 0; x < 8; x++)
6755 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6756 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6757 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
6758 DWORD pixel = mapping[r * 9 + g * 3 + b];
6759 if (x & 1)
6761 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
6762 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
6764 else
6766 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
6767 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
6770 and_bits += dib->stride;
6771 xor_bits += dib->stride;
6775 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6777 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
6778 struct rop_codes codes;
6779 rop_mask rop_mask;
6780 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
6782 /* masks are always 8x8 */
6783 assert( dib->width == 8 );
6784 assert( dib->height == 8 );
6786 get_rop_codes( rop2, &codes );
6788 for (y = 0; y < 8; y++)
6790 *and_bits = *xor_bits = 0;
6791 for (x = 0; x < 8; x++)
6793 if (grey + bayer_8x8[y][x] > 63)
6795 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
6796 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
6798 else
6800 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
6801 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
6803 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
6804 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
6806 and_bits += dib->stride;
6807 xor_bits += dib->stride;
6811 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
6815 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
6817 switch (mode)
6819 default:
6820 case STRETCH_DELETESCANS:
6821 get_rop_codes( R2_COPYPEN, codes );
6822 break;
6823 case STRETCH_ORSCANS:
6824 get_rop_codes( R2_MERGEPEN, codes );
6825 break;
6826 case STRETCH_ANDSCANS:
6827 get_rop_codes( R2_MASKPEN, codes );
6828 break;
6830 return;
6833 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
6834 const dib_info *src_dib, const POINT *src_start,
6835 const struct stretch_params *params, int mode,
6836 BOOL keep_dst)
6838 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
6839 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
6840 int err = params->err_start;
6841 int width;
6843 if (mode == STRETCH_DELETESCANS || !keep_dst)
6845 for (width = params->length; width; width--)
6847 *dst_ptr = *src_ptr;
6848 dst_ptr += params->dst_inc;
6849 if (err > 0)
6851 src_ptr += params->src_inc;
6852 err += params->err_add_1;
6854 else err += params->err_add_2;
6857 else
6859 struct rop_codes codes;
6861 rop_codes_from_stretch_mode( mode, &codes );
6862 for (width = params->length; width; width--)
6864 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
6865 dst_ptr += params->dst_inc;
6866 if (err > 0)
6868 src_ptr += params->src_inc;
6869 err += params->err_add_1;
6871 else err += params->err_add_2;
6876 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
6877 const dib_info *src_dib, const POINT *src_start,
6878 const struct stretch_params *params, int mode,
6879 BOOL keep_dst)
6881 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
6882 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
6883 int err = params->err_start;
6884 int width;
6886 if (mode == STRETCH_DELETESCANS || !keep_dst)
6888 for (width = params->length; width; width--)
6890 dst_ptr[0] = src_ptr[0];
6891 dst_ptr[1] = src_ptr[1];
6892 dst_ptr[2] = src_ptr[2];
6893 dst_ptr += 3 * params->dst_inc;
6894 if (err > 0)
6896 src_ptr += 3 * params->src_inc;
6897 err += params->err_add_1;
6899 else err += params->err_add_2;
6902 else
6904 struct rop_codes codes;
6906 rop_codes_from_stretch_mode( mode, &codes );
6907 for (width = params->length; width; width--)
6909 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6910 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
6911 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
6912 dst_ptr += 3 * params->dst_inc;
6913 if (err > 0)
6915 src_ptr += 3 * params->src_inc;
6916 err += params->err_add_1;
6918 else err += params->err_add_2;
6923 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
6924 const dib_info *src_dib, const POINT *src_start,
6925 const struct stretch_params *params, int mode,
6926 BOOL keep_dst)
6928 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
6929 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
6930 int err = params->err_start;
6931 int width;
6933 if (mode == STRETCH_DELETESCANS || !keep_dst)
6935 for (width = params->length; width; width--)
6937 *dst_ptr = *src_ptr;
6938 dst_ptr += params->dst_inc;
6939 if (err > 0)
6941 src_ptr += params->src_inc;
6942 err += params->err_add_1;
6944 else err += params->err_add_2;
6947 else
6949 struct rop_codes codes;
6951 rop_codes_from_stretch_mode( mode, &codes );
6952 for (width = params->length; width; width--)
6954 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
6955 dst_ptr += params->dst_inc;
6956 if (err > 0)
6958 src_ptr += params->src_inc;
6959 err += params->err_add_1;
6961 else err += params->err_add_2;
6966 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
6967 const dib_info *src_dib, const POINT *src_start,
6968 const struct stretch_params *params, int mode,
6969 BOOL keep_dst)
6971 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
6972 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
6973 int err = params->err_start;
6974 int width;
6976 if (mode == STRETCH_DELETESCANS || !keep_dst)
6978 for (width = params->length; width; width--)
6980 *dst_ptr = *src_ptr;
6981 dst_ptr += params->dst_inc;
6982 if (err > 0)
6984 src_ptr += params->src_inc;
6985 err += params->err_add_1;
6987 else err += params->err_add_2;
6990 else
6992 struct rop_codes codes;
6994 rop_codes_from_stretch_mode( mode, &codes );
6995 for (width = params->length; width; width--)
6997 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
6998 dst_ptr += params->dst_inc;
6999 if (err > 0)
7001 src_ptr += params->src_inc;
7002 err += params->err_add_1;
7004 else err += params->err_add_2;
7009 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
7010 const dib_info *src_dib, const POINT *src_start,
7011 const struct stretch_params *params, int mode,
7012 BOOL keep_dst)
7014 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
7015 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
7016 int err = params->err_start;
7017 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7018 struct rop_codes codes;
7019 BYTE src_val;
7021 if (!keep_dst) mode = STRETCH_DELETESCANS;
7022 rop_codes_from_stretch_mode( mode, &codes );
7023 for (width = params->length; width; width--)
7025 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
7026 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
7028 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
7030 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
7031 dst_ptr += params->dst_inc;
7032 dst_x += params->dst_inc;
7034 if (err > 0)
7036 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
7037 src_ptr += params->src_inc;
7038 src_x += params->src_inc;
7039 err += params->err_add_1;
7041 else err += params->err_add_2;
7045 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
7046 const dib_info *src_dib, const POINT *src_start,
7047 const struct stretch_params *params, int mode,
7048 BOOL keep_dst)
7050 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
7051 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
7052 int err = params->err_start;
7053 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7054 struct rop_codes codes;
7055 BYTE src_val;
7057 if (!keep_dst) mode = STRETCH_DELETESCANS;
7058 rop_codes_from_stretch_mode( mode, &codes );
7059 for (width = params->length; width; width--)
7061 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
7062 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
7064 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
7065 dst_ptr += params->dst_inc;
7066 dst_x += params->dst_inc;
7068 if (err > 0)
7070 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
7071 src_ptr += params->src_inc;
7072 src_x += params->src_inc;
7073 err += params->err_add_1;
7075 else err += params->err_add_2;
7079 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
7080 const dib_info *src_dib, const POINT *src_start,
7081 const struct stretch_params *params, int mode,
7082 BOOL keep_dst)
7084 FIXME("bit count %d\n", dst_dib->bit_count);
7085 return;
7088 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
7089 const dib_info *src_dib, const POINT *src_start,
7090 const struct stretch_params *params, int mode,
7091 BOOL keep_dst)
7093 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
7094 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
7095 int err = params->err_start;
7096 int width;
7098 if (mode == STRETCH_DELETESCANS)
7100 for (width = params->length; width; width--)
7102 *dst_ptr = *src_ptr;
7103 src_ptr += params->src_inc;
7104 if (err > 0)
7106 dst_ptr += params->dst_inc;
7107 err += params->err_add_1;
7109 else err += params->err_add_2;
7112 else
7114 struct rop_codes codes;
7115 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
7116 BOOL new_pix = TRUE;
7118 rop_codes_from_stretch_mode( mode, &codes );
7119 for (width = params->length; width; width--)
7121 if (new_pix && !keep_dst) *dst_ptr = init_val;
7122 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
7123 new_pix = FALSE;
7124 src_ptr += params->src_inc;
7125 if (err > 0)
7127 dst_ptr += params->dst_inc;
7128 new_pix = TRUE;
7129 err += params->err_add_1;
7131 else err += params->err_add_2;
7136 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
7137 const dib_info *src_dib, const POINT *src_start,
7138 const struct stretch_params *params, int mode,
7139 BOOL keep_dst)
7141 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
7142 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
7143 int err = params->err_start;
7144 int width;
7146 if (mode == STRETCH_DELETESCANS)
7148 for (width = params->length; width; width--)
7150 dst_ptr[0] = src_ptr[0];
7151 dst_ptr[1] = src_ptr[1];
7152 dst_ptr[2] = src_ptr[2];
7153 src_ptr += 3 * params->src_inc;
7154 if (err > 0)
7156 dst_ptr += 3 * params->dst_inc;
7157 err += params->err_add_1;
7159 else err += params->err_add_2;
7162 else
7164 struct rop_codes codes;
7165 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7166 BOOL new_pix = TRUE;
7168 rop_codes_from_stretch_mode( mode, &codes );
7169 for (width = params->length; width; width--)
7171 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
7172 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7173 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
7174 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
7175 new_pix = FALSE;
7176 src_ptr += 3 * params->src_inc;
7177 if (err > 0)
7179 dst_ptr += 3 * params->dst_inc;
7180 new_pix = TRUE;
7181 err += params->err_add_1;
7183 else err += params->err_add_2;
7188 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
7189 const dib_info *src_dib, const POINT *src_start,
7190 const struct stretch_params *params, int mode,
7191 BOOL keep_dst)
7193 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
7194 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
7195 int err = params->err_start;
7196 int width;
7198 if (mode == STRETCH_DELETESCANS)
7200 for (width = params->length; width; width--)
7202 *dst_ptr = *src_ptr;
7203 src_ptr += params->src_inc;
7204 if (err > 0)
7206 dst_ptr += params->dst_inc;
7207 err += params->err_add_1;
7209 else err += params->err_add_2;
7212 else
7214 struct rop_codes codes;
7215 WORD init_val = (mode == STRETCH_ANDSCANS) ? 0xffff : 0;
7216 BOOL new_pix = TRUE;
7218 rop_codes_from_stretch_mode( mode, &codes );
7219 for (width = params->length; width; width--)
7221 if (new_pix && !keep_dst) *dst_ptr = init_val;
7222 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
7223 new_pix = FALSE;
7224 src_ptr += params->src_inc;
7225 if (err > 0)
7227 dst_ptr += params->dst_inc;
7228 new_pix = TRUE;
7229 err += params->err_add_1;
7231 else err += params->err_add_2;
7236 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
7237 const dib_info *src_dib, const POINT *src_start,
7238 const struct stretch_params *params, int mode,
7239 BOOL keep_dst)
7241 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
7242 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
7243 int err = params->err_start;
7244 int width;
7246 if (mode == STRETCH_DELETESCANS)
7248 for (width = params->length; width; width--)
7250 *dst_ptr = *src_ptr;
7251 src_ptr += params->src_inc;
7252 if (err > 0)
7254 dst_ptr += params->dst_inc;
7255 err += params->err_add_1;
7257 else err += params->err_add_2;
7260 else
7262 struct rop_codes codes;
7263 BYTE init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7264 BOOL new_pix = TRUE;
7266 rop_codes_from_stretch_mode( mode, &codes );
7267 for (width = params->length; width; width--)
7269 if (new_pix && !keep_dst) *dst_ptr = init_val;
7270 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
7271 new_pix = FALSE;
7272 src_ptr += params->src_inc;
7273 if (err > 0)
7275 dst_ptr += params->dst_inc;
7276 new_pix = TRUE;
7277 err += params->err_add_1;
7279 else err += params->err_add_2;
7284 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
7285 const dib_info *src_dib, const POINT *src_start,
7286 const struct stretch_params *params, int mode,
7287 BOOL keep_dst)
7289 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
7290 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
7291 int err = params->err_start;
7292 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7293 struct rop_codes codes;
7294 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7295 BOOL new_pix = TRUE;
7297 rop_codes_from_stretch_mode( mode, &codes );
7298 for (width = params->length; width; width--)
7300 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
7302 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
7303 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
7305 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
7306 new_pix = FALSE;
7308 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
7309 src_ptr += params->src_inc;
7310 src_x += params->src_inc;
7312 if (err > 0)
7314 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
7315 dst_ptr += params->dst_inc;
7316 dst_x += params->dst_inc;
7317 new_pix = TRUE;
7318 err += params->err_add_1;
7320 else err += params->err_add_2;
7324 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
7325 const dib_info *src_dib, const POINT *src_start,
7326 const struct stretch_params *params, int mode,
7327 BOOL keep_dst)
7329 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
7330 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
7331 int err = params->err_start;
7332 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
7333 struct rop_codes codes;
7334 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? 0xff : 0;
7335 BOOL new_pix = TRUE;
7337 rop_codes_from_stretch_mode( mode, &codes );
7338 for (width = params->length; width; width--)
7340 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
7341 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
7342 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
7343 new_pix = FALSE;
7345 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
7346 src_ptr += params->src_inc;
7347 src_x += params->src_inc;
7349 if (err > 0)
7351 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
7352 dst_ptr += params->dst_inc;
7353 dst_x += params->dst_inc;
7354 new_pix = TRUE;
7355 err += params->err_add_1;
7357 else err += params->err_add_2;
7361 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
7362 const dib_info *src_dib, const POINT *src_start,
7363 const struct stretch_params *params, int mode,
7364 BOOL keep_dst)
7366 FIXME("bit count %d\n", dst_dib->bit_count);
7367 return;
7370 const primitive_funcs funcs_8888 =
7372 solid_rects_32,
7373 solid_line_32,
7374 pattern_rects_32,
7375 copy_rect_32,
7376 blend_rect_8888,
7377 gradient_rect_8888,
7378 mask_rect_32,
7379 draw_glyph_8888,
7380 draw_subpixel_glyph_8888,
7381 get_pixel_32,
7382 colorref_to_pixel_888,
7383 pixel_to_colorref_888,
7384 convert_to_8888,
7385 create_rop_masks_32,
7386 create_dither_masks_null,
7387 stretch_row_32,
7388 shrink_row_32
7391 const primitive_funcs funcs_32 =
7393 solid_rects_32,
7394 solid_line_32,
7395 pattern_rects_32,
7396 copy_rect_32,
7397 blend_rect_32,
7398 gradient_rect_32,
7399 mask_rect_32,
7400 draw_glyph_32,
7401 draw_subpixel_glyph_32,
7402 get_pixel_32,
7403 colorref_to_pixel_masks,
7404 pixel_to_colorref_masks,
7405 convert_to_32,
7406 create_rop_masks_32,
7407 create_dither_masks_null,
7408 stretch_row_32,
7409 shrink_row_32
7412 const primitive_funcs funcs_24 =
7414 solid_rects_24,
7415 solid_line_24,
7416 pattern_rects_24,
7417 copy_rect_24,
7418 blend_rect_24,
7419 gradient_rect_24,
7420 mask_rect_24,
7421 draw_glyph_24,
7422 draw_subpixel_glyph_24,
7423 get_pixel_24,
7424 colorref_to_pixel_888,
7425 pixel_to_colorref_888,
7426 convert_to_24,
7427 create_rop_masks_24,
7428 create_dither_masks_null,
7429 stretch_row_24,
7430 shrink_row_24
7433 const primitive_funcs funcs_555 =
7435 solid_rects_16,
7436 solid_line_16,
7437 pattern_rects_16,
7438 copy_rect_16,
7439 blend_rect_555,
7440 gradient_rect_555,
7441 mask_rect_16,
7442 draw_glyph_555,
7443 draw_subpixel_glyph_555,
7444 get_pixel_16,
7445 colorref_to_pixel_555,
7446 pixel_to_colorref_555,
7447 convert_to_555,
7448 create_rop_masks_16,
7449 create_dither_masks_null,
7450 stretch_row_16,
7451 shrink_row_16
7454 const primitive_funcs funcs_16 =
7456 solid_rects_16,
7457 solid_line_16,
7458 pattern_rects_16,
7459 copy_rect_16,
7460 blend_rect_16,
7461 gradient_rect_16,
7462 mask_rect_16,
7463 draw_glyph_16,
7464 draw_subpixel_glyph_16,
7465 get_pixel_16,
7466 colorref_to_pixel_masks,
7467 pixel_to_colorref_masks,
7468 convert_to_16,
7469 create_rop_masks_16,
7470 create_dither_masks_null,
7471 stretch_row_16,
7472 shrink_row_16
7475 const primitive_funcs funcs_8 =
7477 solid_rects_8,
7478 solid_line_8,
7479 pattern_rects_8,
7480 copy_rect_8,
7481 blend_rect_8,
7482 gradient_rect_8,
7483 mask_rect_8,
7484 draw_glyph_8,
7485 draw_subpixel_glyph_null,
7486 get_pixel_8,
7487 colorref_to_pixel_colortable,
7488 pixel_to_colorref_colortable,
7489 convert_to_8,
7490 create_rop_masks_8,
7491 create_dither_masks_8,
7492 stretch_row_8,
7493 shrink_row_8
7496 const primitive_funcs funcs_4 =
7498 solid_rects_4,
7499 solid_line_4,
7500 pattern_rects_4,
7501 copy_rect_4,
7502 blend_rect_4,
7503 gradient_rect_4,
7504 mask_rect_4,
7505 draw_glyph_4,
7506 draw_subpixel_glyph_null,
7507 get_pixel_4,
7508 colorref_to_pixel_colortable,
7509 pixel_to_colorref_colortable,
7510 convert_to_4,
7511 create_rop_masks_4,
7512 create_dither_masks_4,
7513 stretch_row_4,
7514 shrink_row_4
7517 const primitive_funcs funcs_1 =
7519 solid_rects_1,
7520 solid_line_1,
7521 pattern_rects_1,
7522 copy_rect_1,
7523 blend_rect_1,
7524 gradient_rect_1,
7525 mask_rect_null,
7526 draw_glyph_1,
7527 draw_subpixel_glyph_null,
7528 get_pixel_1,
7529 colorref_to_pixel_colortable,
7530 pixel_to_colorref_colortable,
7531 convert_to_1,
7532 create_rop_masks_1,
7533 create_dither_masks_1,
7534 stretch_row_1,
7535 shrink_row_1
7538 const primitive_funcs funcs_null =
7540 solid_rects_null,
7541 solid_line_null,
7542 pattern_rects_null,
7543 copy_rect_null,
7544 blend_rect_null,
7545 gradient_rect_null,
7546 mask_rect_null,
7547 draw_glyph_null,
7548 draw_subpixel_glyph_null,
7549 get_pixel_null,
7550 colorref_to_pixel_null,
7551 pixel_to_colorref_null,
7552 convert_to_null,
7553 create_rop_masks_null,
7554 create_dither_masks_null,
7555 stretch_row_null,
7556 shrink_row_null