gdi32: Implement dithering of solid brushes when drawing to DDBs.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blob07dd1d51c0a441a3f8aae128634868f576f1054c
1 /*
2 * DIB driver primitives.
4 * Copyright 2011 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
23 #include "gdi_private.h"
24 #include "dibdrv.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dib);
30 /* Bayer matrices for dithering */
32 static const BYTE bayer_4x4[4][4] =
34 { 0, 8, 2, 10 },
35 { 12, 4, 14, 6 },
36 { 3, 11, 1, 9 },
37 { 15, 7, 13, 5 }
40 static const BYTE bayer_8x8[8][8] =
42 { 0, 32, 8, 40, 2, 34, 10, 42 },
43 { 48, 16, 56, 24, 50, 18, 58, 26 },
44 { 12, 44, 4, 36, 14, 46, 6, 38 },
45 { 60, 28, 52, 20, 62, 30, 54, 22 },
46 { 3, 35, 11, 43, 1, 33, 9, 41 },
47 { 51, 19, 59, 27, 49, 17, 57, 25 },
48 { 15, 47, 7, 39, 13, 45, 5, 37 },
49 { 63, 31, 55, 23, 61, 29, 53, 21 }
52 static const BYTE bayer_16x16[16][16] =
54 { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170 },
55 { 192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106 },
56 { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154 },
57 { 240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90 },
58 { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166 },
59 { 204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102 },
60 { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150 },
61 { 252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86 },
62 { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169 },
63 { 195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105 },
64 { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153 },
65 { 243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89 },
66 { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165 },
67 { 207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101 },
68 { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149 },
69 { 255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85 },
72 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
74 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 4);
77 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
79 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride) + (dib->rect.left + x) * 3 / 4;
82 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
84 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 3;
87 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
89 return (WORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 2);
92 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
94 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + dib->rect.left + x;
97 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
99 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 2;
102 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
104 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 8;
107 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
108 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
110 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
112 *ptr = (*ptr & and) ^ xor;
115 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
117 *ptr = (*ptr & and) ^ xor;
120 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
122 *ptr = (*ptr & and) ^ xor;
125 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
127 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
130 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
132 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
135 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
137 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
140 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
142 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
145 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
147 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
150 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
152 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
155 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
157 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
158 do_rop_codes_32( dst, *src, codes );
161 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
163 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
166 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
168 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
169 do_rop_codes_16( dst, *src, codes );
172 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
174 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
177 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
179 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
180 do_rop_codes_8( dst, *src, codes );
183 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
184 struct rop_codes *codes, int len)
186 BYTE src_val;
188 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
190 if (dst_x & 1)
192 if (src_x & 1) src_val = *src++;
193 else src_val = *src >> 4;
194 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
196 else
198 if (src_x & 1) src_val = *src++ << 4;
199 else src_val = *src;
200 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
205 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
206 struct rop_codes *codes, int len)
208 BYTE src_val;
210 src_x += len - 1;
211 dst_x += len - 1;
212 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
214 if (dst_x & 1)
216 if (src_x & 1) src_val = *src;
217 else src_val = *src-- >> 4;
218 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
220 else
222 if (src_x & 1) src_val = *src << 4;
223 else src_val = *src--;
224 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
229 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
230 struct rop_codes *codes, int len)
232 BYTE src_val;
234 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
236 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
237 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
238 if ((src_x & 7) == 7) src++;
239 if ((dst_x & 7) == 7) dst++;
243 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
244 struct rop_codes *codes, int len)
246 BYTE src_val;
248 src_x += len - 1;
249 dst_x += len - 1;
250 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
252 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
253 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
254 if ((src_x & 7) == 0) src--;
255 if ((dst_x & 7) == 0) dst--;
259 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
261 DWORD *ptr, *start;
262 int x, y, i;
264 for(i = 0; i < num; i++, rc++)
266 start = get_pixel_ptr_32(dib, rc->left, rc->top);
267 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
268 for(x = rc->left, ptr = start; x < rc->right; x++)
269 do_rop_32(ptr++, and, xor);
273 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
275 DWORD *ptr, *start;
276 BYTE *byte_ptr, *byte_start;
277 int x, y, i;
278 DWORD and_masks[3], xor_masks[3];
280 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
281 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
282 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
283 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
284 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
285 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
287 for(i = 0; i < num; i++, rc++)
289 int left = dib->rect.left + rc->left;
290 int right = dib->rect.left + rc->right;
292 if (left >= right) continue;
294 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
296 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
297 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
299 for(x = left, byte_ptr = byte_start; x < right; x++)
301 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
302 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
303 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
307 else
309 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
310 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
312 ptr = start;
314 switch(left & 3)
316 case 1:
317 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
318 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
319 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
320 break;
321 case 2:
322 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
323 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
324 break;
325 case 3:
326 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
327 break;
330 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
332 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
333 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
334 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
337 switch(right & 3)
339 case 1:
340 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
341 break;
342 case 2:
343 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
344 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
345 break;
346 case 3:
347 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
348 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
349 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
350 break;
357 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
359 WORD *ptr, *start;
360 int x, y, i;
362 for(i = 0; i < num; i++, rc++)
364 start = get_pixel_ptr_16(dib, rc->left, rc->top);
365 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
366 for(x = rc->left, ptr = start; x < rc->right; x++)
367 do_rop_16(ptr++, and, xor);
371 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
373 BYTE *ptr, *start;
374 int x, y, i;
376 for(i = 0; i < num; i++, rc++)
378 start = get_pixel_ptr_8(dib, rc->left, rc->top);
379 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
380 for(x = rc->left, ptr = start; x < rc->right; x++)
381 do_rop_8(ptr++, and, xor);
385 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
387 BYTE *ptr, *start;
388 int x, y, i;
389 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
390 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
392 for(i = 0; i < num; i++, rc++)
394 int left = dib->rect.left + rc->left;
395 int right = dib->rect.left + rc->right;
397 if (left >= right) continue;
398 start = get_pixel_ptr_4(dib, rc->left, rc->top);
399 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
401 ptr = start;
402 if(left & 1) /* upper nibble untouched */
403 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
405 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
406 do_rop_8(ptr++, byte_and, byte_xor);
408 if(right & 1) /* lower nibble untouched */
409 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
414 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
416 BYTE *ptr, *start;
417 int x, y, i;
418 BYTE byte_and = (and & 1) ? 0xff : 0;
419 BYTE byte_xor = (xor & 1) ? 0xff : 0;
420 BYTE start_and, start_xor, end_and, end_xor, mask;
421 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
423 for(i = 0; i < num; i++, rc++)
425 int left = dib->rect.left + rc->left;
426 int right = dib->rect.left + rc->right;
428 if (left >= right) continue;
430 start = get_pixel_ptr_1(dib, rc->left, rc->top);
432 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
434 mask = masks[left & 7] & ~masks[right & 7];
436 start_and = byte_and | ~mask;
437 start_xor = byte_xor & mask;
438 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
440 do_rop_8(start, start_and, start_xor);
443 else
445 mask = masks[left & 7];
446 start_and = byte_and | ~mask;
447 start_xor = byte_xor & mask;
449 mask = masks[right & 7];
450 /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
451 end_and = byte_and | mask;
452 end_xor = byte_xor & ~mask;
454 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
456 ptr = start;
458 if(left & 7)
459 do_rop_8(ptr++, start_and, start_xor);
461 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
462 do_rop_8(ptr++, byte_and, byte_xor);
464 if(right & 7)
465 do_rop_8(ptr, end_and, end_xor);
471 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
473 return;
476 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
477 DWORD and, DWORD xor)
479 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
480 int len = params->length, err = params->err_start;
481 int major_inc, minor_inc;
483 if (params->x_major)
485 major_inc = params->x_inc;
486 minor_inc = (dib->stride * params->y_inc) / 4;
488 else
490 major_inc = (dib->stride * params->y_inc) / 4;
491 minor_inc = params->x_inc;
494 while (len--)
496 do_rop_32( ptr, and, xor );
497 if (err + params->bias > 0)
499 ptr += minor_inc;
500 err += params->err_add_1;
502 else err += params->err_add_2;
503 ptr += major_inc;
507 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
508 DWORD and, DWORD xor)
510 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
511 int len = params->length, err = params->err_start;
512 int major_inc, minor_inc;
514 if (params->x_major)
516 major_inc = params->x_inc * 3;
517 minor_inc = dib->stride * params->y_inc;
519 else
521 major_inc = dib->stride * params->y_inc;
522 minor_inc = params->x_inc * 3;
525 while (len--)
527 do_rop_8( ptr, and, xor );
528 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
529 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
530 if (err + params->bias > 0)
532 ptr += minor_inc;
533 err += params->err_add_1;
535 else err += params->err_add_2;
536 ptr += major_inc;
540 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
541 DWORD and, DWORD xor)
543 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
544 int len = params->length, err = params->err_start;
545 int major_inc, minor_inc;
547 if (params->x_major)
549 major_inc = params->x_inc;
550 minor_inc = (dib->stride * params->y_inc) / 2;
552 else
554 major_inc = (dib->stride * params->y_inc) / 2;
555 minor_inc = params->x_inc;
558 while (len--)
560 do_rop_16( ptr, and, xor );
561 if (err + params->bias > 0)
563 ptr += minor_inc;
564 err += params->err_add_1;
566 else err += params->err_add_2;
567 ptr += major_inc;
571 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
572 DWORD and, DWORD xor)
574 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
575 int len = params->length, err = params->err_start;
576 int major_inc, minor_inc;
578 if (params->x_major)
580 major_inc = params->x_inc;
581 minor_inc = dib->stride * params->y_inc;
583 else
585 major_inc = dib->stride * params->y_inc;
586 minor_inc = params->x_inc;
589 while (len--)
591 do_rop_8( ptr, and, xor );
592 if (err + params->bias > 0)
594 ptr += minor_inc;
595 err += params->err_add_1;
597 else err += params->err_add_2;
598 ptr += major_inc;
602 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
603 DWORD and, DWORD xor)
605 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
606 int len = params->length, err = params->err_start;
607 int x = dib->rect.left + start->x;
609 and = (and & 0x0f) | ((and << 4) & 0xf0);
610 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
612 if (params->x_major)
614 while (len--)
616 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
617 if (err + params->bias > 0)
619 ptr += dib->stride * params->y_inc;
620 err += params->err_add_1;
622 else err += params->err_add_2;
623 if ((x / 2) != ((x + params->x_inc) / 2))
624 ptr += params->x_inc;
625 x += params->x_inc;
628 else
630 while (len--)
632 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
633 if (err + params->bias > 0)
635 if ((x / 2) != ((x + params->x_inc) / 2))
636 ptr += params->x_inc;
637 x += params->x_inc;
638 err += params->err_add_1;
640 else err += params->err_add_2;
641 ptr += dib->stride * params->y_inc;
646 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
647 DWORD and, DWORD xor)
649 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
650 int len = params->length, err = params->err_start;
651 int x = dib->rect.left + start->x;
653 and = (and & 0x1) ? 0xff : 0;
654 xor = (xor & 0x1) ? 0xff : 0;
656 if (params->x_major)
658 while (len--)
660 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
661 if (err + params->bias > 0)
663 ptr += dib->stride * params->y_inc;
664 err += params->err_add_1;
666 else err += params->err_add_2;
667 if ((x / 8) != ((x + params->x_inc) / 8))
668 ptr += params->x_inc;
669 x += params->x_inc;
672 else
674 while (len--)
676 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
677 if (err + params->bias > 0)
679 if ((x / 8) != ((x + params->x_inc) / 8))
680 ptr += params->x_inc;
681 x += params->x_inc;
682 err += params->err_add_1;
684 else err += params->err_add_2;
685 ptr += dib->stride * params->y_inc;
690 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
691 DWORD and, DWORD xor)
693 return;
696 static inline INT calc_offset(INT edge, INT size, INT origin)
698 INT offset;
700 if(edge - origin >= 0)
701 offset = (edge - origin) % size;
702 else
704 offset = (origin - edge) % size;
705 if(offset) offset = size - offset;
707 return offset;
710 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
712 POINT offset;
714 offset.x = calc_offset(rc->left, brush->width, origin->x);
715 offset.y = calc_offset(rc->top, brush->height, origin->y);
717 return offset;
720 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
721 const dib_info *brush, const rop_mask_bits *bits)
723 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
724 int x, y, i;
725 POINT offset;
727 for(i = 0; i < num; i++, rc++)
729 offset = calc_brush_offset(rc, brush, origin);
731 start = get_pixel_ptr_32(dib, rc->left, rc->top);
732 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
733 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
735 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
737 and_ptr = start_and + offset.x;
738 xor_ptr = start_xor + offset.x;
740 for(x = rc->left, ptr = start; x < rc->right; x++)
742 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
743 if(and_ptr == start_and + brush->width)
745 and_ptr = start_and;
746 xor_ptr = start_xor;
750 offset.y++;
751 if(offset.y == brush->height)
753 start_and = bits->and;
754 start_xor = bits->xor;
755 offset.y = 0;
757 else
759 start_and += brush->stride / 4;
760 start_xor += brush->stride / 4;
766 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
767 const dib_info *brush, const rop_mask_bits *bits)
769 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
770 int x, y, i;
771 POINT offset;
773 for(i = 0; i < num; i++, rc++)
775 offset = calc_brush_offset(rc, brush, origin);
777 start = get_pixel_ptr_24(dib, rc->left, rc->top);
778 start_and = (BYTE*)bits->and + offset.y * brush->stride;
779 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
781 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
783 and_ptr = start_and + offset.x * 3;
784 xor_ptr = start_xor + offset.x * 3;
786 for(x = rc->left, ptr = start; x < rc->right; x++)
788 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
789 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
790 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
791 if(and_ptr == start_and + brush->width * 3)
793 and_ptr = start_and;
794 xor_ptr = start_xor;
798 offset.y++;
799 if(offset.y == brush->height)
801 start_and = bits->and;
802 start_xor = bits->xor;
803 offset.y = 0;
805 else
807 start_and += brush->stride;
808 start_xor += brush->stride;
814 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
815 const dib_info *brush, const rop_mask_bits *bits)
817 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
818 int x, y, i;
819 POINT offset;
821 for(i = 0; i < num; i++, rc++)
823 offset = calc_brush_offset(rc, brush, origin);
825 start = get_pixel_ptr_16(dib, rc->left, rc->top);
826 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
827 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
829 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
831 and_ptr = start_and + offset.x;
832 xor_ptr = start_xor + offset.x;
834 for(x = rc->left, ptr = start; x < rc->right; x++)
836 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
837 if(and_ptr == start_and + brush->width)
839 and_ptr = start_and;
840 xor_ptr = start_xor;
844 offset.y++;
845 if(offset.y == brush->height)
847 start_and = bits->and;
848 start_xor = bits->xor;
849 offset.y = 0;
851 else
853 start_and += brush->stride / 2;
854 start_xor += brush->stride / 2;
860 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
861 const dib_info *brush, const rop_mask_bits *bits)
863 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
864 int x, y, i;
865 POINT offset;
867 for(i = 0; i < num; i++, rc++)
869 offset = calc_brush_offset(rc, brush, origin);
871 start = get_pixel_ptr_8(dib, rc->left, rc->top);
872 start_and = (BYTE*)bits->and + offset.y * brush->stride;
873 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
875 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
877 and_ptr = start_and + offset.x;
878 xor_ptr = start_xor + offset.x;
880 for(x = rc->left, ptr = start; x < rc->right; x++)
882 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
883 if(and_ptr == start_and + brush->width)
885 and_ptr = start_and;
886 xor_ptr = start_xor;
890 offset.y++;
891 if(offset.y == brush->height)
893 start_and = bits->and;
894 start_xor = bits->xor;
895 offset.y = 0;
897 else
899 start_and += brush->stride;
900 start_xor += brush->stride;
906 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
907 const dib_info *brush, const rop_mask_bits *bits)
909 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
910 int x, y, i, left, right;
911 POINT offset;
913 for(i = 0; i < num; i++, rc++)
915 offset = calc_brush_offset(rc, brush, origin);
916 left = dib->rect.left + rc->left;
917 right = dib->rect.left + rc->right;
919 start = get_pixel_ptr_4(dib, rc->left, rc->top);
920 start_and = (BYTE*)bits->and + offset.y * brush->stride;
921 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
923 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
925 INT brush_x = offset.x;
926 BYTE byte_and, byte_xor;
928 and_ptr = start_and + brush_x / 2;
929 xor_ptr = start_xor + brush_x / 2;
931 for(x = left, ptr = start; x < right; x++)
933 /* FIXME: Two pixels at a time */
934 if(x & 1) /* lower dst nibble */
936 if(brush_x & 1) /* lower pat nibble */
938 byte_and = *and_ptr++ | 0xf0;
939 byte_xor = *xor_ptr++ & 0x0f;
941 else /* upper pat nibble */
943 byte_and = (*and_ptr >> 4) | 0xf0;
944 byte_xor = (*xor_ptr >> 4) & 0x0f;
947 else /* upper dst nibble */
949 if(brush_x & 1) /* lower pat nibble */
951 byte_and = (*and_ptr++ << 4) | 0x0f;
952 byte_xor = (*xor_ptr++ << 4) & 0xf0;
954 else /* upper pat nibble */
956 byte_and = *and_ptr | 0x0f;
957 byte_xor = *xor_ptr & 0xf0;
960 do_rop_8(ptr, byte_and, byte_xor);
962 if(x & 1) ptr++;
964 if(++brush_x == brush->width)
966 brush_x = 0;
967 and_ptr = start_and;
968 xor_ptr = start_xor;
972 offset.y++;
973 if(offset.y == brush->height)
975 start_and = bits->and;
976 start_xor = bits->xor;
977 offset.y = 0;
979 else
981 start_and += brush->stride;
982 start_xor += brush->stride;
988 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
989 const dib_info *brush, const rop_mask_bits *bits)
991 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
992 int x, y, i, left, right;
993 POINT offset;
995 for(i = 0; i < num; i++, rc++)
997 offset = calc_brush_offset(rc, brush, origin);
998 left = dib->rect.left + rc->left;
999 right = dib->rect.left + rc->right;
1001 start = get_pixel_ptr_1(dib, rc->left, rc->top);
1002 start_and = (BYTE*)bits->and + offset.y * brush->stride;
1003 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
1005 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
1007 INT brush_x = offset.x;
1008 BYTE byte_and, byte_xor;
1010 and_ptr = start_and + brush_x / 8;
1011 xor_ptr = start_xor + brush_x / 8;
1013 for(x = left, ptr = start; x < right; x++)
1015 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1016 byte_and |= ~pixel_masks_1[x % 8];
1017 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1018 byte_xor &= pixel_masks_1[x % 8];
1020 do_rop_8(ptr, byte_and, byte_xor);
1022 if((x & 7) == 7) ptr++;
1024 if((brush_x & 7) == 7)
1026 and_ptr++;
1027 xor_ptr++;
1030 if(++brush_x == brush->width)
1032 brush_x = 0;
1033 and_ptr = start_and;
1034 xor_ptr = start_xor;
1038 offset.y++;
1039 if(offset.y == brush->height)
1041 start_and = bits->and;
1042 start_xor = bits->xor;
1043 offset.y = 0;
1045 else
1047 start_and += brush->stride;
1048 start_xor += brush->stride;
1054 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1055 const dib_info *brush, const rop_mask_bits *bits)
1057 return;
1060 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1061 const dib_info *src, const POINT *origin, int rop2, int overlap)
1063 DWORD *dst_start, *src_start;
1064 struct rop_codes codes;
1065 int y, dst_stride, src_stride;
1067 if (overlap & OVERLAP_BELOW)
1069 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1070 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1071 dst_stride = -dst->stride / 4;
1072 src_stride = -src->stride / 4;
1074 else
1076 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1077 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1078 dst_stride = dst->stride / 4;
1079 src_stride = src->stride / 4;
1082 if (rop2 == R2_COPYPEN)
1084 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1085 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1086 return;
1089 get_rop_codes( rop2, &codes );
1090 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1092 if (overlap & OVERLAP_RIGHT)
1093 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1094 else
1095 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1099 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1100 const dib_info *src, const POINT *origin, int rop2, int overlap)
1102 BYTE *dst_start, *src_start;
1103 int y, dst_stride, src_stride;
1104 struct rop_codes codes;
1106 if (overlap & OVERLAP_BELOW)
1108 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1109 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1110 dst_stride = -dst->stride;
1111 src_stride = -src->stride;
1113 else
1115 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1116 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1117 dst_stride = dst->stride;
1118 src_stride = src->stride;
1121 if (rop2 == R2_COPYPEN)
1123 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1124 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1125 return;
1128 get_rop_codes( rop2, &codes );
1129 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1131 if (overlap & OVERLAP_RIGHT)
1132 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1133 else
1134 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1138 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1139 const dib_info *src, const POINT *origin, int rop2, int overlap)
1141 WORD *dst_start, *src_start;
1142 int y, dst_stride, src_stride;
1143 struct rop_codes codes;
1145 if (overlap & OVERLAP_BELOW)
1147 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1148 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1149 dst_stride = -dst->stride / 2;
1150 src_stride = -src->stride / 2;
1152 else
1154 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1155 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1156 dst_stride = dst->stride / 2;
1157 src_stride = src->stride / 2;
1160 if (rop2 == R2_COPYPEN)
1162 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1163 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1164 return;
1167 get_rop_codes( rop2, &codes );
1168 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1170 if (overlap & OVERLAP_RIGHT)
1171 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1172 else
1173 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1177 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1178 const dib_info *src, const POINT *origin, int rop2, int overlap)
1180 BYTE *dst_start, *src_start;
1181 int y, dst_stride, src_stride;
1182 struct rop_codes codes;
1184 if (overlap & OVERLAP_BELOW)
1186 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1187 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1188 dst_stride = -dst->stride;
1189 src_stride = -src->stride;
1191 else
1193 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1194 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1195 dst_stride = dst->stride;
1196 src_stride = src->stride;
1199 if (rop2 == R2_COPYPEN)
1201 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1202 memmove( dst_start, src_start, (rc->right - rc->left) );
1203 return;
1206 get_rop_codes( rop2, &codes );
1207 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1209 if (overlap & OVERLAP_RIGHT)
1210 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1211 else
1212 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1216 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1217 const dib_info *src, const POINT *origin, int rop2, int overlap)
1219 BYTE *dst_start, *src_start;
1220 int y, dst_stride, src_stride;
1221 struct rop_codes codes;
1222 int left = dst->rect.left + rc->left;
1223 int right = dst->rect.left + rc->right;
1224 int org_x = src->rect.left + origin->x;
1226 if (overlap & OVERLAP_BELOW)
1228 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1229 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1230 dst_stride = -dst->stride;
1231 src_stride = -src->stride;
1233 else
1235 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1236 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1237 dst_stride = dst->stride;
1238 src_stride = src->stride;
1241 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1243 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1244 memmove( dst_start, src_start, (right - left) / 2 );
1245 return;
1248 get_rop_codes( rop2, &codes );
1249 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1251 if (overlap & OVERLAP_RIGHT)
1252 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1253 else
1254 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1258 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1259 const dib_info *src, const POINT *origin, int rop2, int overlap)
1261 BYTE *dst_start, *src_start;
1262 int y, dst_stride, src_stride;
1263 struct rop_codes codes;
1264 int left = dst->rect.left + rc->left;
1265 int right = dst->rect.left + rc->right;
1266 int org_x = src->rect.left + origin->x;
1268 if (overlap & OVERLAP_BELOW)
1270 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1271 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1272 dst_stride = -dst->stride;
1273 src_stride = -src->stride;
1275 else
1277 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1278 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1279 dst_stride = dst->stride;
1280 src_stride = src->stride;
1283 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1285 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1286 memmove( dst_start, src_start, (right - left) / 8 );
1287 return;
1290 get_rop_codes( rop2, &codes );
1291 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1293 if (overlap & OVERLAP_RIGHT)
1294 do_rop_codes_line_rev_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1295 else
1296 do_rop_codes_line_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1300 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1301 const dib_info *src, const POINT *origin, int rop2, int overlap)
1303 return;
1306 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
1308 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1309 return *ptr;
1312 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1314 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1315 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1318 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1320 WORD *ptr = get_pixel_ptr_16( dib, x, y );
1321 return *ptr;
1324 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1326 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1327 return *ptr;
1330 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1332 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1334 if ((dib->rect.left + x) & 1)
1335 return *ptr & 0x0f;
1336 else
1337 return (*ptr >> 4) & 0x0f;
1340 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1342 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1343 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
1346 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
1348 return 0;
1351 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1353 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1356 static const DWORD field_masks[33] =
1358 0x00, /* should never happen */
1359 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1360 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1361 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1362 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1365 static inline DWORD get_field(DWORD field, int shift, int len)
1367 shift = shift - (8 - len);
1368 if (shift < 0)
1369 field <<= -shift;
1370 else
1371 field >>= shift;
1372 field &= field_masks[len];
1373 field |= field >> len;
1374 return field;
1377 static inline DWORD put_field(DWORD field, int shift, int len)
1379 shift = shift - (8 - len);
1380 field &= field_masks[len];
1381 if (shift < 0)
1382 field >>= -shift;
1383 else
1384 field <<= shift;
1385 return field;
1388 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1390 DWORD r,g,b;
1392 r = GetRValue(colour);
1393 g = GetGValue(colour);
1394 b = GetBValue(colour);
1396 return put_field(r, dib->red_shift, dib->red_len) |
1397 put_field(g, dib->green_shift, dib->green_len) |
1398 put_field(b, dib->blue_shift, dib->blue_len);
1401 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1403 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1406 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1408 const RGBQUAD *color_table = get_dib_color_table( dib );
1409 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
1410 int i, best_index = 0;
1411 DWORD diff, best_diff = 0xffffffff;
1413 /* special case for conversion to 1-bpp without a color table:
1414 * we get a 1-entry table containing the background color
1416 if (dib->bit_count == 1 && size == 1)
1417 return (r == color_table[0].rgbRed &&
1418 g == color_table[0].rgbGreen &&
1419 b == color_table[0].rgbBlue);
1421 for(i = 0; i < size; i++)
1423 const RGBQUAD *cur = color_table + i;
1424 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1425 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1426 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1428 if(diff == 0)
1430 best_index = i;
1431 break;
1434 if(diff < best_diff)
1436 best_diff = diff;
1437 best_index = i;
1440 return best_index;
1443 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, BYTE r, BYTE g, BYTE b)
1445 DWORD ret;
1447 if (!dither)
1448 ret = rgb_to_pixel_colortable( dib, r, g, b );
1449 else
1450 ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255;
1452 return ret ? 0xff : 0;
1455 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1457 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1460 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1462 return 0;
1465 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1467 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1470 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1472 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1473 get_field( pixel, dib->green_shift, dib->green_len ),
1474 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1477 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1479 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1480 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1481 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1484 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1486 const RGBQUAD *color_table = get_dib_color_table( dib );
1488 if (!dib->color_table || pixel < dib->color_table_size)
1490 RGBQUAD quad = color_table[pixel];
1491 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1493 return 0;
1496 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1498 return 0;
1501 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1503 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1505 return d1->red_mask == d2->red_mask &&
1506 d1->green_mask == d2->green_mask &&
1507 d1->blue_mask == d2->blue_mask;
1510 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1512 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1513 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1515 switch(src->bit_count)
1517 case 32:
1519 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1520 if(src->funcs == &funcs_8888)
1522 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1523 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1524 else
1526 for(y = src_rect->top; y < src_rect->bottom; y++)
1528 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1529 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1530 dst_start += dst->stride / 4;
1531 src_start += src->stride / 4;
1535 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1537 for(y = src_rect->top; y < src_rect->bottom; y++)
1539 dst_pixel = dst_start;
1540 src_pixel = src_start;
1541 for(x = src_rect->left; x < src_rect->right; x++)
1543 src_val = *src_pixel++;
1544 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1545 (((src_val >> src->green_shift) & 0xff) << 8) |
1546 ((src_val >> src->blue_shift) & 0xff);
1548 if(pad_size) memset(dst_pixel, 0, pad_size);
1549 dst_start += dst->stride / 4;
1550 src_start += src->stride / 4;
1553 else
1555 for(y = src_rect->top; y < src_rect->bottom; y++)
1557 dst_pixel = dst_start;
1558 src_pixel = src_start;
1559 for(x = src_rect->left; x < src_rect->right; x++)
1561 src_val = *src_pixel++;
1562 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1563 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1564 get_field( src_val, src->blue_shift, src->blue_len ));
1566 if(pad_size) memset(dst_pixel, 0, pad_size);
1567 dst_start += dst->stride / 4;
1568 src_start += src->stride / 4;
1571 break;
1574 case 24:
1576 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1578 for(y = src_rect->top; y < src_rect->bottom; y++)
1580 dst_pixel = dst_start;
1581 src_pixel = src_start;
1582 for(x = src_rect->left; x < src_rect->right; x++)
1584 RGBQUAD rgb;
1585 rgb.rgbBlue = *src_pixel++;
1586 rgb.rgbGreen = *src_pixel++;
1587 rgb.rgbRed = *src_pixel++;
1589 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1591 if(pad_size) memset(dst_pixel, 0, pad_size);
1592 dst_start += dst->stride / 4;
1593 src_start += src->stride;
1595 break;
1598 case 16:
1600 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1601 if(src->funcs == &funcs_555)
1603 for(y = src_rect->top; y < src_rect->bottom; y++)
1605 dst_pixel = dst_start;
1606 src_pixel = src_start;
1607 for(x = src_rect->left; x < src_rect->right; x++)
1609 src_val = *src_pixel++;
1610 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1611 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1612 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1614 if(pad_size) memset(dst_pixel, 0, pad_size);
1615 dst_start += dst->stride / 4;
1616 src_start += src->stride / 2;
1619 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1621 for(y = src_rect->top; y < src_rect->bottom; y++)
1623 dst_pixel = dst_start;
1624 src_pixel = src_start;
1625 for(x = src_rect->left; x < src_rect->right; x++)
1627 src_val = *src_pixel++;
1628 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1629 (((src_val >> src->red_shift) << 14) & 0x070000) |
1630 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1631 (((src_val >> src->green_shift) << 6) & 0x000700) |
1632 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1633 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1635 if(pad_size) memset(dst_pixel, 0, pad_size);
1636 dst_start += dst->stride / 4;
1637 src_start += src->stride / 2;
1640 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1642 for(y = src_rect->top; y < src_rect->bottom; y++)
1644 dst_pixel = dst_start;
1645 src_pixel = src_start;
1646 for(x = src_rect->left; x < src_rect->right; x++)
1648 src_val = *src_pixel++;
1649 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1650 (((src_val >> src->red_shift) << 14) & 0x070000) |
1651 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1652 (((src_val >> src->green_shift) << 4) & 0x000300) |
1653 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1654 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1656 if(pad_size) memset(dst_pixel, 0, pad_size);
1657 dst_start += dst->stride / 4;
1658 src_start += src->stride / 2;
1661 else
1663 for(y = src_rect->top; y < src_rect->bottom; y++)
1665 dst_pixel = dst_start;
1666 src_pixel = src_start;
1667 for(x = src_rect->left; x < src_rect->right; x++)
1669 src_val = *src_pixel++;
1670 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1671 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1672 get_field( src_val, src->blue_shift, src->blue_len ));
1674 if(pad_size) memset(dst_pixel, 0, pad_size);
1675 dst_start += dst->stride / 4;
1676 src_start += src->stride / 2;
1679 break;
1682 case 8:
1684 const RGBQUAD *color_table = get_dib_color_table( src );
1685 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1686 for(y = src_rect->top; y < src_rect->bottom; y++)
1688 dst_pixel = dst_start;
1689 src_pixel = src_start;
1690 for(x = src_rect->left; x < src_rect->right; x++)
1692 RGBQUAD rgb = color_table[*src_pixel++];
1693 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1695 if(pad_size) memset(dst_pixel, 0, pad_size);
1696 dst_start += dst->stride / 4;
1697 src_start += src->stride;
1699 break;
1702 case 4:
1704 const RGBQUAD *color_table = get_dib_color_table( src );
1705 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1706 for(y = src_rect->top; y < src_rect->bottom; y++)
1708 int pos = (src->rect.left + src_rect->left) & 1;
1709 src_pixel = src_start;
1710 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1712 RGBQUAD rgb;
1713 if (pos & 1)
1714 rgb = color_table[*src_pixel++ & 0xf];
1715 else
1716 rgb = color_table[*src_pixel >> 4];
1717 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1719 if(pad_size) memset(dst_start + x, 0, pad_size);
1720 dst_start += dst->stride / 4;
1721 src_start += src->stride;
1723 break;
1726 case 1:
1728 const RGBQUAD *color_table = get_dib_color_table( src );
1729 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1730 for(y = src_rect->top; y < src_rect->bottom; y++)
1732 int pos = (src->rect.left + src_rect->left) & 7;
1733 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1735 RGBQUAD rgb;
1736 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1737 rgb = color_table[src_val];
1738 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1740 if(pad_size) memset(dst_start + x, 0, pad_size);
1741 dst_start += dst->stride / 4;
1742 src_start += src->stride;
1744 break;
1749 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1751 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1752 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1754 switch(src->bit_count)
1756 case 32:
1758 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1760 if(src->funcs == &funcs_8888)
1762 for(y = src_rect->top; y < src_rect->bottom; y++)
1764 dst_pixel = dst_start;
1765 src_pixel = src_start;
1766 for(x = src_rect->left; x < src_rect->right; x++)
1768 src_val = *src_pixel++;
1769 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1770 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1771 put_field(src_val, dst->blue_shift, dst->blue_len);
1773 if(pad_size) memset(dst_pixel, 0, pad_size);
1774 dst_start += dst->stride / 4;
1775 src_start += src->stride / 4;
1778 else if(bit_fields_match(src, dst))
1780 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1781 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1782 else
1784 for(y = src_rect->top; y < src_rect->bottom; y++)
1786 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1787 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1788 dst_start += dst->stride / 4;
1789 src_start += src->stride / 4;
1793 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1794 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1796 for(y = src_rect->top; y < src_rect->bottom; y++)
1798 dst_pixel = dst_start;
1799 src_pixel = src_start;
1800 for(x = src_rect->left; x < src_rect->right; x++)
1802 src_val = *src_pixel++;
1803 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1804 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1805 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1807 if(pad_size) memset(dst_pixel, 0, pad_size);
1808 dst_start += dst->stride / 4;
1809 src_start += src->stride / 4;
1812 else
1814 for(y = src_rect->top; y < src_rect->bottom; y++)
1816 dst_pixel = dst_start;
1817 src_pixel = src_start;
1818 for(x = src_rect->left; x < src_rect->right; x++)
1820 src_val = *src_pixel++;
1821 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1822 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1823 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1825 if(pad_size) memset(dst_pixel, 0, pad_size);
1826 dst_start += dst->stride / 4;
1827 src_start += src->stride / 4;
1830 break;
1833 case 24:
1835 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1837 for(y = src_rect->top; y < src_rect->bottom; y++)
1839 dst_pixel = dst_start;
1840 src_pixel = src_start;
1841 for(x = src_rect->left; x < src_rect->right; x++)
1843 RGBQUAD rgb;
1844 rgb.rgbBlue = *src_pixel++;
1845 rgb.rgbGreen = *src_pixel++;
1846 rgb.rgbRed = *src_pixel++;
1848 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1849 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1850 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1852 if(pad_size) memset(dst_pixel, 0, pad_size);
1853 dst_start += dst->stride / 4;
1854 src_start += src->stride;
1856 break;
1859 case 16:
1861 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1862 if(src->funcs == &funcs_555)
1864 for(y = src_rect->top; y < src_rect->bottom; y++)
1866 dst_pixel = dst_start;
1867 src_pixel = src_start;
1868 for(x = src_rect->left; x < src_rect->right; x++)
1870 src_val = *src_pixel++;
1871 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1872 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1873 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1875 if(pad_size) memset(dst_pixel, 0, pad_size);
1876 dst_start += dst->stride / 4;
1877 src_start += src->stride / 2;
1880 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1882 for(y = src_rect->top; y < src_rect->bottom; y++)
1884 dst_pixel = dst_start;
1885 src_pixel = src_start;
1886 for(x = src_rect->left; x < src_rect->right; x++)
1888 src_val = *src_pixel++;
1889 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1890 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1891 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1892 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1893 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1894 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1896 if(pad_size) memset(dst_pixel, 0, pad_size);
1897 dst_start += dst->stride / 4;
1898 src_start += src->stride / 2;
1901 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1903 for(y = src_rect->top; y < src_rect->bottom; y++)
1905 dst_pixel = dst_start;
1906 src_pixel = src_start;
1907 for(x = src_rect->left; x < src_rect->right; x++)
1909 src_val = *src_pixel++;
1910 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1911 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1912 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1913 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1914 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1915 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1917 if(pad_size) memset(dst_pixel, 0, pad_size);
1918 dst_start += dst->stride / 4;
1919 src_start += src->stride / 2;
1922 else
1924 for(y = src_rect->top; y < src_rect->bottom; y++)
1926 dst_pixel = dst_start;
1927 src_pixel = src_start;
1928 for(x = src_rect->left; x < src_rect->right; x++)
1930 src_val = *src_pixel++;
1931 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1932 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1933 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1935 if(pad_size) memset(dst_pixel, 0, pad_size);
1936 dst_start += dst->stride / 4;
1937 src_start += src->stride / 2;
1940 break;
1943 case 8:
1945 const RGBQUAD *color_table = get_dib_color_table( src );
1946 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1947 for(y = src_rect->top; y < src_rect->bottom; y++)
1949 dst_pixel = dst_start;
1950 src_pixel = src_start;
1951 for(x = src_rect->left; x < src_rect->right; x++)
1953 RGBQUAD rgb = color_table[*src_pixel++];
1954 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1955 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1956 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1958 if(pad_size) memset(dst_pixel, 0, pad_size);
1959 dst_start += dst->stride / 4;
1960 src_start += src->stride;
1962 break;
1965 case 4:
1967 const RGBQUAD *color_table = get_dib_color_table( src );
1968 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1969 for(y = src_rect->top; y < src_rect->bottom; y++)
1971 int pos = (src->rect.left + src_rect->left) & 1;
1972 src_pixel = src_start;
1973 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1975 RGBQUAD rgb;
1976 if (pos & 1)
1977 rgb = color_table[*src_pixel++ & 0xf];
1978 else
1979 rgb = color_table[*src_pixel >> 4];
1980 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1981 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1982 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1984 if(pad_size) memset(dst_start + x, 0, pad_size);
1985 dst_start += dst->stride / 4;
1986 src_start += src->stride;
1988 break;
1991 case 1:
1993 const RGBQUAD *color_table = get_dib_color_table( src );
1994 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1995 for(y = src_rect->top; y < src_rect->bottom; y++)
1997 int pos = (src->rect.left + src_rect->left) & 7;
1998 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2000 RGBQUAD rgb;
2001 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2002 rgb = color_table[src_val];
2003 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2004 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2005 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2007 if(pad_size) memset(dst_start + x, 0, pad_size);
2008 dst_start += dst->stride / 4;
2009 src_start += src->stride;
2011 break;
2016 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2018 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2019 DWORD src_val;
2020 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2022 switch(src->bit_count)
2024 case 32:
2026 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2027 if(src->funcs == &funcs_8888)
2029 for(y = src_rect->top; y < src_rect->bottom; y++)
2031 dst_pixel = dst_start;
2032 src_pixel = src_start;
2033 for(x = src_rect->left; x < src_rect->right; x++)
2035 src_val = *src_pixel++;
2036 *dst_pixel++ = src_val & 0xff;
2037 *dst_pixel++ = (src_val >> 8) & 0xff;
2038 *dst_pixel++ = (src_val >> 16) & 0xff;
2040 if(pad_size) memset(dst_pixel, 0, pad_size);
2041 dst_start += dst->stride;
2042 src_start += src->stride / 4;
2045 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2047 for(y = src_rect->top; y < src_rect->bottom; y++)
2049 dst_pixel = dst_start;
2050 src_pixel = src_start;
2051 for(x = src_rect->left; x < src_rect->right; x++)
2053 src_val = *src_pixel++;
2054 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2055 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2056 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2058 if(pad_size) memset(dst_pixel, 0, pad_size);
2059 dst_start += dst->stride;
2060 src_start += src->stride / 4;
2063 else
2065 for(y = src_rect->top; y < src_rect->bottom; y++)
2067 dst_pixel = dst_start;
2068 src_pixel = src_start;
2069 for(x = src_rect->left; x < src_rect->right; x++)
2071 src_val = *src_pixel++;
2072 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2073 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2074 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2076 if(pad_size) memset(dst_pixel, 0, pad_size);
2077 dst_start += dst->stride;
2078 src_start += src->stride / 4;
2081 break;
2084 case 24:
2086 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2088 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2089 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2090 else
2092 for(y = src_rect->top; y < src_rect->bottom; y++)
2094 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2095 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2096 dst_start += dst->stride;
2097 src_start += src->stride;
2100 break;
2103 case 16:
2105 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2106 if(src->funcs == &funcs_555)
2108 for(y = src_rect->top; y < src_rect->bottom; y++)
2110 dst_pixel = dst_start;
2111 src_pixel = src_start;
2112 for(x = src_rect->left; x < src_rect->right; x++)
2114 src_val = *src_pixel++;
2115 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2116 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2117 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2119 if(pad_size) memset(dst_pixel, 0, pad_size);
2120 dst_start += dst->stride;
2121 src_start += src->stride / 2;
2124 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2126 for(y = src_rect->top; y < src_rect->bottom; y++)
2128 dst_pixel = dst_start;
2129 src_pixel = src_start;
2130 for(x = src_rect->left; x < src_rect->right; x++)
2132 src_val = *src_pixel++;
2133 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2134 (((src_val >> src->blue_shift) >> 2) & 0x07);
2135 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2136 (((src_val >> src->green_shift) >> 2) & 0x07);
2137 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2138 (((src_val >> src->red_shift) >> 2) & 0x07);
2140 if(pad_size) memset(dst_pixel, 0, pad_size);
2141 dst_start += dst->stride;
2142 src_start += src->stride / 2;
2145 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2147 for(y = src_rect->top; y < src_rect->bottom; y++)
2149 dst_pixel = dst_start;
2150 src_pixel = src_start;
2151 for(x = src_rect->left; x < src_rect->right; x++)
2153 src_val = *src_pixel++;
2154 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2155 (((src_val >> src->blue_shift) >> 2) & 0x07);
2156 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2157 (((src_val >> src->green_shift) >> 4) & 0x03);
2158 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2159 (((src_val >> src->red_shift) >> 2) & 0x07);
2161 if(pad_size) memset(dst_pixel, 0, pad_size);
2162 dst_start += dst->stride;
2163 src_start += src->stride / 2;
2166 else
2168 for(y = src_rect->top; y < src_rect->bottom; y++)
2170 dst_pixel = dst_start;
2171 src_pixel = src_start;
2172 for(x = src_rect->left; x < src_rect->right; x++)
2174 src_val = *src_pixel++;
2175 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2176 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2177 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2179 if(pad_size) memset(dst_pixel, 0, pad_size);
2180 dst_start += dst->stride;
2181 src_start += src->stride / 2;
2184 break;
2187 case 8:
2189 const RGBQUAD *color_table = get_dib_color_table( src );
2190 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2191 for(y = src_rect->top; y < src_rect->bottom; y++)
2193 dst_pixel = dst_start;
2194 src_pixel = src_start;
2195 for(x = src_rect->left; x < src_rect->right; x++)
2197 RGBQUAD rgb = color_table[*src_pixel++];
2198 *dst_pixel++ = rgb.rgbBlue;
2199 *dst_pixel++ = rgb.rgbGreen;
2200 *dst_pixel++ = rgb.rgbRed;
2202 if(pad_size) memset(dst_pixel, 0, pad_size);
2203 dst_start += dst->stride;
2204 src_start += src->stride;
2206 break;
2209 case 4:
2211 const RGBQUAD *color_table = get_dib_color_table( src );
2212 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2213 for(y = src_rect->top; y < src_rect->bottom; y++)
2215 int pos = (src->rect.left + src_rect->left) & 1;
2216 src_pixel = src_start;
2217 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2219 RGBQUAD rgb;
2220 if (pos & 1)
2221 rgb = color_table[*src_pixel++ & 0xf];
2222 else
2223 rgb = color_table[*src_pixel >> 4];
2224 dst_start[x * 3] = rgb.rgbBlue;
2225 dst_start[x * 3 + 1] = rgb.rgbGreen;
2226 dst_start[x * 3 + 2] = rgb.rgbRed;
2228 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2229 dst_start += dst->stride;
2230 src_start += src->stride;
2232 break;
2235 case 1:
2237 const RGBQUAD *color_table = get_dib_color_table( src );
2238 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2239 for(y = src_rect->top; y < src_rect->bottom; y++)
2241 int pos = (src->rect.left + src_rect->left) & 7;
2242 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2244 RGBQUAD rgb;
2245 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2246 rgb = color_table[src_val];
2247 dst_start[x * 3] = rgb.rgbBlue;
2248 dst_start[x * 3 + 1] = rgb.rgbGreen;
2249 dst_start[x * 3 + 2] = rgb.rgbRed;
2251 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2252 dst_start += dst->stride;
2253 src_start += src->stride;
2255 break;
2260 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2262 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2263 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2264 DWORD src_val;
2266 switch(src->bit_count)
2268 case 32:
2270 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2272 if(src->funcs == &funcs_8888)
2274 for(y = src_rect->top; y < src_rect->bottom; y++)
2276 dst_pixel = dst_start;
2277 src_pixel = src_start;
2278 for(x = src_rect->left; x < src_rect->right; x++)
2280 src_val = *src_pixel++;
2281 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2282 ((src_val >> 6) & 0x03e0) |
2283 ((src_val >> 3) & 0x001f);
2285 if(pad_size) memset(dst_pixel, 0, pad_size);
2286 dst_start += dst->stride / 2;
2287 src_start += src->stride / 4;
2290 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2292 for(y = src_rect->top; y < src_rect->bottom; y++)
2294 dst_pixel = dst_start;
2295 src_pixel = src_start;
2296 for(x = src_rect->left; x < src_rect->right; x++)
2298 src_val = *src_pixel++;
2299 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2300 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2301 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2303 if(pad_size) memset(dst_pixel, 0, pad_size);
2304 dst_start += dst->stride / 2;
2305 src_start += src->stride / 4;
2308 else
2310 for(y = src_rect->top; y < src_rect->bottom; y++)
2312 dst_pixel = dst_start;
2313 src_pixel = src_start;
2314 for(x = src_rect->left; x < src_rect->right; x++)
2316 src_val = *src_pixel++;
2317 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2318 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2319 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2321 if(pad_size) memset(dst_pixel, 0, pad_size);
2322 dst_start += dst->stride / 2;
2323 src_start += src->stride / 4;
2326 break;
2329 case 24:
2331 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2333 for(y = src_rect->top; y < src_rect->bottom; y++)
2335 dst_pixel = dst_start;
2336 src_pixel = src_start;
2337 for(x = src_rect->left; x < src_rect->right; x++)
2339 RGBQUAD rgb;
2340 rgb.rgbBlue = *src_pixel++;
2341 rgb.rgbGreen = *src_pixel++;
2342 rgb.rgbRed = *src_pixel++;
2344 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2345 ((rgb.rgbGreen << 2) & 0x03e0) |
2346 ((rgb.rgbBlue >> 3) & 0x001f);
2348 if(pad_size) memset(dst_pixel, 0, pad_size);
2349 dst_start += dst->stride / 2;
2350 src_start += src->stride;
2352 break;
2355 case 16:
2357 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2358 if(src->funcs == &funcs_555)
2360 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2361 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2362 else
2364 for(y = src_rect->top; y < src_rect->bottom; y++)
2366 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2367 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2368 dst_start += dst->stride / 2;
2369 src_start += src->stride / 2;
2373 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2375 for(y = src_rect->top; y < src_rect->bottom; y++)
2377 dst_pixel = dst_start;
2378 src_pixel = src_start;
2379 for(x = src_rect->left; x < src_rect->right; x++)
2381 src_val = *src_pixel++;
2382 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2383 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2384 ( (src_val >> src->blue_shift) & 0x001f);
2386 if(pad_size) memset(dst_pixel, 0, pad_size);
2387 dst_start += dst->stride / 2;
2388 src_start += src->stride / 2;
2391 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2393 for(y = src_rect->top; y < src_rect->bottom; y++)
2395 dst_pixel = dst_start;
2396 src_pixel = src_start;
2397 for(x = src_rect->left; x < src_rect->right; x++)
2399 src_val = *src_pixel++;
2400 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2401 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2402 ( (src_val >> src->blue_shift) & 0x001f);
2404 if(pad_size) memset(dst_pixel, 0, pad_size);
2405 dst_start += dst->stride / 2;
2406 src_start += src->stride / 2;
2409 else
2411 for(y = src_rect->top; y < src_rect->bottom; y++)
2413 dst_pixel = dst_start;
2414 src_pixel = src_start;
2415 for(x = src_rect->left; x < src_rect->right; x++)
2417 src_val = *src_pixel++;
2418 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2419 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2420 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2422 if(pad_size) memset(dst_pixel, 0, pad_size);
2423 dst_start += dst->stride / 2;
2424 src_start += src->stride / 2;
2427 break;
2430 case 8:
2432 const RGBQUAD *color_table = get_dib_color_table( src );
2433 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2434 for(y = src_rect->top; y < src_rect->bottom; y++)
2436 dst_pixel = dst_start;
2437 src_pixel = src_start;
2438 for(x = src_rect->left; x < src_rect->right; x++)
2440 RGBQUAD rgb = color_table[*src_pixel++];
2441 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2442 ((rgb.rgbGreen << 2) & 0x03e0) |
2443 ((rgb.rgbBlue >> 3) & 0x001f);
2445 if(pad_size) memset(dst_pixel, 0, pad_size);
2446 dst_start += dst->stride / 2;
2447 src_start += src->stride;
2449 break;
2452 case 4:
2454 const RGBQUAD *color_table = get_dib_color_table( src );
2455 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2456 for(y = src_rect->top; y < src_rect->bottom; y++)
2458 int pos = (src->rect.left + src_rect->left) & 1;
2459 src_pixel = src_start;
2460 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2462 RGBQUAD rgb;
2463 if (pos & 1)
2464 rgb = color_table[*src_pixel++ & 0xf];
2465 else
2466 rgb = color_table[*src_pixel >> 4];
2467 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2468 ((rgb.rgbGreen << 2) & 0x03e0) |
2469 ((rgb.rgbBlue >> 3) & 0x001f);
2471 if(pad_size) memset(dst_start + x, 0, pad_size);
2472 dst_start += dst->stride / 2;
2473 src_start += src->stride;
2475 break;
2478 case 1:
2480 const RGBQUAD *color_table = get_dib_color_table( src );
2481 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2482 for(y = src_rect->top; y < src_rect->bottom; y++)
2484 int pos = (src->rect.left + src_rect->left) & 7;
2485 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2487 RGBQUAD rgb;
2488 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2489 rgb = color_table[src_val];
2490 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2491 ((rgb.rgbGreen << 2) & 0x03e0) |
2492 ((rgb.rgbBlue >> 3) & 0x001f);
2494 if(pad_size) memset(dst_start + x, 0, pad_size);
2495 dst_start += dst->stride / 2;
2496 src_start += src->stride;
2498 break;
2503 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2505 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2506 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2507 DWORD src_val;
2509 switch(src->bit_count)
2511 case 32:
2513 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2515 if(src->funcs == &funcs_8888)
2517 for(y = src_rect->top; y < src_rect->bottom; y++)
2519 dst_pixel = dst_start;
2520 src_pixel = src_start;
2521 for(x = src_rect->left; x < src_rect->right; x++)
2523 src_val = *src_pixel++;
2524 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2525 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2526 put_field(src_val, dst->blue_shift, dst->blue_len);
2528 if(pad_size) memset(dst_pixel, 0, pad_size);
2529 dst_start += dst->stride / 2;
2530 src_start += src->stride / 4;
2533 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2535 for(y = src_rect->top; y < src_rect->bottom; y++)
2537 dst_pixel = dst_start;
2538 src_pixel = src_start;
2539 for(x = src_rect->left; x < src_rect->right; x++)
2541 src_val = *src_pixel++;
2542 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2543 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2544 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2546 if(pad_size) memset(dst_pixel, 0, pad_size);
2547 dst_start += dst->stride / 2;
2548 src_start += src->stride / 4;
2551 else
2553 for(y = src_rect->top; y < src_rect->bottom; y++)
2555 dst_pixel = dst_start;
2556 src_pixel = src_start;
2557 for(x = src_rect->left; x < src_rect->right; x++)
2559 src_val = *src_pixel++;
2560 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2561 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2562 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2564 if(pad_size) memset(dst_pixel, 0, pad_size);
2565 dst_start += dst->stride / 2;
2566 src_start += src->stride / 4;
2569 break;
2572 case 24:
2574 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2576 for(y = src_rect->top; y < src_rect->bottom; y++)
2578 dst_pixel = dst_start;
2579 src_pixel = src_start;
2580 for(x = src_rect->left; x < src_rect->right; x++)
2582 RGBQUAD rgb;
2583 rgb.rgbBlue = *src_pixel++;
2584 rgb.rgbGreen = *src_pixel++;
2585 rgb.rgbRed = *src_pixel++;
2587 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2588 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2589 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2591 if(pad_size) memset(dst_pixel, 0, pad_size);
2592 dst_start += dst->stride / 2;
2593 src_start += src->stride;
2595 break;
2598 case 16:
2600 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2601 if(src->funcs == &funcs_555)
2603 for(y = src_rect->top; y < src_rect->bottom; y++)
2605 dst_pixel = dst_start;
2606 src_pixel = src_start;
2607 for(x = src_rect->left; x < src_rect->right; x++)
2609 src_val = *src_pixel++;
2610 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2611 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2612 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2614 if(pad_size) memset(dst_pixel, 0, pad_size);
2615 dst_start += dst->stride / 2;
2616 src_start += src->stride / 2;
2619 else if(bit_fields_match(src, dst))
2621 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2622 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2623 else
2625 for(y = src_rect->top; y < src_rect->bottom; y++)
2627 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2628 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2629 dst_start += dst->stride / 2;
2630 src_start += src->stride / 2;
2634 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2636 for(y = src_rect->top; y < src_rect->bottom; y++)
2638 dst_pixel = dst_start;
2639 src_pixel = src_start;
2640 for(x = src_rect->left; x < src_rect->right; x++)
2642 src_val = *src_pixel++;
2643 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2644 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2645 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2646 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2647 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2648 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2650 if(pad_size) memset(dst_pixel, 0, pad_size);
2651 dst_start += dst->stride / 2;
2652 src_start += src->stride / 2;
2655 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2657 for(y = src_rect->top; y < src_rect->bottom; y++)
2659 dst_pixel = dst_start;
2660 src_pixel = src_start;
2661 for(x = src_rect->left; x < src_rect->right; x++)
2663 src_val = *src_pixel++;
2664 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2665 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2666 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2667 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2668 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2669 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2671 if(pad_size) memset(dst_pixel, 0, pad_size);
2672 dst_start += dst->stride / 2;
2673 src_start += src->stride / 2;
2676 else
2678 for(y = src_rect->top; y < src_rect->bottom; y++)
2680 dst_pixel = dst_start;
2681 src_pixel = src_start;
2682 for(x = src_rect->left; x < src_rect->right; x++)
2684 src_val = *src_pixel++;
2685 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2686 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2687 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2689 if(pad_size) memset(dst_pixel, 0, pad_size);
2690 dst_start += dst->stride / 2;
2691 src_start += src->stride / 2;
2694 break;
2697 case 8:
2699 const RGBQUAD *color_table = get_dib_color_table( src );
2700 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2701 for(y = src_rect->top; y < src_rect->bottom; y++)
2703 dst_pixel = dst_start;
2704 src_pixel = src_start;
2705 for(x = src_rect->left; x < src_rect->right; x++)
2707 RGBQUAD rgb = color_table[*src_pixel++];
2708 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2709 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2710 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2712 if(pad_size) memset(dst_pixel, 0, pad_size);
2713 dst_start += dst->stride / 2;
2714 src_start += src->stride;
2716 break;
2719 case 4:
2721 const RGBQUAD *color_table = get_dib_color_table( src );
2722 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2723 for(y = src_rect->top; y < src_rect->bottom; y++)
2725 int pos = (src->rect.left + src_rect->left) & 1;
2726 src_pixel = src_start;
2727 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2729 RGBQUAD rgb;
2730 if (pos & 1)
2731 rgb = color_table[*src_pixel++ & 0xf];
2732 else
2733 rgb = color_table[*src_pixel >> 4];
2734 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2735 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2736 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2738 if(pad_size) memset(dst_start + x, 0, pad_size);
2739 dst_start += dst->stride / 2;
2740 src_start += src->stride;
2742 break;
2745 case 1:
2747 const RGBQUAD *color_table = get_dib_color_table( src );
2748 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2749 for(y = src_rect->top; y < src_rect->bottom; y++)
2751 int pos = (src->rect.left + src_rect->left) & 7;
2752 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2754 RGBQUAD rgb;
2755 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2756 rgb = color_table[src_val];
2757 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2758 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2759 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2761 if(pad_size) memset(dst_start + x, 0, pad_size);
2762 dst_start += dst->stride / 2;
2763 src_start += src->stride;
2765 break;
2770 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2772 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
2773 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
2776 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2778 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2779 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2782 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2784 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2785 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2786 DWORD src_val;
2788 switch(src->bit_count)
2790 case 32:
2792 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2794 if(src->funcs == &funcs_8888)
2796 for(y = src_rect->top; y < src_rect->bottom; y++)
2798 dst_pixel = dst_start;
2799 src_pixel = src_start;
2800 for(x = src_rect->left; x < src_rect->right; x++)
2802 src_val = *src_pixel++;
2803 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2805 if(pad_size) memset(dst_pixel, 0, pad_size);
2806 dst_start += dst->stride;
2807 src_start += src->stride / 4;
2810 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2812 for(y = src_rect->top; y < src_rect->bottom; y++)
2814 dst_pixel = dst_start;
2815 src_pixel = src_start;
2816 for(x = src_rect->left; x < src_rect->right; x++)
2818 src_val = *src_pixel++;
2819 *dst_pixel++ = rgb_lookup_colortable(dst,
2820 src_val >> src->red_shift,
2821 src_val >> src->green_shift,
2822 src_val >> src->blue_shift );
2824 if(pad_size) memset(dst_pixel, 0, pad_size);
2825 dst_start += dst->stride;
2826 src_start += src->stride / 4;
2829 else
2831 for(y = src_rect->top; y < src_rect->bottom; y++)
2833 dst_pixel = dst_start;
2834 src_pixel = src_start;
2835 for(x = src_rect->left; x < src_rect->right; x++)
2837 src_val = *src_pixel++;
2838 *dst_pixel++ = rgb_lookup_colortable(dst,
2839 get_field(src_val, src->red_shift, src->red_len),
2840 get_field(src_val, src->green_shift, src->green_len),
2841 get_field(src_val, src->blue_shift, src->blue_len));
2843 if(pad_size) memset(dst_pixel, 0, pad_size);
2844 dst_start += dst->stride;
2845 src_start += src->stride / 4;
2848 break;
2851 case 24:
2853 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2855 for(y = src_rect->top; y < src_rect->bottom; y++)
2857 dst_pixel = dst_start;
2858 src_pixel = src_start;
2859 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2861 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2863 if(pad_size) memset(dst_pixel, 0, pad_size);
2864 dst_start += dst->stride;
2865 src_start += src->stride;
2867 break;
2870 case 16:
2872 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2873 if(src->funcs == &funcs_555)
2875 for(y = src_rect->top; y < src_rect->bottom; y++)
2877 dst_pixel = dst_start;
2878 src_pixel = src_start;
2879 for(x = src_rect->left; x < src_rect->right; x++)
2881 src_val = *src_pixel++;
2882 *dst_pixel++ = rgb_lookup_colortable(dst,
2883 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2884 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2885 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2887 if(pad_size) memset(dst_pixel, 0, pad_size);
2888 dst_start += dst->stride;
2889 src_start += src->stride / 2;
2892 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2894 for(y = src_rect->top; y < src_rect->bottom; y++)
2896 dst_pixel = dst_start;
2897 src_pixel = src_start;
2898 for(x = src_rect->left; x < src_rect->right; x++)
2900 src_val = *src_pixel++;
2901 *dst_pixel++ = rgb_lookup_colortable(dst,
2902 (((src_val >> src->red_shift) << 3) & 0xf8) |
2903 (((src_val >> src->red_shift) >> 2) & 0x07),
2904 (((src_val >> src->green_shift) << 3) & 0xf8) |
2905 (((src_val >> src->green_shift) >> 2) & 0x07),
2906 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2907 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2909 if(pad_size) memset(dst_pixel, 0, pad_size);
2910 dst_start += dst->stride;
2911 src_start += src->stride / 2;
2914 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2916 for(y = src_rect->top; y < src_rect->bottom; y++)
2918 dst_pixel = dst_start;
2919 src_pixel = src_start;
2920 for(x = src_rect->left; x < src_rect->right; x++)
2922 src_val = *src_pixel++;
2923 *dst_pixel++ = rgb_lookup_colortable(dst,
2924 (((src_val >> src->red_shift) << 3) & 0xf8) |
2925 (((src_val >> src->red_shift) >> 2) & 0x07),
2926 (((src_val >> src->green_shift) << 2) & 0xfc) |
2927 (((src_val >> src->green_shift) >> 4) & 0x03),
2928 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2929 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2931 if(pad_size) memset(dst_pixel, 0, pad_size);
2932 dst_start += dst->stride;
2933 src_start += src->stride / 2;
2936 else
2938 for(y = src_rect->top; y < src_rect->bottom; y++)
2940 dst_pixel = dst_start;
2941 src_pixel = src_start;
2942 for(x = src_rect->left; x < src_rect->right; x++)
2944 src_val = *src_pixel++;
2945 *dst_pixel++ = rgb_lookup_colortable(dst,
2946 get_field(src_val, src->red_shift, src->red_len),
2947 get_field(src_val, src->green_shift, src->green_len),
2948 get_field(src_val, src->blue_shift, src->blue_len));
2950 if(pad_size) memset(dst_pixel, 0, pad_size);
2951 dst_start += dst->stride;
2952 src_start += src->stride / 2;
2955 break;
2958 case 8:
2960 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2962 if(color_tables_match(dst, src))
2964 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2965 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2966 else
2968 for(y = src_rect->top; y < src_rect->bottom; y++)
2970 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2971 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2972 dst_start += dst->stride;
2973 src_start += src->stride;
2977 else
2979 const RGBQUAD *color_table = get_dib_color_table( src );
2980 for(y = src_rect->top; y < src_rect->bottom; y++)
2982 dst_pixel = dst_start;
2983 src_pixel = src_start;
2984 for(x = src_rect->left; x < src_rect->right; x++)
2986 RGBQUAD rgb = color_table[*src_pixel++];
2987 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2989 if(pad_size) memset(dst_pixel, 0, pad_size);
2990 dst_start += dst->stride;
2991 src_start += src->stride;
2994 break;
2997 case 4:
2999 const RGBQUAD *color_table = get_dib_color_table( src );
3000 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3001 for(y = src_rect->top; y < src_rect->bottom; y++)
3003 int pos = (src->rect.left + src_rect->left) & 1;
3004 src_pixel = src_start;
3005 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3007 RGBQUAD rgb;
3008 if (pos & 1)
3009 rgb = color_table[*src_pixel++ & 0xf];
3010 else
3011 rgb = color_table[*src_pixel >> 4];
3012 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3014 if(pad_size) memset(dst_start + x, 0, pad_size);
3015 dst_start += dst->stride;
3016 src_start += src->stride;
3018 break;
3021 case 1:
3023 const RGBQUAD *color_table = get_dib_color_table( src );
3024 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3025 for(y = src_rect->top; y < src_rect->bottom; y++)
3027 int pos = (src->rect.left + src_rect->left) & 7;
3028 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3030 RGBQUAD rgb;
3031 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3032 rgb = color_table[src_val];
3033 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3035 if(pad_size) memset(dst_start + x, 0, pad_size);
3036 dst_start += dst->stride;
3037 src_start += src->stride;
3039 break;
3044 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3046 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3047 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3048 DWORD src_val;
3050 switch(src->bit_count)
3052 case 32:
3054 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3056 if(src->funcs == &funcs_8888)
3058 for(y = src_rect->top; y < src_rect->bottom; y++)
3060 dst_pixel = dst_start;
3061 src_pixel = src_start;
3062 for(x = src_rect->left; x < src_rect->right; x++)
3064 src_val = *src_pixel++;
3065 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3066 if((x - src_rect->left) & 1)
3068 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3069 dst_pixel++;
3071 else
3072 *dst_pixel = (dst_val << 4) & 0xf0;
3074 if(pad_size)
3076 if((x - src_rect->left) & 1) dst_pixel++;
3077 memset(dst_pixel, 0, pad_size);
3079 dst_start += dst->stride;
3080 src_start += src->stride / 4;
3083 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3085 for(y = src_rect->top; y < src_rect->bottom; y++)
3087 dst_pixel = dst_start;
3088 src_pixel = src_start;
3089 for(x = src_rect->left; x < src_rect->right; x++)
3091 src_val = *src_pixel++;
3092 dst_val = rgb_to_pixel_colortable(dst,
3093 src_val >> src->red_shift,
3094 src_val >> src->green_shift,
3095 src_val >> src->blue_shift);
3096 if((x - src_rect->left) & 1)
3098 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3099 dst_pixel++;
3101 else
3102 *dst_pixel = (dst_val << 4) & 0xf0;
3104 if(pad_size)
3106 if((x - src_rect->left) & 1) dst_pixel++;
3107 memset(dst_pixel, 0, pad_size);
3109 dst_start += dst->stride;
3110 src_start += src->stride / 4;
3113 else
3115 for(y = src_rect->top; y < src_rect->bottom; y++)
3117 dst_pixel = dst_start;
3118 src_pixel = src_start;
3119 for(x = src_rect->left; x < src_rect->right; x++)
3121 src_val = *src_pixel++;
3122 dst_val = rgb_to_pixel_colortable(dst,
3123 get_field(src_val, src->red_shift, src->red_len),
3124 get_field(src_val, src->green_shift, src->green_len),
3125 get_field(src_val, src->blue_shift, src->blue_len));
3126 if((x - src_rect->left) & 1)
3128 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3129 dst_pixel++;
3131 else
3132 *dst_pixel = (dst_val << 4) & 0xf0;
3134 if(pad_size)
3136 if((x - src_rect->left) & 1) dst_pixel++;
3137 memset(dst_pixel, 0, pad_size);
3139 dst_start += dst->stride;
3140 src_start += src->stride / 4;
3143 break;
3146 case 24:
3148 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3150 for(y = src_rect->top; y < src_rect->bottom; y++)
3152 dst_pixel = dst_start;
3153 src_pixel = src_start;
3154 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3156 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3158 if((x - src_rect->left) & 1)
3160 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3161 dst_pixel++;
3163 else
3164 *dst_pixel = (dst_val << 4) & 0xf0;
3166 if(pad_size)
3168 if((x - src_rect->left) & 1) dst_pixel++;
3169 memset(dst_pixel, 0, pad_size);
3171 dst_start += dst->stride;
3172 src_start += src->stride;
3174 break;
3177 case 16:
3179 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3180 if(src->funcs == &funcs_555)
3182 for(y = src_rect->top; y < src_rect->bottom; y++)
3184 dst_pixel = dst_start;
3185 src_pixel = src_start;
3186 for(x = src_rect->left; x < src_rect->right; x++)
3188 src_val = *src_pixel++;
3189 dst_val = rgb_to_pixel_colortable(dst,
3190 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3191 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3192 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3193 if((x - src_rect->left) & 1)
3195 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3196 dst_pixel++;
3198 else
3199 *dst_pixel = (dst_val << 4) & 0xf0;
3201 if(pad_size)
3203 if((x - src_rect->left) & 1) dst_pixel++;
3204 memset(dst_pixel, 0, pad_size);
3206 dst_start += dst->stride;
3207 src_start += src->stride / 2;
3210 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3212 for(y = src_rect->top; y < src_rect->bottom; y++)
3214 dst_pixel = dst_start;
3215 src_pixel = src_start;
3216 for(x = src_rect->left; x < src_rect->right; x++)
3218 src_val = *src_pixel++;
3219 dst_val = rgb_to_pixel_colortable(dst,
3220 (((src_val >> src->red_shift) << 3) & 0xf8) |
3221 (((src_val >> src->red_shift) >> 2) & 0x07),
3222 (((src_val >> src->green_shift) << 3) & 0xf8) |
3223 (((src_val >> src->green_shift) >> 2) & 0x07),
3224 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3225 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3226 if((x - src_rect->left) & 1)
3228 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3229 dst_pixel++;
3231 else
3232 *dst_pixel = (dst_val << 4) & 0xf0;
3234 if(pad_size)
3236 if((x - src_rect->left) & 1) dst_pixel++;
3237 memset(dst_pixel, 0, pad_size);
3239 dst_start += dst->stride;
3240 src_start += src->stride / 2;
3243 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3245 for(y = src_rect->top; y < src_rect->bottom; y++)
3247 dst_pixel = dst_start;
3248 src_pixel = src_start;
3249 for(x = src_rect->left; x < src_rect->right; x++)
3251 src_val = *src_pixel++;
3252 dst_val = rgb_to_pixel_colortable(dst,
3253 (((src_val >> src->red_shift) << 3) & 0xf8) |
3254 (((src_val >> src->red_shift) >> 2) & 0x07),
3255 (((src_val >> src->green_shift) << 2) & 0xfc) |
3256 (((src_val >> src->green_shift) >> 4) & 0x03),
3257 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3258 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3259 if((x - src_rect->left) & 1)
3261 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3262 dst_pixel++;
3264 else
3265 *dst_pixel = (dst_val << 4) & 0xf0;
3267 if(pad_size)
3269 if((x - src_rect->left) & 1) dst_pixel++;
3270 memset(dst_pixel, 0, pad_size);
3272 dst_start += dst->stride;
3273 src_start += src->stride / 2;
3276 else
3278 for(y = src_rect->top; y < src_rect->bottom; y++)
3280 dst_pixel = dst_start;
3281 src_pixel = src_start;
3282 for(x = src_rect->left; x < src_rect->right; x++)
3284 src_val = *src_pixel++;
3285 dst_val = rgb_to_pixel_colortable(dst,
3286 get_field(src_val, src->red_shift, src->red_len),
3287 get_field(src_val, src->green_shift, src->green_len),
3288 get_field(src_val, src->blue_shift, src->blue_len));
3289 if((x - src_rect->left) & 1)
3291 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3292 dst_pixel++;
3294 else
3295 *dst_pixel = (dst_val << 4) & 0xf0;
3297 if(pad_size)
3299 if((x - src_rect->left) & 1) dst_pixel++;
3300 memset(dst_pixel, 0, pad_size);
3302 dst_start += dst->stride;
3303 src_start += src->stride / 2;
3306 break;
3309 case 8:
3311 const RGBQUAD *color_table = get_dib_color_table( src );
3312 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3314 for(y = src_rect->top; y < src_rect->bottom; y++)
3316 dst_pixel = dst_start;
3317 src_pixel = src_start;
3318 for(x = src_rect->left; x < src_rect->right; x++)
3320 RGBQUAD rgb = color_table[*src_pixel++];
3321 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3322 if((x - src_rect->left) & 1)
3324 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3325 dst_pixel++;
3327 else
3328 *dst_pixel = (dst_val << 4) & 0xf0;
3330 if(pad_size)
3332 if((x - src_rect->left) & 1) dst_pixel++;
3333 memset(dst_pixel, 0, pad_size);
3335 dst_start += dst->stride;
3336 src_start += src->stride;
3338 break;
3341 case 4:
3343 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3345 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
3347 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3348 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3349 else
3351 for(y = src_rect->top; y < src_rect->bottom; y++)
3353 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3354 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3355 dst_start += dst->stride;
3356 src_start += src->stride;
3360 else
3362 const RGBQUAD *color_table = get_dib_color_table( src );
3363 for(y = src_rect->top; y < src_rect->bottom; y++)
3365 int pos = (src->rect.left + src_rect->left) & 1;
3366 dst_pixel = dst_start;
3367 src_pixel = src_start;
3368 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3370 RGBQUAD rgb;
3371 if(pos & 1)
3372 rgb = color_table[*src_pixel++ & 0xf];
3373 else
3374 rgb = color_table[*src_pixel >> 4];
3375 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3376 if((x - src_rect->left) & 1)
3378 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3379 dst_pixel++;
3381 else
3382 *dst_pixel = (dst_val << 4) & 0xf0;
3384 if(pad_size)
3386 if((x - src_rect->left) & 1) dst_pixel++;
3387 memset(dst_pixel, 0, pad_size);
3389 dst_start += dst->stride;
3390 src_start += src->stride;
3393 break;
3396 case 1:
3398 const RGBQUAD *color_table = get_dib_color_table( src );
3399 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3400 for(y = src_rect->top; y < src_rect->bottom; y++)
3402 int pos = (src->rect.left + src_rect->left) & 7;
3403 dst_pixel = dst_start;
3404 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3406 RGBQUAD rgb;
3407 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3408 rgb = color_table[src_val];
3409 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3410 if((x - src_rect->left) & 1)
3412 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3413 dst_pixel++;
3415 else
3416 *dst_pixel = (dst_val << 4) & 0xf0;
3418 if(pad_size)
3420 if((x - src_rect->left) & 1) dst_pixel++;
3421 memset(dst_pixel, 0, pad_size);
3423 dst_start += dst->stride;
3424 src_start += src->stride;
3426 break;
3431 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3433 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3434 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3435 DWORD src_val;
3436 int bit_pos;
3438 switch(src->bit_count)
3440 case 32:
3442 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3444 if(src->funcs == &funcs_8888)
3446 for(y = src_rect->top; y < src_rect->bottom; y++)
3448 dst_pixel = dst_start;
3449 src_pixel = src_start;
3450 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3452 src_val = *src_pixel++;
3453 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val >> 16, src_val >> 8, src_val);
3455 if(bit_pos == 0) *dst_pixel = 0;
3456 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3458 if(++bit_pos == 8)
3460 dst_pixel++;
3461 bit_pos = 0;
3464 if(pad_size)
3466 if(bit_pos != 0) dst_pixel++;
3467 memset(dst_pixel, 0, pad_size);
3469 dst_start += dst->stride;
3470 src_start += src->stride / 4;
3473 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3475 for(y = src_rect->top; y < src_rect->bottom; y++)
3477 dst_pixel = dst_start;
3478 src_pixel = src_start;
3479 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3481 src_val = *src_pixel++;
3482 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3483 src_val >> src->red_shift,
3484 src_val >> src->green_shift,
3485 src_val >> src->blue_shift);
3487 if(bit_pos == 0) *dst_pixel = 0;
3488 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3490 if(++bit_pos == 8)
3492 dst_pixel++;
3493 bit_pos = 0;
3496 if(pad_size)
3498 if(bit_pos != 0) dst_pixel++;
3499 memset(dst_pixel, 0, pad_size);
3501 dst_start += dst->stride;
3502 src_start += src->stride / 4;
3505 else
3507 for(y = src_rect->top; y < src_rect->bottom; y++)
3509 dst_pixel = dst_start;
3510 src_pixel = src_start;
3511 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3513 src_val = *src_pixel++;
3514 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3515 get_field(src_val, src->red_shift, src->red_len),
3516 get_field(src_val, src->green_shift, src->green_len),
3517 get_field(src_val, src->blue_shift, src->blue_len));
3519 if(bit_pos == 0) *dst_pixel = 0;
3520 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3522 if(++bit_pos == 8)
3524 dst_pixel++;
3525 bit_pos = 0;
3528 if(pad_size)
3530 if(bit_pos != 0) dst_pixel++;
3531 memset(dst_pixel, 0, pad_size);
3533 dst_start += dst->stride;
3534 src_start += src->stride / 4;
3537 break;
3540 case 24:
3542 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3544 for(y = src_rect->top; y < src_rect->bottom; y++)
3546 dst_pixel = dst_start;
3547 src_pixel = src_start;
3548 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3550 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_pixel[2], src_pixel[1], src_pixel[0]);
3552 if(bit_pos == 0) *dst_pixel = 0;
3553 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3555 if(++bit_pos == 8)
3557 dst_pixel++;
3558 bit_pos = 0;
3561 if(pad_size)
3563 if(bit_pos != 0) dst_pixel++;
3564 memset(dst_pixel, 0, pad_size);
3566 dst_start += dst->stride;
3567 src_start += src->stride;
3569 break;
3572 case 16:
3574 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3575 if(src->funcs == &funcs_555)
3577 for(y = src_rect->top; y < src_rect->bottom; y++)
3579 dst_pixel = dst_start;
3580 src_pixel = src_start;
3581 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3583 src_val = *src_pixel++;
3584 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3585 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3586 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3587 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3589 if(bit_pos == 0) *dst_pixel = 0;
3590 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3592 if(++bit_pos == 8)
3594 dst_pixel++;
3595 bit_pos = 0;
3598 if(pad_size)
3600 if(bit_pos != 0) dst_pixel++;
3601 memset(dst_pixel, 0, pad_size);
3603 dst_start += dst->stride;
3604 src_start += src->stride / 2;
3607 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3609 for(y = src_rect->top; y < src_rect->bottom; y++)
3611 dst_pixel = dst_start;
3612 src_pixel = src_start;
3613 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3615 src_val = *src_pixel++;
3616 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3617 (((src_val >> src->red_shift) << 3) & 0xf8) |
3618 (((src_val >> src->red_shift) >> 2) & 0x07),
3619 (((src_val >> src->green_shift) << 3) & 0xf8) |
3620 (((src_val >> src->green_shift) >> 2) & 0x07),
3621 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3622 (((src_val >> src->blue_shift) >> 2) & 0x07));
3623 if(bit_pos == 0) *dst_pixel = 0;
3624 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3626 if(++bit_pos == 8)
3628 dst_pixel++;
3629 bit_pos = 0;
3632 if(pad_size)
3634 if(bit_pos != 0) dst_pixel++;
3635 memset(dst_pixel, 0, pad_size);
3637 dst_start += dst->stride;
3638 src_start += src->stride / 2;
3641 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3643 for(y = src_rect->top; y < src_rect->bottom; y++)
3645 dst_pixel = dst_start;
3646 src_pixel = src_start;
3647 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3649 src_val = *src_pixel++;
3650 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3651 (((src_val >> src->red_shift) << 3) & 0xf8) |
3652 (((src_val >> src->red_shift) >> 2) & 0x07),
3653 (((src_val >> src->green_shift) << 2) & 0xfc) |
3654 (((src_val >> src->green_shift) >> 4) & 0x03),
3655 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3656 (((src_val >> src->blue_shift) >> 2) & 0x07));
3657 if(bit_pos == 0) *dst_pixel = 0;
3658 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3660 if(++bit_pos == 8)
3662 dst_pixel++;
3663 bit_pos = 0;
3666 if(pad_size)
3668 if(bit_pos != 0) dst_pixel++;
3669 memset(dst_pixel, 0, pad_size);
3671 dst_start += dst->stride;
3672 src_start += src->stride / 2;
3675 else
3677 for(y = src_rect->top; y < src_rect->bottom; y++)
3679 dst_pixel = dst_start;
3680 src_pixel = src_start;
3681 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3683 src_val = *src_pixel++;
3684 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3685 get_field(src_val, src->red_shift, src->red_len),
3686 get_field(src_val, src->green_shift, src->green_len),
3687 get_field(src_val, src->blue_shift, src->blue_len));
3688 if(bit_pos == 0) *dst_pixel = 0;
3689 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3691 if(++bit_pos == 8)
3693 dst_pixel++;
3694 bit_pos = 0;
3697 if(pad_size)
3699 if(bit_pos != 0) dst_pixel++;
3700 memset(dst_pixel, 0, pad_size);
3702 dst_start += dst->stride;
3703 src_start += src->stride / 2;
3706 break;
3709 case 8:
3711 const RGBQUAD *color_table = get_dib_color_table( src );
3712 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3714 for(y = src_rect->top; y < src_rect->bottom; y++)
3716 dst_pixel = dst_start;
3717 src_pixel = src_start;
3718 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3720 RGBQUAD rgb = color_table[*src_pixel++];
3721 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3723 if(bit_pos == 0) *dst_pixel = 0;
3724 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3726 if(++bit_pos == 8)
3728 dst_pixel++;
3729 bit_pos = 0;
3732 if(pad_size)
3734 if(bit_pos != 0) dst_pixel++;
3735 memset(dst_pixel, 0, pad_size);
3737 dst_start += dst->stride;
3738 src_start += src->stride;
3740 break;
3743 case 4:
3745 const RGBQUAD *color_table = get_dib_color_table( src );
3746 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3748 for(y = src_rect->top; y < src_rect->bottom; y++)
3750 int pos = (src->rect.left + src_rect->left) & 1;
3751 dst_pixel = dst_start;
3752 src_pixel = src_start;
3753 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3755 RGBQUAD rgb;
3756 if (pos & 1)
3757 rgb = color_table[*src_pixel++ & 0xf];
3758 else
3759 rgb = color_table[*src_pixel >> 4];
3760 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3762 if(bit_pos == 0) *dst_pixel = 0;
3763 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3765 if(++bit_pos == 8)
3767 dst_pixel++;
3768 bit_pos = 0;
3771 if(pad_size)
3773 if(bit_pos != 0) dst_pixel++;
3774 memset(dst_pixel, 0, pad_size);
3776 dst_start += dst->stride;
3777 src_start += src->stride;
3779 break;
3782 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3783 uses text/bkgnd colours instead of the dib's colour table, this
3784 doesn't appear to be the case for a dc backed by a
3785 dibsection. */
3787 case 1:
3789 const RGBQUAD *color_table = get_dib_color_table( src );
3790 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3791 for(y = src_rect->top; y < src_rect->bottom; y++)
3793 int pos = (src->rect.left + src_rect->left) & 7;
3794 dst_pixel = dst_start;
3795 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3797 RGBQUAD rgb;
3798 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3799 rgb = color_table[src_val];
3800 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3802 if(bit_pos == 0) *dst_pixel = 0;
3803 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3805 if(++bit_pos == 8)
3807 dst_pixel++;
3808 bit_pos = 0;
3811 if(pad_size)
3813 if(bit_pos != 0) dst_pixel++;
3814 memset(dst_pixel, 0, pad_size);
3816 dst_start += dst->stride;
3817 src_start += src->stride;
3819 break;
3824 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3828 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3830 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3833 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
3835 return (blend_color( dst, src, alpha ) |
3836 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3837 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3838 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3841 static inline DWORD blend_argb( DWORD dst, DWORD src )
3843 BYTE b = (BYTE)src;
3844 BYTE g = (BYTE)(src >> 8);
3845 BYTE r = (BYTE)(src >> 16);
3846 DWORD alpha = (BYTE)(src >> 24);
3847 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3848 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3849 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3850 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3853 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3855 BYTE b = ((BYTE)src * alpha + 127) / 255;
3856 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3857 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3858 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3859 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3860 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3861 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3862 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3865 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3867 if (blend.AlphaFormat & AC_SRC_ALPHA)
3869 DWORD alpha = blend.SourceConstantAlpha;
3870 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3871 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3872 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3873 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3874 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3875 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3876 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3878 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3879 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3880 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3883 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3884 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3886 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3887 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3888 int x, y;
3890 if (blend.AlphaFormat & AC_SRC_ALPHA)
3892 if (blend.SourceConstantAlpha == 255)
3893 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3894 for (x = 0; x < rc->right - rc->left; x++)
3895 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
3896 else
3897 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3898 for (x = 0; x < rc->right - rc->left; x++)
3899 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3901 else
3902 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3903 for (x = 0; x < rc->right - rc->left; x++)
3904 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3907 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3908 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3910 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3911 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3912 int x, y;
3914 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3916 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3918 for (x = 0; x < rc->right - rc->left; x++)
3920 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3921 dst_ptr[x] >> dst->green_shift,
3922 dst_ptr[x] >> dst->blue_shift,
3923 src_ptr[x], blend );
3924 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3925 (((val >> 8) & 0xff) << dst->green_shift) |
3926 (((val >> 16) & 0xff) << dst->red_shift));
3930 else
3932 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3934 for (x = 0; x < rc->right - rc->left; x++)
3936 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3937 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3938 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3939 src_ptr[x], blend );
3940 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3941 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3942 put_field( val, dst->blue_shift, dst->blue_len ));
3948 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3949 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3951 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3952 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3953 int x, y;
3955 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3957 for (x = 0; x < rc->right - rc->left; x++)
3959 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3960 src_ptr[x], blend );
3961 dst_ptr[x * 3] = val;
3962 dst_ptr[x * 3 + 1] = val >> 8;
3963 dst_ptr[x * 3 + 2] = val >> 16;
3968 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3969 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3971 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3972 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3973 int x, y;
3975 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3977 for (x = 0; x < rc->right - rc->left; x++)
3979 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3980 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3981 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3982 src_ptr[x], blend );
3983 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3988 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3989 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3991 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3992 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3993 int x, y;
3995 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3997 for (x = 0; x < rc->right - rc->left; x++)
3999 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4000 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4001 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4002 src_ptr[x], blend );
4003 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
4004 put_field((val >> 8), dst->green_shift, dst->green_len) |
4005 put_field( val, dst->blue_shift, dst->blue_len));
4010 static void blend_rect_8(const dib_info *dst, const RECT *rc,
4011 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4013 const RGBQUAD *color_table = get_dib_color_table( dst );
4014 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4015 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4016 int x, y;
4018 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4020 for (x = 0; x < rc->right - rc->left; x++)
4022 RGBQUAD rgb = color_table[dst_ptr[x]];
4023 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4024 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4029 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4030 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4032 const RGBQUAD *color_table = get_dib_color_table( dst );
4033 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4034 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4035 int i, x, y;
4037 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4039 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4041 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4042 RGBQUAD rgb = color_table[val];
4043 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4044 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4045 if (x & 1)
4046 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4047 else
4048 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4053 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4054 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4056 const RGBQUAD *color_table = get_dib_color_table( dst );
4057 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4058 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4059 int i, x, y;
4061 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4063 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4065 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4066 RGBQUAD rgb = color_table[val];
4067 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4068 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4069 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4074 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4075 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4079 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4081 BYTE r, g, b, a;
4082 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4083 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4084 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4085 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4086 return a << 24 | r << 16 | g << 8 | b;
4089 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4091 BYTE r, g, b;
4092 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4093 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4094 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4095 return r << 16 | g << 8 | b;
4098 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4099 unsigned int x, unsigned int y )
4101 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4102 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4103 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4104 r = min( 31, max( 0, r / 16 ));
4105 g = min( 31, max( 0, g / 16 ));
4106 b = min( 31, max( 0, b / 16 ));
4107 return (r << 10) | (g << 5) | b;
4110 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4111 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4113 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4114 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4115 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4116 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4119 /* compute the left/right triangle limit for row y */
4120 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4122 int x1, x2;
4124 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4125 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4127 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4129 *left = max( rc->left, min( x1, x2 ) );
4130 *right = min( rc->right, max( x1, x2 ) );
4133 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4134 static inline int triangle_det( const TRIVERTEX *v )
4136 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);
4139 /* compute the barycentric weights for a given point inside the triangle */
4140 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4142 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4143 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4146 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4148 INT64 l1, l2;
4149 BYTE r, g, b, a;
4151 triangle_weights( v, x, y, &l1, &l2 );
4152 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4153 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4154 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4155 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4156 return a << 24 | r << 16 | g << 8 | b;
4159 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4161 INT64 l1, l2;
4162 BYTE r, g, b;
4164 triangle_weights( v, x, y, &l1, &l2 );
4165 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4166 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4167 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4168 return r << 16 | g << 8 | b;
4171 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4173 INT64 l1, l2;
4174 int r, g, b;
4176 triangle_weights( v, x, y, &l1, &l2 );
4177 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4178 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4179 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4180 r = min( 31, max( 0, r / 16 ));
4181 g = min( 31, max( 0, g / 16 ));
4182 b = min( 31, max( 0, b / 16 ));
4183 return (r << 10) | (g << 5) | b;
4186 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4188 INT64 l1, l2;
4189 BYTE r, g, b;
4191 triangle_weights( v, x, y, &l1, &l2 );
4192 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4193 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4194 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4195 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4198 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4200 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4201 int x, y, left, right, det;
4203 switch (mode)
4205 case GRADIENT_FILL_RECT_H:
4206 for (x = 0; x < rc->right - rc->left; x++)
4207 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4209 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4210 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4211 break;
4213 case GRADIENT_FILL_RECT_V:
4214 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4216 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4217 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4219 break;
4221 case GRADIENT_FILL_TRIANGLE:
4222 if (!(det = triangle_det( v ))) return FALSE;
4223 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4225 triangle_coords( v, rc, y, &left, &right );
4226 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4228 break;
4230 return TRUE;
4233 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4235 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4236 int x, y, left, right, det;
4238 switch (mode)
4240 case GRADIENT_FILL_RECT_H:
4241 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4243 for (x = 0; x < rc->right - rc->left; x++)
4245 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4246 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4247 (((val >> 8) & 0xff) << dib->green_shift) |
4248 (((val >> 16) & 0xff) << dib->red_shift));
4251 else
4253 for (x = 0; x < rc->right - rc->left; x++)
4255 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4256 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4257 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4258 put_field( val, dib->blue_shift, dib->blue_len ));
4262 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4263 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4264 break;
4266 case GRADIENT_FILL_RECT_V:
4267 for (y = rc->top; y < rc->bottom; y++)
4269 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4270 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4271 val = ((( val & 0xff) << dib->blue_shift) |
4272 (((val >> 8) & 0xff) << dib->green_shift) |
4273 (((val >> 16) & 0xff) << dib->red_shift));
4274 else
4275 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4276 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4277 put_field( val, dib->blue_shift, dib->blue_len ));
4279 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4280 ptr += dib->stride / 4;
4282 break;
4284 case GRADIENT_FILL_TRIANGLE:
4285 if (!(det = triangle_det( v ))) return FALSE;
4286 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4288 triangle_coords( v, rc, y, &left, &right );
4290 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4291 for (x = left; x < right; x++)
4293 DWORD val = gradient_triangle_24( v, x, y, det );
4294 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4295 (((val >> 8) & 0xff) << dib->green_shift) |
4296 (((val >> 16) & 0xff) << dib->red_shift));
4298 else
4299 for (x = left; x < right; x++)
4301 DWORD val = gradient_triangle_24( v, x, y, det );
4302 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4303 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4304 put_field( val, dib->blue_shift, dib->blue_len ));
4307 break;
4309 return TRUE;
4312 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4314 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4315 int x, y, left, right, det;
4317 switch (mode)
4319 case GRADIENT_FILL_RECT_H:
4320 for (x = 0; x < rc->right - rc->left; x++)
4322 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4323 ptr[x * 3] = val;
4324 ptr[x * 3 + 1] = val >> 8;
4325 ptr[x * 3 + 2] = val >> 16;
4328 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4329 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4330 break;
4332 case GRADIENT_FILL_RECT_V:
4333 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4335 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4336 for (x = 0; x < rc->right - rc->left; x++)
4338 ptr[x * 3] = val;
4339 ptr[x * 3 + 1] = val >> 8;
4340 ptr[x * 3 + 2] = val >> 16;
4343 break;
4345 case GRADIENT_FILL_TRIANGLE:
4346 if (!(det = triangle_det( v ))) return FALSE;
4347 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4349 triangle_coords( v, rc, y, &left, &right );
4350 for (x = left; x < right; x++)
4352 DWORD val = gradient_triangle_24( v, x, y, det );
4353 ptr[(x - rc->left) * 3] = val;
4354 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4355 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4358 break;
4360 return TRUE;
4363 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4365 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4366 int x, y, left, right, det;
4368 switch (mode)
4370 case GRADIENT_FILL_RECT_H:
4371 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4372 for (x = rc->left; x < rc->right; x++)
4373 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4374 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4375 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4376 break;
4378 case GRADIENT_FILL_RECT_V:
4379 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4381 WORD values[4];
4382 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4383 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4385 break;
4387 case GRADIENT_FILL_TRIANGLE:
4388 if (!(det = triangle_det( v ))) return FALSE;
4389 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4391 triangle_coords( v, rc, y, &left, &right );
4392 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4394 break;
4396 return TRUE;
4399 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4401 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4402 int x, y, left, right, det;
4404 switch (mode)
4406 case GRADIENT_FILL_RECT_H:
4407 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4408 for (x = rc->left; x < rc->right; x++)
4410 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4411 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4412 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4413 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4415 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4416 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4417 break;
4419 case GRADIENT_FILL_RECT_V:
4420 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4422 WORD values[4];
4423 for (x = 0; x < 4; x++)
4425 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4426 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4427 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4428 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4430 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4432 break;
4434 case GRADIENT_FILL_TRIANGLE:
4435 if (!(det = triangle_det( v ))) return FALSE;
4436 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4438 triangle_coords( v, rc, y, &left, &right );
4439 for (x = left; x < right; x++)
4441 WORD val = gradient_triangle_555( v, x, y, det );
4442 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4443 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4444 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4447 break;
4449 return TRUE;
4452 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4454 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4455 int x, y, left, right, det;
4457 switch (mode)
4459 case GRADIENT_FILL_RECT_H:
4460 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4461 for (x = rc->left; x < rc->right; x++)
4462 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4463 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4464 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4465 break;
4467 case GRADIENT_FILL_RECT_V:
4468 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4470 BYTE values[16];
4471 for (x = 0; x < 16; x++)
4472 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4473 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4475 break;
4477 case GRADIENT_FILL_TRIANGLE:
4478 if (!(det = triangle_det( v ))) return FALSE;
4479 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4481 triangle_coords( v, rc, y, &left, &right );
4482 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4484 break;
4486 return TRUE;
4489 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4491 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4492 int x, y, left, right, det, pos;
4494 switch (mode)
4496 case GRADIENT_FILL_RECT_H:
4497 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4499 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4501 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4502 if (pos & 1)
4503 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4504 else
4505 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4508 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4510 x = rc->left;
4511 pos = (dib->rect.left + rc->left) & 1;
4512 if (pos)
4514 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4515 pos++;
4516 x++;
4518 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4519 if (x < rc->right)
4520 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4522 break;
4524 case GRADIENT_FILL_RECT_V:
4525 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4527 BYTE values[16];
4528 for (x = 0; x < 16; x++)
4529 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4530 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4531 if (pos & 1)
4532 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4533 else
4534 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4536 break;
4538 case GRADIENT_FILL_TRIANGLE:
4539 if (!(det = triangle_det( v ))) return FALSE;
4540 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4542 triangle_coords( v, rc, y, &left, &right );
4543 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4545 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4546 if (pos & 1)
4547 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4548 else
4549 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4552 break;
4554 return TRUE;
4557 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4559 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4560 int x, y, left, right, det, pos;
4562 switch (mode)
4564 case GRADIENT_FILL_RECT_H:
4565 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4567 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4569 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4570 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4573 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4574 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4575 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4576 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4577 break;
4579 case GRADIENT_FILL_RECT_V:
4580 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4582 BYTE values[16];
4583 for (x = 0; x < 16; x++)
4584 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4585 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4586 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4587 (values[x % 16] & pixel_masks_1[pos % 8]);
4589 break;
4591 case GRADIENT_FILL_TRIANGLE:
4592 if (!(det = triangle_det( v ))) return FALSE;
4593 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4595 triangle_coords( v, rc, y, &left, &right );
4596 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4598 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4599 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4602 break;
4604 return TRUE;
4607 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4609 return TRUE;
4612 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4614 if (dst == text) return dst;
4616 if (dst > text)
4618 DWORD diff = dst - text;
4619 DWORD range = max_comp - text;
4620 dst = text + (diff * range ) / (0xff - text);
4621 return dst;
4623 else
4625 DWORD diff = text - dst;
4626 DWORD range = text - min_comp;
4627 dst = text - (diff * range) / text;
4628 return dst;
4632 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4634 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4635 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4636 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4639 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4640 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4642 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4643 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4644 int x, y;
4646 for (y = rect->top; y < rect->bottom; y++)
4648 for (x = 0; x < rect->right - rect->left; x++)
4650 if (glyph_ptr[x] <= 1) continue;
4651 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4652 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4654 dst_ptr += dib->stride / 4;
4655 glyph_ptr += glyph->stride;
4659 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4660 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4662 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4663 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4664 int x, y;
4665 DWORD text, val;
4667 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4668 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4669 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4671 for (y = rect->top; y < rect->bottom; y++)
4673 for (x = 0; x < rect->right - rect->left; x++)
4675 if (glyph_ptr[x] <= 1) continue;
4676 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4677 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4678 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4679 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4680 text, ranges + glyph_ptr[x] );
4681 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4682 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4683 put_field( val, dib->blue_shift, dib->blue_len ));
4685 dst_ptr += dib->stride / 4;
4686 glyph_ptr += glyph->stride;
4690 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4691 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4693 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4694 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4695 int x, y;
4696 DWORD val;
4698 for (y = rect->top; y < rect->bottom; y++)
4700 for (x = 0; x < rect->right - rect->left; x++)
4702 if (glyph_ptr[x] <= 1) continue;
4703 if (glyph_ptr[x] >= 16)
4704 val = text_pixel;
4705 else
4706 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4707 text_pixel, ranges + glyph_ptr[x] );
4708 dst_ptr[x * 3] = val;
4709 dst_ptr[x * 3 + 1] = val >> 8;
4710 dst_ptr[x * 3 + 2] = val >> 16;
4712 dst_ptr += dib->stride;
4713 glyph_ptr += glyph->stride;
4717 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4718 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4720 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4721 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4722 int x, y;
4723 DWORD text, val;
4725 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4726 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4727 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4729 for (y = rect->top; y < rect->bottom; y++)
4731 for (x = 0; x < rect->right - rect->left; x++)
4733 if (glyph_ptr[x] <= 1) continue;
4734 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4735 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4736 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4737 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4738 text, ranges + glyph_ptr[x] );
4739 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4741 dst_ptr += dib->stride / 2;
4742 glyph_ptr += glyph->stride;
4746 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4747 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4749 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4750 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4751 int x, y;
4752 DWORD text, val;
4754 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4755 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4756 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4758 for (y = rect->top; y < rect->bottom; y++)
4760 for (x = 0; x < rect->right - rect->left; x++)
4762 if (glyph_ptr[x] <= 1) continue;
4763 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4764 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4765 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4766 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4767 text, ranges + glyph_ptr[x] );
4768 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4769 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4770 put_field( val, dib->blue_shift, dib->blue_len ));
4772 dst_ptr += dib->stride / 2;
4773 glyph_ptr += glyph->stride;
4777 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4778 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4780 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4781 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4782 int x, y;
4784 for (y = rect->top; y < rect->bottom; y++)
4786 for (x = 0; x < rect->right - rect->left; x++)
4788 /* no antialiasing, glyph should only contain 0 or 16. */
4789 if (glyph_ptr[x] >= 16)
4790 dst_ptr[x] = text_pixel;
4792 dst_ptr += dib->stride;
4793 glyph_ptr += glyph->stride;
4797 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4798 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4800 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
4801 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4802 int x, y, pos;
4804 for (y = rect->top; y < rect->bottom; y++)
4806 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
4808 /* no antialiasing, glyph should only contain 0 or 16. */
4809 if (glyph_ptr[x] >= 16)
4811 if (pos & 1)
4812 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
4813 else
4814 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
4817 dst_ptr += dib->stride;
4818 glyph_ptr += glyph->stride;
4822 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4823 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4825 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
4826 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4827 int x, y, pos;
4828 BYTE text = (text_pixel & 1) ? 0xff : 0;
4830 for (y = rect->top; y < rect->bottom; y++)
4832 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
4834 /* no antialiasing, glyph should only contain 0 or 16. */
4835 if (glyph_ptr[x] >= 16)
4836 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4837 (text & pixel_masks_1[pos % 8]);
4839 dst_ptr += dib->stride;
4840 glyph_ptr += glyph->stride;
4844 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4845 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4847 return;
4850 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
4851 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4853 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4854 int x, y;
4856 /* masks are always 8x8 */
4857 assert( dib->width == 8 );
4858 assert( dib->height == 8 );
4860 for(y = 0; y < 8; y++, hatch_ptr++)
4862 for(x = 0; x < 8; x++)
4864 if(*hatch_ptr & pixel_masks_1[x])
4866 and_bits[x] = fg->and;
4867 xor_bits[x] = fg->xor;
4869 else
4871 and_bits[x] = bg->and;
4872 xor_bits[x] = bg->xor;
4875 and_bits += dib->stride / 4;
4876 xor_bits += dib->stride / 4;
4880 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
4881 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4883 DWORD mask_start = 0, mask_offset;
4884 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4885 int x, y;
4887 /* masks are always 8x8 */
4888 assert( dib->width == 8 );
4889 assert( dib->height == 8 );
4891 for(y = 0; y < 8; y++, hatch_ptr++)
4893 mask_offset = mask_start;
4894 for(x = 0; x < 8; x++)
4896 if(*hatch_ptr & pixel_masks_1[x])
4898 and_bits[mask_offset] = fg->and & 0xff;
4899 xor_bits[mask_offset++] = fg->xor & 0xff;
4900 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4901 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4902 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4903 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4905 else
4907 and_bits[mask_offset] = bg->and & 0xff;
4908 xor_bits[mask_offset++] = bg->xor & 0xff;
4909 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4910 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4911 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4912 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4915 mask_start += dib->stride;
4919 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
4920 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4922 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4923 int x, y;
4925 /* masks are always 8x8 */
4926 assert( dib->width == 8 );
4927 assert( dib->height == 8 );
4929 for(y = 0; y < 8; y++, hatch_ptr++)
4931 for(x = 0; x < 8; x++)
4933 if(*hatch_ptr & pixel_masks_1[x])
4935 and_bits[x] = fg->and;
4936 xor_bits[x] = fg->xor;
4938 else
4940 and_bits[x] = bg->and;
4941 xor_bits[x] = bg->xor;
4944 and_bits += dib->stride / 2;
4945 xor_bits += dib->stride / 2;
4949 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
4950 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4952 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4953 int x, y;
4955 /* masks are always 8x8 */
4956 assert( dib->width == 8 );
4957 assert( dib->height == 8 );
4959 for(y = 0; y < 8; y++, hatch_ptr++)
4961 for(x = 0; x < 8; x++)
4963 if(*hatch_ptr & pixel_masks_1[x])
4965 and_bits[x] = fg->and;
4966 xor_bits[x] = fg->xor;
4968 else
4970 and_bits[x] = bg->and;
4971 xor_bits[x] = bg->xor;
4974 and_bits += dib->stride;
4975 xor_bits += dib->stride;
4979 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
4980 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4982 DWORD mask_offset;
4983 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4984 const rop_mask *rop_mask;
4985 int x, y;
4987 /* masks are always 8x8 */
4988 assert( dib->width == 8 );
4989 assert( dib->height == 8 );
4991 for(y = 0; y < 8; y++, hatch_ptr++)
4993 for(x = mask_offset = 0; x < 8; x++)
4995 if(*hatch_ptr & pixel_masks_1[x])
4996 rop_mask = fg;
4997 else
4998 rop_mask = bg;
5000 if(x & 1)
5002 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
5003 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
5004 mask_offset++;
5006 else
5008 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
5009 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
5012 and_bits += dib->stride;
5013 xor_bits += dib->stride;
5017 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
5018 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5020 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5021 rop_mask rop_mask;
5022 int x, y;
5024 /* masks are always 8x8 */
5025 assert( dib->width == 8 );
5026 assert( dib->height == 8 );
5028 for(y = 0; y < 8; y++, hatch_ptr++)
5030 *and_bits = *xor_bits = 0;
5031 for(x = 0; x < 8; x++)
5033 if(*hatch_ptr & pixel_masks_1[x])
5035 rop_mask.and = (fg->and & 1) ? 0xff : 0;
5036 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
5038 else
5040 rop_mask.and = (bg->and & 1) ? 0xff : 0;
5041 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5043 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5044 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5046 and_bits += dib->stride;
5047 xor_bits += dib->stride;
5051 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
5052 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5056 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5058 /* mapping between RGB triples and the default color table */
5059 static const BYTE mapping[27] =
5061 0, /* 000000 -> 000000 */
5062 4, /* 00007f -> 000080 */
5063 252, /* 0000ff -> 0000ff */
5064 2, /* 007f00 -> 008000 */
5065 6, /* 007f7f -> 008080 */
5066 224, /* 007fff -> 0080c0 */
5067 250, /* 00ff00 -> 00ff00 */
5068 184, /* 00ff7f -> 00e080 */
5069 254, /* 00ffff -> 00ffff */
5070 1, /* 7f0000 -> 800000 */
5071 5, /* 7f007f -> 800080 */
5072 196, /* 7f00ff -> 8000c0 */
5073 3, /* 7f7f00 -> 808000 */
5074 248, /* 7f7f7f -> 808080 */
5075 228, /* 7f7fff -> 8080c0 */
5076 60, /* 7fff00 -> 80e000 */
5077 188, /* 7fff7f -> 80e080 */
5078 244, /* 7fffff -> 80c0c0 */
5079 249, /* ff0000 -> ff0000 */
5080 135, /* ff007f -> e00080 */
5081 253, /* ff00ff -> ff00ff */
5082 39, /* ff7f00 -> e08000 */
5083 167, /* ff7f7f -> e08080 */
5084 231, /* ff7fff -> e080c0 */
5085 251, /* ffff00 -> ffff00 */
5086 191, /* ffff7f -> e0e080 */
5087 255 /* ffffff -> ffffff */
5090 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5091 struct rop_codes codes;
5092 int x, y;
5094 /* masks are always 8x8 */
5095 assert( dib->width == 8 );
5096 assert( dib->height == 8 );
5098 get_rop_codes( rop2, &codes );
5100 for (y = 0; y < 8; y++)
5102 for (x = 0; x < 8; x++)
5104 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5105 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5106 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5107 DWORD pixel = mapping[r * 9 + g * 3 + b];
5108 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
5109 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
5111 and_bits += dib->stride;
5112 xor_bits += dib->stride;
5116 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5118 /* mapping between RGB triples and the default color table */
5119 static const BYTE mapping[27] =
5121 0, /* 000000 -> 000000 */
5122 4, /* 00007f -> 000080 */
5123 12, /* 0000ff -> 0000ff */
5124 2, /* 007f00 -> 008000 */
5125 6, /* 007f7f -> 008080 */
5126 6, /* 007fff -> 008080 */
5127 10, /* 00ff00 -> 00ff00 */
5128 6, /* 00ff7f -> 008080 */
5129 14, /* 00ffff -> 00ffff */
5130 1, /* 7f0000 -> 800000 */
5131 5, /* 7f007f -> 800080 */
5132 5, /* 7f00ff -> 800080 */
5133 3, /* 7f7f00 -> 808000 */
5134 7, /* 7f7f7f -> 808080 */
5135 8, /* 7f7fff -> c0c0c0 */
5136 3, /* 7fff00 -> 808000 */
5137 8, /* 7fff7f -> c0c0c0 */
5138 8, /* 7fffff -> c0c0c0 */
5139 9, /* ff0000 -> ff0000 */
5140 5, /* ff007f -> 800080 */
5141 13, /* ff00ff -> ff00ff */
5142 3, /* ff7f00 -> 808000 */
5143 8, /* ff7f7f -> c0c0c0 */
5144 8, /* ff7fff -> c0c0c0 */
5145 11, /* ffff00 -> ffff00 */
5146 8, /* ffff7f -> c0c0c0 */
5147 15 /* ffffff -> ffffff */
5150 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5151 struct rop_codes codes;
5152 int x, y;
5154 /* masks are always 8x8 */
5155 assert( dib->width == 8 );
5156 assert( dib->height == 8 );
5158 get_rop_codes( rop2, &codes );
5160 for (y = 0; y < 8; y++)
5162 for (x = 0; x < 8; x++)
5164 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5165 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5166 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5167 DWORD pixel = mapping[r * 9 + g * 3 + b];
5168 if (x & 1)
5170 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
5171 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
5173 else
5175 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
5176 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
5179 and_bits += dib->stride;
5180 xor_bits += dib->stride;
5184 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5186 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5187 struct rop_codes codes;
5188 rop_mask rop_mask;
5189 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
5191 /* masks are always 8x8 */
5192 assert( dib->width == 8 );
5193 assert( dib->height == 8 );
5195 get_rop_codes( rop2, &codes );
5197 for (y = 0; y < 8; y++)
5199 *and_bits = *xor_bits = 0;
5200 for (x = 0; x < 8; x++)
5202 if (grey + bayer_8x8[y][x] > 63)
5204 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
5205 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
5207 else
5209 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
5210 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
5212 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5213 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5215 and_bits += dib->stride;
5216 xor_bits += dib->stride;
5220 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5224 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5226 switch (mode)
5228 default:
5229 case STRETCH_DELETESCANS:
5230 get_rop_codes( R2_COPYPEN, codes );
5231 break;
5232 case STRETCH_ORSCANS:
5233 get_rop_codes( R2_MERGEPEN, codes );
5234 break;
5235 case STRETCH_ANDSCANS:
5236 get_rop_codes( R2_MASKPEN, codes );
5237 break;
5239 return;
5242 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5243 const dib_info *src_dib, const POINT *src_start,
5244 const struct stretch_params *params, int mode,
5245 BOOL keep_dst)
5247 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5248 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5249 int err = params->err_start;
5250 int width;
5251 struct rop_codes codes;
5253 rop_codes_from_stretch_mode( mode, &codes );
5254 for (width = params->length; width; width--)
5256 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5257 dst_ptr += params->dst_inc;
5258 if (err > 0)
5260 src_ptr += params->src_inc;
5261 err += params->err_add_1;
5263 else err += params->err_add_2;
5267 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5268 const dib_info *src_dib, const POINT *src_start,
5269 const struct stretch_params *params, int mode,
5270 BOOL keep_dst)
5272 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5273 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5274 int err = params->err_start;
5275 int width;
5276 struct rop_codes codes;
5278 rop_codes_from_stretch_mode( mode, &codes );
5279 for (width = params->length; width; width--)
5281 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5282 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5283 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5284 dst_ptr += 3 * params->dst_inc;
5285 if (err > 0)
5287 src_ptr += 3 * params->src_inc;
5288 err += params->err_add_1;
5290 else err += params->err_add_2;
5294 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5295 const dib_info *src_dib, const POINT *src_start,
5296 const struct stretch_params *params, int mode,
5297 BOOL keep_dst)
5299 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5300 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5301 int err = params->err_start;
5302 int width;
5303 struct rop_codes codes;
5305 rop_codes_from_stretch_mode( mode, &codes );
5306 for (width = params->length; width; width--)
5308 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5309 dst_ptr += params->dst_inc;
5310 if (err > 0)
5312 src_ptr += params->src_inc;
5313 err += params->err_add_1;
5315 else err += params->err_add_2;
5319 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5320 const dib_info *src_dib, const POINT *src_start,
5321 const struct stretch_params *params, int mode,
5322 BOOL keep_dst)
5324 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5325 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5326 int err = params->err_start;
5327 int width;
5328 struct rop_codes codes;
5330 rop_codes_from_stretch_mode( mode, &codes );
5331 for (width = params->length; width; width--)
5333 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5334 dst_ptr += params->dst_inc;
5335 if (err > 0)
5337 src_ptr += params->src_inc;
5338 err += params->err_add_1;
5340 else err += params->err_add_2;
5344 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5345 const dib_info *src_dib, const POINT *src_start,
5346 const struct stretch_params *params, int mode,
5347 BOOL keep_dst)
5349 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5350 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5351 int err = params->err_start;
5352 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5353 struct rop_codes codes;
5354 BYTE src_val;
5356 rop_codes_from_stretch_mode( mode, &codes );
5357 for (width = params->length; width; width--)
5359 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5360 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5362 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5364 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5365 dst_ptr += params->dst_inc;
5366 dst_x += params->dst_inc;
5368 if (err > 0)
5370 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5371 src_ptr += params->src_inc;
5372 src_x += params->src_inc;
5373 err += params->err_add_1;
5375 else err += params->err_add_2;
5379 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5380 const dib_info *src_dib, const POINT *src_start,
5381 const struct stretch_params *params, int mode,
5382 BOOL keep_dst)
5384 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5385 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5386 int err = params->err_start;
5387 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5388 struct rop_codes codes;
5389 BYTE src_val;
5391 rop_codes_from_stretch_mode( mode, &codes );
5392 for (width = params->length; width; width--)
5394 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5395 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5397 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5398 dst_ptr += params->dst_inc;
5399 dst_x += params->dst_inc;
5401 if (err > 0)
5403 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5404 src_ptr += params->src_inc;
5405 src_x += params->src_inc;
5406 err += params->err_add_1;
5408 else err += params->err_add_2;
5412 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5413 const dib_info *src_dib, const POINT *src_start,
5414 const struct stretch_params *params, int mode,
5415 BOOL keep_dst)
5417 FIXME("bit count %d\n", dst_dib->bit_count);
5418 return;
5421 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5422 const dib_info *src_dib, const POINT *src_start,
5423 const struct stretch_params *params, int mode,
5424 BOOL keep_dst)
5426 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5427 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5428 int err = params->err_start;
5429 int width;
5430 struct rop_codes codes;
5431 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5432 BOOL new_pix = TRUE;
5434 rop_codes_from_stretch_mode( mode, &codes );
5435 for (width = params->length; width; width--)
5437 if (new_pix && !keep_dst) *dst_ptr = init_val;
5438 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5439 new_pix = FALSE;
5440 src_ptr += params->src_inc;
5441 if (err > 0)
5443 dst_ptr += params->dst_inc;
5444 new_pix = TRUE;
5445 err += params->err_add_1;
5447 else err += params->err_add_2;
5451 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5452 const dib_info *src_dib, const POINT *src_start,
5453 const struct stretch_params *params, int mode,
5454 BOOL keep_dst)
5456 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5457 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5458 int err = params->err_start;
5459 int width;
5460 struct rop_codes codes;
5461 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5462 BOOL new_pix = TRUE;
5464 rop_codes_from_stretch_mode( mode, &codes );
5465 for (width = params->length; width; width--)
5467 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5468 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5469 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5470 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5471 new_pix = FALSE;
5472 src_ptr += 3 * params->src_inc;
5473 if (err > 0)
5475 dst_ptr += 3 * params->dst_inc;
5476 new_pix = TRUE;
5477 err += params->err_add_1;
5479 else err += params->err_add_2;
5483 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5484 const dib_info *src_dib, const POINT *src_start,
5485 const struct stretch_params *params, int mode,
5486 BOOL keep_dst)
5488 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5489 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5490 int err = params->err_start;
5491 int width;
5492 struct rop_codes codes;
5493 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5494 BOOL new_pix = TRUE;
5496 rop_codes_from_stretch_mode( mode, &codes );
5497 for (width = params->length; width; width--)
5499 if (new_pix && !keep_dst) *dst_ptr = init_val;
5500 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5501 new_pix = FALSE;
5502 src_ptr += params->src_inc;
5503 if (err > 0)
5505 dst_ptr += params->dst_inc;
5506 new_pix = TRUE;
5507 err += params->err_add_1;
5509 else err += params->err_add_2;
5513 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5514 const dib_info *src_dib, const POINT *src_start,
5515 const struct stretch_params *params, int mode,
5516 BOOL keep_dst)
5518 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5519 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5520 int err = params->err_start;
5521 int width;
5522 struct rop_codes codes;
5523 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5524 BOOL new_pix = TRUE;
5526 rop_codes_from_stretch_mode( mode, &codes );
5527 for (width = params->length; width; width--)
5529 if (new_pix && !keep_dst) *dst_ptr = init_val;
5530 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5531 new_pix = FALSE;
5532 src_ptr += params->src_inc;
5533 if (err > 0)
5535 dst_ptr += params->dst_inc;
5536 new_pix = TRUE;
5537 err += params->err_add_1;
5539 else err += params->err_add_2;
5543 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5544 const dib_info *src_dib, const POINT *src_start,
5545 const struct stretch_params *params, int mode,
5546 BOOL keep_dst)
5548 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5549 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5550 int err = params->err_start;
5551 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5552 struct rop_codes codes;
5553 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5554 BOOL new_pix = TRUE;
5556 rop_codes_from_stretch_mode( mode, &codes );
5557 for (width = params->length; width; width--)
5559 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
5561 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5562 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5564 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5565 new_pix = FALSE;
5567 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5568 src_ptr += params->src_inc;
5569 src_x += params->src_inc;
5571 if (err > 0)
5573 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5574 dst_ptr += params->dst_inc;
5575 dst_x += params->dst_inc;
5576 new_pix = TRUE;
5577 err += params->err_add_1;
5579 else err += params->err_add_2;
5583 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5584 const dib_info *src_dib, const POINT *src_start,
5585 const struct stretch_params *params, int mode,
5586 BOOL keep_dst)
5588 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5589 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5590 int err = params->err_start;
5591 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5592 struct rop_codes codes;
5593 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5594 BOOL new_pix = TRUE;
5596 rop_codes_from_stretch_mode( mode, &codes );
5597 for (width = params->length; width; width--)
5599 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5600 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5601 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5602 new_pix = FALSE;
5604 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5605 src_ptr += params->src_inc;
5606 src_x += params->src_inc;
5608 if (err > 0)
5610 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5611 dst_ptr += params->dst_inc;
5612 dst_x += params->dst_inc;
5613 new_pix = TRUE;
5614 err += params->err_add_1;
5616 else err += params->err_add_2;
5620 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5621 const dib_info *src_dib, const POINT *src_start,
5622 const struct stretch_params *params, int mode,
5623 BOOL keep_dst)
5625 FIXME("bit count %d\n", dst_dib->bit_count);
5626 return;
5629 const primitive_funcs funcs_8888 =
5631 solid_rects_32,
5632 solid_line_32,
5633 pattern_rects_32,
5634 copy_rect_32,
5635 blend_rect_8888,
5636 gradient_rect_8888,
5637 draw_glyph_8888,
5638 get_pixel_32,
5639 colorref_to_pixel_888,
5640 pixel_to_colorref_888,
5641 convert_to_8888,
5642 create_rop_masks_32,
5643 create_dither_masks_null,
5644 stretch_row_32,
5645 shrink_row_32
5648 const primitive_funcs funcs_32 =
5650 solid_rects_32,
5651 solid_line_32,
5652 pattern_rects_32,
5653 copy_rect_32,
5654 blend_rect_32,
5655 gradient_rect_32,
5656 draw_glyph_32,
5657 get_pixel_32,
5658 colorref_to_pixel_masks,
5659 pixel_to_colorref_masks,
5660 convert_to_32,
5661 create_rop_masks_32,
5662 create_dither_masks_null,
5663 stretch_row_32,
5664 shrink_row_32
5667 const primitive_funcs funcs_24 =
5669 solid_rects_24,
5670 solid_line_24,
5671 pattern_rects_24,
5672 copy_rect_24,
5673 blend_rect_24,
5674 gradient_rect_24,
5675 draw_glyph_24,
5676 get_pixel_24,
5677 colorref_to_pixel_888,
5678 pixel_to_colorref_888,
5679 convert_to_24,
5680 create_rop_masks_24,
5681 create_dither_masks_null,
5682 stretch_row_24,
5683 shrink_row_24
5686 const primitive_funcs funcs_555 =
5688 solid_rects_16,
5689 solid_line_16,
5690 pattern_rects_16,
5691 copy_rect_16,
5692 blend_rect_555,
5693 gradient_rect_555,
5694 draw_glyph_555,
5695 get_pixel_16,
5696 colorref_to_pixel_555,
5697 pixel_to_colorref_555,
5698 convert_to_555,
5699 create_rop_masks_16,
5700 create_dither_masks_null,
5701 stretch_row_16,
5702 shrink_row_16
5705 const primitive_funcs funcs_16 =
5707 solid_rects_16,
5708 solid_line_16,
5709 pattern_rects_16,
5710 copy_rect_16,
5711 blend_rect_16,
5712 gradient_rect_16,
5713 draw_glyph_16,
5714 get_pixel_16,
5715 colorref_to_pixel_masks,
5716 pixel_to_colorref_masks,
5717 convert_to_16,
5718 create_rop_masks_16,
5719 create_dither_masks_null,
5720 stretch_row_16,
5721 shrink_row_16
5724 const primitive_funcs funcs_8 =
5726 solid_rects_8,
5727 solid_line_8,
5728 pattern_rects_8,
5729 copy_rect_8,
5730 blend_rect_8,
5731 gradient_rect_8,
5732 draw_glyph_8,
5733 get_pixel_8,
5734 colorref_to_pixel_colortable,
5735 pixel_to_colorref_colortable,
5736 convert_to_8,
5737 create_rop_masks_8,
5738 create_dither_masks_8,
5739 stretch_row_8,
5740 shrink_row_8
5743 const primitive_funcs funcs_4 =
5745 solid_rects_4,
5746 solid_line_4,
5747 pattern_rects_4,
5748 copy_rect_4,
5749 blend_rect_4,
5750 gradient_rect_4,
5751 draw_glyph_4,
5752 get_pixel_4,
5753 colorref_to_pixel_colortable,
5754 pixel_to_colorref_colortable,
5755 convert_to_4,
5756 create_rop_masks_4,
5757 create_dither_masks_4,
5758 stretch_row_4,
5759 shrink_row_4
5762 const primitive_funcs funcs_1 =
5764 solid_rects_1,
5765 solid_line_1,
5766 pattern_rects_1,
5767 copy_rect_1,
5768 blend_rect_1,
5769 gradient_rect_1,
5770 draw_glyph_1,
5771 get_pixel_1,
5772 colorref_to_pixel_colortable,
5773 pixel_to_colorref_colortable,
5774 convert_to_1,
5775 create_rop_masks_1,
5776 create_dither_masks_1,
5777 stretch_row_1,
5778 shrink_row_1
5781 const primitive_funcs funcs_null =
5783 solid_rects_null,
5784 solid_line_null,
5785 pattern_rects_null,
5786 copy_rect_null,
5787 blend_rect_null,
5788 gradient_rect_null,
5789 draw_glyph_null,
5790 get_pixel_null,
5791 colorref_to_pixel_null,
5792 pixel_to_colorref_null,
5793 convert_to_null,
5794 create_rop_masks_null,
5795 create_dither_masks_null,
5796 stretch_row_null,
5797 shrink_row_null