gdi32: Get rid of the METAFILEOBJ type, instead store a pointer to the metafile data.
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blob6feb819542912fd1af56fab08b6e6a726ed99593
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_no_src_alpha( DWORD dst, DWORD src, DWORD alpha )
3843 return (blend_color( dst, src, alpha ) |
3844 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3845 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3846 blend_color( dst >> 24, 255, alpha ) << 24);
3849 static inline DWORD blend_argb( DWORD dst, DWORD src )
3851 BYTE b = (BYTE)src;
3852 BYTE g = (BYTE)(src >> 8);
3853 BYTE r = (BYTE)(src >> 16);
3854 DWORD alpha = (BYTE)(src >> 24);
3855 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3856 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3857 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3858 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3861 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3863 BYTE b = ((BYTE)src * alpha + 127) / 255;
3864 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3865 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3866 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3867 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3868 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3869 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3870 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3873 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3875 if (blend.AlphaFormat & AC_SRC_ALPHA)
3877 DWORD alpha = blend.SourceConstantAlpha;
3878 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3879 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3880 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3881 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3882 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3883 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3884 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3886 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3887 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3888 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3891 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3892 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3894 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3895 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3896 int x, y;
3898 if (blend.AlphaFormat & AC_SRC_ALPHA)
3900 if (blend.SourceConstantAlpha == 255)
3901 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3902 for (x = 0; x < rc->right - rc->left; x++)
3903 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
3904 else
3905 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3906 for (x = 0; x < rc->right - rc->left; x++)
3907 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3909 else if (src->compression == BI_RGB)
3910 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3911 for (x = 0; x < rc->right - rc->left; x++)
3912 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3913 else
3914 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3915 for (x = 0; x < rc->right - rc->left; x++)
3916 dst_ptr[x] = blend_argb_no_src_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3919 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3920 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3922 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3923 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3924 int x, y;
3926 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3928 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3930 for (x = 0; x < rc->right - rc->left; x++)
3932 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3933 dst_ptr[x] >> dst->green_shift,
3934 dst_ptr[x] >> dst->blue_shift,
3935 src_ptr[x], blend );
3936 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3937 (((val >> 8) & 0xff) << dst->green_shift) |
3938 (((val >> 16) & 0xff) << dst->red_shift));
3942 else
3944 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3946 for (x = 0; x < rc->right - rc->left; x++)
3948 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3949 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3950 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3951 src_ptr[x], blend );
3952 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3953 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3954 put_field( val, dst->blue_shift, dst->blue_len ));
3960 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3961 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3963 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3964 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3965 int x, y;
3967 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3969 for (x = 0; x < rc->right - rc->left; x++)
3971 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3972 src_ptr[x], blend );
3973 dst_ptr[x * 3] = val;
3974 dst_ptr[x * 3 + 1] = val >> 8;
3975 dst_ptr[x * 3 + 2] = val >> 16;
3980 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3981 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3983 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3984 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3985 int x, y;
3987 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3989 for (x = 0; x < rc->right - rc->left; x++)
3991 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3992 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3993 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3994 src_ptr[x], blend );
3995 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4000 static void blend_rect_16(const dib_info *dst, const RECT *rc,
4001 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4003 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4004 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
4005 int x, y;
4007 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
4009 for (x = 0; x < rc->right - rc->left; x++)
4011 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
4012 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
4013 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
4014 src_ptr[x], blend );
4015 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
4016 put_field((val >> 8), dst->green_shift, dst->green_len) |
4017 put_field( val, dst->blue_shift, dst->blue_len));
4022 static void blend_rect_8(const dib_info *dst, const RECT *rc,
4023 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4025 const RGBQUAD *color_table = get_dib_color_table( dst );
4026 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4027 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4028 int x, y;
4030 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4032 for (x = 0; x < rc->right - rc->left; x++)
4034 RGBQUAD rgb = color_table[dst_ptr[x]];
4035 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4036 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4041 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4042 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4044 const RGBQUAD *color_table = get_dib_color_table( dst );
4045 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4046 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4047 int i, x, y;
4049 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4051 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4053 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4054 RGBQUAD rgb = color_table[val];
4055 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4056 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4057 if (x & 1)
4058 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4059 else
4060 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4065 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4066 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4068 const RGBQUAD *color_table = get_dib_color_table( dst );
4069 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4070 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4071 int i, x, y;
4073 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4075 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4077 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4078 RGBQUAD rgb = color_table[val];
4079 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4080 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4081 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4086 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4087 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4091 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4093 BYTE r, g, b, a;
4094 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4095 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4096 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4097 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4098 return a << 24 | r << 16 | g << 8 | b;
4101 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4103 BYTE r, g, b;
4104 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4105 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4106 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4107 return r << 16 | g << 8 | b;
4110 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4111 unsigned int x, unsigned int y )
4113 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4114 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4115 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4116 r = min( 31, max( 0, r / 16 ));
4117 g = min( 31, max( 0, g / 16 ));
4118 b = min( 31, max( 0, b / 16 ));
4119 return (r << 10) | (g << 5) | b;
4122 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4123 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4125 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4126 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4127 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4128 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4131 /* compute the left/right triangle limit for row y */
4132 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4134 int x1, x2;
4136 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4137 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4139 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4141 *left = max( rc->left, min( x1, x2 ) );
4142 *right = min( rc->right, max( x1, x2 ) );
4145 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4146 static inline int triangle_det( const TRIVERTEX *v )
4148 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);
4151 /* compute the barycentric weights for a given point inside the triangle */
4152 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4154 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4155 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4158 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4160 INT64 l1, l2;
4161 BYTE r, g, b, a;
4163 triangle_weights( v, x, y, &l1, &l2 );
4164 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4165 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4166 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4167 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4168 return a << 24 | r << 16 | g << 8 | b;
4171 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4173 INT64 l1, l2;
4174 BYTE 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 / 256;
4178 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4179 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4180 return r << 16 | g << 8 | b;
4183 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4185 INT64 l1, l2;
4186 int r, g, b;
4188 triangle_weights( v, x, y, &l1, &l2 );
4189 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4190 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4191 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4192 r = min( 31, max( 0, r / 16 ));
4193 g = min( 31, max( 0, g / 16 ));
4194 b = min( 31, max( 0, b / 16 ));
4195 return (r << 10) | (g << 5) | b;
4198 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4200 INT64 l1, l2;
4201 BYTE r, g, b;
4203 triangle_weights( v, x, y, &l1, &l2 );
4204 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4205 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4206 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4207 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4210 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4212 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4213 int x, y, left, right, det;
4215 switch (mode)
4217 case GRADIENT_FILL_RECT_H:
4218 for (x = 0; x < rc->right - rc->left; x++)
4219 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4221 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4222 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4223 break;
4225 case GRADIENT_FILL_RECT_V:
4226 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4228 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4229 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4231 break;
4233 case GRADIENT_FILL_TRIANGLE:
4234 if (!(det = triangle_det( v ))) return FALSE;
4235 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4237 triangle_coords( v, rc, y, &left, &right );
4238 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4240 break;
4242 return TRUE;
4245 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4247 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4248 int x, y, left, right, det;
4250 switch (mode)
4252 case GRADIENT_FILL_RECT_H:
4253 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4255 for (x = 0; x < rc->right - rc->left; x++)
4257 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4258 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4259 (((val >> 8) & 0xff) << dib->green_shift) |
4260 (((val >> 16) & 0xff) << dib->red_shift));
4263 else
4265 for (x = 0; x < rc->right - rc->left; x++)
4267 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4268 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4269 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4270 put_field( val, dib->blue_shift, dib->blue_len ));
4274 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4275 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4276 break;
4278 case GRADIENT_FILL_RECT_V:
4279 for (y = rc->top; y < rc->bottom; y++)
4281 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4282 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4283 val = ((( val & 0xff) << dib->blue_shift) |
4284 (((val >> 8) & 0xff) << dib->green_shift) |
4285 (((val >> 16) & 0xff) << dib->red_shift));
4286 else
4287 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4288 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4289 put_field( val, dib->blue_shift, dib->blue_len ));
4291 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4292 ptr += dib->stride / 4;
4294 break;
4296 case GRADIENT_FILL_TRIANGLE:
4297 if (!(det = triangle_det( v ))) return FALSE;
4298 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4300 triangle_coords( v, rc, y, &left, &right );
4302 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4303 for (x = left; x < right; x++)
4305 DWORD val = gradient_triangle_24( v, x, y, det );
4306 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4307 (((val >> 8) & 0xff) << dib->green_shift) |
4308 (((val >> 16) & 0xff) << dib->red_shift));
4310 else
4311 for (x = left; x < right; x++)
4313 DWORD val = gradient_triangle_24( v, x, y, det );
4314 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4315 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4316 put_field( val, dib->blue_shift, dib->blue_len ));
4319 break;
4321 return TRUE;
4324 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4326 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4327 int x, y, left, right, det;
4329 switch (mode)
4331 case GRADIENT_FILL_RECT_H:
4332 for (x = 0; x < rc->right - rc->left; x++)
4334 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4335 ptr[x * 3] = val;
4336 ptr[x * 3 + 1] = val >> 8;
4337 ptr[x * 3 + 2] = val >> 16;
4340 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4341 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4342 break;
4344 case GRADIENT_FILL_RECT_V:
4345 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4347 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4348 for (x = 0; x < rc->right - rc->left; x++)
4350 ptr[x * 3] = val;
4351 ptr[x * 3 + 1] = val >> 8;
4352 ptr[x * 3 + 2] = val >> 16;
4355 break;
4357 case GRADIENT_FILL_TRIANGLE:
4358 if (!(det = triangle_det( v ))) return FALSE;
4359 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4361 triangle_coords( v, rc, y, &left, &right );
4362 for (x = left; x < right; x++)
4364 DWORD val = gradient_triangle_24( v, x, y, det );
4365 ptr[(x - rc->left) * 3] = val;
4366 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4367 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4370 break;
4372 return TRUE;
4375 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4377 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4378 int x, y, left, right, det;
4380 switch (mode)
4382 case GRADIENT_FILL_RECT_H:
4383 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4384 for (x = rc->left; x < rc->right; x++)
4385 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4386 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4387 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4388 break;
4390 case GRADIENT_FILL_RECT_V:
4391 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4393 WORD values[4];
4394 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4395 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4397 break;
4399 case GRADIENT_FILL_TRIANGLE:
4400 if (!(det = triangle_det( v ))) return FALSE;
4401 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4403 triangle_coords( v, rc, y, &left, &right );
4404 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4406 break;
4408 return TRUE;
4411 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4413 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4414 int x, y, left, right, det;
4416 switch (mode)
4418 case GRADIENT_FILL_RECT_H:
4419 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4420 for (x = rc->left; x < rc->right; x++)
4422 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4423 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4424 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4425 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4427 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4428 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4429 break;
4431 case GRADIENT_FILL_RECT_V:
4432 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4434 WORD values[4];
4435 for (x = 0; x < 4; x++)
4437 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4438 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4439 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4440 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4442 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4444 break;
4446 case GRADIENT_FILL_TRIANGLE:
4447 if (!(det = triangle_det( v ))) return FALSE;
4448 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4450 triangle_coords( v, rc, y, &left, &right );
4451 for (x = left; x < right; x++)
4453 WORD val = gradient_triangle_555( v, x, y, det );
4454 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4455 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4456 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4459 break;
4461 return TRUE;
4464 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4466 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4467 int x, y, left, right, det;
4469 switch (mode)
4471 case GRADIENT_FILL_RECT_H:
4472 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4473 for (x = rc->left; x < rc->right; x++)
4474 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4475 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4476 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4477 break;
4479 case GRADIENT_FILL_RECT_V:
4480 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4482 BYTE values[16];
4483 for (x = 0; x < 16; x++)
4484 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4485 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4487 break;
4489 case GRADIENT_FILL_TRIANGLE:
4490 if (!(det = triangle_det( v ))) return FALSE;
4491 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4493 triangle_coords( v, rc, y, &left, &right );
4494 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4496 break;
4498 return TRUE;
4501 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4503 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4504 int x, y, left, right, det, pos;
4506 switch (mode)
4508 case GRADIENT_FILL_RECT_H:
4509 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4511 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4513 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4514 if (pos & 1)
4515 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4516 else
4517 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4520 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4522 x = rc->left;
4523 pos = (dib->rect.left + rc->left) & 1;
4524 if (pos)
4526 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4527 pos++;
4528 x++;
4530 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4531 if (x < rc->right)
4532 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4534 break;
4536 case GRADIENT_FILL_RECT_V:
4537 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4539 BYTE values[16];
4540 for (x = 0; x < 16; x++)
4541 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4542 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4543 if (pos & 1)
4544 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4545 else
4546 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4548 break;
4550 case GRADIENT_FILL_TRIANGLE:
4551 if (!(det = triangle_det( v ))) return FALSE;
4552 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4554 triangle_coords( v, rc, y, &left, &right );
4555 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4557 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4558 if (pos & 1)
4559 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4560 else
4561 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4564 break;
4566 return TRUE;
4569 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4571 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4572 int x, y, left, right, det, pos;
4574 switch (mode)
4576 case GRADIENT_FILL_RECT_H:
4577 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4579 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4581 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4582 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4585 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4586 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4587 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4588 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4589 break;
4591 case GRADIENT_FILL_RECT_V:
4592 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4594 BYTE values[16];
4595 for (x = 0; x < 16; x++)
4596 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4597 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4598 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4599 (values[x % 16] & pixel_masks_1[pos % 8]);
4601 break;
4603 case GRADIENT_FILL_TRIANGLE:
4604 if (!(det = triangle_det( v ))) return FALSE;
4605 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4607 triangle_coords( v, rc, y, &left, &right );
4608 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4610 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4611 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4614 break;
4616 return TRUE;
4619 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4621 return TRUE;
4624 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4626 if (dst == text) return dst;
4628 if (dst > text)
4630 DWORD diff = dst - text;
4631 DWORD range = max_comp - text;
4632 dst = text + (diff * range ) / (0xff - text);
4633 return dst;
4635 else
4637 DWORD diff = text - dst;
4638 DWORD range = text - min_comp;
4639 dst = text - (diff * range) / text;
4640 return dst;
4644 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4646 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4647 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4648 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4651 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4652 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4654 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4655 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4656 int x, y;
4658 for (y = rect->top; y < rect->bottom; y++)
4660 for (x = 0; x < rect->right - rect->left; x++)
4662 if (glyph_ptr[x] <= 1) continue;
4663 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4664 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4666 dst_ptr += dib->stride / 4;
4667 glyph_ptr += glyph->stride;
4671 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4672 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4674 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4675 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4676 int x, y;
4677 DWORD text, val;
4679 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4680 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4681 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4683 for (y = rect->top; y < rect->bottom; y++)
4685 for (x = 0; x < rect->right - rect->left; x++)
4687 if (glyph_ptr[x] <= 1) continue;
4688 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4689 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4690 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4691 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4692 text, ranges + glyph_ptr[x] );
4693 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4694 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4695 put_field( val, dib->blue_shift, dib->blue_len ));
4697 dst_ptr += dib->stride / 4;
4698 glyph_ptr += glyph->stride;
4702 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4703 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4705 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4706 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4707 int x, y;
4708 DWORD val;
4710 for (y = rect->top; y < rect->bottom; y++)
4712 for (x = 0; x < rect->right - rect->left; x++)
4714 if (glyph_ptr[x] <= 1) continue;
4715 if (glyph_ptr[x] >= 16)
4716 val = text_pixel;
4717 else
4718 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4719 text_pixel, ranges + glyph_ptr[x] );
4720 dst_ptr[x * 3] = val;
4721 dst_ptr[x * 3 + 1] = val >> 8;
4722 dst_ptr[x * 3 + 2] = val >> 16;
4724 dst_ptr += dib->stride;
4725 glyph_ptr += glyph->stride;
4729 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4730 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4732 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4733 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4734 int x, y;
4735 DWORD text, val;
4737 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4738 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4739 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4741 for (y = rect->top; y < rect->bottom; y++)
4743 for (x = 0; x < rect->right - rect->left; x++)
4745 if (glyph_ptr[x] <= 1) continue;
4746 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4747 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4748 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4749 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4750 text, ranges + glyph_ptr[x] );
4751 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4753 dst_ptr += dib->stride / 2;
4754 glyph_ptr += glyph->stride;
4758 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4759 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4761 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4762 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4763 int x, y;
4764 DWORD text, val;
4766 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4767 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4768 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4770 for (y = rect->top; y < rect->bottom; y++)
4772 for (x = 0; x < rect->right - rect->left; x++)
4774 if (glyph_ptr[x] <= 1) continue;
4775 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4776 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4777 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4778 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4779 text, ranges + glyph_ptr[x] );
4780 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4781 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4782 put_field( val, dib->blue_shift, dib->blue_len ));
4784 dst_ptr += dib->stride / 2;
4785 glyph_ptr += glyph->stride;
4789 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4790 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4792 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4793 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4794 int x, y;
4796 for (y = rect->top; y < rect->bottom; y++)
4798 for (x = 0; x < rect->right - rect->left; x++)
4800 /* no antialiasing, glyph should only contain 0 or 16. */
4801 if (glyph_ptr[x] >= 16)
4802 dst_ptr[x] = text_pixel;
4804 dst_ptr += dib->stride;
4805 glyph_ptr += glyph->stride;
4809 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4810 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4812 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
4813 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4814 int x, y, pos;
4816 for (y = rect->top; y < rect->bottom; y++)
4818 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
4820 /* no antialiasing, glyph should only contain 0 or 16. */
4821 if (glyph_ptr[x] >= 16)
4823 if (pos & 1)
4824 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
4825 else
4826 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
4829 dst_ptr += dib->stride;
4830 glyph_ptr += glyph->stride;
4834 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4835 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4837 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
4838 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4839 int x, y, pos;
4840 BYTE text = (text_pixel & 1) ? 0xff : 0;
4842 for (y = rect->top; y < rect->bottom; y++)
4844 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
4846 /* no antialiasing, glyph should only contain 0 or 16. */
4847 if (glyph_ptr[x] >= 16)
4848 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4849 (text & pixel_masks_1[pos % 8]);
4851 dst_ptr += dib->stride;
4852 glyph_ptr += glyph->stride;
4856 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4857 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4859 return;
4862 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
4863 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4865 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4866 int x, y;
4868 /* masks are always 8x8 */
4869 assert( dib->width == 8 );
4870 assert( dib->height == 8 );
4872 for(y = 0; y < 8; y++, hatch_ptr++)
4874 for(x = 0; x < 8; x++)
4876 if(*hatch_ptr & pixel_masks_1[x])
4878 and_bits[x] = fg->and;
4879 xor_bits[x] = fg->xor;
4881 else
4883 and_bits[x] = bg->and;
4884 xor_bits[x] = bg->xor;
4887 and_bits += dib->stride / 4;
4888 xor_bits += dib->stride / 4;
4892 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
4893 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4895 DWORD mask_start = 0, mask_offset;
4896 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4897 int x, y;
4899 /* masks are always 8x8 */
4900 assert( dib->width == 8 );
4901 assert( dib->height == 8 );
4903 for(y = 0; y < 8; y++, hatch_ptr++)
4905 mask_offset = mask_start;
4906 for(x = 0; x < 8; x++)
4908 if(*hatch_ptr & pixel_masks_1[x])
4910 and_bits[mask_offset] = fg->and & 0xff;
4911 xor_bits[mask_offset++] = fg->xor & 0xff;
4912 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4913 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4914 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4915 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4917 else
4919 and_bits[mask_offset] = bg->and & 0xff;
4920 xor_bits[mask_offset++] = bg->xor & 0xff;
4921 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4922 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4923 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4924 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4927 mask_start += dib->stride;
4931 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
4932 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4934 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4935 int x, y;
4937 /* masks are always 8x8 */
4938 assert( dib->width == 8 );
4939 assert( dib->height == 8 );
4941 for(y = 0; y < 8; y++, hatch_ptr++)
4943 for(x = 0; x < 8; x++)
4945 if(*hatch_ptr & pixel_masks_1[x])
4947 and_bits[x] = fg->and;
4948 xor_bits[x] = fg->xor;
4950 else
4952 and_bits[x] = bg->and;
4953 xor_bits[x] = bg->xor;
4956 and_bits += dib->stride / 2;
4957 xor_bits += dib->stride / 2;
4961 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
4962 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4964 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4965 int x, y;
4967 /* masks are always 8x8 */
4968 assert( dib->width == 8 );
4969 assert( dib->height == 8 );
4971 for(y = 0; y < 8; y++, hatch_ptr++)
4973 for(x = 0; x < 8; x++)
4975 if(*hatch_ptr & pixel_masks_1[x])
4977 and_bits[x] = fg->and;
4978 xor_bits[x] = fg->xor;
4980 else
4982 and_bits[x] = bg->and;
4983 xor_bits[x] = bg->xor;
4986 and_bits += dib->stride;
4987 xor_bits += dib->stride;
4991 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
4992 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4994 DWORD mask_offset;
4995 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4996 const rop_mask *rop_mask;
4997 int x, y;
4999 /* masks are always 8x8 */
5000 assert( dib->width == 8 );
5001 assert( dib->height == 8 );
5003 for(y = 0; y < 8; y++, hatch_ptr++)
5005 for(x = mask_offset = 0; x < 8; x++)
5007 if(*hatch_ptr & pixel_masks_1[x])
5008 rop_mask = fg;
5009 else
5010 rop_mask = bg;
5012 if(x & 1)
5014 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
5015 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
5016 mask_offset++;
5018 else
5020 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
5021 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
5024 and_bits += dib->stride;
5025 xor_bits += dib->stride;
5029 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
5030 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5032 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5033 rop_mask rop_mask;
5034 int x, y;
5036 /* masks are always 8x8 */
5037 assert( dib->width == 8 );
5038 assert( dib->height == 8 );
5040 for(y = 0; y < 8; y++, hatch_ptr++)
5042 *and_bits = *xor_bits = 0;
5043 for(x = 0; x < 8; x++)
5045 if(*hatch_ptr & pixel_masks_1[x])
5047 rop_mask.and = (fg->and & 1) ? 0xff : 0;
5048 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
5050 else
5052 rop_mask.and = (bg->and & 1) ? 0xff : 0;
5053 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5055 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5056 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5058 and_bits += dib->stride;
5059 xor_bits += dib->stride;
5063 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
5064 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5068 static void create_dither_masks_8(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5070 /* mapping between RGB triples and the default color table */
5071 static const BYTE mapping[27] =
5073 0, /* 000000 -> 000000 */
5074 4, /* 00007f -> 000080 */
5075 252, /* 0000ff -> 0000ff */
5076 2, /* 007f00 -> 008000 */
5077 6, /* 007f7f -> 008080 */
5078 224, /* 007fff -> 0080c0 */
5079 250, /* 00ff00 -> 00ff00 */
5080 184, /* 00ff7f -> 00e080 */
5081 254, /* 00ffff -> 00ffff */
5082 1, /* 7f0000 -> 800000 */
5083 5, /* 7f007f -> 800080 */
5084 196, /* 7f00ff -> 8000c0 */
5085 3, /* 7f7f00 -> 808000 */
5086 248, /* 7f7f7f -> 808080 */
5087 228, /* 7f7fff -> 8080c0 */
5088 60, /* 7fff00 -> 80e000 */
5089 188, /* 7fff7f -> 80e080 */
5090 244, /* 7fffff -> 80c0c0 */
5091 249, /* ff0000 -> ff0000 */
5092 135, /* ff007f -> e00080 */
5093 253, /* ff00ff -> ff00ff */
5094 39, /* ff7f00 -> e08000 */
5095 167, /* ff7f7f -> e08080 */
5096 231, /* ff7fff -> e080c0 */
5097 251, /* ffff00 -> ffff00 */
5098 191, /* ffff7f -> e0e080 */
5099 255 /* ffffff -> ffffff */
5102 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5103 struct rop_codes codes;
5104 int x, y;
5106 /* masks are always 8x8 */
5107 assert( dib->width == 8 );
5108 assert( dib->height == 8 );
5110 get_rop_codes( rop2, &codes );
5112 for (y = 0; y < 8; y++)
5114 for (x = 0; x < 8; x++)
5116 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5117 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5118 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5119 DWORD pixel = mapping[r * 9 + g * 3 + b];
5120 and_bits[x] = (pixel & codes.a1) ^ codes.a2;
5121 xor_bits[x] = (pixel & codes.x1) ^ codes.x2;
5123 and_bits += dib->stride;
5124 xor_bits += dib->stride;
5128 static void create_dither_masks_4(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5130 /* mapping between RGB triples and the default color table */
5131 static const BYTE mapping[27] =
5133 0, /* 000000 -> 000000 */
5134 4, /* 00007f -> 000080 */
5135 12, /* 0000ff -> 0000ff */
5136 2, /* 007f00 -> 008000 */
5137 6, /* 007f7f -> 008080 */
5138 6, /* 007fff -> 008080 */
5139 10, /* 00ff00 -> 00ff00 */
5140 6, /* 00ff7f -> 008080 */
5141 14, /* 00ffff -> 00ffff */
5142 1, /* 7f0000 -> 800000 */
5143 5, /* 7f007f -> 800080 */
5144 5, /* 7f00ff -> 800080 */
5145 3, /* 7f7f00 -> 808000 */
5146 7, /* 7f7f7f -> 808080 */
5147 8, /* 7f7fff -> c0c0c0 */
5148 3, /* 7fff00 -> 808000 */
5149 8, /* 7fff7f -> c0c0c0 */
5150 8, /* 7fffff -> c0c0c0 */
5151 9, /* ff0000 -> ff0000 */
5152 5, /* ff007f -> 800080 */
5153 13, /* ff00ff -> ff00ff */
5154 3, /* ff7f00 -> 808000 */
5155 8, /* ff7f7f -> c0c0c0 */
5156 8, /* ff7fff -> c0c0c0 */
5157 11, /* ffff00 -> ffff00 */
5158 8, /* ffff7f -> c0c0c0 */
5159 15 /* ffffff -> ffffff */
5162 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5163 struct rop_codes codes;
5164 int x, y;
5166 /* masks are always 8x8 */
5167 assert( dib->width == 8 );
5168 assert( dib->height == 8 );
5170 get_rop_codes( rop2, &codes );
5172 for (y = 0; y < 8; y++)
5174 for (x = 0; x < 8; x++)
5176 DWORD r = ((GetRValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5177 DWORD g = ((GetGValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5178 DWORD b = ((GetBValue(color) + 1) / 2 + bayer_8x8[y][x]) / 64;
5179 DWORD pixel = mapping[r * 9 + g * 3 + b];
5180 if (x & 1)
5182 and_bits[x / 2] |= (pixel & codes.a1) ^ codes.a2;
5183 xor_bits[x / 2] |= (pixel & codes.x1) ^ codes.x2;
5185 else
5187 and_bits[x / 2] = ((pixel & codes.a1) ^ codes.a2) << 4;
5188 xor_bits[x / 2] = ((pixel & codes.x1) ^ codes.x2) << 4;
5191 and_bits += dib->stride;
5192 xor_bits += dib->stride;
5196 static void create_dither_masks_1(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5198 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5199 struct rop_codes codes;
5200 rop_mask rop_mask;
5201 int x, y, grey = (30 * GetRValue(color) + 59 * GetGValue(color) + 11 * GetBValue(color) + 200) / 400;
5203 /* masks are always 8x8 */
5204 assert( dib->width == 8 );
5205 assert( dib->height == 8 );
5207 get_rop_codes( rop2, &codes );
5209 for (y = 0; y < 8; y++)
5211 *and_bits = *xor_bits = 0;
5212 for (x = 0; x < 8; x++)
5214 if (grey + bayer_8x8[y][x] > 63)
5216 rop_mask.and = (0xff & codes.a1) ^ codes.a2;
5217 rop_mask.xor = (0xff & codes.x1) ^ codes.x2;
5219 else
5221 rop_mask.and = (0x00 & codes.a1) ^ codes.a2;
5222 rop_mask.xor = (0x00 & codes.x1) ^ codes.x2;
5224 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5225 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5227 and_bits += dib->stride;
5228 xor_bits += dib->stride;
5232 static void create_dither_masks_null(const dib_info *dib, int rop2, COLORREF color, rop_mask_bits *bits)
5236 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5238 switch (mode)
5240 default:
5241 case STRETCH_DELETESCANS:
5242 get_rop_codes( R2_COPYPEN, codes );
5243 break;
5244 case STRETCH_ORSCANS:
5245 get_rop_codes( R2_MERGEPEN, codes );
5246 break;
5247 case STRETCH_ANDSCANS:
5248 get_rop_codes( R2_MASKPEN, codes );
5249 break;
5251 return;
5254 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5255 const dib_info *src_dib, const POINT *src_start,
5256 const struct stretch_params *params, int mode,
5257 BOOL keep_dst)
5259 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5260 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5261 int err = params->err_start;
5262 int width;
5263 struct rop_codes codes;
5265 rop_codes_from_stretch_mode( mode, &codes );
5266 for (width = params->length; width; width--)
5268 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5269 dst_ptr += params->dst_inc;
5270 if (err > 0)
5272 src_ptr += params->src_inc;
5273 err += params->err_add_1;
5275 else err += params->err_add_2;
5279 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5280 const dib_info *src_dib, const POINT *src_start,
5281 const struct stretch_params *params, int mode,
5282 BOOL keep_dst)
5284 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5285 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5286 int err = params->err_start;
5287 int width;
5288 struct rop_codes codes;
5290 rop_codes_from_stretch_mode( mode, &codes );
5291 for (width = params->length; width; width--)
5293 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5294 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5295 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5296 dst_ptr += 3 * params->dst_inc;
5297 if (err > 0)
5299 src_ptr += 3 * params->src_inc;
5300 err += params->err_add_1;
5302 else err += params->err_add_2;
5306 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5307 const dib_info *src_dib, const POINT *src_start,
5308 const struct stretch_params *params, int mode,
5309 BOOL keep_dst)
5311 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5312 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5313 int err = params->err_start;
5314 int width;
5315 struct rop_codes codes;
5317 rop_codes_from_stretch_mode( mode, &codes );
5318 for (width = params->length; width; width--)
5320 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5321 dst_ptr += params->dst_inc;
5322 if (err > 0)
5324 src_ptr += params->src_inc;
5325 err += params->err_add_1;
5327 else err += params->err_add_2;
5331 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5332 const dib_info *src_dib, const POINT *src_start,
5333 const struct stretch_params *params, int mode,
5334 BOOL keep_dst)
5336 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5337 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5338 int err = params->err_start;
5339 int width;
5340 struct rop_codes codes;
5342 rop_codes_from_stretch_mode( mode, &codes );
5343 for (width = params->length; width; width--)
5345 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5346 dst_ptr += params->dst_inc;
5347 if (err > 0)
5349 src_ptr += params->src_inc;
5350 err += params->err_add_1;
5352 else err += params->err_add_2;
5356 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5357 const dib_info *src_dib, const POINT *src_start,
5358 const struct stretch_params *params, int mode,
5359 BOOL keep_dst)
5361 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5362 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5363 int err = params->err_start;
5364 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5365 struct rop_codes codes;
5366 BYTE src_val;
5368 rop_codes_from_stretch_mode( mode, &codes );
5369 for (width = params->length; width; width--)
5371 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5372 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5374 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5376 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5377 dst_ptr += params->dst_inc;
5378 dst_x += params->dst_inc;
5380 if (err > 0)
5382 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5383 src_ptr += params->src_inc;
5384 src_x += params->src_inc;
5385 err += params->err_add_1;
5387 else err += params->err_add_2;
5391 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5392 const dib_info *src_dib, const POINT *src_start,
5393 const struct stretch_params *params, int mode,
5394 BOOL keep_dst)
5396 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5397 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5398 int err = params->err_start;
5399 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5400 struct rop_codes codes;
5401 BYTE src_val;
5403 rop_codes_from_stretch_mode( mode, &codes );
5404 for (width = params->length; width; width--)
5406 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5407 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5409 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5410 dst_ptr += params->dst_inc;
5411 dst_x += params->dst_inc;
5413 if (err > 0)
5415 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5416 src_ptr += params->src_inc;
5417 src_x += params->src_inc;
5418 err += params->err_add_1;
5420 else err += params->err_add_2;
5424 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5425 const dib_info *src_dib, const POINT *src_start,
5426 const struct stretch_params *params, int mode,
5427 BOOL keep_dst)
5429 FIXME("bit count %d\n", dst_dib->bit_count);
5430 return;
5433 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5434 const dib_info *src_dib, const POINT *src_start,
5435 const struct stretch_params *params, int mode,
5436 BOOL keep_dst)
5438 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5439 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5440 int err = params->err_start;
5441 int width;
5442 struct rop_codes codes;
5443 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5444 BOOL new_pix = TRUE;
5446 rop_codes_from_stretch_mode( mode, &codes );
5447 for (width = params->length; width; width--)
5449 if (new_pix && !keep_dst) *dst_ptr = init_val;
5450 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5451 new_pix = FALSE;
5452 src_ptr += params->src_inc;
5453 if (err > 0)
5455 dst_ptr += params->dst_inc;
5456 new_pix = TRUE;
5457 err += params->err_add_1;
5459 else err += params->err_add_2;
5463 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5464 const dib_info *src_dib, const POINT *src_start,
5465 const struct stretch_params *params, int mode,
5466 BOOL keep_dst)
5468 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5469 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5470 int err = params->err_start;
5471 int width;
5472 struct rop_codes codes;
5473 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5474 BOOL new_pix = TRUE;
5476 rop_codes_from_stretch_mode( mode, &codes );
5477 for (width = params->length; width; width--)
5479 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5480 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5481 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5482 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5483 new_pix = FALSE;
5484 src_ptr += 3 * params->src_inc;
5485 if (err > 0)
5487 dst_ptr += 3 * params->dst_inc;
5488 new_pix = TRUE;
5489 err += params->err_add_1;
5491 else err += params->err_add_2;
5495 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5496 const dib_info *src_dib, const POINT *src_start,
5497 const struct stretch_params *params, int mode,
5498 BOOL keep_dst)
5500 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5501 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5502 int err = params->err_start;
5503 int width;
5504 struct rop_codes codes;
5505 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5506 BOOL new_pix = TRUE;
5508 rop_codes_from_stretch_mode( mode, &codes );
5509 for (width = params->length; width; width--)
5511 if (new_pix && !keep_dst) *dst_ptr = init_val;
5512 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5513 new_pix = FALSE;
5514 src_ptr += params->src_inc;
5515 if (err > 0)
5517 dst_ptr += params->dst_inc;
5518 new_pix = TRUE;
5519 err += params->err_add_1;
5521 else err += params->err_add_2;
5525 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5526 const dib_info *src_dib, const POINT *src_start,
5527 const struct stretch_params *params, int mode,
5528 BOOL keep_dst)
5530 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5531 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5532 int err = params->err_start;
5533 int width;
5534 struct rop_codes codes;
5535 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5536 BOOL new_pix = TRUE;
5538 rop_codes_from_stretch_mode( mode, &codes );
5539 for (width = params->length; width; width--)
5541 if (new_pix && !keep_dst) *dst_ptr = init_val;
5542 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5543 new_pix = FALSE;
5544 src_ptr += params->src_inc;
5545 if (err > 0)
5547 dst_ptr += params->dst_inc;
5548 new_pix = TRUE;
5549 err += params->err_add_1;
5551 else err += params->err_add_2;
5555 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5556 const dib_info *src_dib, const POINT *src_start,
5557 const struct stretch_params *params, int mode,
5558 BOOL keep_dst)
5560 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5561 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5562 int err = params->err_start;
5563 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5564 struct rop_codes codes;
5565 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5566 BOOL new_pix = TRUE;
5568 rop_codes_from_stretch_mode( mode, &codes );
5569 for (width = params->length; width; width--)
5571 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
5573 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5574 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5576 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5577 new_pix = FALSE;
5579 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5580 src_ptr += params->src_inc;
5581 src_x += params->src_inc;
5583 if (err > 0)
5585 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5586 dst_ptr += params->dst_inc;
5587 dst_x += params->dst_inc;
5588 new_pix = TRUE;
5589 err += params->err_add_1;
5591 else err += params->err_add_2;
5595 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5596 const dib_info *src_dib, const POINT *src_start,
5597 const struct stretch_params *params, int mode,
5598 BOOL keep_dst)
5600 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5601 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5602 int err = params->err_start;
5603 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5604 struct rop_codes codes;
5605 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5606 BOOL new_pix = TRUE;
5608 rop_codes_from_stretch_mode( mode, &codes );
5609 for (width = params->length; width; width--)
5611 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5612 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5613 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5614 new_pix = FALSE;
5616 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5617 src_ptr += params->src_inc;
5618 src_x += params->src_inc;
5620 if (err > 0)
5622 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5623 dst_ptr += params->dst_inc;
5624 dst_x += params->dst_inc;
5625 new_pix = TRUE;
5626 err += params->err_add_1;
5628 else err += params->err_add_2;
5632 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5633 const dib_info *src_dib, const POINT *src_start,
5634 const struct stretch_params *params, int mode,
5635 BOOL keep_dst)
5637 FIXME("bit count %d\n", dst_dib->bit_count);
5638 return;
5641 const primitive_funcs funcs_8888 =
5643 solid_rects_32,
5644 solid_line_32,
5645 pattern_rects_32,
5646 copy_rect_32,
5647 blend_rect_8888,
5648 gradient_rect_8888,
5649 draw_glyph_8888,
5650 get_pixel_32,
5651 colorref_to_pixel_888,
5652 pixel_to_colorref_888,
5653 convert_to_8888,
5654 create_rop_masks_32,
5655 create_dither_masks_null,
5656 stretch_row_32,
5657 shrink_row_32
5660 const primitive_funcs funcs_32 =
5662 solid_rects_32,
5663 solid_line_32,
5664 pattern_rects_32,
5665 copy_rect_32,
5666 blend_rect_32,
5667 gradient_rect_32,
5668 draw_glyph_32,
5669 get_pixel_32,
5670 colorref_to_pixel_masks,
5671 pixel_to_colorref_masks,
5672 convert_to_32,
5673 create_rop_masks_32,
5674 create_dither_masks_null,
5675 stretch_row_32,
5676 shrink_row_32
5679 const primitive_funcs funcs_24 =
5681 solid_rects_24,
5682 solid_line_24,
5683 pattern_rects_24,
5684 copy_rect_24,
5685 blend_rect_24,
5686 gradient_rect_24,
5687 draw_glyph_24,
5688 get_pixel_24,
5689 colorref_to_pixel_888,
5690 pixel_to_colorref_888,
5691 convert_to_24,
5692 create_rop_masks_24,
5693 create_dither_masks_null,
5694 stretch_row_24,
5695 shrink_row_24
5698 const primitive_funcs funcs_555 =
5700 solid_rects_16,
5701 solid_line_16,
5702 pattern_rects_16,
5703 copy_rect_16,
5704 blend_rect_555,
5705 gradient_rect_555,
5706 draw_glyph_555,
5707 get_pixel_16,
5708 colorref_to_pixel_555,
5709 pixel_to_colorref_555,
5710 convert_to_555,
5711 create_rop_masks_16,
5712 create_dither_masks_null,
5713 stretch_row_16,
5714 shrink_row_16
5717 const primitive_funcs funcs_16 =
5719 solid_rects_16,
5720 solid_line_16,
5721 pattern_rects_16,
5722 copy_rect_16,
5723 blend_rect_16,
5724 gradient_rect_16,
5725 draw_glyph_16,
5726 get_pixel_16,
5727 colorref_to_pixel_masks,
5728 pixel_to_colorref_masks,
5729 convert_to_16,
5730 create_rop_masks_16,
5731 create_dither_masks_null,
5732 stretch_row_16,
5733 shrink_row_16
5736 const primitive_funcs funcs_8 =
5738 solid_rects_8,
5739 solid_line_8,
5740 pattern_rects_8,
5741 copy_rect_8,
5742 blend_rect_8,
5743 gradient_rect_8,
5744 draw_glyph_8,
5745 get_pixel_8,
5746 colorref_to_pixel_colortable,
5747 pixel_to_colorref_colortable,
5748 convert_to_8,
5749 create_rop_masks_8,
5750 create_dither_masks_8,
5751 stretch_row_8,
5752 shrink_row_8
5755 const primitive_funcs funcs_4 =
5757 solid_rects_4,
5758 solid_line_4,
5759 pattern_rects_4,
5760 copy_rect_4,
5761 blend_rect_4,
5762 gradient_rect_4,
5763 draw_glyph_4,
5764 get_pixel_4,
5765 colorref_to_pixel_colortable,
5766 pixel_to_colorref_colortable,
5767 convert_to_4,
5768 create_rop_masks_4,
5769 create_dither_masks_4,
5770 stretch_row_4,
5771 shrink_row_4
5774 const primitive_funcs funcs_1 =
5776 solid_rects_1,
5777 solid_line_1,
5778 pattern_rects_1,
5779 copy_rect_1,
5780 blend_rect_1,
5781 gradient_rect_1,
5782 draw_glyph_1,
5783 get_pixel_1,
5784 colorref_to_pixel_colortable,
5785 pixel_to_colorref_colortable,
5786 convert_to_1,
5787 create_rop_masks_1,
5788 create_dither_masks_1,
5789 stretch_row_1,
5790 shrink_row_1
5793 const primitive_funcs funcs_null =
5795 solid_rects_null,
5796 solid_line_null,
5797 pattern_rects_null,
5798 copy_rect_null,
5799 blend_rect_null,
5800 gradient_rect_null,
5801 draw_glyph_null,
5802 get_pixel_null,
5803 colorref_to_pixel_null,
5804 pixel_to_colorref_null,
5805 convert_to_null,
5806 create_rop_masks_null,
5807 create_dither_masks_null,
5808 stretch_row_null,
5809 shrink_row_null