gdi32: Pass a rop_mask_bits object to the pattern_rects primitive.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blob74b8f6f63275be97daee0a174780d2f42e3c7982
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 int i, best_index = 0;
1397 DWORD diff, best_diff = 0xffffffff;
1399 /* special case for conversion to 1-bpp without a color table:
1400 * we get a 1-entry table containing the background color
1402 if (dib->bit_count == 1 && dib->color_table_size == 1)
1403 return (r == dib->color_table[0].rgbRed &&
1404 g == dib->color_table[0].rgbGreen &&
1405 b == dib->color_table[0].rgbBlue);
1407 for(i = 0; i < dib->color_table_size; i++)
1409 const RGBQUAD *cur = dib->color_table + i;
1410 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1411 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1412 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1414 if(diff == 0)
1416 best_index = i;
1417 break;
1420 if(diff < best_diff)
1422 best_diff = diff;
1423 best_index = i;
1426 return best_index;
1429 static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, BYTE r, BYTE g, BYTE b)
1431 DWORD ret;
1433 if (!dither)
1434 ret = rgb_to_pixel_colortable( dib, r, g, b );
1435 else
1436 ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255;
1438 return ret ? 0xff : 0;
1441 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1443 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1446 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1448 return 0;
1451 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1453 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1456 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1458 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1459 get_field( pixel, dib->green_shift, dib->green_len ),
1460 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1463 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1465 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1466 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1467 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1470 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1472 if (pixel < dib->color_table_size)
1474 RGBQUAD quad = dib->color_table[pixel];
1475 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1477 return 0;
1480 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1482 return 0;
1485 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1487 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1489 return d1->red_mask == d2->red_mask &&
1490 d1->green_mask == d2->green_mask &&
1491 d1->blue_mask == d2->blue_mask;
1494 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1496 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1497 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1499 switch(src->bit_count)
1501 case 32:
1503 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1504 if(src->funcs == &funcs_8888)
1506 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1507 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1508 else
1510 for(y = src_rect->top; y < src_rect->bottom; y++)
1512 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1513 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1514 dst_start += dst->stride / 4;
1515 src_start += src->stride / 4;
1519 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1521 for(y = src_rect->top; y < src_rect->bottom; y++)
1523 dst_pixel = dst_start;
1524 src_pixel = src_start;
1525 for(x = src_rect->left; x < src_rect->right; x++)
1527 src_val = *src_pixel++;
1528 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1529 (((src_val >> src->green_shift) & 0xff) << 8) |
1530 ((src_val >> src->blue_shift) & 0xff);
1532 if(pad_size) memset(dst_pixel, 0, pad_size);
1533 dst_start += dst->stride / 4;
1534 src_start += src->stride / 4;
1537 else
1539 for(y = src_rect->top; y < src_rect->bottom; y++)
1541 dst_pixel = dst_start;
1542 src_pixel = src_start;
1543 for(x = src_rect->left; x < src_rect->right; x++)
1545 src_val = *src_pixel++;
1546 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1547 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1548 get_field( src_val, src->blue_shift, src->blue_len ));
1550 if(pad_size) memset(dst_pixel, 0, pad_size);
1551 dst_start += dst->stride / 4;
1552 src_start += src->stride / 4;
1555 break;
1558 case 24:
1560 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1562 for(y = src_rect->top; y < src_rect->bottom; y++)
1564 dst_pixel = dst_start;
1565 src_pixel = src_start;
1566 for(x = src_rect->left; x < src_rect->right; x++)
1568 RGBQUAD rgb;
1569 rgb.rgbBlue = *src_pixel++;
1570 rgb.rgbGreen = *src_pixel++;
1571 rgb.rgbRed = *src_pixel++;
1573 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1575 if(pad_size) memset(dst_pixel, 0, pad_size);
1576 dst_start += dst->stride / 4;
1577 src_start += src->stride;
1579 break;
1582 case 16:
1584 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1585 if(src->funcs == &funcs_555)
1587 for(y = src_rect->top; y < src_rect->bottom; y++)
1589 dst_pixel = dst_start;
1590 src_pixel = src_start;
1591 for(x = src_rect->left; x < src_rect->right; x++)
1593 src_val = *src_pixel++;
1594 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1595 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1596 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1598 if(pad_size) memset(dst_pixel, 0, pad_size);
1599 dst_start += dst->stride / 4;
1600 src_start += src->stride / 2;
1603 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1605 for(y = src_rect->top; y < src_rect->bottom; y++)
1607 dst_pixel = dst_start;
1608 src_pixel = src_start;
1609 for(x = src_rect->left; x < src_rect->right; x++)
1611 src_val = *src_pixel++;
1612 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1613 (((src_val >> src->red_shift) << 14) & 0x070000) |
1614 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1615 (((src_val >> src->green_shift) << 6) & 0x000700) |
1616 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1617 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1619 if(pad_size) memset(dst_pixel, 0, pad_size);
1620 dst_start += dst->stride / 4;
1621 src_start += src->stride / 2;
1624 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1626 for(y = src_rect->top; y < src_rect->bottom; y++)
1628 dst_pixel = dst_start;
1629 src_pixel = src_start;
1630 for(x = src_rect->left; x < src_rect->right; x++)
1632 src_val = *src_pixel++;
1633 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1634 (((src_val >> src->red_shift) << 14) & 0x070000) |
1635 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1636 (((src_val >> src->green_shift) << 4) & 0x000300) |
1637 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1638 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1640 if(pad_size) memset(dst_pixel, 0, pad_size);
1641 dst_start += dst->stride / 4;
1642 src_start += src->stride / 2;
1645 else
1647 for(y = src_rect->top; y < src_rect->bottom; y++)
1649 dst_pixel = dst_start;
1650 src_pixel = src_start;
1651 for(x = src_rect->left; x < src_rect->right; x++)
1653 src_val = *src_pixel++;
1654 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1655 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1656 get_field( src_val, src->blue_shift, src->blue_len ));
1658 if(pad_size) memset(dst_pixel, 0, pad_size);
1659 dst_start += dst->stride / 4;
1660 src_start += src->stride / 2;
1663 break;
1666 case 8:
1668 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1669 for(y = src_rect->top; y < src_rect->bottom; y++)
1671 dst_pixel = dst_start;
1672 src_pixel = src_start;
1673 for(x = src_rect->left; x < src_rect->right; x++)
1675 RGBQUAD rgb = src->color_table[*src_pixel++];
1676 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1678 if(pad_size) memset(dst_pixel, 0, pad_size);
1679 dst_start += dst->stride / 4;
1680 src_start += src->stride;
1682 break;
1685 case 4:
1687 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1688 for(y = src_rect->top; y < src_rect->bottom; y++)
1690 int pos = (src->rect.left + src_rect->left) & 1;
1691 src_pixel = src_start;
1692 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1694 RGBQUAD rgb;
1695 if (pos & 1)
1696 rgb = src->color_table[*src_pixel++ & 0xf];
1697 else
1698 rgb = src->color_table[*src_pixel >> 4];
1699 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1701 if(pad_size) memset(dst_start + x, 0, pad_size);
1702 dst_start += dst->stride / 4;
1703 src_start += src->stride;
1705 break;
1708 case 1:
1710 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1711 for(y = src_rect->top; y < src_rect->bottom; y++)
1713 int pos = (src->rect.left + src_rect->left) & 7;
1714 for(x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1716 RGBQUAD rgb;
1717 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1718 rgb = src->color_table[src_val];
1719 dst_start[x] = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1721 if(pad_size) memset(dst_start + x, 0, pad_size);
1722 dst_start += dst->stride / 4;
1723 src_start += src->stride;
1725 break;
1730 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1732 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1733 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1735 switch(src->bit_count)
1737 case 32:
1739 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1741 if(src->funcs == &funcs_8888)
1743 for(y = src_rect->top; y < src_rect->bottom; y++)
1745 dst_pixel = dst_start;
1746 src_pixel = src_start;
1747 for(x = src_rect->left; x < src_rect->right; x++)
1749 src_val = *src_pixel++;
1750 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1751 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1752 put_field(src_val, dst->blue_shift, dst->blue_len);
1754 if(pad_size) memset(dst_pixel, 0, pad_size);
1755 dst_start += dst->stride / 4;
1756 src_start += src->stride / 4;
1759 else if(bit_fields_match(src, dst))
1761 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
1762 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1763 else
1765 for(y = src_rect->top; y < src_rect->bottom; y++)
1767 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1768 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1769 dst_start += dst->stride / 4;
1770 src_start += src->stride / 4;
1774 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1775 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1777 for(y = src_rect->top; y < src_rect->bottom; y++)
1779 dst_pixel = dst_start;
1780 src_pixel = src_start;
1781 for(x = src_rect->left; x < src_rect->right; x++)
1783 src_val = *src_pixel++;
1784 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1785 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1786 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1788 if(pad_size) memset(dst_pixel, 0, pad_size);
1789 dst_start += dst->stride / 4;
1790 src_start += src->stride / 4;
1793 else
1795 for(y = src_rect->top; y < src_rect->bottom; y++)
1797 dst_pixel = dst_start;
1798 src_pixel = src_start;
1799 for(x = src_rect->left; x < src_rect->right; x++)
1801 src_val = *src_pixel++;
1802 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1803 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1804 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1806 if(pad_size) memset(dst_pixel, 0, pad_size);
1807 dst_start += dst->stride / 4;
1808 src_start += src->stride / 4;
1811 break;
1814 case 24:
1816 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1818 for(y = src_rect->top; y < src_rect->bottom; y++)
1820 dst_pixel = dst_start;
1821 src_pixel = src_start;
1822 for(x = src_rect->left; x < src_rect->right; x++)
1824 RGBQUAD rgb;
1825 rgb.rgbBlue = *src_pixel++;
1826 rgb.rgbGreen = *src_pixel++;
1827 rgb.rgbRed = *src_pixel++;
1829 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1830 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1831 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1833 if(pad_size) memset(dst_pixel, 0, pad_size);
1834 dst_start += dst->stride / 4;
1835 src_start += src->stride;
1837 break;
1840 case 16:
1842 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1843 if(src->funcs == &funcs_555)
1845 for(y = src_rect->top; y < src_rect->bottom; y++)
1847 dst_pixel = dst_start;
1848 src_pixel = src_start;
1849 for(x = src_rect->left; x < src_rect->right; x++)
1851 src_val = *src_pixel++;
1852 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1853 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1854 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1856 if(pad_size) memset(dst_pixel, 0, pad_size);
1857 dst_start += dst->stride / 4;
1858 src_start += src->stride / 2;
1861 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1863 for(y = src_rect->top; y < src_rect->bottom; y++)
1865 dst_pixel = dst_start;
1866 src_pixel = src_start;
1867 for(x = src_rect->left; x < src_rect->right; x++)
1869 src_val = *src_pixel++;
1870 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1871 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1872 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1873 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1874 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1875 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1877 if(pad_size) memset(dst_pixel, 0, pad_size);
1878 dst_start += dst->stride / 4;
1879 src_start += src->stride / 2;
1882 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1884 for(y = src_rect->top; y < src_rect->bottom; y++)
1886 dst_pixel = dst_start;
1887 src_pixel = src_start;
1888 for(x = src_rect->left; x < src_rect->right; x++)
1890 src_val = *src_pixel++;
1891 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1892 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1893 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1894 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1895 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1896 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1898 if(pad_size) memset(dst_pixel, 0, pad_size);
1899 dst_start += dst->stride / 4;
1900 src_start += src->stride / 2;
1903 else
1905 for(y = src_rect->top; y < src_rect->bottom; y++)
1907 dst_pixel = dst_start;
1908 src_pixel = src_start;
1909 for(x = src_rect->left; x < src_rect->right; x++)
1911 src_val = *src_pixel++;
1912 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1913 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1914 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1916 if(pad_size) memset(dst_pixel, 0, pad_size);
1917 dst_start += dst->stride / 4;
1918 src_start += src->stride / 2;
1921 break;
1924 case 8:
1926 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1927 for(y = src_rect->top; y < src_rect->bottom; y++)
1929 dst_pixel = dst_start;
1930 src_pixel = src_start;
1931 for(x = src_rect->left; x < src_rect->right; x++)
1933 RGBQUAD rgb = src->color_table[*src_pixel++];
1934 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1935 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1936 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1938 if(pad_size) memset(dst_pixel, 0, pad_size);
1939 dst_start += dst->stride / 4;
1940 src_start += src->stride;
1942 break;
1945 case 4:
1947 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1948 for(y = src_rect->top; y < src_rect->bottom; y++)
1950 int pos = (src->rect.left + src_rect->left) & 1;
1951 src_pixel = src_start;
1952 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1954 RGBQUAD rgb;
1955 if (pos & 1)
1956 rgb = src->color_table[*src_pixel++ & 0xf];
1957 else
1958 rgb = src->color_table[*src_pixel >> 4];
1959 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1960 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1961 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1963 if(pad_size) memset(dst_start + x, 0, pad_size);
1964 dst_start += dst->stride / 4;
1965 src_start += src->stride;
1967 break;
1970 case 1:
1972 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
1973 for(y = src_rect->top; y < src_rect->bottom; y++)
1975 int pos = (src->rect.left + src_rect->left) & 7;
1976 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
1978 RGBQUAD rgb;
1979 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
1980 rgb = src->color_table[src_val];
1981 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1982 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1983 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1985 if(pad_size) memset(dst_start + x, 0, pad_size);
1986 dst_start += dst->stride / 4;
1987 src_start += src->stride;
1989 break;
1994 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
1996 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1997 DWORD src_val;
1998 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
2000 switch(src->bit_count)
2002 case 32:
2004 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2005 if(src->funcs == &funcs_8888)
2007 for(y = src_rect->top; y < src_rect->bottom; y++)
2009 dst_pixel = dst_start;
2010 src_pixel = src_start;
2011 for(x = src_rect->left; x < src_rect->right; x++)
2013 src_val = *src_pixel++;
2014 *dst_pixel++ = src_val & 0xff;
2015 *dst_pixel++ = (src_val >> 8) & 0xff;
2016 *dst_pixel++ = (src_val >> 16) & 0xff;
2018 if(pad_size) memset(dst_pixel, 0, pad_size);
2019 dst_start += dst->stride;
2020 src_start += src->stride / 4;
2023 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2025 for(y = src_rect->top; y < src_rect->bottom; y++)
2027 dst_pixel = dst_start;
2028 src_pixel = src_start;
2029 for(x = src_rect->left; x < src_rect->right; x++)
2031 src_val = *src_pixel++;
2032 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2033 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2034 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2036 if(pad_size) memset(dst_pixel, 0, pad_size);
2037 dst_start += dst->stride;
2038 src_start += src->stride / 4;
2041 else
2043 for(y = src_rect->top; y < src_rect->bottom; y++)
2045 dst_pixel = dst_start;
2046 src_pixel = src_start;
2047 for(x = src_rect->left; x < src_rect->right; x++)
2049 src_val = *src_pixel++;
2050 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2051 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2052 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2054 if(pad_size) memset(dst_pixel, 0, pad_size);
2055 dst_start += dst->stride;
2056 src_start += src->stride / 4;
2059 break;
2062 case 24:
2064 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2066 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2067 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2068 else
2070 for(y = src_rect->top; y < src_rect->bottom; y++)
2072 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2073 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2074 dst_start += dst->stride;
2075 src_start += src->stride;
2078 break;
2081 case 16:
2083 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2084 if(src->funcs == &funcs_555)
2086 for(y = src_rect->top; y < src_rect->bottom; y++)
2088 dst_pixel = dst_start;
2089 src_pixel = src_start;
2090 for(x = src_rect->left; x < src_rect->right; x++)
2092 src_val = *src_pixel++;
2093 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2094 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2095 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2097 if(pad_size) memset(dst_pixel, 0, pad_size);
2098 dst_start += dst->stride;
2099 src_start += src->stride / 2;
2102 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2104 for(y = src_rect->top; y < src_rect->bottom; y++)
2106 dst_pixel = dst_start;
2107 src_pixel = src_start;
2108 for(x = src_rect->left; x < src_rect->right; x++)
2110 src_val = *src_pixel++;
2111 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2112 (((src_val >> src->blue_shift) >> 2) & 0x07);
2113 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2114 (((src_val >> src->green_shift) >> 2) & 0x07);
2115 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2116 (((src_val >> src->red_shift) >> 2) & 0x07);
2118 if(pad_size) memset(dst_pixel, 0, pad_size);
2119 dst_start += dst->stride;
2120 src_start += src->stride / 2;
2123 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2125 for(y = src_rect->top; y < src_rect->bottom; y++)
2127 dst_pixel = dst_start;
2128 src_pixel = src_start;
2129 for(x = src_rect->left; x < src_rect->right; x++)
2131 src_val = *src_pixel++;
2132 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2133 (((src_val >> src->blue_shift) >> 2) & 0x07);
2134 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2135 (((src_val >> src->green_shift) >> 4) & 0x03);
2136 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2137 (((src_val >> src->red_shift) >> 2) & 0x07);
2139 if(pad_size) memset(dst_pixel, 0, pad_size);
2140 dst_start += dst->stride;
2141 src_start += src->stride / 2;
2144 else
2146 for(y = src_rect->top; y < src_rect->bottom; y++)
2148 dst_pixel = dst_start;
2149 src_pixel = src_start;
2150 for(x = src_rect->left; x < src_rect->right; x++)
2152 src_val = *src_pixel++;
2153 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2154 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2155 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2157 if(pad_size) memset(dst_pixel, 0, pad_size);
2158 dst_start += dst->stride;
2159 src_start += src->stride / 2;
2162 break;
2165 case 8:
2167 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2168 for(y = src_rect->top; y < src_rect->bottom; y++)
2170 dst_pixel = dst_start;
2171 src_pixel = src_start;
2172 for(x = src_rect->left; x < src_rect->right; x++)
2174 RGBQUAD rgb = src->color_table[*src_pixel++];
2175 *dst_pixel++ = rgb.rgbBlue;
2176 *dst_pixel++ = rgb.rgbGreen;
2177 *dst_pixel++ = rgb.rgbRed;
2179 if(pad_size) memset(dst_pixel, 0, pad_size);
2180 dst_start += dst->stride;
2181 src_start += src->stride;
2183 break;
2186 case 4:
2188 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2189 for(y = src_rect->top; y < src_rect->bottom; y++)
2191 int pos = (src->rect.left + src_rect->left) & 1;
2192 src_pixel = src_start;
2193 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2195 RGBQUAD rgb;
2196 if (pos & 1)
2197 rgb = src->color_table[*src_pixel++ & 0xf];
2198 else
2199 rgb = src->color_table[*src_pixel >> 4];
2200 dst_start[x * 3] = rgb.rgbBlue;
2201 dst_start[x * 3 + 1] = rgb.rgbGreen;
2202 dst_start[x * 3 + 2] = rgb.rgbRed;
2204 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2205 dst_start += dst->stride;
2206 src_start += src->stride;
2208 break;
2211 case 1:
2213 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2214 for(y = src_rect->top; y < src_rect->bottom; y++)
2216 int pos = (src->rect.left + src_rect->left) & 7;
2217 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2219 RGBQUAD rgb;
2220 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2221 rgb = src->color_table[src_val];
2222 dst_start[x * 3] = rgb.rgbBlue;
2223 dst_start[x * 3 + 1] = rgb.rgbGreen;
2224 dst_start[x * 3 + 2] = rgb.rgbRed;
2226 if(pad_size) memset(dst_start + x * 3, 0, pad_size);
2227 dst_start += dst->stride;
2228 src_start += src->stride;
2230 break;
2235 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2237 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2238 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2239 DWORD src_val;
2241 switch(src->bit_count)
2243 case 32:
2245 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2247 if(src->funcs == &funcs_8888)
2249 for(y = src_rect->top; y < src_rect->bottom; y++)
2251 dst_pixel = dst_start;
2252 src_pixel = src_start;
2253 for(x = src_rect->left; x < src_rect->right; x++)
2255 src_val = *src_pixel++;
2256 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2257 ((src_val >> 6) & 0x03e0) |
2258 ((src_val >> 3) & 0x001f);
2260 if(pad_size) memset(dst_pixel, 0, pad_size);
2261 dst_start += dst->stride / 2;
2262 src_start += src->stride / 4;
2265 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2267 for(y = src_rect->top; y < src_rect->bottom; y++)
2269 dst_pixel = dst_start;
2270 src_pixel = src_start;
2271 for(x = src_rect->left; x < src_rect->right; x++)
2273 src_val = *src_pixel++;
2274 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2275 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2276 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2278 if(pad_size) memset(dst_pixel, 0, pad_size);
2279 dst_start += dst->stride / 2;
2280 src_start += src->stride / 4;
2283 else
2285 for(y = src_rect->top; y < src_rect->bottom; y++)
2287 dst_pixel = dst_start;
2288 src_pixel = src_start;
2289 for(x = src_rect->left; x < src_rect->right; x++)
2291 src_val = *src_pixel++;
2292 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2293 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2294 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2296 if(pad_size) memset(dst_pixel, 0, pad_size);
2297 dst_start += dst->stride / 2;
2298 src_start += src->stride / 4;
2301 break;
2304 case 24:
2306 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2308 for(y = src_rect->top; y < src_rect->bottom; y++)
2310 dst_pixel = dst_start;
2311 src_pixel = src_start;
2312 for(x = src_rect->left; x < src_rect->right; x++)
2314 RGBQUAD rgb;
2315 rgb.rgbBlue = *src_pixel++;
2316 rgb.rgbGreen = *src_pixel++;
2317 rgb.rgbRed = *src_pixel++;
2319 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2320 ((rgb.rgbGreen << 2) & 0x03e0) |
2321 ((rgb.rgbBlue >> 3) & 0x001f);
2323 if(pad_size) memset(dst_pixel, 0, pad_size);
2324 dst_start += dst->stride / 2;
2325 src_start += src->stride;
2327 break;
2330 case 16:
2332 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2333 if(src->funcs == &funcs_555)
2335 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2336 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2337 else
2339 for(y = src_rect->top; y < src_rect->bottom; y++)
2341 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2342 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2343 dst_start += dst->stride / 2;
2344 src_start += src->stride / 2;
2348 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2350 for(y = src_rect->top; y < src_rect->bottom; y++)
2352 dst_pixel = dst_start;
2353 src_pixel = src_start;
2354 for(x = src_rect->left; x < src_rect->right; x++)
2356 src_val = *src_pixel++;
2357 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2358 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2359 ( (src_val >> src->blue_shift) & 0x001f);
2361 if(pad_size) memset(dst_pixel, 0, pad_size);
2362 dst_start += dst->stride / 2;
2363 src_start += src->stride / 2;
2366 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2368 for(y = src_rect->top; y < src_rect->bottom; y++)
2370 dst_pixel = dst_start;
2371 src_pixel = src_start;
2372 for(x = src_rect->left; x < src_rect->right; x++)
2374 src_val = *src_pixel++;
2375 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2376 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2377 ( (src_val >> src->blue_shift) & 0x001f);
2379 if(pad_size) memset(dst_pixel, 0, pad_size);
2380 dst_start += dst->stride / 2;
2381 src_start += src->stride / 2;
2384 else
2386 for(y = src_rect->top; y < src_rect->bottom; y++)
2388 dst_pixel = dst_start;
2389 src_pixel = src_start;
2390 for(x = src_rect->left; x < src_rect->right; x++)
2392 src_val = *src_pixel++;
2393 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2394 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2395 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2397 if(pad_size) memset(dst_pixel, 0, pad_size);
2398 dst_start += dst->stride / 2;
2399 src_start += src->stride / 2;
2402 break;
2405 case 8:
2407 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2408 for(y = src_rect->top; y < src_rect->bottom; y++)
2410 dst_pixel = dst_start;
2411 src_pixel = src_start;
2412 for(x = src_rect->left; x < src_rect->right; x++)
2414 RGBQUAD rgb = src->color_table[*src_pixel++];
2415 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2416 ((rgb.rgbGreen << 2) & 0x03e0) |
2417 ((rgb.rgbBlue >> 3) & 0x001f);
2419 if(pad_size) memset(dst_pixel, 0, pad_size);
2420 dst_start += dst->stride / 2;
2421 src_start += src->stride;
2423 break;
2426 case 4:
2428 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2429 for(y = src_rect->top; y < src_rect->bottom; y++)
2431 int pos = (src->rect.left + src_rect->left) & 1;
2432 src_pixel = src_start;
2433 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2435 RGBQUAD rgb;
2436 if (pos & 1)
2437 rgb = src->color_table[*src_pixel++ & 0xf];
2438 else
2439 rgb = src->color_table[*src_pixel >> 4];
2440 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2441 ((rgb.rgbGreen << 2) & 0x03e0) |
2442 ((rgb.rgbBlue >> 3) & 0x001f);
2444 if(pad_size) memset(dst_start + x, 0, pad_size);
2445 dst_start += dst->stride / 2;
2446 src_start += src->stride;
2448 break;
2451 case 1:
2453 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2454 for(y = src_rect->top; y < src_rect->bottom; y++)
2456 int pos = (src->rect.left + src_rect->left) & 7;
2457 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2459 RGBQUAD rgb;
2460 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2461 rgb = src->color_table[src_val];
2462 dst_start[x] = ((rgb.rgbRed << 7) & 0x7c00) |
2463 ((rgb.rgbGreen << 2) & 0x03e0) |
2464 ((rgb.rgbBlue >> 3) & 0x001f);
2466 if(pad_size) memset(dst_start + x, 0, pad_size);
2467 dst_start += dst->stride / 2;
2468 src_start += src->stride;
2470 break;
2475 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2477 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2478 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2479 DWORD src_val;
2481 switch(src->bit_count)
2483 case 32:
2485 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2487 if(src->funcs == &funcs_8888)
2489 for(y = src_rect->top; y < src_rect->bottom; y++)
2491 dst_pixel = dst_start;
2492 src_pixel = src_start;
2493 for(x = src_rect->left; x < src_rect->right; x++)
2495 src_val = *src_pixel++;
2496 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2497 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2498 put_field(src_val, dst->blue_shift, dst->blue_len);
2500 if(pad_size) memset(dst_pixel, 0, pad_size);
2501 dst_start += dst->stride / 2;
2502 src_start += src->stride / 4;
2505 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2507 for(y = src_rect->top; y < src_rect->bottom; y++)
2509 dst_pixel = dst_start;
2510 src_pixel = src_start;
2511 for(x = src_rect->left; x < src_rect->right; x++)
2513 src_val = *src_pixel++;
2514 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2515 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2516 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2518 if(pad_size) memset(dst_pixel, 0, pad_size);
2519 dst_start += dst->stride / 2;
2520 src_start += src->stride / 4;
2523 else
2525 for(y = src_rect->top; y < src_rect->bottom; y++)
2527 dst_pixel = dst_start;
2528 src_pixel = src_start;
2529 for(x = src_rect->left; x < src_rect->right; x++)
2531 src_val = *src_pixel++;
2532 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2533 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2534 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2536 if(pad_size) memset(dst_pixel, 0, pad_size);
2537 dst_start += dst->stride / 2;
2538 src_start += src->stride / 4;
2541 break;
2544 case 24:
2546 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2548 for(y = src_rect->top; y < src_rect->bottom; y++)
2550 dst_pixel = dst_start;
2551 src_pixel = src_start;
2552 for(x = src_rect->left; x < src_rect->right; x++)
2554 RGBQUAD rgb;
2555 rgb.rgbBlue = *src_pixel++;
2556 rgb.rgbGreen = *src_pixel++;
2557 rgb.rgbRed = *src_pixel++;
2559 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2560 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2561 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2563 if(pad_size) memset(dst_pixel, 0, pad_size);
2564 dst_start += dst->stride / 2;
2565 src_start += src->stride;
2567 break;
2570 case 16:
2572 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2573 if(src->funcs == &funcs_555)
2575 for(y = src_rect->top; y < src_rect->bottom; y++)
2577 dst_pixel = dst_start;
2578 src_pixel = src_start;
2579 for(x = src_rect->left; x < src_rect->right; x++)
2581 src_val = *src_pixel++;
2582 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2583 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2584 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2586 if(pad_size) memset(dst_pixel, 0, pad_size);
2587 dst_start += dst->stride / 2;
2588 src_start += src->stride / 2;
2591 else if(bit_fields_match(src, dst))
2593 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2594 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2595 else
2597 for(y = src_rect->top; y < src_rect->bottom; y++)
2599 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2600 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2601 dst_start += dst->stride / 2;
2602 src_start += src->stride / 2;
2606 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2608 for(y = src_rect->top; y < src_rect->bottom; y++)
2610 dst_pixel = dst_start;
2611 src_pixel = src_start;
2612 for(x = src_rect->left; x < src_rect->right; x++)
2614 src_val = *src_pixel++;
2615 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2616 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2617 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2618 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2619 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2620 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2622 if(pad_size) memset(dst_pixel, 0, pad_size);
2623 dst_start += dst->stride / 2;
2624 src_start += src->stride / 2;
2627 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2629 for(y = src_rect->top; y < src_rect->bottom; y++)
2631 dst_pixel = dst_start;
2632 src_pixel = src_start;
2633 for(x = src_rect->left; x < src_rect->right; x++)
2635 src_val = *src_pixel++;
2636 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2637 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2638 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2639 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2640 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2641 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2643 if(pad_size) memset(dst_pixel, 0, pad_size);
2644 dst_start += dst->stride / 2;
2645 src_start += src->stride / 2;
2648 else
2650 for(y = src_rect->top; y < src_rect->bottom; y++)
2652 dst_pixel = dst_start;
2653 src_pixel = src_start;
2654 for(x = src_rect->left; x < src_rect->right; x++)
2656 src_val = *src_pixel++;
2657 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2658 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2659 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2661 if(pad_size) memset(dst_pixel, 0, pad_size);
2662 dst_start += dst->stride / 2;
2663 src_start += src->stride / 2;
2666 break;
2669 case 8:
2671 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2672 for(y = src_rect->top; y < src_rect->bottom; y++)
2674 dst_pixel = dst_start;
2675 src_pixel = src_start;
2676 for(x = src_rect->left; x < src_rect->right; x++)
2678 RGBQUAD rgb = src->color_table[*src_pixel++];
2679 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2680 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2681 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2683 if(pad_size) memset(dst_pixel, 0, pad_size);
2684 dst_start += dst->stride / 2;
2685 src_start += src->stride;
2687 break;
2690 case 4:
2692 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2693 for(y = src_rect->top; y < src_rect->bottom; y++)
2695 int pos = (src->rect.left + src_rect->left) & 1;
2696 src_pixel = src_start;
2697 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2699 RGBQUAD rgb;
2700 if (pos & 1)
2701 rgb = src->color_table[*src_pixel++ & 0xf];
2702 else
2703 rgb = src->color_table[*src_pixel >> 4];
2704 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2705 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2706 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2708 if(pad_size) memset(dst_start + x, 0, pad_size);
2709 dst_start += dst->stride / 2;
2710 src_start += src->stride;
2712 break;
2715 case 1:
2717 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2718 for(y = src_rect->top; y < src_rect->bottom; y++)
2720 int pos = (src->rect.left + src_rect->left) & 7;
2721 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2723 RGBQUAD rgb;
2724 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2725 rgb = src->color_table[src_val];
2726 dst_start[x] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2727 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2728 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2730 if(pad_size) memset(dst_start + x, 0, pad_size);
2731 dst_start += dst->stride / 2;
2732 src_start += src->stride;
2734 break;
2739 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2741 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
2744 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2746 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2747 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2750 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
2752 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2753 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2754 DWORD src_val;
2756 switch(src->bit_count)
2758 case 32:
2760 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2762 if(src->funcs == &funcs_8888)
2764 for(y = src_rect->top; y < src_rect->bottom; y++)
2766 dst_pixel = dst_start;
2767 src_pixel = src_start;
2768 for(x = src_rect->left; x < src_rect->right; x++)
2770 src_val = *src_pixel++;
2771 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2773 if(pad_size) memset(dst_pixel, 0, pad_size);
2774 dst_start += dst->stride;
2775 src_start += src->stride / 4;
2778 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2780 for(y = src_rect->top; y < src_rect->bottom; y++)
2782 dst_pixel = dst_start;
2783 src_pixel = src_start;
2784 for(x = src_rect->left; x < src_rect->right; x++)
2786 src_val = *src_pixel++;
2787 *dst_pixel++ = rgb_lookup_colortable(dst,
2788 src_val >> src->red_shift,
2789 src_val >> src->green_shift,
2790 src_val >> src->blue_shift );
2792 if(pad_size) memset(dst_pixel, 0, pad_size);
2793 dst_start += dst->stride;
2794 src_start += src->stride / 4;
2797 else
2799 for(y = src_rect->top; y < src_rect->bottom; y++)
2801 dst_pixel = dst_start;
2802 src_pixel = src_start;
2803 for(x = src_rect->left; x < src_rect->right; x++)
2805 src_val = *src_pixel++;
2806 *dst_pixel++ = rgb_lookup_colortable(dst,
2807 get_field(src_val, src->red_shift, src->red_len),
2808 get_field(src_val, src->green_shift, src->green_len),
2809 get_field(src_val, src->blue_shift, src->blue_len));
2811 if(pad_size) memset(dst_pixel, 0, pad_size);
2812 dst_start += dst->stride;
2813 src_start += src->stride / 4;
2816 break;
2819 case 24:
2821 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2823 for(y = src_rect->top; y < src_rect->bottom; y++)
2825 dst_pixel = dst_start;
2826 src_pixel = src_start;
2827 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2829 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2831 if(pad_size) memset(dst_pixel, 0, pad_size);
2832 dst_start += dst->stride;
2833 src_start += src->stride;
2835 break;
2838 case 16:
2840 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2841 if(src->funcs == &funcs_555)
2843 for(y = src_rect->top; y < src_rect->bottom; y++)
2845 dst_pixel = dst_start;
2846 src_pixel = src_start;
2847 for(x = src_rect->left; x < src_rect->right; x++)
2849 src_val = *src_pixel++;
2850 *dst_pixel++ = rgb_lookup_colortable(dst,
2851 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2852 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2853 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2855 if(pad_size) memset(dst_pixel, 0, pad_size);
2856 dst_start += dst->stride;
2857 src_start += src->stride / 2;
2860 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2862 for(y = src_rect->top; y < src_rect->bottom; y++)
2864 dst_pixel = dst_start;
2865 src_pixel = src_start;
2866 for(x = src_rect->left; x < src_rect->right; x++)
2868 src_val = *src_pixel++;
2869 *dst_pixel++ = rgb_lookup_colortable(dst,
2870 (((src_val >> src->red_shift) << 3) & 0xf8) |
2871 (((src_val >> src->red_shift) >> 2) & 0x07),
2872 (((src_val >> src->green_shift) << 3) & 0xf8) |
2873 (((src_val >> src->green_shift) >> 2) & 0x07),
2874 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2875 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2877 if(pad_size) memset(dst_pixel, 0, pad_size);
2878 dst_start += dst->stride;
2879 src_start += src->stride / 2;
2882 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2884 for(y = src_rect->top; y < src_rect->bottom; y++)
2886 dst_pixel = dst_start;
2887 src_pixel = src_start;
2888 for(x = src_rect->left; x < src_rect->right; x++)
2890 src_val = *src_pixel++;
2891 *dst_pixel++ = rgb_lookup_colortable(dst,
2892 (((src_val >> src->red_shift) << 3) & 0xf8) |
2893 (((src_val >> src->red_shift) >> 2) & 0x07),
2894 (((src_val >> src->green_shift) << 2) & 0xfc) |
2895 (((src_val >> src->green_shift) >> 4) & 0x03),
2896 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2897 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2899 if(pad_size) memset(dst_pixel, 0, pad_size);
2900 dst_start += dst->stride;
2901 src_start += src->stride / 2;
2904 else
2906 for(y = src_rect->top; y < src_rect->bottom; y++)
2908 dst_pixel = dst_start;
2909 src_pixel = src_start;
2910 for(x = src_rect->left; x < src_rect->right; x++)
2912 src_val = *src_pixel++;
2913 *dst_pixel++ = rgb_lookup_colortable(dst,
2914 get_field(src_val, src->red_shift, src->red_len),
2915 get_field(src_val, src->green_shift, src->green_len),
2916 get_field(src_val, src->blue_shift, src->blue_len));
2918 if(pad_size) memset(dst_pixel, 0, pad_size);
2919 dst_start += dst->stride;
2920 src_start += src->stride / 2;
2923 break;
2926 case 8:
2928 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2930 if(color_tables_match(dst, src))
2932 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
2933 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2934 else
2936 for(y = src_rect->top; y < src_rect->bottom; y++)
2938 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2939 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2940 dst_start += dst->stride;
2941 src_start += src->stride;
2945 else
2947 for(y = src_rect->top; y < src_rect->bottom; y++)
2949 dst_pixel = dst_start;
2950 src_pixel = src_start;
2951 for(x = src_rect->left; x < src_rect->right; x++)
2953 RGBQUAD rgb = src->color_table[*src_pixel++];
2954 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2956 if(pad_size) memset(dst_pixel, 0, pad_size);
2957 dst_start += dst->stride;
2958 src_start += src->stride;
2961 break;
2964 case 4:
2966 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2967 for(y = src_rect->top; y < src_rect->bottom; y++)
2969 int pos = (src->rect.left + src_rect->left) & 1;
2970 src_pixel = src_start;
2971 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2973 RGBQUAD rgb;
2974 if (pos & 1)
2975 rgb = src->color_table[*src_pixel++ & 0xf];
2976 else
2977 rgb = src->color_table[*src_pixel >> 4];
2978 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2980 if(pad_size) memset(dst_start + x, 0, pad_size);
2981 dst_start += dst->stride;
2982 src_start += src->stride;
2984 break;
2987 case 1:
2989 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
2990 for(y = src_rect->top; y < src_rect->bottom; y++)
2992 int pos = (src->rect.left + src_rect->left) & 7;
2993 for (x = 0; x < src_rect->right - src_rect->left; x++, pos++)
2995 RGBQUAD rgb;
2996 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
2997 rgb = src->color_table[src_val];
2998 dst_start[x] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3000 if(pad_size) memset(dst_start + x, 0, pad_size);
3001 dst_start += dst->stride;
3002 src_start += src->stride;
3004 break;
3009 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3011 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3012 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3013 DWORD src_val;
3015 switch(src->bit_count)
3017 case 32:
3019 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3021 if(src->funcs == &funcs_8888)
3023 for(y = src_rect->top; y < src_rect->bottom; y++)
3025 dst_pixel = dst_start;
3026 src_pixel = src_start;
3027 for(x = src_rect->left; x < src_rect->right; x++)
3029 src_val = *src_pixel++;
3030 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3031 if((x - src_rect->left) & 1)
3033 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3034 dst_pixel++;
3036 else
3037 *dst_pixel = (dst_val << 4) & 0xf0;
3039 if(pad_size)
3041 if((x - src_rect->left) & 1) dst_pixel++;
3042 memset(dst_pixel, 0, pad_size);
3044 dst_start += dst->stride;
3045 src_start += src->stride / 4;
3048 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3050 for(y = src_rect->top; y < src_rect->bottom; y++)
3052 dst_pixel = dst_start;
3053 src_pixel = src_start;
3054 for(x = src_rect->left; x < src_rect->right; x++)
3056 src_val = *src_pixel++;
3057 dst_val = rgb_to_pixel_colortable(dst,
3058 src_val >> src->red_shift,
3059 src_val >> src->green_shift,
3060 src_val >> src->blue_shift);
3061 if((x - src_rect->left) & 1)
3063 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3064 dst_pixel++;
3066 else
3067 *dst_pixel = (dst_val << 4) & 0xf0;
3069 if(pad_size)
3071 if((x - src_rect->left) & 1) dst_pixel++;
3072 memset(dst_pixel, 0, pad_size);
3074 dst_start += dst->stride;
3075 src_start += src->stride / 4;
3078 else
3080 for(y = src_rect->top; y < src_rect->bottom; y++)
3082 dst_pixel = dst_start;
3083 src_pixel = src_start;
3084 for(x = src_rect->left; x < src_rect->right; x++)
3086 src_val = *src_pixel++;
3087 dst_val = rgb_to_pixel_colortable(dst,
3088 get_field(src_val, src->red_shift, src->red_len),
3089 get_field(src_val, src->green_shift, src->green_len),
3090 get_field(src_val, src->blue_shift, src->blue_len));
3091 if((x - src_rect->left) & 1)
3093 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3094 dst_pixel++;
3096 else
3097 *dst_pixel = (dst_val << 4) & 0xf0;
3099 if(pad_size)
3101 if((x - src_rect->left) & 1) dst_pixel++;
3102 memset(dst_pixel, 0, pad_size);
3104 dst_start += dst->stride;
3105 src_start += src->stride / 4;
3108 break;
3111 case 24:
3113 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3115 for(y = src_rect->top; y < src_rect->bottom; y++)
3117 dst_pixel = dst_start;
3118 src_pixel = src_start;
3119 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3121 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3123 if((x - src_rect->left) & 1)
3125 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3126 dst_pixel++;
3128 else
3129 *dst_pixel = (dst_val << 4) & 0xf0;
3131 if(pad_size)
3133 if((x - src_rect->left) & 1) dst_pixel++;
3134 memset(dst_pixel, 0, pad_size);
3136 dst_start += dst->stride;
3137 src_start += src->stride;
3139 break;
3142 case 16:
3144 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3145 if(src->funcs == &funcs_555)
3147 for(y = src_rect->top; y < src_rect->bottom; y++)
3149 dst_pixel = dst_start;
3150 src_pixel = src_start;
3151 for(x = src_rect->left; x < src_rect->right; x++)
3153 src_val = *src_pixel++;
3154 dst_val = rgb_to_pixel_colortable(dst,
3155 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3156 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3157 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3158 if((x - src_rect->left) & 1)
3160 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3161 dst_pixel++;
3163 else
3164 *dst_pixel = (dst_val << 4) & 0xf0;
3166 if(pad_size)
3168 if((x - src_rect->left) & 1) dst_pixel++;
3169 memset(dst_pixel, 0, pad_size);
3171 dst_start += dst->stride;
3172 src_start += src->stride / 2;
3175 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3177 for(y = src_rect->top; y < src_rect->bottom; y++)
3179 dst_pixel = dst_start;
3180 src_pixel = src_start;
3181 for(x = src_rect->left; x < src_rect->right; x++)
3183 src_val = *src_pixel++;
3184 dst_val = rgb_to_pixel_colortable(dst,
3185 (((src_val >> src->red_shift) << 3) & 0xf8) |
3186 (((src_val >> src->red_shift) >> 2) & 0x07),
3187 (((src_val >> src->green_shift) << 3) & 0xf8) |
3188 (((src_val >> src->green_shift) >> 2) & 0x07),
3189 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3190 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3191 if((x - src_rect->left) & 1)
3193 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3194 dst_pixel++;
3196 else
3197 *dst_pixel = (dst_val << 4) & 0xf0;
3199 if(pad_size)
3201 if((x - src_rect->left) & 1) dst_pixel++;
3202 memset(dst_pixel, 0, pad_size);
3204 dst_start += dst->stride;
3205 src_start += src->stride / 2;
3208 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3210 for(y = src_rect->top; y < src_rect->bottom; y++)
3212 dst_pixel = dst_start;
3213 src_pixel = src_start;
3214 for(x = src_rect->left; x < src_rect->right; x++)
3216 src_val = *src_pixel++;
3217 dst_val = rgb_to_pixel_colortable(dst,
3218 (((src_val >> src->red_shift) << 3) & 0xf8) |
3219 (((src_val >> src->red_shift) >> 2) & 0x07),
3220 (((src_val >> src->green_shift) << 2) & 0xfc) |
3221 (((src_val >> src->green_shift) >> 4) & 0x03),
3222 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3223 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3224 if((x - src_rect->left) & 1)
3226 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3227 dst_pixel++;
3229 else
3230 *dst_pixel = (dst_val << 4) & 0xf0;
3232 if(pad_size)
3234 if((x - src_rect->left) & 1) dst_pixel++;
3235 memset(dst_pixel, 0, pad_size);
3237 dst_start += dst->stride;
3238 src_start += src->stride / 2;
3241 else
3243 for(y = src_rect->top; y < src_rect->bottom; y++)
3245 dst_pixel = dst_start;
3246 src_pixel = src_start;
3247 for(x = src_rect->left; x < src_rect->right; x++)
3249 src_val = *src_pixel++;
3250 dst_val = rgb_to_pixel_colortable(dst,
3251 get_field(src_val, src->red_shift, src->red_len),
3252 get_field(src_val, src->green_shift, src->green_len),
3253 get_field(src_val, src->blue_shift, src->blue_len));
3254 if((x - src_rect->left) & 1)
3256 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3257 dst_pixel++;
3259 else
3260 *dst_pixel = (dst_val << 4) & 0xf0;
3262 if(pad_size)
3264 if((x - src_rect->left) & 1) dst_pixel++;
3265 memset(dst_pixel, 0, pad_size);
3267 dst_start += dst->stride;
3268 src_start += src->stride / 2;
3271 break;
3274 case 8:
3276 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3278 for(y = src_rect->top; y < src_rect->bottom; y++)
3280 dst_pixel = dst_start;
3281 src_pixel = src_start;
3282 for(x = src_rect->left; x < src_rect->right; x++)
3284 RGBQUAD rgb = src->color_table[*src_pixel++];
3285 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3286 if((x - src_rect->left) & 1)
3288 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3289 dst_pixel++;
3291 else
3292 *dst_pixel = (dst_val << 4) & 0xf0;
3294 if(pad_size)
3296 if((x - src_rect->left) & 1) dst_pixel++;
3297 memset(dst_pixel, 0, pad_size);
3299 dst_start += dst->stride;
3300 src_start += src->stride;
3302 break;
3305 case 4:
3307 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3309 if(color_tables_match(dst, src) && ((src->rect.left + src_rect->left) & 1) == 0)
3311 if (src->stride > 0 && src->stride == dst->stride && !pad_size)
3312 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3313 else
3315 for(y = src_rect->top; y < src_rect->bottom; y++)
3317 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3318 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3319 dst_start += dst->stride;
3320 src_start += src->stride;
3324 else
3326 for(y = src_rect->top; y < src_rect->bottom; y++)
3328 int pos = (src->rect.left + src_rect->left) & 1;
3329 dst_pixel = dst_start;
3330 src_pixel = src_start;
3331 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3333 RGBQUAD rgb;
3334 if(pos & 1)
3335 rgb = src->color_table[*src_pixel++ & 0xf];
3336 else
3337 rgb = src->color_table[*src_pixel >> 4];
3338 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3339 if((x - src_rect->left) & 1)
3341 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3342 dst_pixel++;
3344 else
3345 *dst_pixel = (dst_val << 4) & 0xf0;
3347 if(pad_size)
3349 if((x - src_rect->left) & 1) dst_pixel++;
3350 memset(dst_pixel, 0, pad_size);
3352 dst_start += dst->stride;
3353 src_start += src->stride;
3356 break;
3359 case 1:
3361 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3362 for(y = src_rect->top; y < src_rect->bottom; y++)
3364 int pos = (src->rect.left + src_rect->left) & 7;
3365 dst_pixel = dst_start;
3366 for(x = src_rect->left; x < src_rect->right; x++, pos++)
3368 RGBQUAD rgb;
3369 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3370 rgb = src->color_table[src_val];
3371 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3372 if((x - src_rect->left) & 1)
3374 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3375 dst_pixel++;
3377 else
3378 *dst_pixel = (dst_val << 4) & 0xf0;
3380 if(pad_size)
3382 if((x - src_rect->left) & 1) dst_pixel++;
3383 memset(dst_pixel, 0, pad_size);
3385 dst_start += dst->stride;
3386 src_start += src->stride;
3388 break;
3393 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3395 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3396 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3397 DWORD src_val;
3398 int bit_pos;
3400 switch(src->bit_count)
3402 case 32:
3404 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3406 if(src->funcs == &funcs_8888)
3408 for(y = src_rect->top; y < src_rect->bottom; y++)
3410 dst_pixel = dst_start;
3411 src_pixel = src_start;
3412 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3414 src_val = *src_pixel++;
3415 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val >> 16, src_val >> 8, src_val);
3417 if(bit_pos == 0) *dst_pixel = 0;
3418 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3420 if(++bit_pos == 8)
3422 dst_pixel++;
3423 bit_pos = 0;
3426 if(pad_size)
3428 if(bit_pos != 0) dst_pixel++;
3429 memset(dst_pixel, 0, pad_size);
3431 dst_start += dst->stride;
3432 src_start += src->stride / 4;
3435 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3437 for(y = src_rect->top; y < src_rect->bottom; y++)
3439 dst_pixel = dst_start;
3440 src_pixel = src_start;
3441 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3443 src_val = *src_pixel++;
3444 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3445 src_val >> src->red_shift,
3446 src_val >> src->green_shift,
3447 src_val >> src->blue_shift);
3449 if(bit_pos == 0) *dst_pixel = 0;
3450 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3452 if(++bit_pos == 8)
3454 dst_pixel++;
3455 bit_pos = 0;
3458 if(pad_size)
3460 if(bit_pos != 0) dst_pixel++;
3461 memset(dst_pixel, 0, pad_size);
3463 dst_start += dst->stride;
3464 src_start += src->stride / 4;
3467 else
3469 for(y = src_rect->top; y < src_rect->bottom; y++)
3471 dst_pixel = dst_start;
3472 src_pixel = src_start;
3473 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3475 src_val = *src_pixel++;
3476 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3477 get_field(src_val, src->red_shift, src->red_len),
3478 get_field(src_val, src->green_shift, src->green_len),
3479 get_field(src_val, src->blue_shift, src->blue_len));
3481 if(bit_pos == 0) *dst_pixel = 0;
3482 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3484 if(++bit_pos == 8)
3486 dst_pixel++;
3487 bit_pos = 0;
3490 if(pad_size)
3492 if(bit_pos != 0) dst_pixel++;
3493 memset(dst_pixel, 0, pad_size);
3495 dst_start += dst->stride;
3496 src_start += src->stride / 4;
3499 break;
3502 case 24:
3504 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3506 for(y = src_rect->top; y < src_rect->bottom; y++)
3508 dst_pixel = dst_start;
3509 src_pixel = src_start;
3510 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3512 dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_pixel[2], src_pixel[1], src_pixel[0]);
3514 if(bit_pos == 0) *dst_pixel = 0;
3515 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3517 if(++bit_pos == 8)
3519 dst_pixel++;
3520 bit_pos = 0;
3523 if(pad_size)
3525 if(bit_pos != 0) dst_pixel++;
3526 memset(dst_pixel, 0, pad_size);
3528 dst_start += dst->stride;
3529 src_start += src->stride;
3531 break;
3534 case 16:
3536 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3537 if(src->funcs == &funcs_555)
3539 for(y = src_rect->top; y < src_rect->bottom; y++)
3541 dst_pixel = dst_start;
3542 src_pixel = src_start;
3543 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3545 src_val = *src_pixel++;
3546 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3547 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3548 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3549 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07));
3551 if(bit_pos == 0) *dst_pixel = 0;
3552 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3554 if(++bit_pos == 8)
3556 dst_pixel++;
3557 bit_pos = 0;
3560 if(pad_size)
3562 if(bit_pos != 0) dst_pixel++;
3563 memset(dst_pixel, 0, pad_size);
3565 dst_start += dst->stride;
3566 src_start += src->stride / 2;
3569 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3571 for(y = src_rect->top; y < src_rect->bottom; y++)
3573 dst_pixel = dst_start;
3574 src_pixel = src_start;
3575 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3577 src_val = *src_pixel++;
3578 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3579 (((src_val >> src->red_shift) << 3) & 0xf8) |
3580 (((src_val >> src->red_shift) >> 2) & 0x07),
3581 (((src_val >> src->green_shift) << 3) & 0xf8) |
3582 (((src_val >> src->green_shift) >> 2) & 0x07),
3583 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3584 (((src_val >> src->blue_shift) >> 2) & 0x07));
3585 if(bit_pos == 0) *dst_pixel = 0;
3586 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3588 if(++bit_pos == 8)
3590 dst_pixel++;
3591 bit_pos = 0;
3594 if(pad_size)
3596 if(bit_pos != 0) dst_pixel++;
3597 memset(dst_pixel, 0, pad_size);
3599 dst_start += dst->stride;
3600 src_start += src->stride / 2;
3603 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3605 for(y = src_rect->top; y < src_rect->bottom; y++)
3607 dst_pixel = dst_start;
3608 src_pixel = src_start;
3609 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3611 src_val = *src_pixel++;
3612 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3613 (((src_val >> src->red_shift) << 3) & 0xf8) |
3614 (((src_val >> src->red_shift) >> 2) & 0x07),
3615 (((src_val >> src->green_shift) << 2) & 0xfc) |
3616 (((src_val >> src->green_shift) >> 4) & 0x03),
3617 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3618 (((src_val >> src->blue_shift) >> 2) & 0x07));
3619 if(bit_pos == 0) *dst_pixel = 0;
3620 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3622 if(++bit_pos == 8)
3624 dst_pixel++;
3625 bit_pos = 0;
3628 if(pad_size)
3630 if(bit_pos != 0) dst_pixel++;
3631 memset(dst_pixel, 0, pad_size);
3633 dst_start += dst->stride;
3634 src_start += src->stride / 2;
3637 else
3639 for(y = src_rect->top; y < src_rect->bottom; y++)
3641 dst_pixel = dst_start;
3642 src_pixel = src_start;
3643 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3645 src_val = *src_pixel++;
3646 dst_val = rgb_to_pixel_mono(dst, dither, x, y,
3647 get_field(src_val, src->red_shift, src->red_len),
3648 get_field(src_val, src->green_shift, src->green_len),
3649 get_field(src_val, src->blue_shift, src->blue_len));
3650 if(bit_pos == 0) *dst_pixel = 0;
3651 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3653 if(++bit_pos == 8)
3655 dst_pixel++;
3656 bit_pos = 0;
3659 if(pad_size)
3661 if(bit_pos != 0) dst_pixel++;
3662 memset(dst_pixel, 0, pad_size);
3664 dst_start += dst->stride;
3665 src_start += src->stride / 2;
3668 break;
3671 case 8:
3673 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3675 for(y = src_rect->top; y < src_rect->bottom; y++)
3677 dst_pixel = dst_start;
3678 src_pixel = src_start;
3679 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3681 RGBQUAD rgb = src->color_table[*src_pixel++];
3682 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3684 if(bit_pos == 0) *dst_pixel = 0;
3685 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3687 if(++bit_pos == 8)
3689 dst_pixel++;
3690 bit_pos = 0;
3693 if(pad_size)
3695 if(bit_pos != 0) dst_pixel++;
3696 memset(dst_pixel, 0, pad_size);
3698 dst_start += dst->stride;
3699 src_start += src->stride;
3701 break;
3704 case 4:
3706 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3708 for(y = src_rect->top; y < src_rect->bottom; y++)
3710 int pos = (src->rect.left + src_rect->left) & 1;
3711 dst_pixel = dst_start;
3712 src_pixel = src_start;
3713 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3715 RGBQUAD rgb;
3716 if (pos & 1)
3717 rgb = src->color_table[*src_pixel++ & 0xf];
3718 else
3719 rgb = src->color_table[*src_pixel >> 4];
3720 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3722 if(bit_pos == 0) *dst_pixel = 0;
3723 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3725 if(++bit_pos == 8)
3727 dst_pixel++;
3728 bit_pos = 0;
3731 if(pad_size)
3733 if(bit_pos != 0) dst_pixel++;
3734 memset(dst_pixel, 0, pad_size);
3736 dst_start += dst->stride;
3737 src_start += src->stride;
3739 break;
3742 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3743 uses text/bkgnd colours instead of the dib's colour table, this
3744 doesn't appear to be the case for a dc backed by a
3745 dibsection. */
3747 case 1:
3749 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
3750 for(y = src_rect->top; y < src_rect->bottom; y++)
3752 int pos = (src->rect.left + src_rect->left) & 7;
3753 dst_pixel = dst_start;
3754 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++)
3756 RGBQUAD rgb;
3757 src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
3758 rgb = src->color_table[src_val];
3759 dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3761 if(bit_pos == 0) *dst_pixel = 0;
3762 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3764 if(++bit_pos == 8)
3766 dst_pixel++;
3767 bit_pos = 0;
3770 if(pad_size)
3772 if(bit_pos != 0) dst_pixel++;
3773 memset(dst_pixel, 0, pad_size);
3775 dst_start += dst->stride;
3776 src_start += src->stride;
3778 break;
3783 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect, BOOL dither)
3787 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3789 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3792 static inline DWORD blend_argb_constant_alpha( DWORD dst, DWORD src, DWORD alpha )
3794 return (blend_color( dst, src, alpha ) |
3795 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3796 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3797 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3800 static inline DWORD blend_argb( DWORD dst, DWORD src )
3802 BYTE b = (BYTE)src;
3803 BYTE g = (BYTE)(src >> 8);
3804 BYTE r = (BYTE)(src >> 16);
3805 DWORD alpha = (BYTE)(src >> 24);
3806 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3807 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3808 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3809 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3812 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3814 BYTE b = ((BYTE)src * alpha + 127) / 255;
3815 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3816 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3817 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3818 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3819 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3820 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3821 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3824 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3826 if (blend.AlphaFormat & AC_SRC_ALPHA)
3828 DWORD alpha = blend.SourceConstantAlpha;
3829 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3830 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3831 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3832 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3833 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3834 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3835 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3837 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3838 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3839 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3842 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3843 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3845 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3846 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3847 int x, y;
3849 if (blend.AlphaFormat & AC_SRC_ALPHA)
3851 if (blend.SourceConstantAlpha == 255)
3852 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3853 for (x = 0; x < rc->right - rc->left; x++)
3854 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x] );
3855 else
3856 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3857 for (x = 0; x < rc->right - rc->left; x++)
3858 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3860 else
3861 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3862 for (x = 0; x < rc->right - rc->left; x++)
3863 dst_ptr[x] = blend_argb_constant_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3866 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3867 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3869 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3870 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3871 int x, y;
3873 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3875 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3877 for (x = 0; x < rc->right - rc->left; x++)
3879 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3880 dst_ptr[x] >> dst->green_shift,
3881 dst_ptr[x] >> dst->blue_shift,
3882 src_ptr[x], blend );
3883 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3884 (((val >> 8) & 0xff) << dst->green_shift) |
3885 (((val >> 16) & 0xff) << dst->red_shift));
3889 else
3891 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3893 for (x = 0; x < rc->right - rc->left; x++)
3895 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3896 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3897 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3898 src_ptr[x], blend );
3899 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3900 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3901 put_field( val, dst->blue_shift, dst->blue_len ));
3907 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3908 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3910 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3911 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3912 int x, y;
3914 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3916 for (x = 0; x < rc->right - rc->left; x++)
3918 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3919 src_ptr[x], blend );
3920 dst_ptr[x * 3] = val;
3921 dst_ptr[x * 3 + 1] = val >> 8;
3922 dst_ptr[x * 3 + 2] = val >> 16;
3927 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3928 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3930 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3931 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3932 int x, y;
3934 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3936 for (x = 0; x < rc->right - rc->left; x++)
3938 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3939 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3940 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3941 src_ptr[x], blend );
3942 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3947 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3948 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3950 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3951 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3952 int x, y;
3954 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3956 for (x = 0; x < rc->right - rc->left; x++)
3958 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3959 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3960 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3961 src_ptr[x], blend );
3962 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3963 put_field((val >> 8), dst->green_shift, dst->green_len) |
3964 put_field( val, dst->blue_shift, dst->blue_len));
3969 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3970 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3972 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3973 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3974 int x, y;
3976 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3978 for (x = 0; x < rc->right - rc->left; x++)
3980 RGBQUAD rgb = dst->color_table[dst_ptr[x]];
3981 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3982 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3987 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3988 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3990 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3991 BYTE *dst_ptr = get_pixel_ptr_4( dst, rc->left, rc->top );
3992 int i, x, y;
3994 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3996 for (i = 0, x = (dst->rect.left + rc->left) & 1; i < rc->right - rc->left; i++, x++)
3998 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3999 RGBQUAD rgb = dst->color_table[val];
4000 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4001 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
4002 if (x & 1)
4003 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
4004 else
4005 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
4010 static void blend_rect_1(const dib_info *dst, const RECT *rc,
4011 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4013 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
4014 BYTE *dst_ptr = get_pixel_ptr_1( dst, rc->left, rc->top );
4015 int i, x, y;
4017 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
4019 for (i = 0, x = (dst->rect.left + rc->left) & 7; i < rc->right - rc->left; i++, x++)
4021 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
4022 RGBQUAD rgb = dst->color_table[val];
4023 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[i], blend );
4024 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4025 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4030 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4031 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4035 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4037 BYTE r, g, b, a;
4038 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4039 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4040 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4041 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4042 return a << 24 | r << 16 | g << 8 | b;
4045 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4047 BYTE r, g, b;
4048 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4049 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4050 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4051 return r << 16 | g << 8 | b;
4054 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4055 unsigned int x, unsigned int y )
4057 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4058 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4059 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4060 r = min( 31, max( 0, r / 16 ));
4061 g = min( 31, max( 0, g / 16 ));
4062 b = min( 31, max( 0, b / 16 ));
4063 return (r << 10) | (g << 5) | b;
4066 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4067 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4069 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4070 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4071 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4072 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4075 /* compute the left/right triangle limit for row y */
4076 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4078 int x1, x2;
4080 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4081 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4083 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4085 *left = max( rc->left, min( x1, x2 ) );
4086 *right = min( rc->right, max( x1, x2 ) );
4089 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4090 static inline int triangle_det( const TRIVERTEX *v )
4092 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);
4095 /* compute the barycentric weights for a given point inside the triangle */
4096 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4098 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4099 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4102 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4104 INT64 l1, l2;
4105 BYTE r, g, b, a;
4107 triangle_weights( v, x, y, &l1, &l2 );
4108 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4109 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4110 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4111 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4112 return a << 24 | r << 16 | g << 8 | b;
4115 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4117 INT64 l1, l2;
4118 BYTE r, g, b;
4120 triangle_weights( v, x, y, &l1, &l2 );
4121 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4122 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4123 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4124 return r << 16 | g << 8 | b;
4127 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4129 INT64 l1, l2;
4130 int r, g, b;
4132 triangle_weights( v, x, y, &l1, &l2 );
4133 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4134 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4135 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4136 r = min( 31, max( 0, r / 16 ));
4137 g = min( 31, max( 0, g / 16 ));
4138 b = min( 31, max( 0, b / 16 ));
4139 return (r << 10) | (g << 5) | b;
4142 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4144 INT64 l1, l2;
4145 BYTE r, g, b;
4147 triangle_weights( v, x, y, &l1, &l2 );
4148 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4149 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4150 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4151 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4154 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4156 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4157 int x, y, left, right, det;
4159 switch (mode)
4161 case GRADIENT_FILL_RECT_H:
4162 for (x = 0; x < rc->right - rc->left; x++)
4163 ptr[x] = gradient_rgb_8888( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4165 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4166 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4167 break;
4169 case GRADIENT_FILL_RECT_V:
4170 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4172 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4173 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4175 break;
4177 case GRADIENT_FILL_TRIANGLE:
4178 if (!(det = triangle_det( v ))) return FALSE;
4179 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4181 triangle_coords( v, rc, y, &left, &right );
4182 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8888( v, x, y, det );
4184 break;
4186 return TRUE;
4189 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4191 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4192 int x, y, left, right, det;
4194 switch (mode)
4196 case GRADIENT_FILL_RECT_H:
4197 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4199 for (x = 0; x < rc->right - rc->left; x++)
4201 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4202 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4203 (((val >> 8) & 0xff) << dib->green_shift) |
4204 (((val >> 16) & 0xff) << dib->red_shift));
4207 else
4209 for (x = 0; x < rc->right - rc->left; x++)
4211 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4212 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4213 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4214 put_field( val, dib->blue_shift, dib->blue_len ));
4218 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4219 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4220 break;
4222 case GRADIENT_FILL_RECT_V:
4223 for (y = rc->top; y < rc->bottom; y++)
4225 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4226 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4227 val = ((( val & 0xff) << dib->blue_shift) |
4228 (((val >> 8) & 0xff) << dib->green_shift) |
4229 (((val >> 16) & 0xff) << dib->red_shift));
4230 else
4231 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4232 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4233 put_field( val, dib->blue_shift, dib->blue_len ));
4235 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4236 ptr += dib->stride / 4;
4238 break;
4240 case GRADIENT_FILL_TRIANGLE:
4241 if (!(det = triangle_det( v ))) return FALSE;
4242 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4244 triangle_coords( v, rc, y, &left, &right );
4246 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4247 for (x = left; x < right; x++)
4249 DWORD val = gradient_triangle_24( v, x, y, det );
4250 ptr[x - rc->left] = ((( val & 0xff) << dib->blue_shift) |
4251 (((val >> 8) & 0xff) << dib->green_shift) |
4252 (((val >> 16) & 0xff) << dib->red_shift));
4254 else
4255 for (x = left; x < right; x++)
4257 DWORD val = gradient_triangle_24( v, x, y, det );
4258 ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4259 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4260 put_field( val, dib->blue_shift, dib->blue_len ));
4263 break;
4265 return TRUE;
4268 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4270 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4271 int x, y, left, right, det;
4273 switch (mode)
4275 case GRADIENT_FILL_RECT_H:
4276 for (x = 0; x < rc->right - rc->left; x++)
4278 DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x );
4279 ptr[x * 3] = val;
4280 ptr[x * 3 + 1] = val >> 8;
4281 ptr[x * 3 + 2] = val >> 16;
4284 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4285 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4286 break;
4288 case GRADIENT_FILL_RECT_V:
4289 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4291 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4292 for (x = 0; x < rc->right - rc->left; x++)
4294 ptr[x * 3] = val;
4295 ptr[x * 3 + 1] = val >> 8;
4296 ptr[x * 3 + 2] = val >> 16;
4299 break;
4301 case GRADIENT_FILL_TRIANGLE:
4302 if (!(det = triangle_det( v ))) return FALSE;
4303 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4305 triangle_coords( v, rc, y, &left, &right );
4306 for (x = left; x < right; x++)
4308 DWORD val = gradient_triangle_24( v, x, y, det );
4309 ptr[(x - rc->left) * 3] = val;
4310 ptr[(x - rc->left) * 3 + 1] = val >> 8;
4311 ptr[(x - rc->left) * 3 + 2] = val >> 16;
4314 break;
4316 return TRUE;
4319 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4321 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4322 int x, y, left, right, det;
4324 switch (mode)
4326 case GRADIENT_FILL_RECT_H:
4327 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4328 for (x = rc->left; x < rc->right; x++)
4329 ptr[x - rc->left] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4330 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4331 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4332 break;
4334 case GRADIENT_FILL_RECT_V:
4335 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4337 WORD values[4];
4338 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4339 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4341 break;
4343 case GRADIENT_FILL_TRIANGLE:
4344 if (!(det = triangle_det( v ))) return FALSE;
4345 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4347 triangle_coords( v, rc, y, &left, &right );
4348 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_555( v, x, y, det );
4350 break;
4352 return TRUE;
4355 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4357 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4358 int x, y, left, right, det;
4360 switch (mode)
4362 case GRADIENT_FILL_RECT_H:
4363 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4364 for (x = rc->left; x < rc->right; x++)
4366 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4367 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4368 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4369 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4371 for ( ; y < rc->bottom; y++, ptr += dib->stride / 2)
4372 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4373 break;
4375 case GRADIENT_FILL_RECT_V:
4376 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4378 WORD values[4];
4379 for (x = 0; x < 4; x++)
4381 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4382 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4383 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4384 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4386 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4];
4388 break;
4390 case GRADIENT_FILL_TRIANGLE:
4391 if (!(det = triangle_det( v ))) return FALSE;
4392 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4394 triangle_coords( v, rc, y, &left, &right );
4395 for (x = left; x < right; x++)
4397 WORD val = gradient_triangle_555( v, x, y, det );
4398 ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4399 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4400 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4403 break;
4405 return TRUE;
4408 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4410 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4411 int x, y, left, right, det;
4413 switch (mode)
4415 case GRADIENT_FILL_RECT_H:
4416 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4417 for (x = rc->left; x < rc->right; x++)
4418 ptr[x - rc->left] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4419 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4420 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4421 break;
4423 case GRADIENT_FILL_RECT_V:
4424 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4426 BYTE values[16];
4427 for (x = 0; x < 16; x++)
4428 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4429 for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 16];
4431 break;
4433 case GRADIENT_FILL_TRIANGLE:
4434 if (!(det = triangle_det( v ))) return FALSE;
4435 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4437 triangle_coords( v, rc, y, &left, &right );
4438 for (x = left; x < right; x++) ptr[x - rc->left] = gradient_triangle_8( dib, v, x, y, det );
4440 break;
4442 return TRUE;
4445 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4447 BYTE *ptr = get_pixel_ptr_4( dib, rc->left, rc->top );
4448 int x, y, left, right, det, pos;
4450 switch (mode)
4452 case GRADIENT_FILL_RECT_H:
4453 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4455 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4457 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4458 if (pos & 1)
4459 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4460 else
4461 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4464 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4466 x = rc->left;
4467 pos = (dib->rect.left + rc->left) & 1;
4468 if (pos)
4470 ptr[0] = (ptr[-16 * dib->stride] & 0x0f) | (ptr[0] & 0xf0);
4471 pos++;
4472 x++;
4474 for (; x < rc->right - 1; x += 2, pos += 2) ptr[pos / 2] = ptr[pos / 2 - 16 * dib->stride];
4475 if (x < rc->right)
4476 ptr[pos / 2] = (ptr[pos / 2] & 0x0f) | (ptr[pos / 2 - 16 * dib->stride] & 0xf0);
4478 break;
4480 case GRADIENT_FILL_RECT_V:
4481 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4483 BYTE values[16];
4484 for (x = 0; x < 16; x++)
4485 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4486 for (x = rc->left, pos = (dib->rect.left + rc->left) & 1; x < rc->right; x++, pos++)
4487 if (pos & 1)
4488 ptr[pos / 2] = values[x % 16] | (ptr[pos / 2] & 0xf0);
4489 else
4490 ptr[pos / 2] = (values[x % 16] << 4) | (ptr[pos / 2] & 0x0f);
4492 break;
4494 case GRADIENT_FILL_TRIANGLE:
4495 if (!(det = triangle_det( v ))) return FALSE;
4496 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4498 triangle_coords( v, rc, y, &left, &right );
4499 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 1); x < right; x++, pos++)
4501 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4502 if (pos & 1)
4503 ptr[pos / 2] = val | (ptr[pos / 2] & 0xf0);
4504 else
4505 ptr[pos / 2] = (val << 4) | (ptr[pos / 2] & 0x0f);
4508 break;
4510 return TRUE;
4513 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4515 BYTE *ptr = get_pixel_ptr_1( dib, rc->left, rc->top );
4516 int x, y, left, right, det, pos;
4518 switch (mode)
4520 case GRADIENT_FILL_RECT_H:
4521 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4523 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4525 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4526 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4529 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4530 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4531 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4532 (ptr[pos / 8 - 16 * dib->stride] & pixel_masks_1[pos % 8]);
4533 break;
4535 case GRADIENT_FILL_RECT_V:
4536 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4538 BYTE values[16];
4539 for (x = 0; x < 16; x++)
4540 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4541 for (x = rc->left, pos = (dib->rect.left + rc->left) & 7; x < rc->right; x++, pos++)
4542 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4543 (values[x % 16] & pixel_masks_1[pos % 8]);
4545 break;
4547 case GRADIENT_FILL_TRIANGLE:
4548 if (!(det = triangle_det( v ))) return FALSE;
4549 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4551 triangle_coords( v, rc, y, &left, &right );
4552 for (x = left, pos = left - rc->left + ((dib->rect.left + rc->left) & 7); x < right; x++, pos++)
4554 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4555 ptr[pos / 8] = (ptr[pos / 8] & ~pixel_masks_1[pos % 8]) | (val & pixel_masks_1[pos % 8]);
4558 break;
4560 return TRUE;
4563 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4565 return TRUE;
4568 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4570 if (dst == text) return dst;
4572 if (dst > text)
4574 DWORD diff = dst - text;
4575 DWORD range = max_comp - text;
4576 dst = text + (diff * range ) / (0xff - text);
4577 return dst;
4579 else
4581 DWORD diff = text - dst;
4582 DWORD range = text - min_comp;
4583 dst = text - (diff * range) / text;
4584 return dst;
4588 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4590 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4591 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4592 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4595 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4596 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4598 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4599 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4600 int x, y;
4602 for (y = rect->top; y < rect->bottom; y++)
4604 for (x = 0; x < rect->right - rect->left; x++)
4606 if (glyph_ptr[x] <= 1) continue;
4607 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4608 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4610 dst_ptr += dib->stride / 4;
4611 glyph_ptr += glyph->stride;
4615 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4616 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4618 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4619 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4620 int x, y;
4621 DWORD text, val;
4623 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4624 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4625 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4627 for (y = rect->top; y < rect->bottom; y++)
4629 for (x = 0; x < rect->right - rect->left; x++)
4631 if (glyph_ptr[x] <= 1) continue;
4632 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4633 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4634 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4635 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4636 text, ranges + glyph_ptr[x] );
4637 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4638 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4639 put_field( val, dib->blue_shift, dib->blue_len ));
4641 dst_ptr += dib->stride / 4;
4642 glyph_ptr += glyph->stride;
4646 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4647 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4649 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4650 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4651 int x, y;
4652 DWORD val;
4654 for (y = rect->top; y < rect->bottom; y++)
4656 for (x = 0; x < rect->right - rect->left; x++)
4658 if (glyph_ptr[x] <= 1) continue;
4659 if (glyph_ptr[x] >= 16)
4660 val = text_pixel;
4661 else
4662 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4663 text_pixel, ranges + glyph_ptr[x] );
4664 dst_ptr[x * 3] = val;
4665 dst_ptr[x * 3 + 1] = val >> 8;
4666 dst_ptr[x * 3 + 2] = val >> 16;
4668 dst_ptr += dib->stride;
4669 glyph_ptr += glyph->stride;
4673 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4674 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4676 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4677 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4678 int x, y;
4679 DWORD text, val;
4681 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4682 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4683 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4685 for (y = rect->top; y < rect->bottom; y++)
4687 for (x = 0; x < rect->right - rect->left; x++)
4689 if (glyph_ptr[x] <= 1) continue;
4690 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4691 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4692 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4693 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4694 text, ranges + glyph_ptr[x] );
4695 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4697 dst_ptr += dib->stride / 2;
4698 glyph_ptr += glyph->stride;
4702 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4703 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4705 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4706 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4707 int x, y;
4708 DWORD text, val;
4710 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4711 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4712 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4714 for (y = rect->top; y < rect->bottom; y++)
4716 for (x = 0; x < rect->right - rect->left; x++)
4718 if (glyph_ptr[x] <= 1) continue;
4719 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4720 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4721 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4722 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4723 text, ranges + glyph_ptr[x] );
4724 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4725 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4726 put_field( val, dib->blue_shift, dib->blue_len ));
4728 dst_ptr += dib->stride / 2;
4729 glyph_ptr += glyph->stride;
4733 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4734 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4736 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4737 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4738 int x, y;
4740 for (y = rect->top; y < rect->bottom; y++)
4742 for (x = 0; x < rect->right - rect->left; x++)
4744 /* no antialiasing, glyph should only contain 0 or 16. */
4745 if (glyph_ptr[x] >= 16)
4746 dst_ptr[x] = text_pixel;
4748 dst_ptr += dib->stride;
4749 glyph_ptr += glyph->stride;
4753 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4754 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4756 BYTE *dst_ptr = get_pixel_ptr_4( dib, rect->left, rect->top );
4757 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4758 int x, y, pos;
4760 for (y = rect->top; y < rect->bottom; y++)
4762 for (x = 0, pos = (dib->rect.left + rect->left) & 1; x < rect->right - rect->left; x++, pos++)
4764 /* no antialiasing, glyph should only contain 0 or 16. */
4765 if (glyph_ptr[x] >= 16)
4767 if (pos & 1)
4768 dst_ptr[pos / 2] = text_pixel | (dst_ptr[pos / 2] & 0xf0);
4769 else
4770 dst_ptr[pos / 2] = (text_pixel << 4) | (dst_ptr[pos / 2] & 0x0f);
4773 dst_ptr += dib->stride;
4774 glyph_ptr += glyph->stride;
4778 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4779 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4781 BYTE *dst_ptr = get_pixel_ptr_1( dib, rect->left, rect->top );
4782 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4783 int x, y, pos;
4784 BYTE text = (text_pixel & 1) ? 0xff : 0;
4786 for (y = rect->top; y < rect->bottom; y++)
4788 for (x = 0, pos = (dib->rect.left + rect->left) & 7; x < rect->right - rect->left; x++, pos++)
4790 /* no antialiasing, glyph should only contain 0 or 16. */
4791 if (glyph_ptr[x] >= 16)
4792 dst_ptr[pos / 8] = (dst_ptr[pos / 8] & ~pixel_masks_1[pos % 8]) |
4793 (text & pixel_masks_1[pos % 8]);
4795 dst_ptr += dib->stride;
4796 glyph_ptr += glyph->stride;
4800 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4801 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4803 return;
4806 static BOOL create_rop_masks_32(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4808 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4809 DWORD mask_start = 0, mask_offset;
4810 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4811 int x, y;
4813 for(y = 0; y < hatch->height; y++)
4815 hatch_ptr = hatch_start;
4816 mask_offset = mask_start;
4817 for(x = 0; x < hatch->width; x++)
4819 if(*hatch_ptr & pixel_masks_1[x % 8])
4821 and_bits[mask_offset] = fg->and;
4822 xor_bits[mask_offset] = fg->xor;
4824 else
4826 and_bits[mask_offset] = bg->and;
4827 xor_bits[mask_offset] = bg->xor;
4829 if(x % 8 == 7) hatch_ptr++;
4830 mask_offset++;
4832 hatch_start += hatch->stride;
4833 mask_start += dib->stride / 4;
4836 return TRUE;
4839 static BOOL create_rop_masks_24(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4841 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4842 DWORD mask_start = 0, mask_offset;
4843 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4844 int x, y;
4846 for(y = 0; y < hatch->height; y++)
4848 hatch_ptr = hatch_start;
4849 mask_offset = mask_start;
4850 for(x = 0; x < hatch->width; x++)
4852 if(*hatch_ptr & pixel_masks_1[x % 8])
4854 and_bits[mask_offset] = fg->and & 0xff;
4855 xor_bits[mask_offset++] = fg->xor & 0xff;
4856 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4857 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4858 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4859 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4861 else
4863 and_bits[mask_offset] = bg->and & 0xff;
4864 xor_bits[mask_offset++] = bg->xor & 0xff;
4865 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4866 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4867 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4868 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4870 if(x % 8 == 7) hatch_ptr++;
4872 hatch_start += hatch->stride;
4873 mask_start += dib->stride;
4876 return TRUE;
4879 static BOOL create_rop_masks_16(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4881 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4882 DWORD mask_start = 0, mask_offset;
4883 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4884 int x, y;
4886 for(y = 0; y < hatch->height; y++)
4888 hatch_ptr = hatch_start;
4889 mask_offset = mask_start;
4890 for(x = 0; x < hatch->width; x++)
4892 if(*hatch_ptr & pixel_masks_1[x % 8])
4894 and_bits[mask_offset] = fg->and;
4895 xor_bits[mask_offset] = fg->xor;
4897 else
4899 and_bits[mask_offset] = bg->and;
4900 xor_bits[mask_offset] = bg->xor;
4902 if(x % 8 == 7) hatch_ptr++;
4903 mask_offset++;
4905 hatch_start += hatch->stride;
4906 mask_start += dib->stride / 2;
4909 return TRUE;
4912 static BOOL create_rop_masks_8(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4914 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4915 DWORD mask_start = 0, mask_offset;
4916 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4917 int x, y;
4919 for(y = 0; y < hatch->height; y++)
4921 hatch_ptr = hatch_start;
4922 mask_offset = mask_start;
4923 for(x = 0; x < hatch->width; x++)
4925 if(*hatch_ptr & pixel_masks_1[x % 8])
4927 and_bits[mask_offset] = fg->and;
4928 xor_bits[mask_offset] = fg->xor;
4930 else
4932 and_bits[mask_offset] = bg->and;
4933 xor_bits[mask_offset] = bg->xor;
4935 if(x % 8 == 7) hatch_ptr++;
4936 mask_offset++;
4938 hatch_start += hatch->stride;
4939 mask_start += dib->stride;
4942 return TRUE;
4945 static BOOL create_rop_masks_4(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4947 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4948 DWORD mask_start = 0, mask_offset;
4949 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4950 const rop_mask *rop_mask;
4951 int x, y;
4953 for(y = 0; y < hatch->height; y++)
4955 hatch_ptr = hatch_start;
4956 mask_offset = mask_start;
4957 for(x = 0; x < hatch->width; x++)
4959 if(*hatch_ptr & pixel_masks_1[x % 8])
4960 rop_mask = fg;
4961 else
4962 rop_mask = bg;
4964 if(x & 1)
4966 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4967 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4968 mask_offset++;
4970 else
4972 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4973 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4976 if(x % 8 == 7) hatch_ptr++;
4978 hatch_start += hatch->stride;
4979 mask_start += dib->stride;
4982 return TRUE;
4985 static BOOL create_rop_masks_1(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
4987 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4988 DWORD mask_start = 0, mask_offset;
4989 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4990 rop_mask rop_mask;
4991 int x, y, bit_pos;
4993 for(y = 0; y < hatch->height; y++)
4995 hatch_ptr = hatch_start;
4996 mask_offset = mask_start;
4997 for(x = 0, bit_pos = 0; x < hatch->width; x++)
4999 if(*hatch_ptr & pixel_masks_1[x % 8])
5001 rop_mask.and = (fg->and & 1) ? 0xff : 0;
5002 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
5004 else
5006 rop_mask.and = (bg->and & 1) ? 0xff : 0;
5007 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
5010 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
5012 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
5013 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
5015 if(++bit_pos == 8)
5017 mask_offset++;
5018 hatch_ptr++;
5019 bit_pos = 0;
5022 hatch_start += hatch->stride;
5023 mask_start += dib->stride;
5026 return TRUE;
5029 static BOOL create_rop_masks_null(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits)
5031 return FALSE;
5034 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5036 switch (mode)
5038 default:
5039 case STRETCH_DELETESCANS:
5040 get_rop_codes( R2_COPYPEN, codes );
5041 break;
5042 case STRETCH_ORSCANS:
5043 get_rop_codes( R2_MERGEPEN, codes );
5044 break;
5045 case STRETCH_ANDSCANS:
5046 get_rop_codes( R2_MASKPEN, codes );
5047 break;
5049 return;
5052 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5053 const dib_info *src_dib, const POINT *src_start,
5054 const struct stretch_params *params, int mode,
5055 BOOL keep_dst)
5057 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5058 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5059 int err = params->err_start;
5060 int width;
5061 struct rop_codes codes;
5063 rop_codes_from_stretch_mode( mode, &codes );
5064 for (width = params->length; width; width--)
5066 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5067 dst_ptr += params->dst_inc;
5068 if (err > 0)
5070 src_ptr += params->src_inc;
5071 err += params->err_add_1;
5073 else err += params->err_add_2;
5077 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5078 const dib_info *src_dib, const POINT *src_start,
5079 const struct stretch_params *params, int mode,
5080 BOOL keep_dst)
5082 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5083 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5084 int err = params->err_start;
5085 int width;
5086 struct rop_codes codes;
5088 rop_codes_from_stretch_mode( mode, &codes );
5089 for (width = params->length; width; width--)
5091 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5092 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5093 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5094 dst_ptr += 3 * params->dst_inc;
5095 if (err > 0)
5097 src_ptr += 3 * params->src_inc;
5098 err += params->err_add_1;
5100 else err += params->err_add_2;
5104 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5105 const dib_info *src_dib, const POINT *src_start,
5106 const struct stretch_params *params, int mode,
5107 BOOL keep_dst)
5109 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5110 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5111 int err = params->err_start;
5112 int width;
5113 struct rop_codes codes;
5115 rop_codes_from_stretch_mode( mode, &codes );
5116 for (width = params->length; width; width--)
5118 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5119 dst_ptr += params->dst_inc;
5120 if (err > 0)
5122 src_ptr += params->src_inc;
5123 err += params->err_add_1;
5125 else err += params->err_add_2;
5129 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5130 const dib_info *src_dib, const POINT *src_start,
5131 const struct stretch_params *params, int mode,
5132 BOOL keep_dst)
5134 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5135 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5136 int err = params->err_start;
5137 int width;
5138 struct rop_codes codes;
5140 rop_codes_from_stretch_mode( mode, &codes );
5141 for (width = params->length; width; width--)
5143 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5144 dst_ptr += params->dst_inc;
5145 if (err > 0)
5147 src_ptr += params->src_inc;
5148 err += params->err_add_1;
5150 else err += params->err_add_2;
5154 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5155 const dib_info *src_dib, const POINT *src_start,
5156 const struct stretch_params *params, int mode,
5157 BOOL keep_dst)
5159 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5160 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5161 int err = params->err_start;
5162 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5163 struct rop_codes codes;
5164 BYTE src_val;
5166 rop_codes_from_stretch_mode( mode, &codes );
5167 for (width = params->length; width; width--)
5169 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5170 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5172 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5174 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5175 dst_ptr += params->dst_inc;
5176 dst_x += params->dst_inc;
5178 if (err > 0)
5180 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5181 src_ptr += params->src_inc;
5182 src_x += params->src_inc;
5183 err += params->err_add_1;
5185 else err += params->err_add_2;
5189 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5190 const dib_info *src_dib, const POINT *src_start,
5191 const struct stretch_params *params, int mode,
5192 BOOL keep_dst)
5194 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5195 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5196 int err = params->err_start;
5197 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5198 struct rop_codes codes;
5199 BYTE src_val;
5201 rop_codes_from_stretch_mode( mode, &codes );
5202 for (width = params->length; width; width--)
5204 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5205 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5207 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5208 dst_ptr += params->dst_inc;
5209 dst_x += params->dst_inc;
5211 if (err > 0)
5213 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5214 src_ptr += params->src_inc;
5215 src_x += params->src_inc;
5216 err += params->err_add_1;
5218 else err += params->err_add_2;
5222 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5223 const dib_info *src_dib, const POINT *src_start,
5224 const struct stretch_params *params, int mode,
5225 BOOL keep_dst)
5227 FIXME("bit count %d\n", dst_dib->bit_count);
5228 return;
5231 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5232 const dib_info *src_dib, const POINT *src_start,
5233 const struct stretch_params *params, int mode,
5234 BOOL keep_dst)
5236 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5237 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5238 int err = params->err_start;
5239 int width;
5240 struct rop_codes codes;
5241 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5242 BOOL new_pix = TRUE;
5244 rop_codes_from_stretch_mode( mode, &codes );
5245 for (width = params->length; width; width--)
5247 if (new_pix && !keep_dst) *dst_ptr = init_val;
5248 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5249 new_pix = FALSE;
5250 src_ptr += params->src_inc;
5251 if (err > 0)
5253 dst_ptr += params->dst_inc;
5254 new_pix = TRUE;
5255 err += params->err_add_1;
5257 else err += params->err_add_2;
5261 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5262 const dib_info *src_dib, const POINT *src_start,
5263 const struct stretch_params *params, int mode,
5264 BOOL keep_dst)
5266 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5267 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5268 int err = params->err_start;
5269 int width;
5270 struct rop_codes codes;
5271 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5272 BOOL new_pix = TRUE;
5274 rop_codes_from_stretch_mode( mode, &codes );
5275 for (width = params->length; width; width--)
5277 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5278 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5279 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5280 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5281 new_pix = FALSE;
5282 src_ptr += 3 * params->src_inc;
5283 if (err > 0)
5285 dst_ptr += 3 * params->dst_inc;
5286 new_pix = TRUE;
5287 err += params->err_add_1;
5289 else err += params->err_add_2;
5293 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5294 const dib_info *src_dib, const POINT *src_start,
5295 const struct stretch_params *params, int mode,
5296 BOOL keep_dst)
5298 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5299 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5300 int err = params->err_start;
5301 int width;
5302 struct rop_codes codes;
5303 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5304 BOOL new_pix = TRUE;
5306 rop_codes_from_stretch_mode( mode, &codes );
5307 for (width = params->length; width; width--)
5309 if (new_pix && !keep_dst) *dst_ptr = init_val;
5310 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5311 new_pix = FALSE;
5312 src_ptr += params->src_inc;
5313 if (err > 0)
5315 dst_ptr += params->dst_inc;
5316 new_pix = TRUE;
5317 err += params->err_add_1;
5319 else err += params->err_add_2;
5323 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5324 const dib_info *src_dib, const POINT *src_start,
5325 const struct stretch_params *params, int mode,
5326 BOOL keep_dst)
5328 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5329 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5330 int err = params->err_start;
5331 int width;
5332 struct rop_codes codes;
5333 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5334 BOOL new_pix = TRUE;
5336 rop_codes_from_stretch_mode( mode, &codes );
5337 for (width = params->length; width; width--)
5339 if (new_pix && !keep_dst) *dst_ptr = init_val;
5340 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5341 new_pix = FALSE;
5342 src_ptr += params->src_inc;
5343 if (err > 0)
5345 dst_ptr += params->dst_inc;
5346 new_pix = TRUE;
5347 err += params->err_add_1;
5349 else err += params->err_add_2;
5353 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5354 const dib_info *src_dib, const POINT *src_start,
5355 const struct stretch_params *params, int mode,
5356 BOOL keep_dst)
5358 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5359 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5360 int err = params->err_start;
5361 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5362 struct rop_codes codes;
5363 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5364 BOOL new_pix = TRUE;
5366 rop_codes_from_stretch_mode( mode, &codes );
5367 for (width = params->length; width; width--)
5369 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0x0f : 0xf0 );
5371 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5372 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5374 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5375 new_pix = FALSE;
5377 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5378 src_ptr += params->src_inc;
5379 src_x += params->src_inc;
5381 if (err > 0)
5383 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5384 dst_ptr += params->dst_inc;
5385 dst_x += params->dst_inc;
5386 new_pix = TRUE;
5387 err += params->err_add_1;
5389 else err += params->err_add_2;
5393 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5394 const dib_info *src_dib, const POINT *src_start,
5395 const struct stretch_params *params, int mode,
5396 BOOL keep_dst)
5398 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5399 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5400 int err = params->err_start;
5401 int width, dst_x = dst_dib->rect.left + dst_start->x, src_x = src_dib->rect.left + src_start->x;
5402 struct rop_codes codes;
5403 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5404 BOOL new_pix = TRUE;
5406 rop_codes_from_stretch_mode( mode, &codes );
5407 for (width = params->length; width; width--)
5409 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5410 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5411 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5412 new_pix = FALSE;
5414 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5415 src_ptr += params->src_inc;
5416 src_x += params->src_inc;
5418 if (err > 0)
5420 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5421 dst_ptr += params->dst_inc;
5422 dst_x += params->dst_inc;
5423 new_pix = TRUE;
5424 err += params->err_add_1;
5426 else err += params->err_add_2;
5430 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5431 const dib_info *src_dib, const POINT *src_start,
5432 const struct stretch_params *params, int mode,
5433 BOOL keep_dst)
5435 FIXME("bit count %d\n", dst_dib->bit_count);
5436 return;
5439 const primitive_funcs funcs_8888 =
5441 solid_rects_32,
5442 solid_line_32,
5443 pattern_rects_32,
5444 copy_rect_32,
5445 blend_rect_8888,
5446 gradient_rect_8888,
5447 draw_glyph_8888,
5448 get_pixel_32,
5449 colorref_to_pixel_888,
5450 pixel_to_colorref_888,
5451 convert_to_8888,
5452 create_rop_masks_32,
5453 stretch_row_32,
5454 shrink_row_32
5457 const primitive_funcs funcs_32 =
5459 solid_rects_32,
5460 solid_line_32,
5461 pattern_rects_32,
5462 copy_rect_32,
5463 blend_rect_32,
5464 gradient_rect_32,
5465 draw_glyph_32,
5466 get_pixel_32,
5467 colorref_to_pixel_masks,
5468 pixel_to_colorref_masks,
5469 convert_to_32,
5470 create_rop_masks_32,
5471 stretch_row_32,
5472 shrink_row_32
5475 const primitive_funcs funcs_24 =
5477 solid_rects_24,
5478 solid_line_24,
5479 pattern_rects_24,
5480 copy_rect_24,
5481 blend_rect_24,
5482 gradient_rect_24,
5483 draw_glyph_24,
5484 get_pixel_24,
5485 colorref_to_pixel_888,
5486 pixel_to_colorref_888,
5487 convert_to_24,
5488 create_rop_masks_24,
5489 stretch_row_24,
5490 shrink_row_24
5493 const primitive_funcs funcs_555 =
5495 solid_rects_16,
5496 solid_line_16,
5497 pattern_rects_16,
5498 copy_rect_16,
5499 blend_rect_555,
5500 gradient_rect_555,
5501 draw_glyph_555,
5502 get_pixel_16,
5503 colorref_to_pixel_555,
5504 pixel_to_colorref_555,
5505 convert_to_555,
5506 create_rop_masks_16,
5507 stretch_row_16,
5508 shrink_row_16
5511 const primitive_funcs funcs_16 =
5513 solid_rects_16,
5514 solid_line_16,
5515 pattern_rects_16,
5516 copy_rect_16,
5517 blend_rect_16,
5518 gradient_rect_16,
5519 draw_glyph_16,
5520 get_pixel_16,
5521 colorref_to_pixel_masks,
5522 pixel_to_colorref_masks,
5523 convert_to_16,
5524 create_rop_masks_16,
5525 stretch_row_16,
5526 shrink_row_16
5529 const primitive_funcs funcs_8 =
5531 solid_rects_8,
5532 solid_line_8,
5533 pattern_rects_8,
5534 copy_rect_8,
5535 blend_rect_8,
5536 gradient_rect_8,
5537 draw_glyph_8,
5538 get_pixel_8,
5539 colorref_to_pixel_colortable,
5540 pixel_to_colorref_colortable,
5541 convert_to_8,
5542 create_rop_masks_8,
5543 stretch_row_8,
5544 shrink_row_8
5547 const primitive_funcs funcs_4 =
5549 solid_rects_4,
5550 solid_line_4,
5551 pattern_rects_4,
5552 copy_rect_4,
5553 blend_rect_4,
5554 gradient_rect_4,
5555 draw_glyph_4,
5556 get_pixel_4,
5557 colorref_to_pixel_colortable,
5558 pixel_to_colorref_colortable,
5559 convert_to_4,
5560 create_rop_masks_4,
5561 stretch_row_4,
5562 shrink_row_4
5565 const primitive_funcs funcs_1 =
5567 solid_rects_1,
5568 solid_line_1,
5569 pattern_rects_1,
5570 copy_rect_1,
5571 blend_rect_1,
5572 gradient_rect_1,
5573 draw_glyph_1,
5574 get_pixel_1,
5575 colorref_to_pixel_colortable,
5576 pixel_to_colorref_colortable,
5577 convert_to_1,
5578 create_rop_masks_1,
5579 stretch_row_1,
5580 shrink_row_1
5583 const primitive_funcs funcs_null =
5585 solid_rects_null,
5586 solid_line_null,
5587 pattern_rects_null,
5588 copy_rect_null,
5589 blend_rect_null,
5590 gradient_rect_null,
5591 draw_glyph_null,
5592 get_pixel_null,
5593 colorref_to_pixel_null,
5594 pixel_to_colorref_null,
5595 convert_to_null,
5596 create_rop_masks_null,
5597 stretch_row_null,
5598 shrink_row_null