gdi32: Use the default color table when mapping colors in bitmaps that don't have...
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blob19c7bc99548071adb12c8d41c98adb5c840ff139
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_16x16[16][16] =
42 { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170 },
43 { 192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106 },
44 { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154 },
45 { 240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90 },
46 { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166 },
47 { 204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102 },
48 { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150 },
49 { 252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86 },
50 { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169 },
51 { 195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105 },
52 { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153 },
53 { 243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89 },
54 { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165 },
55 { 207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101 },
56 { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149 },
57 { 255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85 },
60 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
62 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 4);
65 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
67 return (DWORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride) + (dib->rect.left + x) * 3 / 4;
70 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
72 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 3;
75 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
77 return (WORD *)((BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) * 2);
80 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
82 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + dib->rect.left + x;
85 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
87 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 2;
90 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
92 return (BYTE*)dib->bits.ptr + (dib->rect.top + y) * dib->stride + (dib->rect.left + x) / 8;
95 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
96 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
98 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
100 *ptr = (*ptr & and) ^ xor;
103 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
105 *ptr = (*ptr & and) ^ xor;
108 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
110 *ptr = (*ptr & and) ^ xor;
113 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
115 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
118 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
120 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
123 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
125 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
128 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
130 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
133 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
135 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
138 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
140 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
143 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
145 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
146 do_rop_codes_32( dst, *src, codes );
149 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
151 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
154 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
156 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
157 do_rop_codes_16( dst, *src, codes );
160 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
162 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
165 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
167 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
168 do_rop_codes_8( dst, *src, codes );
171 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
172 struct rop_codes *codes, int len)
174 BYTE src_val;
176 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
178 if (dst_x & 1)
180 if (src_x & 1) src_val = *src++;
181 else src_val = *src >> 4;
182 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
184 else
186 if (src_x & 1) src_val = *src++ << 4;
187 else src_val = *src;
188 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
193 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
194 struct rop_codes *codes, int len)
196 BYTE src_val;
198 src_x += len - 1;
199 dst_x += len - 1;
200 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
202 if (dst_x & 1)
204 if (src_x & 1) src_val = *src;
205 else src_val = *src-- >> 4;
206 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
208 else
210 if (src_x & 1) src_val = *src << 4;
211 else src_val = *src--;
212 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
217 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
218 struct rop_codes *codes, int len)
220 BYTE src_val;
222 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
224 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
225 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
226 if ((src_x & 7) == 7) src++;
227 if ((dst_x & 7) == 7) dst++;
231 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
232 struct rop_codes *codes, int len)
234 BYTE src_val;
236 src_x += len - 1;
237 dst_x += len - 1;
238 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
240 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
241 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
242 if ((src_x & 7) == 0) src--;
243 if ((dst_x & 7) == 0) dst--;
247 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
249 DWORD *ptr, *start;
250 int x, y, i;
252 for(i = 0; i < num; i++, rc++)
254 start = get_pixel_ptr_32(dib, rc->left, rc->top);
255 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
256 for(x = rc->left, ptr = start; x < rc->right; x++)
257 do_rop_32(ptr++, and, xor);
261 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
263 DWORD *ptr, *start;
264 BYTE *byte_ptr, *byte_start;
265 int x, y, i;
266 DWORD and_masks[3], xor_masks[3];
268 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
269 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
270 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
271 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
272 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
273 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
275 for(i = 0; i < num; i++, rc++)
277 int left = dib->rect.left + rc->left;
278 int right = dib->rect.left + rc->right;
280 if (left >= right) continue;
282 if ((left & ~3) == (right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
284 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
285 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
287 for(x = left, byte_ptr = byte_start; x < right; x++)
289 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
290 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
291 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
295 else
297 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
298 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
300 ptr = start;
302 switch(left & 3)
304 case 1:
305 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
306 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
307 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
308 break;
309 case 2:
310 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
311 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
312 break;
313 case 3:
314 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
315 break;
318 for(x = (left + 3) & ~3; x < (right & ~3); x += 4)
320 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
321 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
322 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
325 switch(right & 3)
327 case 1:
328 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
329 break;
330 case 2:
331 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
332 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
333 break;
334 case 3:
335 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
336 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
337 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
338 break;
345 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
347 WORD *ptr, *start;
348 int x, y, i;
350 for(i = 0; i < num; i++, rc++)
352 start = get_pixel_ptr_16(dib, rc->left, rc->top);
353 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
354 for(x = rc->left, ptr = start; x < rc->right; x++)
355 do_rop_16(ptr++, and, xor);
359 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
361 BYTE *ptr, *start;
362 int x, y, i;
364 for(i = 0; i < num; i++, rc++)
366 start = get_pixel_ptr_8(dib, rc->left, rc->top);
367 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
368 for(x = rc->left, ptr = start; x < rc->right; x++)
369 do_rop_8(ptr++, and, xor);
373 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
375 BYTE *ptr, *start;
376 int x, y, i;
377 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
378 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
380 for(i = 0; i < num; i++, rc++)
382 int left = dib->rect.left + rc->left;
383 int right = dib->rect.left + rc->right;
385 if (left >= right) continue;
386 start = get_pixel_ptr_4(dib, rc->left, rc->top);
387 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
389 ptr = start;
390 if(left & 1) /* upper nibble untouched */
391 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
393 for(x = (left + 1) & ~1; x < (right & ~1); x += 2)
394 do_rop_8(ptr++, byte_and, byte_xor);
396 if(right & 1) /* lower nibble untouched */
397 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
402 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
404 BYTE *ptr, *start;
405 int x, y, i;
406 BYTE byte_and = (and & 1) ? 0xff : 0;
407 BYTE byte_xor = (xor & 1) ? 0xff : 0;
408 BYTE start_and, start_xor, end_and, end_xor, mask;
409 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
411 for(i = 0; i < num; i++, rc++)
413 int left = dib->rect.left + rc->left;
414 int right = dib->rect.left + rc->right;
416 if (left >= right) continue;
418 start = get_pixel_ptr_1(dib, rc->left, rc->top);
420 if ((left & ~7) == (right & ~7)) /* Special case for lines that start and end in the same byte */
422 mask = masks[left & 7] & ~masks[right & 7];
424 start_and = byte_and | ~mask;
425 start_xor = byte_xor & mask;
426 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
428 do_rop_8(start, start_and, start_xor);
431 else
433 mask = masks[left & 7];
434 start_and = byte_and | ~mask;
435 start_xor = byte_xor & mask;
437 mask = masks[right & 7];
438 /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
439 end_and = byte_and | mask;
440 end_xor = byte_xor & ~mask;
442 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
444 ptr = start;
446 if(left & 7)
447 do_rop_8(ptr++, start_and, start_xor);
449 for(x = (left + 7) & ~7; x < (right & ~7); x += 8)
450 do_rop_8(ptr++, byte_and, byte_xor);
452 if(right & 7)
453 do_rop_8(ptr, end_and, end_xor);
459 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
461 return;
464 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
465 DWORD and, DWORD xor)
467 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
468 int len = params->length, err = params->err_start;
469 int major_inc, minor_inc;
471 if (params->x_major)
473 major_inc = params->x_inc;
474 minor_inc = (dib->stride * params->y_inc) / 4;
476 else
478 major_inc = (dib->stride * params->y_inc) / 4;
479 minor_inc = params->x_inc;
482 while (len--)
484 do_rop_32( ptr, and, xor );
485 if (err + params->bias > 0)
487 ptr += minor_inc;
488 err += params->err_add_1;
490 else err += params->err_add_2;
491 ptr += major_inc;
495 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
496 DWORD and, DWORD xor)
498 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
499 int len = params->length, err = params->err_start;
500 int major_inc, minor_inc;
502 if (params->x_major)
504 major_inc = params->x_inc * 3;
505 minor_inc = dib->stride * params->y_inc;
507 else
509 major_inc = dib->stride * params->y_inc;
510 minor_inc = params->x_inc * 3;
513 while (len--)
515 do_rop_8( ptr, and, xor );
516 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
517 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
518 if (err + params->bias > 0)
520 ptr += minor_inc;
521 err += params->err_add_1;
523 else err += params->err_add_2;
524 ptr += major_inc;
528 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
529 DWORD and, DWORD xor)
531 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
532 int len = params->length, err = params->err_start;
533 int major_inc, minor_inc;
535 if (params->x_major)
537 major_inc = params->x_inc;
538 minor_inc = (dib->stride * params->y_inc) / 2;
540 else
542 major_inc = (dib->stride * params->y_inc) / 2;
543 minor_inc = params->x_inc;
546 while (len--)
548 do_rop_16( ptr, and, xor );
549 if (err + params->bias > 0)
551 ptr += minor_inc;
552 err += params->err_add_1;
554 else err += params->err_add_2;
555 ptr += major_inc;
559 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
560 DWORD and, DWORD xor)
562 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
563 int len = params->length, err = params->err_start;
564 int major_inc, minor_inc;
566 if (params->x_major)
568 major_inc = params->x_inc;
569 minor_inc = dib->stride * params->y_inc;
571 else
573 major_inc = dib->stride * params->y_inc;
574 minor_inc = params->x_inc;
577 while (len--)
579 do_rop_8( ptr, and, xor );
580 if (err + params->bias > 0)
582 ptr += minor_inc;
583 err += params->err_add_1;
585 else err += params->err_add_2;
586 ptr += major_inc;
590 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
591 DWORD and, DWORD xor)
593 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
594 int len = params->length, err = params->err_start;
595 int x = dib->rect.left + start->x;
597 and = (and & 0x0f) | ((and << 4) & 0xf0);
598 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
600 if (params->x_major)
602 while (len--)
604 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
605 if (err + params->bias > 0)
607 ptr += dib->stride * params->y_inc;
608 err += params->err_add_1;
610 else err += params->err_add_2;
611 if ((x / 2) != ((x + params->x_inc) / 2))
612 ptr += params->x_inc;
613 x += params->x_inc;
616 else
618 while (len--)
620 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
621 if (err + params->bias > 0)
623 if ((x / 2) != ((x + params->x_inc) / 2))
624 ptr += params->x_inc;
625 x += params->x_inc;
626 err += params->err_add_1;
628 else err += params->err_add_2;
629 ptr += dib->stride * params->y_inc;
634 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
635 DWORD and, DWORD xor)
637 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
638 int len = params->length, err = params->err_start;
639 int x = dib->rect.left + start->x;
641 and = (and & 0x1) ? 0xff : 0;
642 xor = (xor & 0x1) ? 0xff : 0;
644 if (params->x_major)
646 while (len--)
648 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
649 if (err + params->bias > 0)
651 ptr += dib->stride * params->y_inc;
652 err += params->err_add_1;
654 else err += params->err_add_2;
655 if ((x / 8) != ((x + params->x_inc) / 8))
656 ptr += params->x_inc;
657 x += params->x_inc;
660 else
662 while (len--)
664 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
665 if (err + params->bias > 0)
667 if ((x / 8) != ((x + params->x_inc) / 8))
668 ptr += params->x_inc;
669 x += params->x_inc;
670 err += params->err_add_1;
672 else err += params->err_add_2;
673 ptr += dib->stride * params->y_inc;
678 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
679 DWORD and, DWORD xor)
681 return;
684 static inline INT calc_offset(INT edge, INT size, INT origin)
686 INT offset;
688 if(edge - origin >= 0)
689 offset = (edge - origin) % size;
690 else
692 offset = (origin - edge) % size;
693 if(offset) offset = size - offset;
695 return offset;
698 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
700 POINT offset;
702 offset.x = calc_offset(rc->left, brush->width, origin->x);
703 offset.y = calc_offset(rc->top, brush->height, origin->y);
705 return offset;
708 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
709 const dib_info *brush, const rop_mask_bits *bits)
711 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
712 int x, y, i;
713 POINT offset;
715 for(i = 0; i < num; i++, rc++)
717 offset = calc_brush_offset(rc, brush, origin);
719 start = get_pixel_ptr_32(dib, rc->left, rc->top);
720 start_and = (DWORD*)bits->and + offset.y * brush->stride / 4;
721 start_xor = (DWORD*)bits->xor + offset.y * brush->stride / 4;
723 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
725 and_ptr = start_and + offset.x;
726 xor_ptr = start_xor + offset.x;
728 for(x = rc->left, ptr = start; x < rc->right; x++)
730 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
731 if(and_ptr == start_and + brush->width)
733 and_ptr = start_and;
734 xor_ptr = start_xor;
738 offset.y++;
739 if(offset.y == brush->height)
741 start_and = bits->and;
742 start_xor = bits->xor;
743 offset.y = 0;
745 else
747 start_and += brush->stride / 4;
748 start_xor += brush->stride / 4;
754 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
755 const dib_info *brush, const rop_mask_bits *bits)
757 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
758 int x, y, i;
759 POINT offset;
761 for(i = 0; i < num; i++, rc++)
763 offset = calc_brush_offset(rc, brush, origin);
765 start = get_pixel_ptr_24(dib, rc->left, rc->top);
766 start_and = (BYTE*)bits->and + offset.y * brush->stride;
767 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
769 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
771 and_ptr = start_and + offset.x * 3;
772 xor_ptr = start_xor + offset.x * 3;
774 for(x = rc->left, ptr = start; x < rc->right; x++)
776 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
777 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
778 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
779 if(and_ptr == start_and + brush->width * 3)
781 and_ptr = start_and;
782 xor_ptr = start_xor;
786 offset.y++;
787 if(offset.y == brush->height)
789 start_and = bits->and;
790 start_xor = bits->xor;
791 offset.y = 0;
793 else
795 start_and += brush->stride;
796 start_xor += brush->stride;
802 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
803 const dib_info *brush, const rop_mask_bits *bits)
805 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
806 int x, y, i;
807 POINT offset;
809 for(i = 0; i < num; i++, rc++)
811 offset = calc_brush_offset(rc, brush, origin);
813 start = get_pixel_ptr_16(dib, rc->left, rc->top);
814 start_and = (WORD*)bits->and + offset.y * brush->stride / 2;
815 start_xor = (WORD*)bits->xor + offset.y * brush->stride / 2;
817 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
819 and_ptr = start_and + offset.x;
820 xor_ptr = start_xor + offset.x;
822 for(x = rc->left, ptr = start; x < rc->right; x++)
824 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
825 if(and_ptr == start_and + brush->width)
827 and_ptr = start_and;
828 xor_ptr = start_xor;
832 offset.y++;
833 if(offset.y == brush->height)
835 start_and = bits->and;
836 start_xor = bits->xor;
837 offset.y = 0;
839 else
841 start_and += brush->stride / 2;
842 start_xor += brush->stride / 2;
848 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
849 const dib_info *brush, const rop_mask_bits *bits)
851 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
852 int x, y, i;
853 POINT offset;
855 for(i = 0; i < num; i++, rc++)
857 offset = calc_brush_offset(rc, brush, origin);
859 start = get_pixel_ptr_8(dib, rc->left, rc->top);
860 start_and = (BYTE*)bits->and + offset.y * brush->stride;
861 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
863 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
865 and_ptr = start_and + offset.x;
866 xor_ptr = start_xor + offset.x;
868 for(x = rc->left, ptr = start; x < rc->right; x++)
870 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
871 if(and_ptr == start_and + brush->width)
873 and_ptr = start_and;
874 xor_ptr = start_xor;
878 offset.y++;
879 if(offset.y == brush->height)
881 start_and = bits->and;
882 start_xor = bits->xor;
883 offset.y = 0;
885 else
887 start_and += brush->stride;
888 start_xor += brush->stride;
894 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
895 const dib_info *brush, const rop_mask_bits *bits)
897 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
898 int x, y, i, left, right;
899 POINT offset;
901 for(i = 0; i < num; i++, rc++)
903 offset = calc_brush_offset(rc, brush, origin);
904 left = dib->rect.left + rc->left;
905 right = dib->rect.left + rc->right;
907 start = get_pixel_ptr_4(dib, rc->left, rc->top);
908 start_and = (BYTE*)bits->and + offset.y * brush->stride;
909 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
911 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
913 INT brush_x = offset.x;
914 BYTE byte_and, byte_xor;
916 and_ptr = start_and + brush_x / 2;
917 xor_ptr = start_xor + brush_x / 2;
919 for(x = left, ptr = start; x < right; x++)
921 /* FIXME: Two pixels at a time */
922 if(x & 1) /* lower dst nibble */
924 if(brush_x & 1) /* lower pat nibble */
926 byte_and = *and_ptr++ | 0xf0;
927 byte_xor = *xor_ptr++ & 0x0f;
929 else /* upper pat nibble */
931 byte_and = (*and_ptr >> 4) | 0xf0;
932 byte_xor = (*xor_ptr >> 4) & 0x0f;
935 else /* upper dst nibble */
937 if(brush_x & 1) /* lower pat nibble */
939 byte_and = (*and_ptr++ << 4) | 0x0f;
940 byte_xor = (*xor_ptr++ << 4) & 0xf0;
942 else /* upper pat nibble */
944 byte_and = *and_ptr | 0x0f;
945 byte_xor = *xor_ptr & 0xf0;
948 do_rop_8(ptr, byte_and, byte_xor);
950 if(x & 1) ptr++;
952 if(++brush_x == brush->width)
954 brush_x = 0;
955 and_ptr = start_and;
956 xor_ptr = start_xor;
960 offset.y++;
961 if(offset.y == brush->height)
963 start_and = bits->and;
964 start_xor = bits->xor;
965 offset.y = 0;
967 else
969 start_and += brush->stride;
970 start_xor += brush->stride;
976 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
977 const dib_info *brush, const rop_mask_bits *bits)
979 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
980 int x, y, i, left, right;
981 POINT offset;
983 for(i = 0; i < num; i++, rc++)
985 offset = calc_brush_offset(rc, brush, origin);
986 left = dib->rect.left + rc->left;
987 right = dib->rect.left + rc->right;
989 start = get_pixel_ptr_1(dib, rc->left, rc->top);
990 start_and = (BYTE*)bits->and + offset.y * brush->stride;
991 start_xor = (BYTE*)bits->xor + offset.y * brush->stride;
993 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
995 INT brush_x = offset.x;
996 BYTE byte_and, byte_xor;
998 and_ptr = start_and + brush_x / 8;
999 xor_ptr = start_xor + brush_x / 8;
1001 for(x = left, ptr = start; x < right; x++)
1003 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1004 byte_and |= ~pixel_masks_1[x % 8];
1005 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
1006 byte_xor &= pixel_masks_1[x % 8];
1008 do_rop_8(ptr, byte_and, byte_xor);
1010 if((x & 7) == 7) ptr++;
1012 if((brush_x & 7) == 7)
1014 and_ptr++;
1015 xor_ptr++;
1018 if(++brush_x == brush->width)
1020 brush_x = 0;
1021 and_ptr = start_and;
1022 xor_ptr = start_xor;
1026 offset.y++;
1027 if(offset.y == brush->height)
1029 start_and = bits->and;
1030 start_xor = bits->xor;
1031 offset.y = 0;
1033 else
1035 start_and += brush->stride;
1036 start_xor += brush->stride;
1042 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1043 const dib_info *brush, const rop_mask_bits *bits)
1045 return;
1048 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1049 const dib_info *src, const POINT *origin, int rop2, int overlap)
1051 DWORD *dst_start, *src_start;
1052 struct rop_codes codes;
1053 int y, dst_stride, src_stride;
1055 if (overlap & OVERLAP_BELOW)
1057 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1058 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1059 dst_stride = -dst->stride / 4;
1060 src_stride = -src->stride / 4;
1062 else
1064 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1065 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1066 dst_stride = dst->stride / 4;
1067 src_stride = src->stride / 4;
1070 if (rop2 == R2_COPYPEN)
1072 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1073 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1074 return;
1077 get_rop_codes( rop2, &codes );
1078 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1080 if (overlap & OVERLAP_RIGHT)
1081 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1082 else
1083 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1087 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1088 const dib_info *src, const POINT *origin, int rop2, int overlap)
1090 BYTE *dst_start, *src_start;
1091 int y, dst_stride, src_stride;
1092 struct rop_codes codes;
1094 if (overlap & OVERLAP_BELOW)
1096 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1097 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1098 dst_stride = -dst->stride;
1099 src_stride = -src->stride;
1101 else
1103 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1104 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1105 dst_stride = dst->stride;
1106 src_stride = src->stride;
1109 if (rop2 == R2_COPYPEN)
1111 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1112 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1113 return;
1116 get_rop_codes( rop2, &codes );
1117 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1119 if (overlap & OVERLAP_RIGHT)
1120 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1121 else
1122 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1126 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1127 const dib_info *src, const POINT *origin, int rop2, int overlap)
1129 WORD *dst_start, *src_start;
1130 int y, dst_stride, src_stride;
1131 struct rop_codes codes;
1133 if (overlap & OVERLAP_BELOW)
1135 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1136 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1137 dst_stride = -dst->stride / 2;
1138 src_stride = -src->stride / 2;
1140 else
1142 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1143 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1144 dst_stride = dst->stride / 2;
1145 src_stride = src->stride / 2;
1148 if (rop2 == R2_COPYPEN)
1150 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1151 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1152 return;
1155 get_rop_codes( rop2, &codes );
1156 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1158 if (overlap & OVERLAP_RIGHT)
1159 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1160 else
1161 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1165 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1166 const dib_info *src, const POINT *origin, int rop2, int overlap)
1168 BYTE *dst_start, *src_start;
1169 int y, dst_stride, src_stride;
1170 struct rop_codes codes;
1172 if (overlap & OVERLAP_BELOW)
1174 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1175 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1176 dst_stride = -dst->stride;
1177 src_stride = -src->stride;
1179 else
1181 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1182 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1183 dst_stride = dst->stride;
1184 src_stride = src->stride;
1187 if (rop2 == R2_COPYPEN)
1189 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1190 memmove( dst_start, src_start, (rc->right - rc->left) );
1191 return;
1194 get_rop_codes( rop2, &codes );
1195 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1197 if (overlap & OVERLAP_RIGHT)
1198 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1199 else
1200 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1204 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1205 const dib_info *src, const POINT *origin, int rop2, int overlap)
1207 BYTE *dst_start, *src_start;
1208 int y, dst_stride, src_stride;
1209 struct rop_codes codes;
1210 int left = dst->rect.left + rc->left;
1211 int right = dst->rect.left + rc->right;
1212 int org_x = src->rect.left + origin->x;
1214 if (overlap & OVERLAP_BELOW)
1216 dst_start = get_pixel_ptr_4(dst, rc->left, rc->bottom - 1);
1217 src_start = get_pixel_ptr_4(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1218 dst_stride = -dst->stride;
1219 src_stride = -src->stride;
1221 else
1223 dst_start = get_pixel_ptr_4(dst, rc->left, rc->top);
1224 src_start = get_pixel_ptr_4(src, origin->x, origin->y);
1225 dst_stride = dst->stride;
1226 src_stride = src->stride;
1229 if (rop2 == R2_COPYPEN && (left & 1) == 0 && (org_x & 1) == 0 && (right & 1) == 0)
1231 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1232 memmove( dst_start, src_start, (right - left) / 2 );
1233 return;
1236 get_rop_codes( rop2, &codes );
1237 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1239 if (overlap & OVERLAP_RIGHT)
1240 do_rop_codes_line_rev_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1241 else
1242 do_rop_codes_line_4( dst_start, left & 1, src_start, org_x & 1, &codes, right - left );
1246 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1247 const dib_info *src, const POINT *origin, int rop2, int overlap)
1249 BYTE *dst_start, *src_start;
1250 int y, dst_stride, src_stride;
1251 struct rop_codes codes;
1252 int left = dst->rect.left + rc->left;
1253 int right = dst->rect.left + rc->right;
1254 int org_x = src->rect.left + origin->x;
1256 if (overlap & OVERLAP_BELOW)
1258 dst_start = get_pixel_ptr_1(dst, rc->left, rc->bottom - 1);
1259 src_start = get_pixel_ptr_1(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1260 dst_stride = -dst->stride;
1261 src_stride = -src->stride;
1263 else
1265 dst_start = get_pixel_ptr_1(dst, rc->left, rc->top);
1266 src_start = get_pixel_ptr_1(src, origin->x, origin->y);
1267 dst_stride = dst->stride;
1268 src_stride = src->stride;
1271 if (rop2 == R2_COPYPEN && (left & 7) == 0 && (org_x & 7) == 0 && (right & 7) == 0)
1273 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1274 memmove( dst_start, src_start, (right - left) / 8 );
1275 return;
1278 get_rop_codes( rop2, &codes );
1279 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1281 if (overlap & OVERLAP_RIGHT)
1282 do_rop_codes_line_rev_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1283 else
1284 do_rop_codes_line_1( dst_start, left & 7, src_start, org_x & 7, &codes, right - left );
1288 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1289 const dib_info *src, const POINT *origin, int rop2, int overlap)
1291 return;
1294 static DWORD get_pixel_32(const dib_info *dib, int x, int y)
1296 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1297 return *ptr;
1300 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1302 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1303 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1306 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1308 WORD *ptr = get_pixel_ptr_16( dib, x, y );
1309 return *ptr;
1312 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1314 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1315 return *ptr;
1318 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1320 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1322 if ((dib->rect.left + x) & 1)
1323 return *ptr & 0x0f;
1324 else
1325 return (*ptr >> 4) & 0x0f;
1328 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1330 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1331 return (*ptr & pixel_masks_1[(dib->rect.left + x) & 7]) ? 1 : 0;
1334 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
1336 return 0;
1339 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1341 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1344 static const DWORD field_masks[33] =
1346 0x00, /* should never happen */
1347 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1348 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1349 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1350 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1353 static inline DWORD get_field(DWORD field, int shift, int len)
1355 shift = shift - (8 - len);
1356 if (shift < 0)
1357 field <<= -shift;
1358 else
1359 field >>= shift;
1360 field &= field_masks[len];
1361 field |= field >> len;
1362 return field;
1365 static inline DWORD put_field(DWORD field, int shift, int len)
1367 shift = shift - (8 - len);
1368 field &= field_masks[len];
1369 if (shift < 0)
1370 field >>= -shift;
1371 else
1372 field <<= shift;
1373 return field;
1376 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1378 DWORD r,g,b;
1380 r = GetRValue(colour);
1381 g = GetGValue(colour);
1382 b = GetBValue(colour);
1384 return put_field(r, dib->red_shift, dib->red_len) |
1385 put_field(g, dib->green_shift, dib->green_len) |
1386 put_field(b, dib->blue_shift, dib->blue_len);
1389 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1391 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1394 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1396 const RGBQUAD *color_table = get_dib_color_table( dib );
1397 int size = dib->color_table ? dib->color_table_size : 1 << dib->bit_count;
1398 int i, best_index = 0;
1399 DWORD diff, best_diff = 0xffffffff;
1401 /* special case for conversion to 1-bpp without a color table:
1402 * we get a 1-entry table containing the background color
1404 if (dib->bit_count == 1 && size == 1)
1405 return (r == color_table[0].rgbRed &&
1406 g == color_table[0].rgbGreen &&
1407 b == color_table[0].rgbBlue);
1409 for(i = 0; i < size; i++)
1411 const RGBQUAD *cur = color_table + i;
1412 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1413 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1414 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1416 if(diff == 0)
1418 best_index = i;
1419 break;
1422 if(diff < best_diff)
1424 best_diff = diff;
1425 best_index = i;
1428 return best_index;
1431 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, BYTE r, BYTE g, BYTE b)
1433 DWORD ret;
1435 if (!dither)
1436 ret = rgb_to_pixel_colortable( dib, r, g, b );
1437 else
1438 ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255;
1440 return ret ? 0xff : 0;
1443 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1445 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1448 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1450 return 0;
1453 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1455 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1458 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1460 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1461 get_field( pixel, dib->green_shift, dib->green_len ),
1462 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1465 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1467 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1468 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1469 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1472 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1474 const RGBQUAD *color_table = get_dib_color_table( dib );
1476 if (!dib->color_table || pixel < dib->color_table_size)
1478 RGBQUAD quad = color_table[pixel];
1479 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1481 return 0;
1484 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1486 return 0;
1489 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1491 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1493 return d1->red_mask == d2->red_mask &&
1494 d1->green_mask == d2->green_mask &&
1495 d1->blue_mask == d2->blue_mask;
1498 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1500 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1501 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1503 switch(src->bit_count)
1505 case 32:
1507 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1508 if(src->funcs == &funcs_8888)
1510 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1511 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1512 else
1514 for(y = src_rect->top; y < src_rect->bottom; y++)
1516 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1517 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1518 dst_start += dst->stride / 4;
1519 src_start += src->stride / 4;
1523 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1525 for(y = src_rect->top; y < src_rect->bottom; y++)
1527 dst_pixel = dst_start;
1528 src_pixel = src_start;
1529 for(x = src_rect->left; x < src_rect->right; x++)
1531 src_val = *src_pixel++;
1532 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1533 (((src_val >> src->green_shift) & 0xff) << 8) |
1534 ((src_val >> src->blue_shift) & 0xff);
1536 if(pad_size) memset(dst_pixel, 0, pad_size);
1537 dst_start += dst->stride / 4;
1538 src_start += src->stride / 4;
1541 else
1543 for(y = src_rect->top; y < src_rect->bottom; y++)
1545 dst_pixel = dst_start;
1546 src_pixel = src_start;
1547 for(x = src_rect->left; x < src_rect->right; x++)
1549 src_val = *src_pixel++;
1550 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1551 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1552 get_field( src_val, src->blue_shift, src->blue_len ));
1554 if(pad_size) memset(dst_pixel, 0, pad_size);
1555 dst_start += dst->stride / 4;
1556 src_start += src->stride / 4;
1559 break;
1562 case 24:
1564 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1566 for(y = src_rect->top; y < src_rect->bottom; y++)
1568 dst_pixel = dst_start;
1569 src_pixel = src_start;
1570 for(x = src_rect->left; x < src_rect->right; x++)
1572 RGBQUAD rgb;
1573 rgb.rgbBlue = *src_pixel++;
1574 rgb.rgbGreen = *src_pixel++;
1575 rgb.rgbRed = *src_pixel++;
1577 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1579 if(pad_size) memset(dst_pixel, 0, pad_size);
1580 dst_start += dst->stride / 4;
1581 src_start += src->stride;
1583 break;
1586 case 16:
1588 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1589 if(src->funcs == &funcs_555)
1591 for(y = src_rect->top; y < src_rect->bottom; y++)
1593 dst_pixel = dst_start;
1594 src_pixel = src_start;
1595 for(x = src_rect->left; x < src_rect->right; x++)
1597 src_val = *src_pixel++;
1598 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1599 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1600 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1602 if(pad_size) memset(dst_pixel, 0, pad_size);
1603 dst_start += dst->stride / 4;
1604 src_start += src->stride / 2;
1607 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1609 for(y = src_rect->top; y < src_rect->bottom; y++)
1611 dst_pixel = dst_start;
1612 src_pixel = src_start;
1613 for(x = src_rect->left; x < src_rect->right; x++)
1615 src_val = *src_pixel++;
1616 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1617 (((src_val >> src->red_shift) << 14) & 0x070000) |
1618 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1619 (((src_val >> src->green_shift) << 6) & 0x000700) |
1620 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1621 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1623 if(pad_size) memset(dst_pixel, 0, pad_size);
1624 dst_start += dst->stride / 4;
1625 src_start += src->stride / 2;
1628 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1630 for(y = src_rect->top; y < src_rect->bottom; y++)
1632 dst_pixel = dst_start;
1633 src_pixel = src_start;
1634 for(x = src_rect->left; x < src_rect->right; x++)
1636 src_val = *src_pixel++;
1637 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1638 (((src_val >> src->red_shift) << 14) & 0x070000) |
1639 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1640 (((src_val >> src->green_shift) << 4) & 0x000300) |
1641 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1642 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1644 if(pad_size) memset(dst_pixel, 0, pad_size);
1645 dst_start += dst->stride / 4;
1646 src_start += src->stride / 2;
1649 else
1651 for(y = src_rect->top; y < src_rect->bottom; y++)
1653 dst_pixel = dst_start;
1654 src_pixel = src_start;
1655 for(x = src_rect->left; x < src_rect->right; x++)
1657 src_val = *src_pixel++;
1658 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1659 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1660 get_field( src_val, src->blue_shift, src->blue_len ));
1662 if(pad_size) memset(dst_pixel, 0, pad_size);
1663 dst_start += dst->stride / 4;
1664 src_start += src->stride / 2;
1667 break;
1670 case 8:
1672 const RGBQUAD *color_table = get_dib_color_table( src );
1673 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1674 for(y = src_rect->top; y < src_rect->bottom; y++)
1676 dst_pixel = dst_start;
1677 src_pixel = src_start;
1678 for(x = src_rect->left; x < src_rect->right; x++)
1680 RGBQUAD rgb = color_table[*src_pixel++];
1681 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1683 if(pad_size) memset(dst_pixel, 0, pad_size);
1684 dst_start += dst->stride / 4;
1685 src_start += src->stride;
1687 break;
1690 case 4:
1692 const RGBQUAD *color_table = get_dib_color_table( src );
1693 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1694 for(y = src_rect->top; y < src_rect->bottom; y++)
1696 int pos = (src->rect.left + src_rect->left) & 1;
1697 src_pixel = src_start;
1698 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1700 RGBQUAD rgb;
1701 if (pos & 1)
1702 rgb = color_table[*src_pixel++ & 0xf];
1703 else
1704 rgb = color_table[*src_pixel >> 4];
1705 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1707 if(pad_size) memset(dst_start + x, 0, pad_size);
1708 dst_start += dst->stride / 4;
1709 src_start += src->stride;
1711 break;
1714 case 1:
1716 const RGBQUAD *color_table = get_dib_color_table( src );
1717 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1718 for(y = src_rect->top; y < src_rect->bottom; y++)
1720 int pos = (src->rect.left + src_rect->left) & 7;
1721 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1723 RGBQUAD rgb;
1724 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1725 rgb = color_table[src_val];
1726 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1728 if(pad_size) memset(dst_start + x, 0, pad_size);
1729 dst_start += dst->stride / 4;
1730 src_start += src->stride;
1732 break;
1737 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1739 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1740 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1742 switch(src->bit_count)
1744 case 32:
1746 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1748 if(src->funcs == &funcs_8888)
1750 for(y = src_rect->top; y < src_rect->bottom; y++)
1752 dst_pixel = dst_start;
1753 src_pixel = src_start;
1754 for(x = src_rect->left; x < src_rect->right; x++)
1756 src_val = *src_pixel++;
1757 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1758 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1759 put_field(src_val, dst->blue_shift, dst->blue_len);
1761 if(pad_size) memset(dst_pixel, 0, pad_size);
1762 dst_start += dst->stride / 4;
1763 src_start += src->stride / 4;
1766 else if(bit_fields_match(src, dst))
1768 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1769 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1770 else
1772 for(y = src_rect->top; y < src_rect->bottom; y++)
1774 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1775 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1776 dst_start += dst->stride / 4;
1777 src_start += src->stride / 4;
1781 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1782 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1784 for(y = src_rect->top; y < src_rect->bottom; y++)
1786 dst_pixel = dst_start;
1787 src_pixel = src_start;
1788 for(x = src_rect->left; x < src_rect->right; x++)
1790 src_val = *src_pixel++;
1791 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1792 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1793 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1795 if(pad_size) memset(dst_pixel, 0, pad_size);
1796 dst_start += dst->stride / 4;
1797 src_start += src->stride / 4;
1800 else
1802 for(y = src_rect->top; y < src_rect->bottom; y++)
1804 dst_pixel = dst_start;
1805 src_pixel = src_start;
1806 for(x = src_rect->left; x < src_rect->right; x++)
1808 src_val = *src_pixel++;
1809 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1810 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1811 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1813 if(pad_size) memset(dst_pixel, 0, pad_size);
1814 dst_start += dst->stride / 4;
1815 src_start += src->stride / 4;
1818 break;
1821 case 24:
1823 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1825 for(y = src_rect->top; y < src_rect->bottom; y++)
1827 dst_pixel = dst_start;
1828 src_pixel = src_start;
1829 for(x = src_rect->left; x < src_rect->right; x++)
1831 RGBQUAD rgb;
1832 rgb.rgbBlue = *src_pixel++;
1833 rgb.rgbGreen = *src_pixel++;
1834 rgb.rgbRed = *src_pixel++;
1836 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1837 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1838 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1840 if(pad_size) memset(dst_pixel, 0, pad_size);
1841 dst_start += dst->stride / 4;
1842 src_start += src->stride;
1844 break;
1847 case 16:
1849 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1850 if(src->funcs == &funcs_555)
1852 for(y = src_rect->top; y < src_rect->bottom; y++)
1854 dst_pixel = dst_start;
1855 src_pixel = src_start;
1856 for(x = src_rect->left; x < src_rect->right; x++)
1858 src_val = *src_pixel++;
1859 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1860 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1861 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1863 if(pad_size) memset(dst_pixel, 0, pad_size);
1864 dst_start += dst->stride / 4;
1865 src_start += src->stride / 2;
1868 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1870 for(y = src_rect->top; y < src_rect->bottom; y++)
1872 dst_pixel = dst_start;
1873 src_pixel = src_start;
1874 for(x = src_rect->left; x < src_rect->right; x++)
1876 src_val = *src_pixel++;
1877 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1878 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1879 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1880 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1881 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1882 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1884 if(pad_size) memset(dst_pixel, 0, pad_size);
1885 dst_start += dst->stride / 4;
1886 src_start += src->stride / 2;
1889 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1891 for(y = src_rect->top; y < src_rect->bottom; y++)
1893 dst_pixel = dst_start;
1894 src_pixel = src_start;
1895 for(x = src_rect->left; x < src_rect->right; x++)
1897 src_val = *src_pixel++;
1898 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1899 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1900 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1901 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1902 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1903 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1905 if(pad_size) memset(dst_pixel, 0, pad_size);
1906 dst_start += dst->stride / 4;
1907 src_start += src->stride / 2;
1910 else
1912 for(y = src_rect->top; y < src_rect->bottom; y++)
1914 dst_pixel = dst_start;
1915 src_pixel = src_start;
1916 for(x = src_rect->left; x < src_rect->right; x++)
1918 src_val = *src_pixel++;
1919 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1920 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1921 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1923 if(pad_size) memset(dst_pixel, 0, pad_size);
1924 dst_start += dst->stride / 4;
1925 src_start += src->stride / 2;
1928 break;
1931 case 8:
1933 const RGBQUAD *color_table = get_dib_color_table( src );
1934 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1935 for(y = src_rect->top; y < src_rect->bottom; y++)
1937 dst_pixel = dst_start;
1938 src_pixel = src_start;
1939 for(x = src_rect->left; x < src_rect->right; x++)
1941 RGBQUAD rgb = color_table[*src_pixel++];
1942 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1943 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1944 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1946 if(pad_size) memset(dst_pixel, 0, pad_size);
1947 dst_start += dst->stride / 4;
1948 src_start += src->stride;
1950 break;
1953 case 4:
1955 const RGBQUAD *color_table = get_dib_color_table( src );
1956 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1957 for(y = src_rect->top; y < src_rect->bottom; y++)
1959 int pos = (src->rect.left + src_rect->left) & 1;
1960 src_pixel = src_start;
1961 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1963 RGBQUAD rgb;
1964 if (pos & 1)
1965 rgb = color_table[*src_pixel++ & 0xf];
1966 else
1967 rgb = color_table[*src_pixel >> 4];
1968 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1969 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1970 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1972 if(pad_size) memset(dst_start + x, 0, pad_size);
1973 dst_start += dst->stride / 4;
1974 src_start += src->stride;
1976 break;
1979 case 1:
1981 const RGBQUAD *color_table = get_dib_color_table( src );
1982 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1983 for(y = src_rect->top; y < src_rect->bottom; y++)
1985 int pos = (src->rect.left + src_rect->left) & 7;
1986 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1988 RGBQUAD rgb;
1989 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1990 rgb = color_table[src_val];
1991 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1992 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1993 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1995 if(pad_size) memset(dst_start + x, 0, pad_size);
1996 dst_start += dst->stride / 4;
1997 src_start += src->stride;
1999 break;
2004 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2006 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
2007 DWORD src_val;
2008 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2010 switch(src->bit_count)
2012 case 32:
2014 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2015 if(src->funcs == &funcs_8888)
2017 for(y = src_rect->top; y < src_rect->bottom; y++)
2019 dst_pixel = dst_start;
2020 src_pixel = src_start;
2021 for(x = src_rect->left; x < src_rect->right; x++)
2023 src_val = *src_pixel++;
2024 *dst_pixel++ = src_val & 0xff;
2025 *dst_pixel++ = (src_val >> 8) & 0xff;
2026 *dst_pixel++ = (src_val >> 16) & 0xff;
2028 if(pad_size) memset(dst_pixel, 0, pad_size);
2029 dst_start += dst->stride;
2030 src_start += src->stride / 4;
2033 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2035 for(y = src_rect->top; y < src_rect->bottom; y++)
2037 dst_pixel = dst_start;
2038 src_pixel = src_start;
2039 for(x = src_rect->left; x < src_rect->right; x++)
2041 src_val = *src_pixel++;
2042 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2043 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2044 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2046 if(pad_size) memset(dst_pixel, 0, pad_size);
2047 dst_start += dst->stride;
2048 src_start += src->stride / 4;
2051 else
2053 for(y = src_rect->top; y < src_rect->bottom; y++)
2055 dst_pixel = dst_start;
2056 src_pixel = src_start;
2057 for(x = src_rect->left; x < src_rect->right; x++)
2059 src_val = *src_pixel++;
2060 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2061 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2062 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2064 if(pad_size) memset(dst_pixel, 0, pad_size);
2065 dst_start += dst->stride;
2066 src_start += src->stride / 4;
2069 break;
2072 case 24:
2074 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2076 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2077 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2078 else
2080 for(y = src_rect->top; y < src_rect->bottom; y++)
2082 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2083 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2084 dst_start += dst->stride;
2085 src_start += src->stride;
2088 break;
2091 case 16:
2093 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2094 if(src->funcs == &funcs_555)
2096 for(y = src_rect->top; y < src_rect->bottom; y++)
2098 dst_pixel = dst_start;
2099 src_pixel = src_start;
2100 for(x = src_rect->left; x < src_rect->right; x++)
2102 src_val = *src_pixel++;
2103 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2104 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2105 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2107 if(pad_size) memset(dst_pixel, 0, pad_size);
2108 dst_start += dst->stride;
2109 src_start += src->stride / 2;
2112 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2114 for(y = src_rect->top; y < src_rect->bottom; y++)
2116 dst_pixel = dst_start;
2117 src_pixel = src_start;
2118 for(x = src_rect->left; x < src_rect->right; x++)
2120 src_val = *src_pixel++;
2121 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2122 (((src_val >> src->blue_shift) >> 2) & 0x07);
2123 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2124 (((src_val >> src->green_shift) >> 2) & 0x07);
2125 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2126 (((src_val >> src->red_shift) >> 2) & 0x07);
2128 if(pad_size) memset(dst_pixel, 0, pad_size);
2129 dst_start += dst->stride;
2130 src_start += src->stride / 2;
2133 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2135 for(y = src_rect->top; y < src_rect->bottom; y++)
2137 dst_pixel = dst_start;
2138 src_pixel = src_start;
2139 for(x = src_rect->left; x < src_rect->right; x++)
2141 src_val = *src_pixel++;
2142 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2143 (((src_val >> src->blue_shift) >> 2) & 0x07);
2144 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2145 (((src_val >> src->green_shift) >> 4) & 0x03);
2146 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2147 (((src_val >> src->red_shift) >> 2) & 0x07);
2149 if(pad_size) memset(dst_pixel, 0, pad_size);
2150 dst_start += dst->stride;
2151 src_start += src->stride / 2;
2154 else
2156 for(y = src_rect->top; y < src_rect->bottom; y++)
2158 dst_pixel = dst_start;
2159 src_pixel = src_start;
2160 for(x = src_rect->left; x < src_rect->right; x++)
2162 src_val = *src_pixel++;
2163 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2164 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2165 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2167 if(pad_size) memset(dst_pixel, 0, pad_size);
2168 dst_start += dst->stride;
2169 src_start += src->stride / 2;
2172 break;
2175 case 8:
2177 const RGBQUAD *color_table = get_dib_color_table( src );
2178 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2179 for(y = src_rect->top; y < src_rect->bottom; y++)
2181 dst_pixel = dst_start;
2182 src_pixel = src_start;
2183 for(x = src_rect->left; x < src_rect->right; x++)
2185 RGBQUAD rgb = color_table[*src_pixel++];
2186 *dst_pixel++ = rgb.rgbBlue;
2187 *dst_pixel++ = rgb.rgbGreen;
2188 *dst_pixel++ = rgb.rgbRed;
2190 if(pad_size) memset(dst_pixel, 0, pad_size);
2191 dst_start += dst->stride;
2192 src_start += src->stride;
2194 break;
2197 case 4:
2199 const RGBQUAD *color_table = get_dib_color_table( src );
2200 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2201 for(y = src_rect->top; y < src_rect->bottom; y++)
2203 int pos = (src->rect.left + src_rect->left) & 1;
2204 src_pixel = src_start;
2205 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2207 RGBQUAD rgb;
2208 if (pos & 1)
2209 rgb = color_table[*src_pixel++ & 0xf];
2210 else
2211 rgb = color_table[*src_pixel >> 4];
2212 dst_start[x * 3] = rgb.rgbBlue;
2213 dst_start[x * 3 + 1] = rgb.rgbGreen;
2214 dst_start[x * 3 + 2] = rgb.rgbRed;
2216 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2217 dst_start += dst->stride;
2218 src_start += src->stride;
2220 break;
2223 case 1:
2225 const RGBQUAD *color_table = get_dib_color_table( src );
2226 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2227 for(y = src_rect->top; y < src_rect->bottom; y++)
2229 int pos = (src->rect.left + src_rect->left) & 7;
2230 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2232 RGBQUAD rgb;
2233 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2234 rgb = color_table[src_val];
2235 dst_start[x * 3] = rgb.rgbBlue;
2236 dst_start[x * 3 + 1] = rgb.rgbGreen;
2237 dst_start[x * 3 + 2] = rgb.rgbRed;
2239 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2240 dst_start += dst->stride;
2241 src_start += src->stride;
2243 break;
2248 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2250 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2251 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2252 DWORD src_val;
2254 switch(src->bit_count)
2256 case 32:
2258 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2260 if(src->funcs == &funcs_8888)
2262 for(y = src_rect->top; y < src_rect->bottom; y++)
2264 dst_pixel = dst_start;
2265 src_pixel = src_start;
2266 for(x = src_rect->left; x < src_rect->right; x++)
2268 src_val = *src_pixel++;
2269 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2270 ((src_val >> 6) & 0x03e0) |
2271 ((src_val >> 3) & 0x001f);
2273 if(pad_size) memset(dst_pixel, 0, pad_size);
2274 dst_start += dst->stride / 2;
2275 src_start += src->stride / 4;
2278 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2280 for(y = src_rect->top; y < src_rect->bottom; y++)
2282 dst_pixel = dst_start;
2283 src_pixel = src_start;
2284 for(x = src_rect->left; x < src_rect->right; x++)
2286 src_val = *src_pixel++;
2287 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2288 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2289 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2291 if(pad_size) memset(dst_pixel, 0, pad_size);
2292 dst_start += dst->stride / 2;
2293 src_start += src->stride / 4;
2296 else
2298 for(y = src_rect->top; y < src_rect->bottom; y++)
2300 dst_pixel = dst_start;
2301 src_pixel = src_start;
2302 for(x = src_rect->left; x < src_rect->right; x++)
2304 src_val = *src_pixel++;
2305 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2306 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2307 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2309 if(pad_size) memset(dst_pixel, 0, pad_size);
2310 dst_start += dst->stride / 2;
2311 src_start += src->stride / 4;
2314 break;
2317 case 24:
2319 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2321 for(y = src_rect->top; y < src_rect->bottom; y++)
2323 dst_pixel = dst_start;
2324 src_pixel = src_start;
2325 for(x = src_rect->left; x < src_rect->right; x++)
2327 RGBQUAD rgb;
2328 rgb.rgbBlue = *src_pixel++;
2329 rgb.rgbGreen = *src_pixel++;
2330 rgb.rgbRed = *src_pixel++;
2332 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2333 ((rgb.rgbGreen << 2) & 0x03e0) |
2334 ((rgb.rgbBlue >> 3) & 0x001f);
2336 if(pad_size) memset(dst_pixel, 0, pad_size);
2337 dst_start += dst->stride / 2;
2338 src_start += src->stride;
2340 break;
2343 case 16:
2345 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2346 if(src->funcs == &funcs_555)
2348 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2349 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2350 else
2352 for(y = src_rect->top; y < src_rect->bottom; y++)
2354 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2355 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2356 dst_start += dst->stride / 2;
2357 src_start += src->stride / 2;
2361 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2363 for(y = src_rect->top; y < src_rect->bottom; y++)
2365 dst_pixel = dst_start;
2366 src_pixel = src_start;
2367 for(x = src_rect->left; x < src_rect->right; x++)
2369 src_val = *src_pixel++;
2370 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2371 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2372 ( (src_val >> src->blue_shift) & 0x001f);
2374 if(pad_size) memset(dst_pixel, 0, pad_size);
2375 dst_start += dst->stride / 2;
2376 src_start += src->stride / 2;
2379 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2381 for(y = src_rect->top; y < src_rect->bottom; y++)
2383 dst_pixel = dst_start;
2384 src_pixel = src_start;
2385 for(x = src_rect->left; x < src_rect->right; x++)
2387 src_val = *src_pixel++;
2388 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2389 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2390 ( (src_val >> src->blue_shift) & 0x001f);
2392 if(pad_size) memset(dst_pixel, 0, pad_size);
2393 dst_start += dst->stride / 2;
2394 src_start += src->stride / 2;
2397 else
2399 for(y = src_rect->top; y < src_rect->bottom; y++)
2401 dst_pixel = dst_start;
2402 src_pixel = src_start;
2403 for(x = src_rect->left; x < src_rect->right; x++)
2405 src_val = *src_pixel++;
2406 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2407 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2408 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2410 if(pad_size) memset(dst_pixel, 0, pad_size);
2411 dst_start += dst->stride / 2;
2412 src_start += src->stride / 2;
2415 break;
2418 case 8:
2420 const RGBQUAD *color_table = get_dib_color_table( src );
2421 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2422 for(y = src_rect->top; y < src_rect->bottom; y++)
2424 dst_pixel = dst_start;
2425 src_pixel = src_start;
2426 for(x = src_rect->left; x < src_rect->right; x++)
2428 RGBQUAD rgb = color_table[*src_pixel++];
2429 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2430 ((rgb.rgbGreen << 2) & 0x03e0) |
2431 ((rgb.rgbBlue >> 3) & 0x001f);
2433 if(pad_size) memset(dst_pixel, 0, pad_size);
2434 dst_start += dst->stride / 2;
2435 src_start += src->stride;
2437 break;
2440 case 4:
2442 const RGBQUAD *color_table = get_dib_color_table( src );
2443 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2444 for(y = src_rect->top; y < src_rect->bottom; y++)
2446 int pos = (src->rect.left + src_rect->left) & 1;
2447 src_pixel = src_start;
2448 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2450 RGBQUAD rgb;
2451 if (pos & 1)
2452 rgb = color_table[*src_pixel++ & 0xf];
2453 else
2454 rgb = color_table[*src_pixel >> 4];
2455 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2456 ((rgb.rgbGreen << 2) & 0x03e0) |
2457 ((rgb.rgbBlue >> 3) & 0x001f);
2459 if(pad_size) memset(dst_start + x, 0, pad_size);
2460 dst_start += dst->stride / 2;
2461 src_start += src->stride;
2463 break;
2466 case 1:
2468 const RGBQUAD *color_table = get_dib_color_table( src );
2469 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2470 for(y = src_rect->top; y < src_rect->bottom; y++)
2472 int pos = (src->rect.left + src_rect->left) & 7;
2473 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2475 RGBQUAD rgb;
2476 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2477 rgb = color_table[src_val];
2478 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2479 ((rgb.rgbGreen << 2) & 0x03e0) |
2480 ((rgb.rgbBlue >> 3) & 0x001f);
2482 if(pad_size) memset(dst_start + x, 0, pad_size);
2483 dst_start += dst->stride / 2;
2484 src_start += src->stride;
2486 break;
2491 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2493 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2494 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2495 DWORD src_val;
2497 switch(src->bit_count)
2499 case 32:
2501 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2503 if(src->funcs == &funcs_8888)
2505 for(y = src_rect->top; y < src_rect->bottom; y++)
2507 dst_pixel = dst_start;
2508 src_pixel = src_start;
2509 for(x = src_rect->left; x < src_rect->right; x++)
2511 src_val = *src_pixel++;
2512 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2513 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2514 put_field(src_val, dst->blue_shift, dst->blue_len);
2516 if(pad_size) memset(dst_pixel, 0, pad_size);
2517 dst_start += dst->stride / 2;
2518 src_start += src->stride / 4;
2521 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2523 for(y = src_rect->top; y < src_rect->bottom; y++)
2525 dst_pixel = dst_start;
2526 src_pixel = src_start;
2527 for(x = src_rect->left; x < src_rect->right; x++)
2529 src_val = *src_pixel++;
2530 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2531 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2532 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2534 if(pad_size) memset(dst_pixel, 0, pad_size);
2535 dst_start += dst->stride / 2;
2536 src_start += src->stride / 4;
2539 else
2541 for(y = src_rect->top; y < src_rect->bottom; y++)
2543 dst_pixel = dst_start;
2544 src_pixel = src_start;
2545 for(x = src_rect->left; x < src_rect->right; x++)
2547 src_val = *src_pixel++;
2548 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2549 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2550 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2552 if(pad_size) memset(dst_pixel, 0, pad_size);
2553 dst_start += dst->stride / 2;
2554 src_start += src->stride / 4;
2557 break;
2560 case 24:
2562 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2564 for(y = src_rect->top; y < src_rect->bottom; y++)
2566 dst_pixel = dst_start;
2567 src_pixel = src_start;
2568 for(x = src_rect->left; x < src_rect->right; x++)
2570 RGBQUAD rgb;
2571 rgb.rgbBlue = *src_pixel++;
2572 rgb.rgbGreen = *src_pixel++;
2573 rgb.rgbRed = *src_pixel++;
2575 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2576 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2577 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2579 if(pad_size) memset(dst_pixel, 0, pad_size);
2580 dst_start += dst->stride / 2;
2581 src_start += src->stride;
2583 break;
2586 case 16:
2588 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2589 if(src->funcs == &funcs_555)
2591 for(y = src_rect->top; y < src_rect->bottom; y++)
2593 dst_pixel = dst_start;
2594 src_pixel = src_start;
2595 for(x = src_rect->left; x < src_rect->right; x++)
2597 src_val = *src_pixel++;
2598 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2599 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2600 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2602 if(pad_size) memset(dst_pixel, 0, pad_size);
2603 dst_start += dst->stride / 2;
2604 src_start += src->stride / 2;
2607 else if(bit_fields_match(src, dst))
2609 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2610 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2611 else
2613 for(y = src_rect->top; y < src_rect->bottom; y++)
2615 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2616 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2617 dst_start += dst->stride / 2;
2618 src_start += src->stride / 2;
2622 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2624 for(y = src_rect->top; y < src_rect->bottom; y++)
2626 dst_pixel = dst_start;
2627 src_pixel = src_start;
2628 for(x = src_rect->left; x < src_rect->right; x++)
2630 src_val = *src_pixel++;
2631 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2632 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2633 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2634 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2635 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2636 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2638 if(pad_size) memset(dst_pixel, 0, pad_size);
2639 dst_start += dst->stride / 2;
2640 src_start += src->stride / 2;
2643 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2645 for(y = src_rect->top; y < src_rect->bottom; y++)
2647 dst_pixel = dst_start;
2648 src_pixel = src_start;
2649 for(x = src_rect->left; x < src_rect->right; x++)
2651 src_val = *src_pixel++;
2652 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2653 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2654 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2655 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2656 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2657 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2659 if(pad_size) memset(dst_pixel, 0, pad_size);
2660 dst_start += dst->stride / 2;
2661 src_start += src->stride / 2;
2664 else
2666 for(y = src_rect->top; y < src_rect->bottom; y++)
2668 dst_pixel = dst_start;
2669 src_pixel = src_start;
2670 for(x = src_rect->left; x < src_rect->right; x++)
2672 src_val = *src_pixel++;
2673 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2674 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2675 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2677 if(pad_size) memset(dst_pixel, 0, pad_size);
2678 dst_start += dst->stride / 2;
2679 src_start += src->stride / 2;
2682 break;
2685 case 8:
2687 const RGBQUAD *color_table = get_dib_color_table( src );
2688 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2689 for(y = src_rect->top; y < src_rect->bottom; y++)
2691 dst_pixel = dst_start;
2692 src_pixel = src_start;
2693 for(x = src_rect->left; x < src_rect->right; x++)
2695 RGBQUAD rgb = color_table[*src_pixel++];
2696 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2697 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2698 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2700 if(pad_size) memset(dst_pixel, 0, pad_size);
2701 dst_start += dst->stride / 2;
2702 src_start += src->stride;
2704 break;
2707 case 4:
2709 const RGBQUAD *color_table = get_dib_color_table( src );
2710 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2711 for(y = src_rect->top; y < src_rect->bottom; y++)
2713 int pos = (src->rect.left + src_rect->left) & 1;
2714 src_pixel = src_start;
2715 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2717 RGBQUAD rgb;
2718 if (pos & 1)
2719 rgb = color_table[*src_pixel++ & 0xf];
2720 else
2721 rgb = color_table[*src_pixel >> 4];
2722 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2723 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2724 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2726 if(pad_size) memset(dst_start + x, 0, pad_size);
2727 dst_start += dst->stride / 2;
2728 src_start += src->stride;
2730 break;
2733 case 1:
2735 const RGBQUAD *color_table = get_dib_color_table( src );
2736 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2737 for(y = src_rect->top; y < src_rect->bottom; y++)
2739 int pos = (src->rect.left + src_rect->left) & 7;
2740 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2742 RGBQUAD rgb;
2743 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2744 rgb = color_table[src_val];
2745 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2746 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2747 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2749 if(pad_size) memset(dst_start + x, 0, pad_size);
2750 dst_start += dst->stride / 2;
2751 src_start += src->stride;
2753 break;
2758 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2760 if (!d1->color_table || !d2->color_table) return (!d1->color_table && !d2->color_table);
2761 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
2764 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2766 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2767 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2770 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2772 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2773 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2774 DWORD src_val;
2776 switch(src->bit_count)
2778 case 32:
2780 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2782 if(src->funcs == &funcs_8888)
2784 for(y = src_rect->top; y < src_rect->bottom; y++)
2786 dst_pixel = dst_start;
2787 src_pixel = src_start;
2788 for(x = src_rect->left; x < src_rect->right; x++)
2790 src_val = *src_pixel++;
2791 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2793 if(pad_size) memset(dst_pixel, 0, pad_size);
2794 dst_start += dst->stride;
2795 src_start += src->stride / 4;
2798 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2800 for(y = src_rect->top; y < src_rect->bottom; y++)
2802 dst_pixel = dst_start;
2803 src_pixel = src_start;
2804 for(x = src_rect->left; x < src_rect->right; x++)
2806 src_val = *src_pixel++;
2807 *dst_pixel++ = rgb_lookup_colortable(dst,
2808 src_val >> src->red_shift,
2809 src_val >> src->green_shift,
2810 src_val >> src->blue_shift );
2812 if(pad_size) memset(dst_pixel, 0, pad_size);
2813 dst_start += dst->stride;
2814 src_start += src->stride / 4;
2817 else
2819 for(y = src_rect->top; y < src_rect->bottom; y++)
2821 dst_pixel = dst_start;
2822 src_pixel = src_start;
2823 for(x = src_rect->left; x < src_rect->right; x++)
2825 src_val = *src_pixel++;
2826 *dst_pixel++ = rgb_lookup_colortable(dst,
2827 get_field(src_val, src->red_shift, src->red_len),
2828 get_field(src_val, src->green_shift, src->green_len),
2829 get_field(src_val, src->blue_shift, src->blue_len));
2831 if(pad_size) memset(dst_pixel, 0, pad_size);
2832 dst_start += dst->stride;
2833 src_start += src->stride / 4;
2836 break;
2839 case 24:
2841 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2843 for(y = src_rect->top; y < src_rect->bottom; y++)
2845 dst_pixel = dst_start;
2846 src_pixel = src_start;
2847 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2849 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2851 if(pad_size) memset(dst_pixel, 0, pad_size);
2852 dst_start += dst->stride;
2853 src_start += src->stride;
2855 break;
2858 case 16:
2860 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2861 if(src->funcs == &funcs_555)
2863 for(y = src_rect->top; y < src_rect->bottom; y++)
2865 dst_pixel = dst_start;
2866 src_pixel = src_start;
2867 for(x = src_rect->left; x < src_rect->right; x++)
2869 src_val = *src_pixel++;
2870 *dst_pixel++ = rgb_lookup_colortable(dst,
2871 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2872 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2873 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2875 if(pad_size) memset(dst_pixel, 0, pad_size);
2876 dst_start += dst->stride;
2877 src_start += src->stride / 2;
2880 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2882 for(y = src_rect->top; y < src_rect->bottom; y++)
2884 dst_pixel = dst_start;
2885 src_pixel = src_start;
2886 for(x = src_rect->left; x < src_rect->right; x++)
2888 src_val = *src_pixel++;
2889 *dst_pixel++ = rgb_lookup_colortable(dst,
2890 (((src_val >> src->red_shift) << 3) & 0xf8) |
2891 (((src_val >> src->red_shift) >> 2) & 0x07),
2892 (((src_val >> src->green_shift) << 3) & 0xf8) |
2893 (((src_val >> src->green_shift) >> 2) & 0x07),
2894 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2895 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2897 if(pad_size) memset(dst_pixel, 0, pad_size);
2898 dst_start += dst->stride;
2899 src_start += src->stride / 2;
2902 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2904 for(y = src_rect->top; y < src_rect->bottom; y++)
2906 dst_pixel = dst_start;
2907 src_pixel = src_start;
2908 for(x = src_rect->left; x < src_rect->right; x++)
2910 src_val = *src_pixel++;
2911 *dst_pixel++ = rgb_lookup_colortable(dst,
2912 (((src_val >> src->red_shift) << 3) & 0xf8) |
2913 (((src_val >> src->red_shift) >> 2) & 0x07),
2914 (((src_val >> src->green_shift) << 2) & 0xfc) |
2915 (((src_val >> src->green_shift) >> 4) & 0x03),
2916 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2917 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2919 if(pad_size) memset(dst_pixel, 0, pad_size);
2920 dst_start += dst->stride;
2921 src_start += src->stride / 2;
2924 else
2926 for(y = src_rect->top; y < src_rect->bottom; y++)
2928 dst_pixel = dst_start;
2929 src_pixel = src_start;
2930 for(x = src_rect->left; x < src_rect->right; x++)
2932 src_val = *src_pixel++;
2933 *dst_pixel++ = rgb_lookup_colortable(dst,
2934 get_field(src_val, src->red_shift, src->red_len),
2935 get_field(src_val, src->green_shift, src->green_len),
2936 get_field(src_val, src->blue_shift, src->blue_len));
2938 if(pad_size) memset(dst_pixel, 0, pad_size);
2939 dst_start += dst->stride;
2940 src_start += src->stride / 2;
2943 break;
2946 case 8:
2948 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2950 if(color_tables_match(dst, src))
2952 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2953 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2954 else
2956 for(y = src_rect->top; y < src_rect->bottom; y++)
2958 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2959 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2960 dst_start += dst->stride;
2961 src_start += src->stride;
2965 else
2967 const RGBQUAD *color_table = get_dib_color_table( src );
2968 for(y = src_rect->top; y < src_rect->bottom; y++)
2970 dst_pixel = dst_start;
2971 src_pixel = src_start;
2972 for(x = src_rect->left; x < src_rect->right; x++)
2974 RGBQUAD rgb = color_table[*src_pixel++];
2975 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2977 if(pad_size) memset(dst_pixel, 0, pad_size);
2978 dst_start += dst->stride;
2979 src_start += src->stride;
2982 break;
2985 case 4:
2987 const RGBQUAD *color_table = get_dib_color_table( src );
2988 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2989 for(y = src_rect->top; y < src_rect->bottom; y++)
2991 int pos = (src->rect.left + src_rect->left) & 1;
2992 src_pixel = src_start;
2993 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2995 RGBQUAD rgb;
2996 if (pos & 1)
2997 rgb = color_table[*src_pixel++ & 0xf];
2998 else
2999 rgb = color_table[*src_pixel >> 4];
3000 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3002 if(pad_size) memset(dst_start + x, 0, pad_size);
3003 dst_start += dst->stride;
3004 src_start += src->stride;
3006 break;
3009 case 1:
3011 const RGBQUAD *color_table = get_dib_color_table( src );
3012 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3013 for(y = src_rect->top; y < src_rect->bottom; y++)
3015 int pos = (src->rect.left + src_rect->left) & 7;
3016 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
3018 RGBQUAD rgb;
3019 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3020 rgb = color_table[src_val];
3021 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3023 if(pad_size) memset(dst_start + x, 0, pad_size);
3024 dst_start += dst->stride;
3025 src_start += src->stride;
3027 break;
3032 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3034 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3035 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3036 DWORD src_val;
3038 switch(src->bit_count)
3040 case 32:
3042 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3044 if(src->funcs == &funcs_8888)
3046 for(y = src_rect->top; y < src_rect->bottom; y++)
3048 dst_pixel = dst_start;
3049 src_pixel = src_start;
3050 for(x = src_rect->left; x < src_rect->right; x++)
3052 src_val = *src_pixel++;
3053 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3054 if((x - src_rect->left) & 1)
3056 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3057 dst_pixel++;
3059 else
3060 *dst_pixel = (dst_val << 4) & 0xf0;
3062 if(pad_size)
3064 if((x - src_rect->left) & 1) dst_pixel++;
3065 memset(dst_pixel, 0, pad_size);
3067 dst_start += dst->stride;
3068 src_start += src->stride / 4;
3071 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3073 for(y = src_rect->top; y < src_rect->bottom; y++)
3075 dst_pixel = dst_start;
3076 src_pixel = src_start;
3077 for(x = src_rect->left; x < src_rect->right; x++)
3079 src_val = *src_pixel++;
3080 dst_val = rgb_to_pixel_colortable(dst,
3081 src_val >> src->red_shift,
3082 src_val >> src->green_shift,
3083 src_val >> src->blue_shift);
3084 if((x - src_rect->left) & 1)
3086 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3087 dst_pixel++;
3089 else
3090 *dst_pixel = (dst_val << 4) & 0xf0;
3092 if(pad_size)
3094 if((x - src_rect->left) & 1) dst_pixel++;
3095 memset(dst_pixel, 0, pad_size);
3097 dst_start += dst->stride;
3098 src_start += src->stride / 4;
3101 else
3103 for(y = src_rect->top; y < src_rect->bottom; y++)
3105 dst_pixel = dst_start;
3106 src_pixel = src_start;
3107 for(x = src_rect->left; x < src_rect->right; x++)
3109 src_val = *src_pixel++;
3110 dst_val = rgb_to_pixel_colortable(dst,
3111 get_field(src_val, src->red_shift, src->red_len),
3112 get_field(src_val, src->green_shift, src->green_len),
3113 get_field(src_val, src->blue_shift, src->blue_len));
3114 if((x - src_rect->left) & 1)
3116 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3117 dst_pixel++;
3119 else
3120 *dst_pixel = (dst_val << 4) & 0xf0;
3122 if(pad_size)
3124 if((x - src_rect->left) & 1) dst_pixel++;
3125 memset(dst_pixel, 0, pad_size);
3127 dst_start += dst->stride;
3128 src_start += src->stride / 4;
3131 break;
3134 case 24:
3136 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3138 for(y = src_rect->top; y < src_rect->bottom; y++)
3140 dst_pixel = dst_start;
3141 src_pixel = src_start;
3142 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3144 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3146 if((x - src_rect->left) & 1)
3148 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3149 dst_pixel++;
3151 else
3152 *dst_pixel = (dst_val << 4) & 0xf0;
3154 if(pad_size)
3156 if((x - src_rect->left) & 1) dst_pixel++;
3157 memset(dst_pixel, 0, pad_size);
3159 dst_start += dst->stride;
3160 src_start += src->stride;
3162 break;
3165 case 16:
3167 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3168 if(src->funcs == &funcs_555)
3170 for(y = src_rect->top; y < src_rect->bottom; y++)
3172 dst_pixel = dst_start;
3173 src_pixel = src_start;
3174 for(x = src_rect->left; x < src_rect->right; x++)
3176 src_val = *src_pixel++;
3177 dst_val = rgb_to_pixel_colortable(dst,
3178 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3179 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3180 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3181 if((x - src_rect->left) & 1)
3183 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3184 dst_pixel++;
3186 else
3187 *dst_pixel = (dst_val << 4) & 0xf0;
3189 if(pad_size)
3191 if((x - src_rect->left) & 1) dst_pixel++;
3192 memset(dst_pixel, 0, pad_size);
3194 dst_start += dst->stride;
3195 src_start += src->stride / 2;
3198 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3200 for(y = src_rect->top; y < src_rect->bottom; y++)
3202 dst_pixel = dst_start;
3203 src_pixel = src_start;
3204 for(x = src_rect->left; x < src_rect->right; x++)
3206 src_val = *src_pixel++;
3207 dst_val = rgb_to_pixel_colortable(dst,
3208 (((src_val >> src->red_shift) << 3) & 0xf8) |
3209 (((src_val >> src->red_shift) >> 2) & 0x07),
3210 (((src_val >> src->green_shift) << 3) & 0xf8) |
3211 (((src_val >> src->green_shift) >> 2) & 0x07),
3212 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3213 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3214 if((x - src_rect->left) & 1)
3216 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3217 dst_pixel++;
3219 else
3220 *dst_pixel = (dst_val << 4) & 0xf0;
3222 if(pad_size)
3224 if((x - src_rect->left) & 1) dst_pixel++;
3225 memset(dst_pixel, 0, pad_size);
3227 dst_start += dst->stride;
3228 src_start += src->stride / 2;
3231 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3233 for(y = src_rect->top; y < src_rect->bottom; y++)
3235 dst_pixel = dst_start;
3236 src_pixel = src_start;
3237 for(x = src_rect->left; x < src_rect->right; x++)
3239 src_val = *src_pixel++;
3240 dst_val = rgb_to_pixel_colortable(dst,
3241 (((src_val >> src->red_shift) << 3) & 0xf8) |
3242 (((src_val >> src->red_shift) >> 2) & 0x07),
3243 (((src_val >> src->green_shift) << 2) & 0xfc) |
3244 (((src_val >> src->green_shift) >> 4) & 0x03),
3245 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3246 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3247 if((x - src_rect->left) & 1)
3249 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3250 dst_pixel++;
3252 else
3253 *dst_pixel = (dst_val << 4) & 0xf0;
3255 if(pad_size)
3257 if((x - src_rect->left) & 1) dst_pixel++;
3258 memset(dst_pixel, 0, pad_size);
3260 dst_start += dst->stride;
3261 src_start += src->stride / 2;
3264 else
3266 for(y = src_rect->top; y < src_rect->bottom; y++)
3268 dst_pixel = dst_start;
3269 src_pixel = src_start;
3270 for(x = src_rect->left; x < src_rect->right; x++)
3272 src_val = *src_pixel++;
3273 dst_val = rgb_to_pixel_colortable(dst,
3274 get_field(src_val, src->red_shift, src->red_len),
3275 get_field(src_val, src->green_shift, src->green_len),
3276 get_field(src_val, src->blue_shift, src->blue_len));
3277 if((x - src_rect->left) & 1)
3279 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3280 dst_pixel++;
3282 else
3283 *dst_pixel = (dst_val << 4) & 0xf0;
3285 if(pad_size)
3287 if((x - src_rect->left) & 1) dst_pixel++;
3288 memset(dst_pixel, 0, pad_size);
3290 dst_start += dst->stride;
3291 src_start += src->stride / 2;
3294 break;
3297 case 8:
3299 const RGBQUAD *color_table = get_dib_color_table( src );
3300 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3302 for(y = src_rect->top; y < src_rect->bottom; y++)
3304 dst_pixel = dst_start;
3305 src_pixel = src_start;
3306 for(x = src_rect->left; x < src_rect->right; x++)
3308 RGBQUAD rgb = color_table[*src_pixel++];
3309 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3310 if((x - src_rect->left) & 1)
3312 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3313 dst_pixel++;
3315 else
3316 *dst_pixel = (dst_val << 4) & 0xf0;
3318 if(pad_size)
3320 if((x - src_rect->left) & 1) dst_pixel++;
3321 memset(dst_pixel, 0, pad_size);
3323 dst_start += dst->stride;
3324 src_start += src->stride;
3326 break;
3329 case 4:
3331 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3333 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
3335 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3336 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3337 else
3339 for(y = src_rect->top; y < src_rect->bottom; y++)
3341 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3342 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3343 dst_start += dst->stride;
3344 src_start += src->stride;
3348 else
3350 const RGBQUAD *color_table = get_dib_color_table( src );
3351 for(y = src_rect->top; y < src_rect->bottom; y++)
3353 int pos = (src->rect.left + src_rect->left) & 1;
3354 dst_pixel = dst_start;
3355 src_pixel = src_start;
3356 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3358 RGBQUAD rgb;
3359 if(pos & 1)
3360 rgb = color_table[*src_pixel++ & 0xf];
3361 else
3362 rgb = color_table[*src_pixel >> 4];
3363 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3364 if((x - src_rect->left) & 1)
3366 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3367 dst_pixel++;
3369 else
3370 *dst_pixel = (dst_val << 4) & 0xf0;
3372 if(pad_size)
3374 if((x - src_rect->left) & 1) dst_pixel++;
3375 memset(dst_pixel, 0, pad_size);
3377 dst_start += dst->stride;
3378 src_start += src->stride;
3381 break;
3384 case 1:
3386 const RGBQUAD *color_table = get_dib_color_table( src );
3387 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3388 for(y = src_rect->top; y < src_rect->bottom; y++)
3390 int pos = (src->rect.left + src_rect->left) & 7;
3391 dst_pixel = dst_start;
3392 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3394 RGBQUAD rgb;
3395 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3396 rgb = color_table[src_val];
3397 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3398 if((x - src_rect->left) & 1)
3400 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3401 dst_pixel++;
3403 else
3404 *dst_pixel = (dst_val << 4) & 0xf0;
3406 if(pad_size)
3408 if((x - src_rect->left) & 1) dst_pixel++;
3409 memset(dst_pixel, 0, pad_size);
3411 dst_start += dst->stride;
3412 src_start += src->stride;
3414 break;
3419 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3421 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3422 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3423 DWORD src_val;
3424 int bit_pos;
3426 switch(src->bit_count)
3428 case 32:
3430 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3432 if(src->funcs == &funcs_8888)
3434 for(y = src_rect->top; y < src_rect->bottom; y++)
3436 dst_pixel = dst_start;
3437 src_pixel = src_start;
3438 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3440 src_val = *src_pixel++;
3441 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val >> 16, src_val >> 8, src_val);
3443 if(bit_pos == 0) *dst_pixel = 0;
3444 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3446 if(++bit_pos == 8)
3448 dst_pixel++;
3449 bit_pos = 0;
3452 if(pad_size)
3454 if(bit_pos != 0) dst_pixel++;
3455 memset(dst_pixel, 0, pad_size);
3457 dst_start += dst->stride;
3458 src_start += src->stride / 4;
3461 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3463 for(y = src_rect->top; y < src_rect->bottom; y++)
3465 dst_pixel = dst_start;
3466 src_pixel = src_start;
3467 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3469 src_val = *src_pixel++;
3470 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3471 src_val >> src->red_shift,
3472 src_val >> src->green_shift,
3473 src_val >> src->blue_shift);
3475 if(bit_pos == 0) *dst_pixel = 0;
3476 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3478 if(++bit_pos == 8)
3480 dst_pixel++;
3481 bit_pos = 0;
3484 if(pad_size)
3486 if(bit_pos != 0) dst_pixel++;
3487 memset(dst_pixel, 0, pad_size);
3489 dst_start += dst->stride;
3490 src_start += src->stride / 4;
3493 else
3495 for(y = src_rect->top; y < src_rect->bottom; y++)
3497 dst_pixel = dst_start;
3498 src_pixel = src_start;
3499 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3501 src_val = *src_pixel++;
3502 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3503 get_field(src_val, src->red_shift, src->red_len),
3504 get_field(src_val, src->green_shift, src->green_len),
3505 get_field(src_val, src->blue_shift, src->blue_len));
3507 if(bit_pos == 0) *dst_pixel = 0;
3508 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3510 if(++bit_pos == 8)
3512 dst_pixel++;
3513 bit_pos = 0;
3516 if(pad_size)
3518 if(bit_pos != 0) dst_pixel++;
3519 memset(dst_pixel, 0, pad_size);
3521 dst_start += dst->stride;
3522 src_start += src->stride / 4;
3525 break;
3528 case 24:
3530 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3532 for(y = src_rect->top; y < src_rect->bottom; y++)
3534 dst_pixel = dst_start;
3535 src_pixel = src_start;
3536 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3538 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_pixel[2], src_pixel[1], src_pixel[0]);
3540 if(bit_pos == 0) *dst_pixel = 0;
3541 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3543 if(++bit_pos == 8)
3545 dst_pixel++;
3546 bit_pos = 0;
3549 if(pad_size)
3551 if(bit_pos != 0) dst_pixel++;
3552 memset(dst_pixel, 0, pad_size);
3554 dst_start += dst->stride;
3555 src_start += src->stride;
3557 break;
3560 case 16:
3562 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3563 if(src->funcs == &funcs_555)
3565 for(y = src_rect->top; y < src_rect->bottom; y++)
3567 dst_pixel = dst_start;
3568 src_pixel = src_start;
3569 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3571 src_val = *src_pixel++;
3572 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3573 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3574 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3575 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3577 if(bit_pos == 0) *dst_pixel = 0;
3578 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3580 if(++bit_pos == 8)
3582 dst_pixel++;
3583 bit_pos = 0;
3586 if(pad_size)
3588 if(bit_pos != 0) dst_pixel++;
3589 memset(dst_pixel, 0, pad_size);
3591 dst_start += dst->stride;
3592 src_start += src->stride / 2;
3595 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3597 for(y = src_rect->top; y < src_rect->bottom; y++)
3599 dst_pixel = dst_start;
3600 src_pixel = src_start;
3601 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3603 src_val = *src_pixel++;
3604 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3605 (((src_val >> src->red_shift) << 3) & 0xf8) |
3606 (((src_val >> src->red_shift) >> 2) & 0x07),
3607 (((src_val >> src->green_shift) << 3) & 0xf8) |
3608 (((src_val >> src->green_shift) >> 2) & 0x07),
3609 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3610 (((src_val >> src->blue_shift) >> 2) & 0x07));
3611 if(bit_pos == 0) *dst_pixel = 0;
3612 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3614 if(++bit_pos == 8)
3616 dst_pixel++;
3617 bit_pos = 0;
3620 if(pad_size)
3622 if(bit_pos != 0) dst_pixel++;
3623 memset(dst_pixel, 0, pad_size);
3625 dst_start += dst->stride;
3626 src_start += src->stride / 2;
3629 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3631 for(y = src_rect->top; y < src_rect->bottom; y++)
3633 dst_pixel = dst_start;
3634 src_pixel = src_start;
3635 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3637 src_val = *src_pixel++;
3638 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3639 (((src_val >> src->red_shift) << 3) & 0xf8) |
3640 (((src_val >> src->red_shift) >> 2) & 0x07),
3641 (((src_val >> src->green_shift) << 2) & 0xfc) |
3642 (((src_val >> src->green_shift) >> 4) & 0x03),
3643 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3644 (((src_val >> src->blue_shift) >> 2) & 0x07));
3645 if(bit_pos == 0) *dst_pixel = 0;
3646 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3648 if(++bit_pos == 8)
3650 dst_pixel++;
3651 bit_pos = 0;
3654 if(pad_size)
3656 if(bit_pos != 0) dst_pixel++;
3657 memset(dst_pixel, 0, pad_size);
3659 dst_start += dst->stride;
3660 src_start += src->stride / 2;
3663 else
3665 for(y = src_rect->top; y < src_rect->bottom; y++)
3667 dst_pixel = dst_start;
3668 src_pixel = src_start;
3669 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3671 src_val = *src_pixel++;
3672 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3673 get_field(src_val, src->red_shift, src->red_len),
3674 get_field(src_val, src->green_shift, src->green_len),
3675 get_field(src_val, src->blue_shift, src->blue_len));
3676 if(bit_pos == 0) *dst_pixel = 0;
3677 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3679 if(++bit_pos == 8)
3681 dst_pixel++;
3682 bit_pos = 0;
3685 if(pad_size)
3687 if(bit_pos != 0) dst_pixel++;
3688 memset(dst_pixel, 0, pad_size);
3690 dst_start += dst->stride;
3691 src_start += src->stride / 2;
3694 break;
3697 case 8:
3699 const RGBQUAD *color_table = get_dib_color_table( src );
3700 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3702 for(y = src_rect->top; y < src_rect->bottom; y++)
3704 dst_pixel = dst_start;
3705 src_pixel = src_start;
3706 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3708 RGBQUAD rgb = color_table[*src_pixel++];
3709 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3711 if(bit_pos == 0) *dst_pixel = 0;
3712 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3714 if(++bit_pos == 8)
3716 dst_pixel++;
3717 bit_pos = 0;
3720 if(pad_size)
3722 if(bit_pos != 0) dst_pixel++;
3723 memset(dst_pixel, 0, pad_size);
3725 dst_start += dst->stride;
3726 src_start += src->stride;
3728 break;
3731 case 4:
3733 const RGBQUAD *color_table = get_dib_color_table( src );
3734 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3736 for(y = src_rect->top; y < src_rect->bottom; y++)
3738 int pos = (src->rect.left + src_rect->left) & 1;
3739 dst_pixel = dst_start;
3740 src_pixel = src_start;
3741 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3743 RGBQUAD rgb;
3744 if (pos & 1)
3745 rgb = color_table[*src_pixel++ & 0xf];
3746 else
3747 rgb = color_table[*src_pixel >> 4];
3748 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3750 if(bit_pos == 0) *dst_pixel = 0;
3751 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3753 if(++bit_pos == 8)
3755 dst_pixel++;
3756 bit_pos = 0;
3759 if(pad_size)
3761 if(bit_pos != 0) dst_pixel++;
3762 memset(dst_pixel, 0, pad_size);
3764 dst_start += dst->stride;
3765 src_start += src->stride;
3767 break;
3770 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3771 uses text/bkgnd colours instead of the dib's colour table, this
3772 doesn't appear to be the case for a dc backed by a
3773 dibsection. */
3775 case 1:
3777 const RGBQUAD *color_table = get_dib_color_table( src );
3778 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3779 for(y = src_rect->top; y < src_rect->bottom; y++)
3781 int pos = (src->rect.left + src_rect->left) & 7;
3782 dst_pixel = dst_start;
3783 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3785 RGBQUAD rgb;
3786 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3787 rgb = color_table[src_val];
3788 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3790 if(bit_pos == 0) *dst_pixel = 0;
3791 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3793 if(++bit_pos == 8)
3795 dst_pixel++;
3796 bit_pos = 0;
3799 if(pad_size)
3801 if(bit_pos != 0) dst_pixel++;
3802 memset(dst_pixel, 0, pad_size);
3804 dst_start += dst->stride;
3805 src_start += src->stride;
3807 break;
3812 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3816 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3818 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3821 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
3823 return (blend_color( dst, src, alpha ) |
3824 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3825 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3826 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3829 static inline DWORD blend_argb( DWORD dst, DWORD src )
3831 BYTE b = (BYTE)src;
3832 BYTE g = (BYTE)(src >> 8);
3833 BYTE r = (BYTE)(src >> 16);
3834 DWORD alpha = (BYTE)(src >> 24);
3835 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3836 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3837 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3838 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3841 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3843 BYTE b = ((BYTE)src * alpha + 127) / 255;
3844 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3845 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3846 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3847 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3848 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3849 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3850 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3853 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3855 if (blend.AlphaFormat & AC_SRC_ALPHA)
3857 DWORD alpha = blend.SourceConstantAlpha;
3858 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3859 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3860 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3861 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3862 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3863 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3864 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3866 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3867 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3868 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3871 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3872 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3874 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3875 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3876 int x, y;
3878 if (blend.AlphaFormat & AC_SRC_ALPHA)
3880 if (blend.SourceConstantAlpha == 255)
3881 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3882 for (x = 0; x < rc->right - rc->left; x++)
3883 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
3884 else
3885 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3886 for (x = 0; x < rc->right - rc->left; x++)
3887 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3889 else
3890 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3891 for (x = 0; x < rc->right - rc->left; x++)
3892 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3895 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3896 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3898 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3899 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3900 int x, y;
3902 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3904 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++)
3908 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3909 dst_ptr[x] >> dst->green_shift,
3910 dst_ptr[x] >> dst->blue_shift,
3911 src_ptr[x], blend );
3912 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3913 (((val >> 8) & 0xff) << dst->green_shift) |
3914 (((val >> 16) & 0xff) << dst->red_shift));
3918 else
3920 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3922 for (x = 0; x < rc->right - rc->left; x++)
3924 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3925 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3926 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3927 src_ptr[x], blend );
3928 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3929 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3930 put_field( val, dst->blue_shift, dst->blue_len ));
3936 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3937 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3939 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3940 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3941 int x, y;
3943 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3945 for (x = 0; x < rc->right - rc->left; x++)
3947 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3948 src_ptr[x], blend );
3949 dst_ptr[x * 3] = val;
3950 dst_ptr[x * 3 + 1] = val >> 8;
3951 dst_ptr[x * 3 + 2] = val >> 16;
3956 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3957 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3959 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3960 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3961 int x, y;
3963 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3965 for (x = 0; x < rc->right - rc->left; x++)
3967 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3968 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3969 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3970 src_ptr[x], blend );
3971 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3976 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3977 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3979 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3980 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3981 int x, y;
3983 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3985 for (x = 0; x < rc->right - rc->left; x++)
3987 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3988 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3989 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3990 src_ptr[x], blend );
3991 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3992 put_field((val >> 8), dst->green_shift, dst->green_len) |
3993 put_field( val, dst->blue_shift, dst->blue_len));
3998 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3999 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4001 const RGBQUAD *color_table = get_dib_color_table( dst );
4002 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4003 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
4004 int x, y;
4006 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4008 for (x = 0; x < rc->right - rc->left; x++)
4010 RGBQUAD rgb = color_table[dst_ptr[x]];
4011 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
4012 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4017 static void blend_rect_4(const dib_info *dst, const RECT *rc,
4018 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4020 const RGBQUAD *color_table = get_dib_color_table( dst );
4021 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4022 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
4023 int i, x, y;
4025 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4027 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
4029 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
4030 RGBQUAD rgb = color_table[val];
4031 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4032 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4033 if (x & 1)
4034 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4035 else
4036 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4041 static void blend_rect_1(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_1( 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) & 7; i < rc->right - rc->left; i++, x++)
4053 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4054 RGBQUAD rgb = color_table[val];
4055 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4056 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4057 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4062 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4063 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4067 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4069 BYTE r, g, b, a;
4070 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4071 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4072 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4073 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4074 return a << 24 | r << 16 | g << 8 | b;
4077 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4079 BYTE r, g, b;
4080 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4081 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4082 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4083 return r << 16 | g << 8 | b;
4086 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4087 unsigned int x, unsigned int y )
4089 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4090 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4091 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4092 r = min( 31, max( 0, r / 16 ));
4093 g = min( 31, max( 0, g / 16 ));
4094 b = min( 31, max( 0, b / 16 ));
4095 return (r << 10) | (g << 5) | b;
4098 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4099 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4101 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4102 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4103 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4104 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4107 /* compute the left/right triangle limit for row y */
4108 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4110 int x1, x2;
4112 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4113 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4115 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4117 *left = max( rc->left, min( x1, x2 ) );
4118 *right = min( rc->right, max( x1, x2 ) );
4121 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4122 static inline int triangle_det( const TRIVERTEX *v )
4124 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);
4127 /* compute the barycentric weights for a given point inside the triangle */
4128 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4130 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4131 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4134 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4136 INT64 l1, l2;
4137 BYTE r, g, b, a;
4139 triangle_weights( v, x, y, &l1, &l2 );
4140 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4141 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4142 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4143 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4144 return a << 24 | r << 16 | g << 8 | b;
4147 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4149 INT64 l1, l2;
4150 BYTE r, g, b;
4152 triangle_weights( v, x, y, &l1, &l2 );
4153 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4154 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4155 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4156 return r << 16 | g << 8 | b;
4159 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4161 INT64 l1, l2;
4162 int r, g, b;
4164 triangle_weights( v, x, y, &l1, &l2 );
4165 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4166 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4167 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4168 r = min( 31, max( 0, r / 16 ));
4169 g = min( 31, max( 0, g / 16 ));
4170 b = min( 31, max( 0, b / 16 ));
4171 return (r << 10) | (g << 5) | b;
4174 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4176 INT64 l1, l2;
4177 BYTE r, g, b;
4179 triangle_weights( v, x, y, &l1, &l2 );
4180 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4181 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4182 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4183 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4186 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4188 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4189 int x, y, left, right, det;
4191 switch (mode)
4193 case GRADIENT_FILL_RECT_H:
4194 for (x = 0; x < rc->right - rc->left; x++)
4195 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4197 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4198 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4199 break;
4201 case GRADIENT_FILL_RECT_V:
4202 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4204 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4205 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4207 break;
4209 case GRADIENT_FILL_TRIANGLE:
4210 if (!(det = triangle_det( v ))) return FALSE;
4211 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4213 triangle_coords( v, rc, y, &left, &right );
4214 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4216 break;
4218 return TRUE;
4221 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4223 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4224 int x, y, left, right, det;
4226 switch (mode)
4228 case GRADIENT_FILL_RECT_H:
4229 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4231 for (x = 0; x < rc->right - rc->left; x++)
4233 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4234 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4235 (((val >> 8) & 0xff) << dib->green_shift) |
4236 (((val >> 16) & 0xff) << dib->red_shift));
4239 else
4241 for (x = 0; x < rc->right - rc->left; x++)
4243 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4244 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4245 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4246 put_field( val, dib->blue_shift, dib->blue_len ));
4250 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4251 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4252 break;
4254 case GRADIENT_FILL_RECT_V:
4255 for (y = rc->top; y < rc->bottom; y++)
4257 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4258 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4259 val = ((( val & 0xff) << dib->blue_shift) |
4260 (((val >> 8) & 0xff) << dib->green_shift) |
4261 (((val >> 16) & 0xff) << dib->red_shift));
4262 else
4263 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4264 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4265 put_field( val, dib->blue_shift, dib->blue_len ));
4267 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4268 ptr += dib->stride / 4;
4270 break;
4272 case GRADIENT_FILL_TRIANGLE:
4273 if (!(det = triangle_det( v ))) return FALSE;
4274 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4276 triangle_coords( v, rc, y, &left, &right );
4278 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4279 for (x = left; x < right; x++)
4281 DWORD val = gradient_triangle_24( v, x, y, det );
4282 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4283 (((val >> 8) & 0xff) << dib->green_shift) |
4284 (((val >> 16) & 0xff) << dib->red_shift));
4286 else
4287 for (x = left; x < right; x++)
4289 DWORD val = gradient_triangle_24( v, x, y, det );
4290 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4291 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4292 put_field( val, dib->blue_shift, dib->blue_len ));
4295 break;
4297 return TRUE;
4300 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4302 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4303 int x, y, left, right, det;
4305 switch (mode)
4307 case GRADIENT_FILL_RECT_H:
4308 for (x = 0; x < rc->right - rc->left; x++)
4310 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4311 ptr[x * 3] = val;
4312 ptr[x * 3 + 1] = val >> 8;
4313 ptr[x * 3 + 2] = val >> 16;
4316 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4317 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4318 break;
4320 case GRADIENT_FILL_RECT_V:
4321 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4323 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4324 for (x = 0; x < rc->right - rc->left; x++)
4326 ptr[x * 3] = val;
4327 ptr[x * 3 + 1] = val >> 8;
4328 ptr[x * 3 + 2] = val >> 16;
4331 break;
4333 case GRADIENT_FILL_TRIANGLE:
4334 if (!(det = triangle_det( v ))) return FALSE;
4335 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4337 triangle_coords( v, rc, y, &left, &right );
4338 for (x = left; x < right; x++)
4340 DWORD val = gradient_triangle_24( v, x, y, det );
4341 ptr[(x - rc->left) * 3] = val;
4342 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4343 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4346 break;
4348 return TRUE;
4351 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4353 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4354 int x, y, left, right, det;
4356 switch (mode)
4358 case GRADIENT_FILL_RECT_H:
4359 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4360 for (x = rc->left; x < rc->right; x++)
4361 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4362 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4363 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4364 break;
4366 case GRADIENT_FILL_RECT_V:
4367 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4369 WORD values[4];
4370 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4371 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4373 break;
4375 case GRADIENT_FILL_TRIANGLE:
4376 if (!(det = triangle_det( v ))) return FALSE;
4377 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4379 triangle_coords( v, rc, y, &left, &right );
4380 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4382 break;
4384 return TRUE;
4387 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4389 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4390 int x, y, left, right, det;
4392 switch (mode)
4394 case GRADIENT_FILL_RECT_H:
4395 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4396 for (x = rc->left; x < rc->right; x++)
4398 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4399 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4400 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4401 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4403 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4404 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4405 break;
4407 case GRADIENT_FILL_RECT_V:
4408 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4410 WORD values[4];
4411 for (x = 0; x < 4; x++)
4413 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4414 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4415 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4416 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4418 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4420 break;
4422 case GRADIENT_FILL_TRIANGLE:
4423 if (!(det = triangle_det( v ))) return FALSE;
4424 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4426 triangle_coords( v, rc, y, &left, &right );
4427 for (x = left; x < right; x++)
4429 WORD val = gradient_triangle_555( v, x, y, det );
4430 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4431 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4432 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4435 break;
4437 return TRUE;
4440 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4442 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4443 int x, y, left, right, det;
4445 switch (mode)
4447 case GRADIENT_FILL_RECT_H:
4448 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4449 for (x = rc->left; x < rc->right; x++)
4450 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4451 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4452 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4453 break;
4455 case GRADIENT_FILL_RECT_V:
4456 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4458 BYTE values[16];
4459 for (x = 0; x < 16; x++)
4460 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4461 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4463 break;
4465 case GRADIENT_FILL_TRIANGLE:
4466 if (!(det = triangle_det( v ))) return FALSE;
4467 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4469 triangle_coords( v, rc, y, &left, &right );
4470 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4472 break;
4474 return TRUE;
4477 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4479 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4480 int x, y, left, right, det, pos;
4482 switch (mode)
4484 case GRADIENT_FILL_RECT_H:
4485 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4487 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4489 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4490 if (pos & 1)
4491 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4492 else
4493 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4496 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4498 x = rc->left;
4499 pos = (dib->rect.left + rc->left) & 1;
4500 if (pos)
4502 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4503 pos++;
4504 x++;
4506 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4507 if (x < rc->right)
4508 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4510 break;
4512 case GRADIENT_FILL_RECT_V:
4513 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4515 BYTE values[16];
4516 for (x = 0; x < 16; x++)
4517 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4518 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4519 if (pos & 1)
4520 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4521 else
4522 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4524 break;
4526 case GRADIENT_FILL_TRIANGLE:
4527 if (!(det = triangle_det( v ))) return FALSE;
4528 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4530 triangle_coords( v, rc, y, &left, &right );
4531 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4533 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4534 if (pos & 1)
4535 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4536 else
4537 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4540 break;
4542 return TRUE;
4545 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4547 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4548 int x, y, left, right, det, pos;
4550 switch (mode)
4552 case GRADIENT_FILL_RECT_H:
4553 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4555 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4557 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4558 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4561 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4562 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4563 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4564 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4565 break;
4567 case GRADIENT_FILL_RECT_V:
4568 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4570 BYTE values[16];
4571 for (x = 0; x < 16; x++)
4572 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4573 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4574 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4575 (values[x % 16] & pixel_masks_1[pos % 8]);
4577 break;
4579 case GRADIENT_FILL_TRIANGLE:
4580 if (!(det = triangle_det( v ))) return FALSE;
4581 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4583 triangle_coords( v, rc, y, &left, &right );
4584 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4586 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4587 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4590 break;
4592 return TRUE;
4595 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4597 return TRUE;
4600 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4602 if (dst == text) return dst;
4604 if (dst > text)
4606 DWORD diff = dst - text;
4607 DWORD range = max_comp - text;
4608 dst = text + (diff * range ) / (0xff - text);
4609 return dst;
4611 else
4613 DWORD diff = text - dst;
4614 DWORD range = text - min_comp;
4615 dst = text - (diff * range) / text;
4616 return dst;
4620 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4622 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4623 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4624 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4627 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4628 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4630 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4631 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4632 int x, y;
4634 for (y = rect->top; y < rect->bottom; y++)
4636 for (x = 0; x < rect->right - rect->left; x++)
4638 if (glyph_ptr[x] <= 1) continue;
4639 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4640 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4642 dst_ptr += dib->stride / 4;
4643 glyph_ptr += glyph->stride;
4647 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4648 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4650 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4651 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4652 int x, y;
4653 DWORD text, val;
4655 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4656 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4657 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4659 for (y = rect->top; y < rect->bottom; y++)
4661 for (x = 0; x < rect->right - rect->left; x++)
4663 if (glyph_ptr[x] <= 1) continue;
4664 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4665 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4666 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4667 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4668 text, ranges + glyph_ptr[x] );
4669 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4670 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4671 put_field( val, dib->blue_shift, dib->blue_len ));
4673 dst_ptr += dib->stride / 4;
4674 glyph_ptr += glyph->stride;
4678 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4679 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4681 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4682 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4683 int x, y;
4684 DWORD val;
4686 for (y = rect->top; y < rect->bottom; y++)
4688 for (x = 0; x < rect->right - rect->left; x++)
4690 if (glyph_ptr[x] <= 1) continue;
4691 if (glyph_ptr[x] >= 16)
4692 val = text_pixel;
4693 else
4694 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4695 text_pixel, ranges + glyph_ptr[x] );
4696 dst_ptr[x * 3] = val;
4697 dst_ptr[x * 3 + 1] = val >> 8;
4698 dst_ptr[x * 3 + 2] = val >> 16;
4700 dst_ptr += dib->stride;
4701 glyph_ptr += glyph->stride;
4705 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4706 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4708 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4709 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4710 int x, y;
4711 DWORD text, val;
4713 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4714 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4715 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4717 for (y = rect->top; y < rect->bottom; y++)
4719 for (x = 0; x < rect->right - rect->left; x++)
4721 if (glyph_ptr[x] <= 1) continue;
4722 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4723 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4724 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4725 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4726 text, ranges + glyph_ptr[x] );
4727 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4729 dst_ptr += dib->stride / 2;
4730 glyph_ptr += glyph->stride;
4734 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4735 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4737 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4738 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4739 int x, y;
4740 DWORD text, val;
4742 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4743 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4744 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4746 for (y = rect->top; y < rect->bottom; y++)
4748 for (x = 0; x < rect->right - rect->left; x++)
4750 if (glyph_ptr[x] <= 1) continue;
4751 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4752 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4753 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4754 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4755 text, ranges + glyph_ptr[x] );
4756 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4757 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4758 put_field( val, dib->blue_shift, dib->blue_len ));
4760 dst_ptr += dib->stride / 2;
4761 glyph_ptr += glyph->stride;
4765 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4766 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4768 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4769 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4770 int x, y;
4772 for (y = rect->top; y < rect->bottom; y++)
4774 for (x = 0; x < rect->right - rect->left; x++)
4776 /* no antialiasing, glyph should only contain 0 or 16. */
4777 if (glyph_ptr[x] >= 16)
4778 dst_ptr[x] = text_pixel;
4780 dst_ptr += dib->stride;
4781 glyph_ptr += glyph->stride;
4785 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4786 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4788 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
4789 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4790 int x, y, pos;
4792 for (y = rect->top; y < rect->bottom; y++)
4794 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
4796 /* no antialiasing, glyph should only contain 0 or 16. */
4797 if (glyph_ptr[x] >= 16)
4799 if (pos & 1)
4800 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
4801 else
4802 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
4805 dst_ptr += dib->stride;
4806 glyph_ptr += glyph->stride;
4810 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4811 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4813 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
4814 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4815 int x, y, pos;
4816 BYTE text = (text_pixel & 1) ? 0xff : 0;
4818 for (y = rect->top; y < rect->bottom; y++)
4820 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
4822 /* no antialiasing, glyph should only contain 0 or 16. */
4823 if (glyph_ptr[x] >= 16)
4824 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4825 (text & pixel_masks_1[pos % 8]);
4827 dst_ptr += dib->stride;
4828 glyph_ptr += glyph->stride;
4832 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4833 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4835 return;
4838 static void create_rop_masks_32(const dib_info *dib, const BYTE *hatch_ptr,
4839 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4841 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4842 int x, y;
4844 /* masks are always 8x8 */
4845 assert( dib->width == 8 );
4846 assert( dib->height == 8 );
4848 for(y = 0; y < 8; y++, hatch_ptr++)
4850 for(x = 0; x < 8; x++)
4852 if(*hatch_ptr & pixel_masks_1[x])
4854 and_bits[x] = fg->and;
4855 xor_bits[x] = fg->xor;
4857 else
4859 and_bits[x] = bg->and;
4860 xor_bits[x] = bg->xor;
4863 and_bits += dib->stride / 4;
4864 xor_bits += dib->stride / 4;
4868 static void create_rop_masks_24(const dib_info *dib, const BYTE *hatch_ptr,
4869 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4871 DWORD mask_start = 0, mask_offset;
4872 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4873 int x, y;
4875 /* masks are always 8x8 */
4876 assert( dib->width == 8 );
4877 assert( dib->height == 8 );
4879 for(y = 0; y < 8; y++, hatch_ptr++)
4881 mask_offset = mask_start;
4882 for(x = 0; x < 8; x++)
4884 if(*hatch_ptr & pixel_masks_1[x])
4886 and_bits[mask_offset] = fg->and & 0xff;
4887 xor_bits[mask_offset++] = fg->xor & 0xff;
4888 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4889 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4890 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4891 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4893 else
4895 and_bits[mask_offset] = bg->and & 0xff;
4896 xor_bits[mask_offset++] = bg->xor & 0xff;
4897 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4898 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4899 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4900 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4903 mask_start += dib->stride;
4907 static void create_rop_masks_16(const dib_info *dib, const BYTE *hatch_ptr,
4908 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4910 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4911 int x, y;
4913 /* masks are always 8x8 */
4914 assert( dib->width == 8 );
4915 assert( dib->height == 8 );
4917 for(y = 0; y < 8; y++, hatch_ptr++)
4919 for(x = 0; x < 8; x++)
4921 if(*hatch_ptr & pixel_masks_1[x])
4923 and_bits[x] = fg->and;
4924 xor_bits[x] = fg->xor;
4926 else
4928 and_bits[x] = bg->and;
4929 xor_bits[x] = bg->xor;
4932 and_bits += dib->stride / 2;
4933 xor_bits += dib->stride / 2;
4937 static void create_rop_masks_8(const dib_info *dib, const BYTE *hatch_ptr,
4938 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4940 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4941 int x, y;
4943 /* masks are always 8x8 */
4944 assert( dib->width == 8 );
4945 assert( dib->height == 8 );
4947 for(y = 0; y < 8; y++, hatch_ptr++)
4949 for(x = 0; x < 8; x++)
4951 if(*hatch_ptr & pixel_masks_1[x])
4953 and_bits[x] = fg->and;
4954 xor_bits[x] = fg->xor;
4956 else
4958 and_bits[x] = bg->and;
4959 xor_bits[x] = bg->xor;
4962 and_bits += dib->stride;
4963 xor_bits += dib->stride;
4967 static void create_rop_masks_4(const dib_info *dib, const BYTE *hatch_ptr,
4968 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4970 DWORD mask_offset;
4971 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4972 const rop_mask *rop_mask;
4973 int x, y;
4975 /* masks are always 8x8 */
4976 assert( dib->width == 8 );
4977 assert( dib->height == 8 );
4979 for(y = 0; y < 8; y++, hatch_ptr++)
4981 for(x = mask_offset = 0; x < 8; x++)
4983 if(*hatch_ptr & pixel_masks_1[x])
4984 rop_mask = fg;
4985 else
4986 rop_mask = bg;
4988 if(x & 1)
4990 and_bits[mask_offset] |= (rop_mask->and & 0x0f);
4991 xor_bits[mask_offset] |= (rop_mask->xor & 0x0f);
4992 mask_offset++;
4994 else
4996 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4997 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
5000 and_bits += dib->stride;
5001 xor_bits += dib->stride;
5005 static void create_rop_masks_1(const dib_info *dib, const BYTE *hatch_ptr,
5006 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5008 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
5009 rop_mask rop_mask;
5010 int x, y;
5012 /* masks are always 8x8 */
5013 assert( dib->width == 8 );
5014 assert( dib->height == 8 );
5016 for(y = 0; y < 8; y++, hatch_ptr++)
5018 *and_bits = *xor_bits = 0;
5019 for(x = 0; x < 8; x++)
5021 if(*hatch_ptr & pixel_masks_1[x])
5023 rop_mask.and = (fg->and & 1) ? 0xff : 0;
5024 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
5026 else
5028 rop_mask.and = (bg->and & 1) ? 0xff : 0;
5029 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5031 *and_bits |= (rop_mask.and & pixel_masks_1[x]);
5032 *xor_bits |= (rop_mask.xor & pixel_masks_1[x]);
5034 and_bits += dib->stride;
5035 xor_bits += dib->stride;
5039 static void create_rop_masks_null(const dib_info *dib, const BYTE *hatch_ptr,
5040 const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5044 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5046 switch (mode)
5048 default:
5049 case STRETCH_DELETESCANS:
5050 get_rop_codes( R2_COPYPEN, codes );
5051 break;
5052 case STRETCH_ORSCANS:
5053 get_rop_codes( R2_MERGEPEN, codes );
5054 break;
5055 case STRETCH_ANDSCANS:
5056 get_rop_codes( R2_MASKPEN, codes );
5057 break;
5059 return;
5062 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5063 const dib_info *src_dib, const POINT *src_start,
5064 const struct stretch_params *params, int mode,
5065 BOOL keep_dst)
5067 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5068 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5069 int err = params->err_start;
5070 int width;
5071 struct rop_codes codes;
5073 rop_codes_from_stretch_mode( mode, &codes );
5074 for (width = params->length; width; width--)
5076 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5077 dst_ptr += params->dst_inc;
5078 if (err > 0)
5080 src_ptr += params->src_inc;
5081 err += params->err_add_1;
5083 else err += params->err_add_2;
5087 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5088 const dib_info *src_dib, const POINT *src_start,
5089 const struct stretch_params *params, int mode,
5090 BOOL keep_dst)
5092 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5093 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5094 int err = params->err_start;
5095 int width;
5096 struct rop_codes codes;
5098 rop_codes_from_stretch_mode( mode, &codes );
5099 for (width = params->length; width; width--)
5101 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5102 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5103 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5104 dst_ptr += 3 * params->dst_inc;
5105 if (err > 0)
5107 src_ptr += 3 * params->src_inc;
5108 err += params->err_add_1;
5110 else err += params->err_add_2;
5114 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5115 const dib_info *src_dib, const POINT *src_start,
5116 const struct stretch_params *params, int mode,
5117 BOOL keep_dst)
5119 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5120 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5121 int err = params->err_start;
5122 int width;
5123 struct rop_codes codes;
5125 rop_codes_from_stretch_mode( mode, &codes );
5126 for (width = params->length; width; width--)
5128 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5129 dst_ptr += params->dst_inc;
5130 if (err > 0)
5132 src_ptr += params->src_inc;
5133 err += params->err_add_1;
5135 else err += params->err_add_2;
5139 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5140 const dib_info *src_dib, const POINT *src_start,
5141 const struct stretch_params *params, int mode,
5142 BOOL keep_dst)
5144 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5145 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5146 int err = params->err_start;
5147 int width;
5148 struct rop_codes codes;
5150 rop_codes_from_stretch_mode( mode, &codes );
5151 for (width = params->length; width; width--)
5153 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5154 dst_ptr += params->dst_inc;
5155 if (err > 0)
5157 src_ptr += params->src_inc;
5158 err += params->err_add_1;
5160 else err += params->err_add_2;
5164 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5165 const dib_info *src_dib, const POINT *src_start,
5166 const struct stretch_params *params, int mode,
5167 BOOL keep_dst)
5169 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5170 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5171 int err = params->err_start;
5172 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5173 struct rop_codes codes;
5174 BYTE src_val;
5176 rop_codes_from_stretch_mode( mode, &codes );
5177 for (width = params->length; width; width--)
5179 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5180 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5182 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5184 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5185 dst_ptr += params->dst_inc;
5186 dst_x += params->dst_inc;
5188 if (err > 0)
5190 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5191 src_ptr += params->src_inc;
5192 src_x += params->src_inc;
5193 err += params->err_add_1;
5195 else err += params->err_add_2;
5199 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5200 const dib_info *src_dib, const POINT *src_start,
5201 const struct stretch_params *params, int mode,
5202 BOOL keep_dst)
5204 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5205 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5206 int err = params->err_start;
5207 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5208 struct rop_codes codes;
5209 BYTE src_val;
5211 rop_codes_from_stretch_mode( mode, &codes );
5212 for (width = params->length; width; width--)
5214 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5215 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5217 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5218 dst_ptr += params->dst_inc;
5219 dst_x += params->dst_inc;
5221 if (err > 0)
5223 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5224 src_ptr += params->src_inc;
5225 src_x += params->src_inc;
5226 err += params->err_add_1;
5228 else err += params->err_add_2;
5232 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5233 const dib_info *src_dib, const POINT *src_start,
5234 const struct stretch_params *params, int mode,
5235 BOOL keep_dst)
5237 FIXME("bit count %d\n", dst_dib->bit_count);
5238 return;
5241 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5242 const dib_info *src_dib, const POINT *src_start,
5243 const struct stretch_params *params, int mode,
5244 BOOL keep_dst)
5246 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5247 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5248 int err = params->err_start;
5249 int width;
5250 struct rop_codes codes;
5251 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5252 BOOL new_pix = TRUE;
5254 rop_codes_from_stretch_mode( mode, &codes );
5255 for (width = params->length; width; width--)
5257 if (new_pix && !keep_dst) *dst_ptr = init_val;
5258 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5259 new_pix = FALSE;
5260 src_ptr += params->src_inc;
5261 if (err > 0)
5263 dst_ptr += params->dst_inc;
5264 new_pix = TRUE;
5265 err += params->err_add_1;
5267 else err += params->err_add_2;
5271 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5272 const dib_info *src_dib, const POINT *src_start,
5273 const struct stretch_params *params, int mode,
5274 BOOL keep_dst)
5276 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5277 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5278 int err = params->err_start;
5279 int width;
5280 struct rop_codes codes;
5281 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5282 BOOL new_pix = TRUE;
5284 rop_codes_from_stretch_mode( mode, &codes );
5285 for (width = params->length; width; width--)
5287 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5288 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5289 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5290 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5291 new_pix = FALSE;
5292 src_ptr += 3 * params->src_inc;
5293 if (err > 0)
5295 dst_ptr += 3 * params->dst_inc;
5296 new_pix = TRUE;
5297 err += params->err_add_1;
5299 else err += params->err_add_2;
5303 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5304 const dib_info *src_dib, const POINT *src_start,
5305 const struct stretch_params *params, int mode,
5306 BOOL keep_dst)
5308 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5309 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5310 int err = params->err_start;
5311 int width;
5312 struct rop_codes codes;
5313 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5314 BOOL new_pix = TRUE;
5316 rop_codes_from_stretch_mode( mode, &codes );
5317 for (width = params->length; width; width--)
5319 if (new_pix && !keep_dst) *dst_ptr = init_val;
5320 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5321 new_pix = FALSE;
5322 src_ptr += params->src_inc;
5323 if (err > 0)
5325 dst_ptr += params->dst_inc;
5326 new_pix = TRUE;
5327 err += params->err_add_1;
5329 else err += params->err_add_2;
5333 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5334 const dib_info *src_dib, const POINT *src_start,
5335 const struct stretch_params *params, int mode,
5336 BOOL keep_dst)
5338 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5339 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5340 int err = params->err_start;
5341 int width;
5342 struct rop_codes codes;
5343 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5344 BOOL new_pix = TRUE;
5346 rop_codes_from_stretch_mode( mode, &codes );
5347 for (width = params->length; width; width--)
5349 if (new_pix && !keep_dst) *dst_ptr = init_val;
5350 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5351 new_pix = FALSE;
5352 src_ptr += params->src_inc;
5353 if (err > 0)
5355 dst_ptr += params->dst_inc;
5356 new_pix = TRUE;
5357 err += params->err_add_1;
5359 else err += params->err_add_2;
5363 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5364 const dib_info *src_dib, const POINT *src_start,
5365 const struct stretch_params *params, int mode,
5366 BOOL keep_dst)
5368 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5369 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5370 int err = params->err_start;
5371 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5372 struct rop_codes codes;
5373 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5374 BOOL new_pix = TRUE;
5376 rop_codes_from_stretch_mode( mode, &codes );
5377 for (width = params->length; width; width--)
5379 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
5381 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5382 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5384 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5385 new_pix = FALSE;
5387 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5388 src_ptr += params->src_inc;
5389 src_x += params->src_inc;
5391 if (err > 0)
5393 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5394 dst_ptr += params->dst_inc;
5395 dst_x += params->dst_inc;
5396 new_pix = TRUE;
5397 err += params->err_add_1;
5399 else err += params->err_add_2;
5403 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5404 const dib_info *src_dib, const POINT *src_start,
5405 const struct stretch_params *params, int mode,
5406 BOOL keep_dst)
5408 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5409 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5410 int err = params->err_start;
5411 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5412 struct rop_codes codes;
5413 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5414 BOOL new_pix = TRUE;
5416 rop_codes_from_stretch_mode( mode, &codes );
5417 for (width = params->length; width; width--)
5419 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5420 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5421 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5422 new_pix = FALSE;
5424 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5425 src_ptr += params->src_inc;
5426 src_x += params->src_inc;
5428 if (err > 0)
5430 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5431 dst_ptr += params->dst_inc;
5432 dst_x += params->dst_inc;
5433 new_pix = TRUE;
5434 err += params->err_add_1;
5436 else err += params->err_add_2;
5440 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5441 const dib_info *src_dib, const POINT *src_start,
5442 const struct stretch_params *params, int mode,
5443 BOOL keep_dst)
5445 FIXME("bit count %d\n", dst_dib->bit_count);
5446 return;
5449 const primitive_funcs funcs_8888 =
5451 solid_rects_32,
5452 solid_line_32,
5453 pattern_rects_32,
5454 copy_rect_32,
5455 blend_rect_8888,
5456 gradient_rect_8888,
5457 draw_glyph_8888,
5458 get_pixel_32,
5459 colorref_to_pixel_888,
5460 pixel_to_colorref_888,
5461 convert_to_8888,
5462 create_rop_masks_32,
5463 stretch_row_32,
5464 shrink_row_32
5467 const primitive_funcs funcs_32 =
5469 solid_rects_32,
5470 solid_line_32,
5471 pattern_rects_32,
5472 copy_rect_32,
5473 blend_rect_32,
5474 gradient_rect_32,
5475 draw_glyph_32,
5476 get_pixel_32,
5477 colorref_to_pixel_masks,
5478 pixel_to_colorref_masks,
5479 convert_to_32,
5480 create_rop_masks_32,
5481 stretch_row_32,
5482 shrink_row_32
5485 const primitive_funcs funcs_24 =
5487 solid_rects_24,
5488 solid_line_24,
5489 pattern_rects_24,
5490 copy_rect_24,
5491 blend_rect_24,
5492 gradient_rect_24,
5493 draw_glyph_24,
5494 get_pixel_24,
5495 colorref_to_pixel_888,
5496 pixel_to_colorref_888,
5497 convert_to_24,
5498 create_rop_masks_24,
5499 stretch_row_24,
5500 shrink_row_24
5503 const primitive_funcs funcs_555 =
5505 solid_rects_16,
5506 solid_line_16,
5507 pattern_rects_16,
5508 copy_rect_16,
5509 blend_rect_555,
5510 gradient_rect_555,
5511 draw_glyph_555,
5512 get_pixel_16,
5513 colorref_to_pixel_555,
5514 pixel_to_colorref_555,
5515 convert_to_555,
5516 create_rop_masks_16,
5517 stretch_row_16,
5518 shrink_row_16
5521 const primitive_funcs funcs_16 =
5523 solid_rects_16,
5524 solid_line_16,
5525 pattern_rects_16,
5526 copy_rect_16,
5527 blend_rect_16,
5528 gradient_rect_16,
5529 draw_glyph_16,
5530 get_pixel_16,
5531 colorref_to_pixel_masks,
5532 pixel_to_colorref_masks,
5533 convert_to_16,
5534 create_rop_masks_16,
5535 stretch_row_16,
5536 shrink_row_16
5539 const primitive_funcs funcs_8 =
5541 solid_rects_8,
5542 solid_line_8,
5543 pattern_rects_8,
5544 copy_rect_8,
5545 blend_rect_8,
5546 gradient_rect_8,
5547 draw_glyph_8,
5548 get_pixel_8,
5549 colorref_to_pixel_colortable,
5550 pixel_to_colorref_colortable,
5551 convert_to_8,
5552 create_rop_masks_8,
5553 stretch_row_8,
5554 shrink_row_8
5557 const primitive_funcs funcs_4 =
5559 solid_rects_4,
5560 solid_line_4,
5561 pattern_rects_4,
5562 copy_rect_4,
5563 blend_rect_4,
5564 gradient_rect_4,
5565 draw_glyph_4,
5566 get_pixel_4,
5567 colorref_to_pixel_colortable,
5568 pixel_to_colorref_colortable,
5569 convert_to_4,
5570 create_rop_masks_4,
5571 stretch_row_4,
5572 shrink_row_4
5575 const primitive_funcs funcs_1 =
5577 solid_rects_1,
5578 solid_line_1,
5579 pattern_rects_1,
5580 copy_rect_1,
5581 blend_rect_1,
5582 gradient_rect_1,
5583 draw_glyph_1,
5584 get_pixel_1,
5585 colorref_to_pixel_colortable,
5586 pixel_to_colorref_colortable,
5587 convert_to_1,
5588 create_rop_masks_1,
5589 stretch_row_1,
5590 shrink_row_1
5593 const primitive_funcs funcs_null =
5595 solid_rects_null,
5596 solid_line_null,
5597 pattern_rects_null,
5598 copy_rect_null,
5599 blend_rect_null,
5600 gradient_rect_null,
5601 draw_glyph_null,
5602 get_pixel_null,
5603 colorref_to_pixel_null,
5604 pixel_to_colorref_null,
5605 convert_to_null,
5606 create_rop_masks_null,
5607 stretch_row_null,
5608 shrink_row_null