gdi32: Implement triangular gradients in the DIB engine.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blob47ba0e1a40bb5ed8cc3657006f46f36c92463600
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 + y * dib->stride + 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 + y * dib->stride) + 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 + y * dib->stride + 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 + y * dib->stride + x * 2);
80 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
82 return (BYTE*)dib->bits.ptr + y * dib->stride + x;
85 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
87 return (BYTE*)dib->bits.ptr + y * dib->stride + x / 2;
90 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
92 return (BYTE*)dib->bits.ptr + y * dib->stride + 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 if(rc->left >= rc->right) continue;
279 if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
281 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
282 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
284 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
286 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
287 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
288 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
292 else
294 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
295 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
297 ptr = start;
299 switch(rc->left & 3)
301 case 1:
302 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
303 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
304 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
305 break;
306 case 2:
307 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
308 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
309 break;
310 case 3:
311 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
312 break;
315 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
317 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
318 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
319 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
322 switch(rc->right & 3)
324 case 1:
325 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
326 break;
327 case 2:
328 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
329 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
330 break;
331 case 3:
332 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
333 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
334 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
335 break;
342 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
344 WORD *ptr, *start;
345 int x, y, i;
347 for(i = 0; i < num; i++, rc++)
349 start = get_pixel_ptr_16(dib, rc->left, rc->top);
350 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
351 for(x = rc->left, ptr = start; x < rc->right; x++)
352 do_rop_16(ptr++, and, xor);
356 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
358 BYTE *ptr, *start;
359 int x, y, i;
361 for(i = 0; i < num; i++, rc++)
363 start = get_pixel_ptr_8(dib, rc->left, rc->top);
364 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
365 for(x = rc->left, ptr = start; x < rc->right; x++)
366 do_rop_8(ptr++, and, xor);
370 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
372 BYTE *ptr, *start;
373 int x, y, i;
374 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
375 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
377 for(i = 0; i < num; i++, rc++)
379 if(rc->left >= rc->right) continue;
380 start = get_pixel_ptr_4(dib, rc->left, rc->top);
381 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
383 ptr = start;
384 if(rc->left & 1) /* upper nibble untouched */
385 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
387 for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
388 do_rop_8(ptr++, byte_and, byte_xor);
390 if(rc->right & 1) /* lower nibble untouched */
391 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
396 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
398 BYTE *ptr, *start;
399 int x, y, i;
400 BYTE byte_and = (and & 1) ? 0xff : 0;
401 BYTE byte_xor = (xor & 1) ? 0xff : 0;
402 BYTE start_and, start_xor, end_and, end_xor, mask;
403 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
405 for(i = 0; i < num; i++, rc++)
407 if(rc->left >= rc->right) continue;
409 start = get_pixel_ptr_1(dib, rc->left, rc->top);
411 if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
413 mask = masks[rc->left & 7] & ~masks[rc->right & 7];
415 start_and = byte_and | ~mask;
416 start_xor = byte_xor & mask;
417 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
419 do_rop_8(start, start_and, start_xor);
422 else
424 mask = masks[rc->left & 7];
425 start_and = byte_and | ~mask;
426 start_xor = byte_xor & mask;
428 mask = masks[rc->right & 7];
429 /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
430 end_and = byte_and | mask;
431 end_xor = byte_xor & ~mask;
433 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
435 ptr = start;
437 if(rc->left & 7)
438 do_rop_8(ptr++, start_and, start_xor);
440 for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
441 do_rop_8(ptr++, byte_and, byte_xor);
443 if(rc->right & 7)
444 do_rop_8(ptr, end_and, end_xor);
450 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
452 return;
455 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
456 DWORD and, DWORD xor)
458 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
459 int len = params->length, err = params->err_start;
460 int major_inc, minor_inc;
462 if (params->x_major)
464 major_inc = params->x_inc;
465 minor_inc = (dib->stride * params->y_inc) / 4;
467 else
469 major_inc = (dib->stride * params->y_inc) / 4;
470 minor_inc = params->x_inc;
473 while (len--)
475 do_rop_32( ptr, and, xor );
476 if (err + params->bias > 0)
478 ptr += minor_inc;
479 err += params->err_add_1;
481 else err += params->err_add_2;
482 ptr += major_inc;
486 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
487 DWORD and, DWORD xor)
489 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
490 int len = params->length, err = params->err_start;
491 int major_inc, minor_inc;
493 if (params->x_major)
495 major_inc = params->x_inc * 3;
496 minor_inc = dib->stride * params->y_inc;
498 else
500 major_inc = dib->stride * params->y_inc;
501 minor_inc = params->x_inc * 3;
504 while (len--)
506 do_rop_8( ptr, and, xor );
507 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
508 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
509 if (err + params->bias > 0)
511 ptr += minor_inc;
512 err += params->err_add_1;
514 else err += params->err_add_2;
515 ptr += major_inc;
519 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
520 DWORD and, DWORD xor)
522 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
523 int len = params->length, err = params->err_start;
524 int major_inc, minor_inc;
526 if (params->x_major)
528 major_inc = params->x_inc;
529 minor_inc = (dib->stride * params->y_inc) / 2;
531 else
533 major_inc = (dib->stride * params->y_inc) / 2;
534 minor_inc = params->x_inc;
537 while (len--)
539 do_rop_16( ptr, and, xor );
540 if (err + params->bias > 0)
542 ptr += minor_inc;
543 err += params->err_add_1;
545 else err += params->err_add_2;
546 ptr += major_inc;
550 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
551 DWORD and, DWORD xor)
553 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
554 int len = params->length, err = params->err_start;
555 int major_inc, minor_inc;
557 if (params->x_major)
559 major_inc = params->x_inc;
560 minor_inc = dib->stride * params->y_inc;
562 else
564 major_inc = dib->stride * params->y_inc;
565 minor_inc = params->x_inc;
568 while (len--)
570 do_rop_8( ptr, and, xor );
571 if (err + params->bias > 0)
573 ptr += minor_inc;
574 err += params->err_add_1;
576 else err += params->err_add_2;
577 ptr += major_inc;
581 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
582 DWORD and, DWORD xor)
584 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
585 int len = params->length, err = params->err_start;
586 int x = start->x;
588 and = (and & 0x0f) | ((and << 4) & 0xf0);
589 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
591 if (params->x_major)
593 while (len--)
595 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
596 if (err + params->bias > 0)
598 ptr += dib->stride * params->y_inc;
599 err += params->err_add_1;
601 else err += params->err_add_2;
602 if ((x / 2) != ((x + params->x_inc) / 2))
603 ptr += params->x_inc;
604 x += params->x_inc;
607 else
609 while (len--)
611 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
612 if (err + params->bias > 0)
614 if ((x / 2) != ((x + params->x_inc) / 2))
615 ptr += params->x_inc;
616 x += params->x_inc;
617 err += params->err_add_1;
619 else err += params->err_add_2;
620 ptr += dib->stride * params->y_inc;
625 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
626 DWORD and, DWORD xor)
628 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
629 int len = params->length, err = params->err_start;
630 int x = start->x;
632 and = (and & 0x1) ? 0xff : 0;
633 xor = (xor & 0x1) ? 0xff : 0;
635 if (params->x_major)
637 while (len--)
639 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
640 if (err + params->bias > 0)
642 ptr += dib->stride * params->y_inc;
643 err += params->err_add_1;
645 else err += params->err_add_2;
646 if ((x / 8) != ((x + params->x_inc) / 8))
647 ptr += params->x_inc;
648 x += params->x_inc;
651 else
653 while (len--)
655 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
656 if (err + params->bias > 0)
658 if ((x / 8) != ((x + params->x_inc) / 8))
659 ptr += params->x_inc;
660 x += params->x_inc;
661 err += params->err_add_1;
663 else err += params->err_add_2;
664 ptr += dib->stride * params->y_inc;
669 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
670 DWORD and, DWORD xor)
672 return;
675 static inline INT calc_offset(INT edge, INT size, INT origin)
677 INT offset;
679 if(edge - origin >= 0)
680 offset = (edge - origin) % size;
681 else
683 offset = (origin - edge) % size;
684 if(offset) offset = size - offset;
686 return offset;
689 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
691 POINT offset;
693 offset.x = calc_offset(rc->left, brush->width, origin->x);
694 offset.y = calc_offset(rc->top, brush->height, origin->y);
696 return offset;
699 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
700 const dib_info *brush, void *and_bits, void *xor_bits)
702 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
703 int x, y, i;
704 POINT offset;
706 for(i = 0; i < num; i++, rc++)
708 offset = calc_brush_offset(rc, brush, origin);
710 start = get_pixel_ptr_32(dib, rc->left, rc->top);
711 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
712 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
714 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
716 and_ptr = start_and + offset.x;
717 xor_ptr = start_xor + offset.x;
719 for(x = rc->left, ptr = start; x < rc->right; x++)
721 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
722 if(and_ptr == start_and + brush->width)
724 and_ptr = start_and;
725 xor_ptr = start_xor;
729 offset.y++;
730 if(offset.y == brush->height)
732 start_and = and_bits;
733 start_xor = xor_bits;
734 offset.y = 0;
736 else
738 start_and += brush->stride / 4;
739 start_xor += brush->stride / 4;
745 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
746 const dib_info *brush, void *and_bits, void *xor_bits)
748 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
749 int x, y, i;
750 POINT offset;
752 for(i = 0; i < num; i++, rc++)
754 offset = calc_brush_offset(rc, brush, origin);
756 start = get_pixel_ptr_24(dib, rc->left, rc->top);
757 start_and = (BYTE*)and_bits + offset.y * brush->stride;
758 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
760 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
762 and_ptr = start_and + offset.x * 3;
763 xor_ptr = start_xor + offset.x * 3;
765 for(x = rc->left, ptr = start; x < rc->right; x++)
767 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
768 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
769 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
770 if(and_ptr == start_and + brush->width * 3)
772 and_ptr = start_and;
773 xor_ptr = start_xor;
777 offset.y++;
778 if(offset.y == brush->height)
780 start_and = and_bits;
781 start_xor = xor_bits;
782 offset.y = 0;
784 else
786 start_and += brush->stride;
787 start_xor += brush->stride;
793 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
794 const dib_info *brush, void *and_bits, void *xor_bits)
796 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
797 int x, y, i;
798 POINT offset;
800 for(i = 0; i < num; i++, rc++)
802 offset = calc_brush_offset(rc, brush, origin);
804 start = get_pixel_ptr_16(dib, rc->left, rc->top);
805 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
806 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
808 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
810 and_ptr = start_and + offset.x;
811 xor_ptr = start_xor + offset.x;
813 for(x = rc->left, ptr = start; x < rc->right; x++)
815 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
816 if(and_ptr == start_and + brush->width)
818 and_ptr = start_and;
819 xor_ptr = start_xor;
823 offset.y++;
824 if(offset.y == brush->height)
826 start_and = and_bits;
827 start_xor = xor_bits;
828 offset.y = 0;
830 else
832 start_and += brush->stride / 2;
833 start_xor += brush->stride / 2;
839 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
840 const dib_info *brush, void *and_bits, void *xor_bits)
842 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
843 int x, y, i;
844 POINT offset;
846 for(i = 0; i < num; i++, rc++)
848 offset = calc_brush_offset(rc, brush, origin);
850 start = get_pixel_ptr_8(dib, rc->left, rc->top);
851 start_and = (BYTE*)and_bits + offset.y * brush->stride;
852 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
854 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
856 and_ptr = start_and + offset.x;
857 xor_ptr = start_xor + offset.x;
859 for(x = rc->left, ptr = start; x < rc->right; x++)
861 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
862 if(and_ptr == start_and + brush->width)
864 and_ptr = start_and;
865 xor_ptr = start_xor;
869 offset.y++;
870 if(offset.y == brush->height)
872 start_and = and_bits;
873 start_xor = xor_bits;
874 offset.y = 0;
876 else
878 start_and += brush->stride;
879 start_xor += brush->stride;
885 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
886 const dib_info *brush, void *and_bits, void *xor_bits)
888 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
889 int x, y, i;
890 POINT offset;
892 for(i = 0; i < num; i++, rc++)
894 offset = calc_brush_offset(rc, brush, origin);
896 start = get_pixel_ptr_4(dib, rc->left, rc->top);
897 start_and = (BYTE*)and_bits + offset.y * brush->stride;
898 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
900 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
902 INT brush_x = offset.x;
903 BYTE byte_and, byte_xor;
905 and_ptr = start_and + brush_x / 2;
906 xor_ptr = start_xor + brush_x / 2;
908 for(x = rc->left, ptr = start; x < rc->right; x++)
910 /* FIXME: Two pixels at a time */
911 if(x & 1) /* lower dst nibble */
913 if(brush_x & 1) /* lower pat nibble */
915 byte_and = *and_ptr++ | 0xf0;
916 byte_xor = *xor_ptr++ & 0x0f;
918 else /* upper pat nibble */
920 byte_and = (*and_ptr >> 4) | 0xf0;
921 byte_xor = (*xor_ptr >> 4) & 0x0f;
924 else /* upper dst nibble */
926 if(brush_x & 1) /* lower pat nibble */
928 byte_and = (*and_ptr++ << 4) | 0x0f;
929 byte_xor = (*xor_ptr++ << 4) & 0xf0;
931 else /* upper pat nibble */
933 byte_and = *and_ptr | 0x0f;
934 byte_xor = *xor_ptr & 0xf0;
937 do_rop_8(ptr, byte_and, byte_xor);
939 if(x & 1) ptr++;
941 if(++brush_x == brush->width)
943 brush_x = 0;
944 and_ptr = start_and;
945 xor_ptr = start_xor;
949 offset.y++;
950 if(offset.y == brush->height)
952 start_and = and_bits;
953 start_xor = xor_bits;
954 offset.y = 0;
956 else
958 start_and += brush->stride;
959 start_xor += brush->stride;
965 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
966 const dib_info *brush, void *and_bits, void *xor_bits)
968 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
969 int x, y, i;
970 POINT offset;
972 for(i = 0; i < num; i++, rc++)
974 offset = calc_brush_offset(rc, brush, origin);
976 start = get_pixel_ptr_1(dib, rc->left, rc->top);
977 start_and = (BYTE*)and_bits + offset.y * brush->stride;
978 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
980 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
982 INT brush_x = offset.x;
983 BYTE byte_and, byte_xor;
985 and_ptr = start_and + brush_x / 8;
986 xor_ptr = start_xor + brush_x / 8;
988 for(x = rc->left, ptr = start; x < rc->right; x++)
990 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
991 byte_and |= ~pixel_masks_1[x % 8];
992 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
993 byte_xor &= pixel_masks_1[x % 8];
995 do_rop_8(ptr, byte_and, byte_xor);
997 if((x & 7) == 7) ptr++;
999 if((brush_x & 7) == 7)
1001 and_ptr++;
1002 xor_ptr++;
1005 if(++brush_x == brush->width)
1007 brush_x = 0;
1008 and_ptr = start_and;
1009 xor_ptr = start_xor;
1013 offset.y++;
1014 if(offset.y == brush->height)
1016 start_and = and_bits;
1017 start_xor = xor_bits;
1018 offset.y = 0;
1020 else
1022 start_and += brush->stride;
1023 start_xor += brush->stride;
1029 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1030 const dib_info *brush, void *and_bits, void *xor_bits)
1032 return;
1035 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1036 const dib_info *src, const POINT *origin, int rop2, int overlap)
1038 DWORD *dst_start, *src_start;
1039 struct rop_codes codes;
1040 int y, dst_stride, src_stride;
1042 if (overlap & OVERLAP_BELOW)
1044 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1045 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1046 dst_stride = -dst->stride / 4;
1047 src_stride = -src->stride / 4;
1049 else
1051 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1052 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1053 dst_stride = dst->stride / 4;
1054 src_stride = src->stride / 4;
1057 if (rop2 == R2_COPYPEN)
1059 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1060 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1061 return;
1064 get_rop_codes( rop2, &codes );
1065 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1067 if (overlap & OVERLAP_RIGHT)
1068 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1069 else
1070 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1074 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1075 const dib_info *src, const POINT *origin, int rop2, int overlap)
1077 BYTE *dst_start, *src_start;
1078 int y, dst_stride, src_stride;
1079 struct rop_codes codes;
1081 if (overlap & OVERLAP_BELOW)
1083 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1084 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1085 dst_stride = -dst->stride;
1086 src_stride = -src->stride;
1088 else
1090 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1091 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1092 dst_stride = dst->stride;
1093 src_stride = src->stride;
1096 if (rop2 == R2_COPYPEN)
1098 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1099 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1100 return;
1103 get_rop_codes( rop2, &codes );
1104 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1106 if (overlap & OVERLAP_RIGHT)
1107 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1108 else
1109 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1113 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1114 const dib_info *src, const POINT *origin, int rop2, int overlap)
1116 WORD *dst_start, *src_start;
1117 int y, dst_stride, src_stride;
1118 struct rop_codes codes;
1120 if (overlap & OVERLAP_BELOW)
1122 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1123 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1124 dst_stride = -dst->stride / 2;
1125 src_stride = -src->stride / 2;
1127 else
1129 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1130 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1131 dst_stride = dst->stride / 2;
1132 src_stride = src->stride / 2;
1135 if (rop2 == R2_COPYPEN)
1137 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1138 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1139 return;
1142 get_rop_codes( rop2, &codes );
1143 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1145 if (overlap & OVERLAP_RIGHT)
1146 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1147 else
1148 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1152 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1153 const dib_info *src, const POINT *origin, int rop2, int overlap)
1155 BYTE *dst_start, *src_start;
1156 int y, dst_stride, src_stride;
1157 struct rop_codes codes;
1159 if (overlap & OVERLAP_BELOW)
1161 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1162 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1163 dst_stride = -dst->stride;
1164 src_stride = -src->stride;
1166 else
1168 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1169 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1170 dst_stride = dst->stride;
1171 src_stride = src->stride;
1174 if (rop2 == R2_COPYPEN)
1176 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1177 memmove( dst_start, src_start, (rc->right - rc->left) );
1178 return;
1181 get_rop_codes( rop2, &codes );
1182 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1184 if (overlap & OVERLAP_RIGHT)
1185 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1186 else
1187 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1191 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1192 const dib_info *src, const POINT *origin, int rop2, int overlap)
1194 BYTE *dst_start, *src_start;
1195 int y, dst_stride, src_stride;
1196 struct rop_codes codes;
1198 if (overlap & OVERLAP_BELOW)
1200 dst_start = get_pixel_ptr_4(dst, 0, rc->bottom - 1);
1201 src_start = get_pixel_ptr_4(src, 0, origin->y + rc->bottom - rc->top - 1);
1202 dst_stride = -dst->stride;
1203 src_stride = -src->stride;
1205 else
1207 dst_start = get_pixel_ptr_4(dst, 0, rc->top);
1208 src_start = get_pixel_ptr_4(src, 0, origin->y);
1209 dst_stride = dst->stride;
1210 src_stride = src->stride;
1213 if (rop2 == R2_COPYPEN && (rc->left & 1) == 0 && (origin->x & 1) == 0 && (rc->right & 1) == 0)
1215 dst_start += rc->left / 2;
1216 src_start += origin->x / 2;
1217 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1218 memmove( dst_start, src_start, (rc->right - rc->left) / 2 );
1219 return;
1222 get_rop_codes( rop2, &codes );
1223 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1225 if (overlap & OVERLAP_RIGHT)
1226 do_rop_codes_line_rev_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1227 else
1228 do_rop_codes_line_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1232 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1233 const dib_info *src, const POINT *origin, int rop2, int overlap)
1235 BYTE *dst_start, *src_start;
1236 int y, dst_stride, src_stride;
1237 struct rop_codes codes;
1239 if (overlap & OVERLAP_BELOW)
1241 dst_start = get_pixel_ptr_1(dst, 0, rc->bottom - 1);
1242 src_start = get_pixel_ptr_1(src, 0, origin->y + rc->bottom - rc->top - 1);
1243 dst_stride = -dst->stride;
1244 src_stride = -src->stride;
1246 else
1248 dst_start = get_pixel_ptr_1(dst, 0, rc->top);
1249 src_start = get_pixel_ptr_1(src, 0, origin->y);
1250 dst_stride = dst->stride;
1251 src_stride = src->stride;
1254 if (rop2 == R2_COPYPEN && (rc->left & 7) == 0 && (origin->x & 7) == 0 && (rc->right & 7) == 0)
1256 dst_start += rc->left / 8;
1257 src_start += origin->x / 8;
1258 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1259 memmove( dst_start, src_start, (rc->right - rc->left) / 8 );
1260 return;
1263 get_rop_codes( rop2, &codes );
1264 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1266 if (overlap & OVERLAP_RIGHT)
1267 do_rop_codes_line_rev_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1268 else
1269 do_rop_codes_line_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1273 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1274 const dib_info *src, const POINT *origin, int rop2, int overlap)
1276 return;
1279 static DWORD get_pixel_32(const dib_info *dib, const POINT *pt)
1281 DWORD *ptr = get_pixel_ptr_32( dib, pt->x, pt->y );
1282 return *ptr;
1285 static DWORD get_pixel_24(const dib_info *dib, const POINT *pt)
1287 BYTE *ptr = get_pixel_ptr_24( dib, pt->x, pt->y );
1288 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1291 static DWORD get_pixel_16(const dib_info *dib, const POINT *pt)
1293 WORD *ptr = get_pixel_ptr_16( dib, pt->x, pt->y );
1294 return *ptr;
1297 static DWORD get_pixel_8(const dib_info *dib, const POINT *pt)
1299 BYTE *ptr = get_pixel_ptr_8( dib, pt->x, pt->y );
1300 return *ptr;
1303 static DWORD get_pixel_4(const dib_info *dib, const POINT *pt)
1305 BYTE *ptr = get_pixel_ptr_4( dib, pt->x, pt->y );
1307 if (pt->x & 1)
1308 return *ptr & 0x0f;
1309 else
1310 return (*ptr >> 4) & 0x0f;
1313 static DWORD get_pixel_1(const dib_info *dib, const POINT *pt)
1315 BYTE *ptr = get_pixel_ptr_1( dib, pt->x, pt->y );
1316 return (*ptr & pixel_masks_1[pt->x & 0x7]) ? 1 : 0;
1319 static DWORD get_pixel_null(const dib_info *dib, const POINT *pt)
1321 return 0;
1324 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1326 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1329 static const DWORD field_masks[33] =
1331 0x00, /* should never happen */
1332 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1333 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1334 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1335 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1338 static inline DWORD get_field(DWORD field, int shift, int len)
1340 shift = shift - (8 - len);
1341 if (shift < 0)
1342 field <<= -shift;
1343 else
1344 field >>= shift;
1345 field &= field_masks[len];
1346 field |= field >> len;
1347 return field;
1350 static inline DWORD put_field(DWORD field, int shift, int len)
1352 shift = shift - (8 - len);
1353 field &= field_masks[len];
1354 if (shift < 0)
1355 field >>= -shift;
1356 else
1357 field <<= shift;
1358 return field;
1361 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1363 DWORD r,g,b;
1365 r = GetRValue(colour);
1366 g = GetGValue(colour);
1367 b = GetBValue(colour);
1369 return put_field(r, dib->red_shift, dib->red_len) |
1370 put_field(g, dib->green_shift, dib->green_len) |
1371 put_field(b, dib->blue_shift, dib->blue_len);
1374 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1376 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1379 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1381 int i, best_index = 0;
1382 DWORD diff, best_diff = 0xffffffff;
1384 /* special case for conversion to 1-bpp without a color table:
1385 * we get a 1-entry table containing the background color
1387 if (dib->bit_count == 1 && dib->color_table_size == 1)
1388 return (r == dib->color_table[0].rgbRed &&
1389 g == dib->color_table[0].rgbGreen &&
1390 b == dib->color_table[0].rgbBlue);
1392 for(i = 0; i < dib->color_table_size; i++)
1394 RGBQUAD *cur = dib->color_table + i;
1395 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1396 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1397 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1399 if(diff == 0)
1401 best_index = i;
1402 break;
1405 if(diff < best_diff)
1407 best_diff = diff;
1408 best_index = i;
1411 return best_index;
1414 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1416 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1419 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1421 return 0;
1424 static inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1426 static const RGBQUAD default_rgb;
1427 if (index < dib->color_table_size) return dib->color_table[index];
1428 return default_rgb;
1431 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1433 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1436 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1438 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1439 get_field( pixel, dib->green_shift, dib->green_len ),
1440 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1443 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1445 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1446 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1447 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1450 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1452 RGBQUAD quad = colortable_entry( dib, pixel );
1454 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1457 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1459 return 0;
1462 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1464 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1466 return d1->red_mask == d2->red_mask &&
1467 d1->green_mask == d2->green_mask &&
1468 d1->blue_mask == d2->blue_mask;
1471 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1473 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1474 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1476 switch(src->bit_count)
1478 case 32:
1480 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1481 if(src->funcs == &funcs_8888)
1483 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1484 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1485 else
1487 for(y = src_rect->top; y < src_rect->bottom; y++)
1489 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1490 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1491 dst_start += dst->stride / 4;
1492 src_start += src->stride / 4;
1496 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1498 for(y = src_rect->top; y < src_rect->bottom; y++)
1500 dst_pixel = dst_start;
1501 src_pixel = src_start;
1502 for(x = src_rect->left; x < src_rect->right; x++)
1504 src_val = *src_pixel++;
1505 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1506 (((src_val >> src->green_shift) & 0xff) << 8) |
1507 ((src_val >> src->blue_shift) & 0xff);
1509 if(pad_size) memset(dst_pixel, 0, pad_size);
1510 dst_start += dst->stride / 4;
1511 src_start += src->stride / 4;
1514 else
1516 for(y = src_rect->top; y < src_rect->bottom; y++)
1518 dst_pixel = dst_start;
1519 src_pixel = src_start;
1520 for(x = src_rect->left; x < src_rect->right; x++)
1522 src_val = *src_pixel++;
1523 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1524 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1525 get_field( src_val, src->blue_shift, src->blue_len ));
1527 if(pad_size) memset(dst_pixel, 0, pad_size);
1528 dst_start += dst->stride / 4;
1529 src_start += src->stride / 4;
1532 break;
1535 case 24:
1537 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
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 RGBQUAD rgb;
1546 rgb.rgbBlue = *src_pixel++;
1547 rgb.rgbGreen = *src_pixel++;
1548 rgb.rgbRed = *src_pixel++;
1550 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1552 if(pad_size) memset(dst_pixel, 0, pad_size);
1553 dst_start += dst->stride / 4;
1554 src_start += src->stride;
1556 break;
1559 case 16:
1561 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1562 if(src->funcs == &funcs_555)
1564 for(y = src_rect->top; y < src_rect->bottom; y++)
1566 dst_pixel = dst_start;
1567 src_pixel = src_start;
1568 for(x = src_rect->left; x < src_rect->right; x++)
1570 src_val = *src_pixel++;
1571 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1572 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1573 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1575 if(pad_size) memset(dst_pixel, 0, pad_size);
1576 dst_start += dst->stride / 4;
1577 src_start += src->stride / 2;
1580 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1582 for(y = src_rect->top; y < src_rect->bottom; y++)
1584 dst_pixel = dst_start;
1585 src_pixel = src_start;
1586 for(x = src_rect->left; x < src_rect->right; x++)
1588 src_val = *src_pixel++;
1589 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1590 (((src_val >> src->red_shift) << 14) & 0x070000) |
1591 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1592 (((src_val >> src->green_shift) << 6) & 0x000700) |
1593 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1594 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1596 if(pad_size) memset(dst_pixel, 0, pad_size);
1597 dst_start += dst->stride / 4;
1598 src_start += src->stride / 2;
1601 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1603 for(y = src_rect->top; y < src_rect->bottom; y++)
1605 dst_pixel = dst_start;
1606 src_pixel = src_start;
1607 for(x = src_rect->left; x < src_rect->right; x++)
1609 src_val = *src_pixel++;
1610 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1611 (((src_val >> src->red_shift) << 14) & 0x070000) |
1612 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1613 (((src_val >> src->green_shift) << 4) & 0x000300) |
1614 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1615 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1617 if(pad_size) memset(dst_pixel, 0, pad_size);
1618 dst_start += dst->stride / 4;
1619 src_start += src->stride / 2;
1622 else
1624 for(y = src_rect->top; y < src_rect->bottom; y++)
1626 dst_pixel = dst_start;
1627 src_pixel = src_start;
1628 for(x = src_rect->left; x < src_rect->right; x++)
1630 src_val = *src_pixel++;
1631 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1632 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1633 get_field( src_val, src->blue_shift, src->blue_len ));
1635 if(pad_size) memset(dst_pixel, 0, pad_size);
1636 dst_start += dst->stride / 4;
1637 src_start += src->stride / 2;
1640 break;
1643 case 8:
1645 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1646 for(y = src_rect->top; y < src_rect->bottom; y++)
1648 dst_pixel = dst_start;
1649 src_pixel = src_start;
1650 for(x = src_rect->left; x < src_rect->right; x++)
1652 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1653 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1655 if(pad_size) memset(dst_pixel, 0, pad_size);
1656 dst_start += dst->stride / 4;
1657 src_start += src->stride;
1659 break;
1662 case 4:
1664 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1665 for(y = src_rect->top; y < src_rect->bottom; y++)
1667 dst_pixel = dst_start;
1668 src_pixel = src_start;
1669 for(x = src_rect->left; x < src_rect->right; x++)
1671 RGBQUAD rgb;
1672 if(x & 1)
1673 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1674 else
1675 rgb = colortable_entry( src, *src_pixel >> 4 );
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 1:
1687 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1688 for(y = src_rect->top; y < src_rect->bottom; y++)
1690 dst_pixel = dst_start;
1691 src_pixel = src_start;
1692 for(x = src_rect->left; x < src_rect->right; x++)
1694 RGBQUAD rgb;
1695 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1696 if((x % 8) == 7) src_pixel++;
1697 rgb = src->color_table[src_val];
1698 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1700 if(pad_size) memset(dst_pixel, 0, pad_size);
1701 dst_start += dst->stride / 4;
1702 src_start += src->stride;
1704 break;
1709 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1711 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1712 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1714 switch(src->bit_count)
1716 case 32:
1718 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1720 if(src->funcs == &funcs_8888)
1722 for(y = src_rect->top; y < src_rect->bottom; y++)
1724 dst_pixel = dst_start;
1725 src_pixel = src_start;
1726 for(x = src_rect->left; x < src_rect->right; x++)
1728 src_val = *src_pixel++;
1729 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1730 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1731 put_field(src_val, dst->blue_shift, dst->blue_len);
1733 if(pad_size) memset(dst_pixel, 0, pad_size);
1734 dst_start += dst->stride / 4;
1735 src_start += src->stride / 4;
1738 else if(bit_fields_match(src, dst))
1740 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1741 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1742 else
1744 for(y = src_rect->top; y < src_rect->bottom; y++)
1746 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1747 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1748 dst_start += dst->stride / 4;
1749 src_start += src->stride / 4;
1753 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1754 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1756 for(y = src_rect->top; y < src_rect->bottom; y++)
1758 dst_pixel = dst_start;
1759 src_pixel = src_start;
1760 for(x = src_rect->left; x < src_rect->right; x++)
1762 src_val = *src_pixel++;
1763 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1764 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1765 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1767 if(pad_size) memset(dst_pixel, 0, pad_size);
1768 dst_start += dst->stride / 4;
1769 src_start += src->stride / 4;
1772 else
1774 for(y = src_rect->top; y < src_rect->bottom; y++)
1776 dst_pixel = dst_start;
1777 src_pixel = src_start;
1778 for(x = src_rect->left; x < src_rect->right; x++)
1780 src_val = *src_pixel++;
1781 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1782 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1783 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1785 if(pad_size) memset(dst_pixel, 0, pad_size);
1786 dst_start += dst->stride / 4;
1787 src_start += src->stride / 4;
1790 break;
1793 case 24:
1795 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1797 for(y = src_rect->top; y < src_rect->bottom; y++)
1799 dst_pixel = dst_start;
1800 src_pixel = src_start;
1801 for(x = src_rect->left; x < src_rect->right; x++)
1803 RGBQUAD rgb;
1804 rgb.rgbBlue = *src_pixel++;
1805 rgb.rgbGreen = *src_pixel++;
1806 rgb.rgbRed = *src_pixel++;
1808 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1809 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1810 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1812 if(pad_size) memset(dst_pixel, 0, pad_size);
1813 dst_start += dst->stride / 4;
1814 src_start += src->stride;
1816 break;
1819 case 16:
1821 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1822 if(src->funcs == &funcs_555)
1824 for(y = src_rect->top; y < src_rect->bottom; y++)
1826 dst_pixel = dst_start;
1827 src_pixel = src_start;
1828 for(x = src_rect->left; x < src_rect->right; x++)
1830 src_val = *src_pixel++;
1831 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1832 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1833 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1835 if(pad_size) memset(dst_pixel, 0, pad_size);
1836 dst_start += dst->stride / 4;
1837 src_start += src->stride / 2;
1840 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1842 for(y = src_rect->top; y < src_rect->bottom; y++)
1844 dst_pixel = dst_start;
1845 src_pixel = src_start;
1846 for(x = src_rect->left; x < src_rect->right; x++)
1848 src_val = *src_pixel++;
1849 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1850 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1851 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1852 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1853 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1854 (((src_val >> src->blue_shift) >> 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 == 6 && 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) << 2) & 0xfc) |
1873 (((src_val >> src->green_shift) >> 4) & 0x03), 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
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(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1892 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1893 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1895 if(pad_size) memset(dst_pixel, 0, pad_size);
1896 dst_start += dst->stride / 4;
1897 src_start += src->stride / 2;
1900 break;
1903 case 8:
1905 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1906 for(y = src_rect->top; y < src_rect->bottom; y++)
1908 dst_pixel = dst_start;
1909 src_pixel = src_start;
1910 for(x = src_rect->left; x < src_rect->right; x++)
1912 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1913 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1914 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1915 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1917 if(pad_size) memset(dst_pixel, 0, pad_size);
1918 dst_start += dst->stride / 4;
1919 src_start += src->stride;
1921 break;
1924 case 4:
1926 BYTE *src_start = get_pixel_ptr_4(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;
1934 if(x & 1)
1935 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1936 else
1937 rgb = colortable_entry( src, *src_pixel >> 4 );
1938 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1939 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1940 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1942 if(pad_size) memset(dst_pixel, 0, pad_size);
1943 dst_start += dst->stride / 4;
1944 src_start += src->stride;
1946 break;
1949 case 1:
1951 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1952 for(y = src_rect->top; y < src_rect->bottom; y++)
1954 dst_pixel = dst_start;
1955 src_pixel = src_start;
1956 for(x = src_rect->left; x < src_rect->right; x++)
1958 RGBQUAD rgb;
1959 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1960 if((x % 8) == 7) src_pixel++;
1961 rgb = src->color_table[src_val];
1962 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1963 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1964 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1966 if(pad_size) memset(dst_pixel, 0, pad_size);
1967 dst_start += dst->stride / 4;
1968 src_start += src->stride;
1970 break;
1975 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1977 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1978 DWORD src_val;
1979 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1981 switch(src->bit_count)
1983 case 32:
1985 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1986 if(src->funcs == &funcs_8888)
1988 for(y = src_rect->top; y < src_rect->bottom; y++)
1990 dst_pixel = dst_start;
1991 src_pixel = src_start;
1992 for(x = src_rect->left; x < src_rect->right; x++)
1994 src_val = *src_pixel++;
1995 *dst_pixel++ = src_val & 0xff;
1996 *dst_pixel++ = (src_val >> 8) & 0xff;
1997 *dst_pixel++ = (src_val >> 16) & 0xff;
1999 if(pad_size) memset(dst_pixel, 0, pad_size);
2000 dst_start += dst->stride;
2001 src_start += src->stride / 4;
2004 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2006 for(y = src_rect->top; y < src_rect->bottom; y++)
2008 dst_pixel = dst_start;
2009 src_pixel = src_start;
2010 for(x = src_rect->left; x < src_rect->right; x++)
2012 src_val = *src_pixel++;
2013 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2014 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2015 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2017 if(pad_size) memset(dst_pixel, 0, pad_size);
2018 dst_start += dst->stride;
2019 src_start += src->stride / 4;
2022 else
2024 for(y = src_rect->top; y < src_rect->bottom; y++)
2026 dst_pixel = dst_start;
2027 src_pixel = src_start;
2028 for(x = src_rect->left; x < src_rect->right; x++)
2030 src_val = *src_pixel++;
2031 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2032 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2033 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2035 if(pad_size) memset(dst_pixel, 0, pad_size);
2036 dst_start += dst->stride;
2037 src_start += src->stride / 4;
2040 break;
2043 case 24:
2045 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2047 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2048 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2049 else
2051 for(y = src_rect->top; y < src_rect->bottom; y++)
2053 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2054 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2055 dst_start += dst->stride;
2056 src_start += src->stride;
2059 break;
2062 case 16:
2064 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2065 if(src->funcs == &funcs_555)
2067 for(y = src_rect->top; y < src_rect->bottom; y++)
2069 dst_pixel = dst_start;
2070 src_pixel = src_start;
2071 for(x = src_rect->left; x < src_rect->right; x++)
2073 src_val = *src_pixel++;
2074 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2075 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2076 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2078 if(pad_size) memset(dst_pixel, 0, pad_size);
2079 dst_start += dst->stride;
2080 src_start += src->stride / 2;
2083 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2085 for(y = src_rect->top; y < src_rect->bottom; y++)
2087 dst_pixel = dst_start;
2088 src_pixel = src_start;
2089 for(x = src_rect->left; x < src_rect->right; x++)
2091 src_val = *src_pixel++;
2092 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2093 (((src_val >> src->blue_shift) >> 2) & 0x07);
2094 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2095 (((src_val >> src->green_shift) >> 2) & 0x07);
2096 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2097 (((src_val >> src->red_shift) >> 2) & 0x07);
2099 if(pad_size) memset(dst_pixel, 0, pad_size);
2100 dst_start += dst->stride;
2101 src_start += src->stride / 2;
2104 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2106 for(y = src_rect->top; y < src_rect->bottom; y++)
2108 dst_pixel = dst_start;
2109 src_pixel = src_start;
2110 for(x = src_rect->left; x < src_rect->right; x++)
2112 src_val = *src_pixel++;
2113 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2114 (((src_val >> src->blue_shift) >> 2) & 0x07);
2115 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2116 (((src_val >> src->green_shift) >> 4) & 0x03);
2117 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2118 (((src_val >> src->red_shift) >> 2) & 0x07);
2120 if(pad_size) memset(dst_pixel, 0, pad_size);
2121 dst_start += dst->stride;
2122 src_start += src->stride / 2;
2125 else
2127 for(y = src_rect->top; y < src_rect->bottom; y++)
2129 dst_pixel = dst_start;
2130 src_pixel = src_start;
2131 for(x = src_rect->left; x < src_rect->right; x++)
2133 src_val = *src_pixel++;
2134 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2135 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2136 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2138 if(pad_size) memset(dst_pixel, 0, pad_size);
2139 dst_start += dst->stride;
2140 src_start += src->stride / 2;
2143 break;
2146 case 8:
2148 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2149 for(y = src_rect->top; y < src_rect->bottom; y++)
2151 dst_pixel = dst_start;
2152 src_pixel = src_start;
2153 for(x = src_rect->left; x < src_rect->right; x++)
2155 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2156 *dst_pixel++ = rgb.rgbBlue;
2157 *dst_pixel++ = rgb.rgbGreen;
2158 *dst_pixel++ = rgb.rgbRed;
2160 if(pad_size) memset(dst_pixel, 0, pad_size);
2161 dst_start += dst->stride;
2162 src_start += src->stride;
2164 break;
2167 case 4:
2169 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2170 for(y = src_rect->top; y < src_rect->bottom; y++)
2172 dst_pixel = dst_start;
2173 src_pixel = src_start;
2174 for(x = src_rect->left; x < src_rect->right; x++)
2176 RGBQUAD rgb;
2177 if(x & 1)
2178 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2179 else
2180 rgb = colortable_entry( src, *src_pixel >> 4 );
2181 *dst_pixel++ = rgb.rgbBlue;
2182 *dst_pixel++ = rgb.rgbGreen;
2183 *dst_pixel++ = rgb.rgbRed;
2185 if(pad_size) memset(dst_pixel, 0, pad_size);
2186 dst_start += dst->stride;
2187 src_start += src->stride;
2189 break;
2192 case 1:
2194 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2195 for(y = src_rect->top; y < src_rect->bottom; y++)
2197 dst_pixel = dst_start;
2198 src_pixel = src_start;
2199 for(x = src_rect->left; x < src_rect->right; x++)
2201 RGBQUAD rgb;
2202 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2203 if((x % 8) == 7) src_pixel++;
2204 rgb = src->color_table[src_val];
2205 *dst_pixel++ = rgb.rgbBlue;
2206 *dst_pixel++ = rgb.rgbGreen;
2207 *dst_pixel++ = rgb.rgbRed;
2209 if(pad_size) memset(dst_pixel, 0, pad_size);
2210 dst_start += dst->stride;
2211 src_start += src->stride;
2213 break;
2218 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
2220 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2221 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2222 DWORD src_val;
2224 switch(src->bit_count)
2226 case 32:
2228 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2230 if(src->funcs == &funcs_8888)
2232 for(y = src_rect->top; y < src_rect->bottom; y++)
2234 dst_pixel = dst_start;
2235 src_pixel = src_start;
2236 for(x = src_rect->left; x < src_rect->right; x++)
2238 src_val = *src_pixel++;
2239 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2240 ((src_val >> 6) & 0x03e0) |
2241 ((src_val >> 3) & 0x001f);
2243 if(pad_size) memset(dst_pixel, 0, pad_size);
2244 dst_start += dst->stride / 2;
2245 src_start += src->stride / 4;
2248 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2250 for(y = src_rect->top; y < src_rect->bottom; y++)
2252 dst_pixel = dst_start;
2253 src_pixel = src_start;
2254 for(x = src_rect->left; x < src_rect->right; x++)
2256 src_val = *src_pixel++;
2257 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2258 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2259 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2261 if(pad_size) memset(dst_pixel, 0, pad_size);
2262 dst_start += dst->stride / 2;
2263 src_start += src->stride / 4;
2266 else
2268 for(y = src_rect->top; y < src_rect->bottom; y++)
2270 dst_pixel = dst_start;
2271 src_pixel = src_start;
2272 for(x = src_rect->left; x < src_rect->right; x++)
2274 src_val = *src_pixel++;
2275 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2276 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2277 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2279 if(pad_size) memset(dst_pixel, 0, pad_size);
2280 dst_start += dst->stride / 2;
2281 src_start += src->stride / 4;
2284 break;
2287 case 24:
2289 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2291 for(y = src_rect->top; y < src_rect->bottom; y++)
2293 dst_pixel = dst_start;
2294 src_pixel = src_start;
2295 for(x = src_rect->left; x < src_rect->right; x++)
2297 RGBQUAD rgb;
2298 rgb.rgbBlue = *src_pixel++;
2299 rgb.rgbGreen = *src_pixel++;
2300 rgb.rgbRed = *src_pixel++;
2302 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2303 ((rgb.rgbGreen << 2) & 0x03e0) |
2304 ((rgb.rgbBlue >> 3) & 0x001f);
2306 if(pad_size) memset(dst_pixel, 0, pad_size);
2307 dst_start += dst->stride / 2;
2308 src_start += src->stride;
2310 break;
2313 case 16:
2315 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2316 if(src->funcs == &funcs_555)
2318 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2319 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2320 else
2322 for(y = src_rect->top; y < src_rect->bottom; y++)
2324 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2325 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2326 dst_start += dst->stride / 2;
2327 src_start += src->stride / 2;
2331 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2333 for(y = src_rect->top; y < src_rect->bottom; y++)
2335 dst_pixel = dst_start;
2336 src_pixel = src_start;
2337 for(x = src_rect->left; x < src_rect->right; x++)
2339 src_val = *src_pixel++;
2340 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2341 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2342 ( (src_val >> src->blue_shift) & 0x001f);
2344 if(pad_size) memset(dst_pixel, 0, pad_size);
2345 dst_start += dst->stride / 2;
2346 src_start += src->stride / 2;
2349 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2351 for(y = src_rect->top; y < src_rect->bottom; y++)
2353 dst_pixel = dst_start;
2354 src_pixel = src_start;
2355 for(x = src_rect->left; x < src_rect->right; x++)
2357 src_val = *src_pixel++;
2358 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2359 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2360 ( (src_val >> src->blue_shift) & 0x001f);
2362 if(pad_size) memset(dst_pixel, 0, pad_size);
2363 dst_start += dst->stride / 2;
2364 src_start += src->stride / 2;
2367 else
2369 for(y = src_rect->top; y < src_rect->bottom; y++)
2371 dst_pixel = dst_start;
2372 src_pixel = src_start;
2373 for(x = src_rect->left; x < src_rect->right; x++)
2375 src_val = *src_pixel++;
2376 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2377 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2378 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2380 if(pad_size) memset(dst_pixel, 0, pad_size);
2381 dst_start += dst->stride / 2;
2382 src_start += src->stride / 2;
2385 break;
2388 case 8:
2390 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2391 for(y = src_rect->top; y < src_rect->bottom; y++)
2393 dst_pixel = dst_start;
2394 src_pixel = src_start;
2395 for(x = src_rect->left; x < src_rect->right; x++)
2397 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2398 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2399 ((rgb.rgbGreen << 2) & 0x03e0) |
2400 ((rgb.rgbBlue >> 3) & 0x001f);
2402 if(pad_size) memset(dst_pixel, 0, pad_size);
2403 dst_start += dst->stride / 2;
2404 src_start += src->stride;
2406 break;
2409 case 4:
2411 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2412 for(y = src_rect->top; y < src_rect->bottom; y++)
2414 dst_pixel = dst_start;
2415 src_pixel = src_start;
2416 for(x = src_rect->left; x < src_rect->right; x++)
2418 RGBQUAD rgb;
2419 if(x & 1)
2420 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2421 else
2422 rgb = colortable_entry( src, *src_pixel >> 4 );
2423 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2424 ((rgb.rgbGreen << 2) & 0x03e0) |
2425 ((rgb.rgbBlue >> 3) & 0x001f);
2427 if(pad_size) memset(dst_pixel, 0, pad_size);
2428 dst_start += dst->stride / 2;
2429 src_start += src->stride;
2431 break;
2434 case 1:
2436 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2437 for(y = src_rect->top; y < src_rect->bottom; y++)
2439 dst_pixel = dst_start;
2440 src_pixel = src_start;
2441 for(x = src_rect->left; x < src_rect->right; x++)
2443 RGBQUAD rgb;
2444 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2445 if((x % 8) == 7) src_pixel++;
2446 rgb = src->color_table[src_val];
2447 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2448 ((rgb.rgbGreen << 2) & 0x03e0) |
2449 ((rgb.rgbBlue >> 3) & 0x001f);
2451 if(pad_size) memset(dst_pixel, 0, pad_size);
2452 dst_start += dst->stride / 2;
2453 src_start += src->stride;
2455 break;
2460 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2462 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2463 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2464 DWORD src_val;
2466 switch(src->bit_count)
2468 case 32:
2470 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2472 if(src->funcs == &funcs_8888)
2474 for(y = src_rect->top; y < src_rect->bottom; y++)
2476 dst_pixel = dst_start;
2477 src_pixel = src_start;
2478 for(x = src_rect->left; x < src_rect->right; x++)
2480 src_val = *src_pixel++;
2481 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2482 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2483 put_field(src_val, dst->blue_shift, dst->blue_len);
2485 if(pad_size) memset(dst_pixel, 0, pad_size);
2486 dst_start += dst->stride / 2;
2487 src_start += src->stride / 4;
2490 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2492 for(y = src_rect->top; y < src_rect->bottom; y++)
2494 dst_pixel = dst_start;
2495 src_pixel = src_start;
2496 for(x = src_rect->left; x < src_rect->right; x++)
2498 src_val = *src_pixel++;
2499 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2500 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2501 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2503 if(pad_size) memset(dst_pixel, 0, pad_size);
2504 dst_start += dst->stride / 2;
2505 src_start += src->stride / 4;
2508 else
2510 for(y = src_rect->top; y < src_rect->bottom; y++)
2512 dst_pixel = dst_start;
2513 src_pixel = src_start;
2514 for(x = src_rect->left; x < src_rect->right; x++)
2516 src_val = *src_pixel++;
2517 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2518 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2519 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2521 if(pad_size) memset(dst_pixel, 0, pad_size);
2522 dst_start += dst->stride / 2;
2523 src_start += src->stride / 4;
2526 break;
2529 case 24:
2531 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2533 for(y = src_rect->top; y < src_rect->bottom; y++)
2535 dst_pixel = dst_start;
2536 src_pixel = src_start;
2537 for(x = src_rect->left; x < src_rect->right; x++)
2539 RGBQUAD rgb;
2540 rgb.rgbBlue = *src_pixel++;
2541 rgb.rgbGreen = *src_pixel++;
2542 rgb.rgbRed = *src_pixel++;
2544 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2545 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2546 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2548 if(pad_size) memset(dst_pixel, 0, pad_size);
2549 dst_start += dst->stride / 2;
2550 src_start += src->stride;
2552 break;
2555 case 16:
2557 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2558 if(src->funcs == &funcs_555)
2560 for(y = src_rect->top; y < src_rect->bottom; y++)
2562 dst_pixel = dst_start;
2563 src_pixel = src_start;
2564 for(x = src_rect->left; x < src_rect->right; x++)
2566 src_val = *src_pixel++;
2567 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2568 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2569 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2571 if(pad_size) memset(dst_pixel, 0, pad_size);
2572 dst_start += dst->stride / 2;
2573 src_start += src->stride / 2;
2576 else if(bit_fields_match(src, dst))
2578 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2579 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2580 else
2582 for(y = src_rect->top; y < src_rect->bottom; y++)
2584 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2585 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2586 dst_start += dst->stride / 2;
2587 src_start += src->stride / 2;
2591 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2593 for(y = src_rect->top; y < src_rect->bottom; y++)
2595 dst_pixel = dst_start;
2596 src_pixel = src_start;
2597 for(x = src_rect->left; x < src_rect->right; x++)
2599 src_val = *src_pixel++;
2600 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2601 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2602 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2603 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2604 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2605 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2607 if(pad_size) memset(dst_pixel, 0, pad_size);
2608 dst_start += dst->stride / 2;
2609 src_start += src->stride / 2;
2612 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2614 for(y = src_rect->top; y < src_rect->bottom; y++)
2616 dst_pixel = dst_start;
2617 src_pixel = src_start;
2618 for(x = src_rect->left; x < src_rect->right; x++)
2620 src_val = *src_pixel++;
2621 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2622 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2623 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2624 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2625 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2626 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2628 if(pad_size) memset(dst_pixel, 0, pad_size);
2629 dst_start += dst->stride / 2;
2630 src_start += src->stride / 2;
2633 else
2635 for(y = src_rect->top; y < src_rect->bottom; y++)
2637 dst_pixel = dst_start;
2638 src_pixel = src_start;
2639 for(x = src_rect->left; x < src_rect->right; x++)
2641 src_val = *src_pixel++;
2642 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2643 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2644 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2646 if(pad_size) memset(dst_pixel, 0, pad_size);
2647 dst_start += dst->stride / 2;
2648 src_start += src->stride / 2;
2651 break;
2654 case 8:
2656 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2657 for(y = src_rect->top; y < src_rect->bottom; y++)
2659 dst_pixel = dst_start;
2660 src_pixel = src_start;
2661 for(x = src_rect->left; x < src_rect->right; x++)
2663 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2664 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2665 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2666 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2668 if(pad_size) memset(dst_pixel, 0, pad_size);
2669 dst_start += dst->stride / 2;
2670 src_start += src->stride;
2672 break;
2675 case 4:
2677 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2678 for(y = src_rect->top; y < src_rect->bottom; y++)
2680 dst_pixel = dst_start;
2681 src_pixel = src_start;
2682 for(x = src_rect->left; x < src_rect->right; x++)
2684 RGBQUAD rgb;
2685 if(x & 1)
2686 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2687 else
2688 rgb = colortable_entry( src, *src_pixel >> 4 );
2689 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2690 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2691 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2693 if(pad_size) memset(dst_pixel, 0, pad_size);
2694 dst_start += dst->stride / 2;
2695 src_start += src->stride;
2697 break;
2700 case 1:
2702 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2703 for(y = src_rect->top; y < src_rect->bottom; y++)
2705 dst_pixel = dst_start;
2706 src_pixel = src_start;
2707 for(x = src_rect->left; x < src_rect->right; x++)
2709 RGBQUAD rgb;
2710 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2711 if((x % 8) == 7) src_pixel++;
2712 rgb = src->color_table[src_val];
2713 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2714 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2715 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2717 if(pad_size) memset(dst_pixel, 0, pad_size);
2718 dst_start += dst->stride / 2;
2719 src_start += src->stride;
2721 break;
2726 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2728 assert(d1->color_table_size && d2->color_table_size);
2730 if(d1->color_table_size != d2->color_table_size) return FALSE;
2731 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2734 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2736 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2737 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2740 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2742 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2743 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2744 DWORD src_val;
2746 switch(src->bit_count)
2748 case 32:
2750 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2752 if(src->funcs == &funcs_8888)
2754 for(y = src_rect->top; y < src_rect->bottom; y++)
2756 dst_pixel = dst_start;
2757 src_pixel = src_start;
2758 for(x = src_rect->left; x < src_rect->right; x++)
2760 src_val = *src_pixel++;
2761 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2763 if(pad_size) memset(dst_pixel, 0, pad_size);
2764 dst_start += dst->stride;
2765 src_start += src->stride / 4;
2768 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2770 for(y = src_rect->top; y < src_rect->bottom; y++)
2772 dst_pixel = dst_start;
2773 src_pixel = src_start;
2774 for(x = src_rect->left; x < src_rect->right; x++)
2776 src_val = *src_pixel++;
2777 *dst_pixel++ = rgb_lookup_colortable(dst,
2778 src_val >> src->red_shift,
2779 src_val >> src->green_shift,
2780 src_val >> src->blue_shift );
2782 if(pad_size) memset(dst_pixel, 0, pad_size);
2783 dst_start += dst->stride;
2784 src_start += src->stride / 4;
2787 else
2789 for(y = src_rect->top; y < src_rect->bottom; y++)
2791 dst_pixel = dst_start;
2792 src_pixel = src_start;
2793 for(x = src_rect->left; x < src_rect->right; x++)
2795 src_val = *src_pixel++;
2796 *dst_pixel++ = rgb_lookup_colortable(dst,
2797 get_field(src_val, src->red_shift, src->red_len),
2798 get_field(src_val, src->green_shift, src->green_len),
2799 get_field(src_val, src->blue_shift, src->blue_len));
2801 if(pad_size) memset(dst_pixel, 0, pad_size);
2802 dst_start += dst->stride;
2803 src_start += src->stride / 4;
2806 break;
2809 case 24:
2811 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2813 for(y = src_rect->top; y < src_rect->bottom; y++)
2815 dst_pixel = dst_start;
2816 src_pixel = src_start;
2817 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2819 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2821 if(pad_size) memset(dst_pixel, 0, pad_size);
2822 dst_start += dst->stride;
2823 src_start += src->stride;
2825 break;
2828 case 16:
2830 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2831 if(src->funcs == &funcs_555)
2833 for(y = src_rect->top; y < src_rect->bottom; y++)
2835 dst_pixel = dst_start;
2836 src_pixel = src_start;
2837 for(x = src_rect->left; x < src_rect->right; x++)
2839 src_val = *src_pixel++;
2840 *dst_pixel++ = rgb_lookup_colortable(dst,
2841 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2842 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2843 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2845 if(pad_size) memset(dst_pixel, 0, pad_size);
2846 dst_start += dst->stride;
2847 src_start += src->stride / 2;
2850 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2852 for(y = src_rect->top; y < src_rect->bottom; y++)
2854 dst_pixel = dst_start;
2855 src_pixel = src_start;
2856 for(x = src_rect->left; x < src_rect->right; x++)
2858 src_val = *src_pixel++;
2859 *dst_pixel++ = rgb_lookup_colortable(dst,
2860 (((src_val >> src->red_shift) << 3) & 0xf8) |
2861 (((src_val >> src->red_shift) >> 2) & 0x07),
2862 (((src_val >> src->green_shift) << 3) & 0xf8) |
2863 (((src_val >> src->green_shift) >> 2) & 0x07),
2864 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2865 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2867 if(pad_size) memset(dst_pixel, 0, pad_size);
2868 dst_start += dst->stride;
2869 src_start += src->stride / 2;
2872 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2874 for(y = src_rect->top; y < src_rect->bottom; y++)
2876 dst_pixel = dst_start;
2877 src_pixel = src_start;
2878 for(x = src_rect->left; x < src_rect->right; x++)
2880 src_val = *src_pixel++;
2881 *dst_pixel++ = rgb_lookup_colortable(dst,
2882 (((src_val >> src->red_shift) << 3) & 0xf8) |
2883 (((src_val >> src->red_shift) >> 2) & 0x07),
2884 (((src_val >> src->green_shift) << 2) & 0xfc) |
2885 (((src_val >> src->green_shift) >> 4) & 0x03),
2886 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2887 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2889 if(pad_size) memset(dst_pixel, 0, pad_size);
2890 dst_start += dst->stride;
2891 src_start += src->stride / 2;
2894 else
2896 for(y = src_rect->top; y < src_rect->bottom; y++)
2898 dst_pixel = dst_start;
2899 src_pixel = src_start;
2900 for(x = src_rect->left; x < src_rect->right; x++)
2902 src_val = *src_pixel++;
2903 *dst_pixel++ = rgb_lookup_colortable(dst,
2904 get_field(src_val, src->red_shift, src->red_len),
2905 get_field(src_val, src->green_shift, src->green_len),
2906 get_field(src_val, src->blue_shift, src->blue_len));
2908 if(pad_size) memset(dst_pixel, 0, pad_size);
2909 dst_start += dst->stride;
2910 src_start += src->stride / 2;
2913 break;
2916 case 8:
2918 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2920 if(color_tables_match(dst, src))
2922 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2923 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2924 else
2926 for(y = src_rect->top; y < src_rect->bottom; y++)
2928 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2929 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2930 dst_start += dst->stride;
2931 src_start += src->stride;
2935 else
2937 for(y = src_rect->top; y < src_rect->bottom; y++)
2939 dst_pixel = dst_start;
2940 src_pixel = src_start;
2941 for(x = src_rect->left; x < src_rect->right; x++)
2943 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2944 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2946 if(pad_size) memset(dst_pixel, 0, pad_size);
2947 dst_start += dst->stride;
2948 src_start += src->stride;
2951 break;
2954 case 4:
2956 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2957 for(y = src_rect->top; y < src_rect->bottom; y++)
2959 dst_pixel = dst_start;
2960 src_pixel = src_start;
2961 for(x = src_rect->left; x < src_rect->right; x++)
2963 RGBQUAD rgb;
2964 if(x & 1)
2965 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2966 else
2967 rgb = colortable_entry( src, *src_pixel >> 4 );
2968 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2970 if(pad_size) memset(dst_pixel, 0, pad_size);
2971 dst_start += dst->stride;
2972 src_start += src->stride;
2974 break;
2977 case 1:
2979 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2980 for(y = src_rect->top; y < src_rect->bottom; y++)
2982 dst_pixel = dst_start;
2983 src_pixel = src_start;
2984 for(x = src_rect->left; x < src_rect->right; x++)
2986 RGBQUAD rgb;
2987 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2988 if((x % 8) == 7) src_pixel++;
2989 rgb = src->color_table[src_val];
2990 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2992 if(pad_size) memset(dst_pixel, 0, pad_size);
2993 dst_start += dst->stride;
2994 src_start += src->stride;
2996 break;
3001 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
3003 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
3004 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
3005 DWORD src_val;
3007 switch(src->bit_count)
3009 case 32:
3011 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3013 if(src->funcs == &funcs_8888)
3015 for(y = src_rect->top; y < src_rect->bottom; y++)
3017 dst_pixel = dst_start;
3018 src_pixel = src_start;
3019 for(x = src_rect->left; x < src_rect->right; x++)
3021 src_val = *src_pixel++;
3022 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3023 if((x - src_rect->left) & 1)
3025 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3026 dst_pixel++;
3028 else
3029 *dst_pixel = (dst_val << 4) & 0xf0;
3031 if(pad_size)
3033 if((x - src_rect->left) & 1) dst_pixel++;
3034 memset(dst_pixel, 0, pad_size);
3036 dst_start += dst->stride;
3037 src_start += src->stride / 4;
3040 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3042 for(y = src_rect->top; y < src_rect->bottom; y++)
3044 dst_pixel = dst_start;
3045 src_pixel = src_start;
3046 for(x = src_rect->left; x < src_rect->right; x++)
3048 src_val = *src_pixel++;
3049 dst_val = rgb_to_pixel_colortable(dst,
3050 src_val >> src->red_shift,
3051 src_val >> src->green_shift,
3052 src_val >> src->blue_shift);
3053 if((x - src_rect->left) & 1)
3055 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3056 dst_pixel++;
3058 else
3059 *dst_pixel = (dst_val << 4) & 0xf0;
3061 if(pad_size)
3063 if((x - src_rect->left) & 1) dst_pixel++;
3064 memset(dst_pixel, 0, pad_size);
3066 dst_start += dst->stride;
3067 src_start += src->stride / 4;
3070 else
3072 for(y = src_rect->top; y < src_rect->bottom; y++)
3074 dst_pixel = dst_start;
3075 src_pixel = src_start;
3076 for(x = src_rect->left; x < src_rect->right; x++)
3078 src_val = *src_pixel++;
3079 dst_val = rgb_to_pixel_colortable(dst,
3080 get_field(src_val, src->red_shift, src->red_len),
3081 get_field(src_val, src->green_shift, src->green_len),
3082 get_field(src_val, src->blue_shift, src->blue_len));
3083 if((x - src_rect->left) & 1)
3085 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3086 dst_pixel++;
3088 else
3089 *dst_pixel = (dst_val << 4) & 0xf0;
3091 if(pad_size)
3093 if((x - src_rect->left) & 1) dst_pixel++;
3094 memset(dst_pixel, 0, pad_size);
3096 dst_start += dst->stride;
3097 src_start += src->stride / 4;
3100 break;
3103 case 24:
3105 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3107 for(y = src_rect->top; y < src_rect->bottom; y++)
3109 dst_pixel = dst_start;
3110 src_pixel = src_start;
3111 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3113 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3115 if((x - src_rect->left) & 1)
3117 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3118 dst_pixel++;
3120 else
3121 *dst_pixel = (dst_val << 4) & 0xf0;
3123 if(pad_size)
3125 if((x - src_rect->left) & 1) dst_pixel++;
3126 memset(dst_pixel, 0, pad_size);
3128 dst_start += dst->stride;
3129 src_start += src->stride;
3131 break;
3134 case 16:
3136 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3137 if(src->funcs == &funcs_555)
3139 for(y = src_rect->top; y < src_rect->bottom; y++)
3141 dst_pixel = dst_start;
3142 src_pixel = src_start;
3143 for(x = src_rect->left; x < src_rect->right; x++)
3145 src_val = *src_pixel++;
3146 dst_val = rgb_to_pixel_colortable(dst,
3147 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3148 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3149 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3150 if((x - src_rect->left) & 1)
3152 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3153 dst_pixel++;
3155 else
3156 *dst_pixel = (dst_val << 4) & 0xf0;
3158 if(pad_size)
3160 if((x - src_rect->left) & 1) dst_pixel++;
3161 memset(dst_pixel, 0, pad_size);
3163 dst_start += dst->stride;
3164 src_start += src->stride / 2;
3167 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3169 for(y = src_rect->top; y < src_rect->bottom; y++)
3171 dst_pixel = dst_start;
3172 src_pixel = src_start;
3173 for(x = src_rect->left; x < src_rect->right; x++)
3175 src_val = *src_pixel++;
3176 dst_val = rgb_to_pixel_colortable(dst,
3177 (((src_val >> src->red_shift) << 3) & 0xf8) |
3178 (((src_val >> src->red_shift) >> 2) & 0x07),
3179 (((src_val >> src->green_shift) << 3) & 0xf8) |
3180 (((src_val >> src->green_shift) >> 2) & 0x07),
3181 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3182 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3183 if((x - src_rect->left) & 1)
3185 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3186 dst_pixel++;
3188 else
3189 *dst_pixel = (dst_val << 4) & 0xf0;
3191 if(pad_size)
3193 if((x - src_rect->left) & 1) dst_pixel++;
3194 memset(dst_pixel, 0, pad_size);
3196 dst_start += dst->stride;
3197 src_start += src->stride / 2;
3200 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3202 for(y = src_rect->top; y < src_rect->bottom; y++)
3204 dst_pixel = dst_start;
3205 src_pixel = src_start;
3206 for(x = src_rect->left; x < src_rect->right; x++)
3208 src_val = *src_pixel++;
3209 dst_val = rgb_to_pixel_colortable(dst,
3210 (((src_val >> src->red_shift) << 3) & 0xf8) |
3211 (((src_val >> src->red_shift) >> 2) & 0x07),
3212 (((src_val >> src->green_shift) << 2) & 0xfc) |
3213 (((src_val >> src->green_shift) >> 4) & 0x03),
3214 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3215 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3216 if((x - src_rect->left) & 1)
3218 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3219 dst_pixel++;
3221 else
3222 *dst_pixel = (dst_val << 4) & 0xf0;
3224 if(pad_size)
3226 if((x - src_rect->left) & 1) dst_pixel++;
3227 memset(dst_pixel, 0, pad_size);
3229 dst_start += dst->stride;
3230 src_start += src->stride / 2;
3233 else
3235 for(y = src_rect->top; y < src_rect->bottom; y++)
3237 dst_pixel = dst_start;
3238 src_pixel = src_start;
3239 for(x = src_rect->left; x < src_rect->right; x++)
3241 src_val = *src_pixel++;
3242 dst_val = rgb_to_pixel_colortable(dst,
3243 get_field(src_val, src->red_shift, src->red_len),
3244 get_field(src_val, src->green_shift, src->green_len),
3245 get_field(src_val, src->blue_shift, src->blue_len));
3246 if((x - src_rect->left) & 1)
3248 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3249 dst_pixel++;
3251 else
3252 *dst_pixel = (dst_val << 4) & 0xf0;
3254 if(pad_size)
3256 if((x - src_rect->left) & 1) dst_pixel++;
3257 memset(dst_pixel, 0, pad_size);
3259 dst_start += dst->stride;
3260 src_start += src->stride / 2;
3263 break;
3266 case 8:
3268 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3270 for(y = src_rect->top; y < src_rect->bottom; y++)
3272 dst_pixel = dst_start;
3273 src_pixel = src_start;
3274 for(x = src_rect->left; x < src_rect->right; x++)
3276 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3277 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3278 if((x - src_rect->left) & 1)
3280 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3281 dst_pixel++;
3283 else
3284 *dst_pixel = (dst_val << 4) & 0xf0;
3286 if(pad_size)
3288 if((x - src_rect->left) & 1) dst_pixel++;
3289 memset(dst_pixel, 0, pad_size);
3291 dst_start += dst->stride;
3292 src_start += src->stride;
3294 break;
3297 case 4:
3299 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3301 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
3303 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
3304 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3305 else
3307 for(y = src_rect->top; y < src_rect->bottom; y++)
3309 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3310 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3311 dst_start += dst->stride;
3312 src_start += src->stride;
3316 else
3318 for(y = src_rect->top; y < src_rect->bottom; y++)
3320 dst_pixel = dst_start;
3321 src_pixel = src_start;
3322 for(x = src_rect->left; x < src_rect->right; x++)
3324 RGBQUAD rgb;
3325 if(x & 1)
3326 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3327 else
3328 rgb = colortable_entry( src, *src_pixel >> 4 );
3329 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3330 if((x - src_rect->left) & 1)
3332 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3333 dst_pixel++;
3335 else
3336 *dst_pixel = (dst_val << 4) & 0xf0;
3338 if(pad_size)
3340 if((x - src_rect->left) & 1) dst_pixel++;
3341 memset(dst_pixel, 0, pad_size);
3343 dst_start += dst->stride;
3344 src_start += src->stride;
3347 break;
3350 case 1:
3352 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3353 for(y = src_rect->top; y < src_rect->bottom; y++)
3355 dst_pixel = dst_start;
3356 src_pixel = src_start;
3357 for(x = src_rect->left; x < src_rect->right; x++)
3359 RGBQUAD rgb;
3360 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3361 if((x % 8) == 7) src_pixel++;
3362 rgb = src->color_table[src_val];
3363 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3364 if((x - src_rect->left) & 1)
3366 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3367 dst_pixel++;
3369 else
3370 *dst_pixel = (dst_val << 4) & 0xf0;
3372 if(pad_size)
3374 if((x - src_rect->left) & 1) dst_pixel++;
3375 memset(dst_pixel, 0, pad_size);
3377 dst_start += dst->stride;
3378 src_start += src->stride;
3380 break;
3385 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3387 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3388 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3389 DWORD src_val;
3390 int bit_pos;
3392 /* FIXME: Brushes should be dithered. */
3394 switch(src->bit_count)
3396 case 32:
3398 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3400 if(src->funcs == &funcs_8888)
3402 for(y = src_rect->top; y < src_rect->bottom; y++)
3404 dst_pixel = dst_start;
3405 src_pixel = src_start;
3406 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3408 src_val = *src_pixel++;
3409 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3411 if(bit_pos == 0) *dst_pixel = 0;
3412 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3414 if(++bit_pos == 8)
3416 dst_pixel++;
3417 bit_pos = 0;
3420 if(pad_size)
3422 if(bit_pos != 0) dst_pixel++;
3423 memset(dst_pixel, 0, pad_size);
3425 dst_start += dst->stride;
3426 src_start += src->stride / 4;
3429 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3431 for(y = src_rect->top; y < src_rect->bottom; y++)
3433 dst_pixel = dst_start;
3434 src_pixel = src_start;
3435 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3437 src_val = *src_pixel++;
3438 dst_val = rgb_to_pixel_colortable(dst,
3439 src_val >> src->red_shift,
3440 src_val >> src->green_shift,
3441 src_val >> src->blue_shift) ? 0xff : 0;
3443 if(bit_pos == 0) *dst_pixel = 0;
3444 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3446 if(++bit_pos == 8)
3448 dst_pixel++;
3449 bit_pos = 0;
3452 if(pad_size)
3454 if(bit_pos != 0) dst_pixel++;
3455 memset(dst_pixel, 0, pad_size);
3457 dst_start += dst->stride;
3458 src_start += src->stride / 4;
3461 else
3463 for(y = src_rect->top; y < src_rect->bottom; y++)
3465 dst_pixel = dst_start;
3466 src_pixel = src_start;
3467 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3469 src_val = *src_pixel++;
3470 dst_val = rgb_to_pixel_colortable(dst,
3471 get_field(src_val, src->red_shift, src->red_len),
3472 get_field(src_val, src->green_shift, src->green_len),
3473 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3475 if(bit_pos == 0) *dst_pixel = 0;
3476 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3478 if(++bit_pos == 8)
3480 dst_pixel++;
3481 bit_pos = 0;
3484 if(pad_size)
3486 if(bit_pos != 0) dst_pixel++;
3487 memset(dst_pixel, 0, pad_size);
3489 dst_start += dst->stride;
3490 src_start += src->stride / 4;
3493 break;
3496 case 24:
3498 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3500 for(y = src_rect->top; y < src_rect->bottom; y++)
3502 dst_pixel = dst_start;
3503 src_pixel = src_start;
3504 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3506 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3508 if(bit_pos == 0) *dst_pixel = 0;
3509 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3511 if(++bit_pos == 8)
3513 dst_pixel++;
3514 bit_pos = 0;
3517 if(pad_size)
3519 if(bit_pos != 0) dst_pixel++;
3520 memset(dst_pixel, 0, pad_size);
3522 dst_start += dst->stride;
3523 src_start += src->stride;
3525 break;
3528 case 16:
3530 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3531 if(src->funcs == &funcs_555)
3533 for(y = src_rect->top; y < src_rect->bottom; y++)
3535 dst_pixel = dst_start;
3536 src_pixel = src_start;
3537 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3539 src_val = *src_pixel++;
3540 dst_val = rgb_to_pixel_colortable(dst,
3541 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3542 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3543 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3545 if(bit_pos == 0) *dst_pixel = 0;
3546 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3548 if(++bit_pos == 8)
3550 dst_pixel++;
3551 bit_pos = 0;
3554 if(pad_size)
3556 if(bit_pos != 0) dst_pixel++;
3557 memset(dst_pixel, 0, pad_size);
3559 dst_start += dst->stride;
3560 src_start += src->stride / 2;
3563 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3565 for(y = src_rect->top; y < src_rect->bottom; y++)
3567 dst_pixel = dst_start;
3568 src_pixel = src_start;
3569 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3571 src_val = *src_pixel++;
3572 dst_val = rgb_to_pixel_colortable(dst,
3573 (((src_val >> src->red_shift) << 3) & 0xf8) |
3574 (((src_val >> src->red_shift) >> 2) & 0x07),
3575 (((src_val >> src->green_shift) << 3) & 0xf8) |
3576 (((src_val >> src->green_shift) >> 2) & 0x07),
3577 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3578 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3579 if(bit_pos == 0) *dst_pixel = 0;
3580 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3582 if(++bit_pos == 8)
3584 dst_pixel++;
3585 bit_pos = 0;
3588 if(pad_size)
3590 if(bit_pos != 0) dst_pixel++;
3591 memset(dst_pixel, 0, pad_size);
3593 dst_start += dst->stride;
3594 src_start += src->stride / 2;
3597 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3599 for(y = src_rect->top; y < src_rect->bottom; y++)
3601 dst_pixel = dst_start;
3602 src_pixel = src_start;
3603 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3605 src_val = *src_pixel++;
3606 dst_val = rgb_to_pixel_colortable(dst,
3607 (((src_val >> src->red_shift) << 3) & 0xf8) |
3608 (((src_val >> src->red_shift) >> 2) & 0x07),
3609 (((src_val >> src->green_shift) << 2) & 0xfc) |
3610 (((src_val >> src->green_shift) >> 4) & 0x03),
3611 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3612 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3613 if(bit_pos == 0) *dst_pixel = 0;
3614 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3616 if(++bit_pos == 8)
3618 dst_pixel++;
3619 bit_pos = 0;
3622 if(pad_size)
3624 if(bit_pos != 0) dst_pixel++;
3625 memset(dst_pixel, 0, pad_size);
3627 dst_start += dst->stride;
3628 src_start += src->stride / 2;
3631 else
3633 for(y = src_rect->top; y < src_rect->bottom; y++)
3635 dst_pixel = dst_start;
3636 src_pixel = src_start;
3637 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3639 src_val = *src_pixel++;
3640 dst_val = rgb_to_pixel_colortable(dst,
3641 get_field(src_val, src->red_shift, src->red_len),
3642 get_field(src_val, src->green_shift, src->green_len),
3643 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3644 if(bit_pos == 0) *dst_pixel = 0;
3645 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3647 if(++bit_pos == 8)
3649 dst_pixel++;
3650 bit_pos = 0;
3653 if(pad_size)
3655 if(bit_pos != 0) dst_pixel++;
3656 memset(dst_pixel, 0, pad_size);
3658 dst_start += dst->stride;
3659 src_start += src->stride / 2;
3662 break;
3665 case 8:
3667 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3669 for(y = src_rect->top; y < src_rect->bottom; y++)
3671 dst_pixel = dst_start;
3672 src_pixel = src_start;
3673 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3675 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3676 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3678 if(bit_pos == 0) *dst_pixel = 0;
3679 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3681 if(++bit_pos == 8)
3683 dst_pixel++;
3684 bit_pos = 0;
3687 if(pad_size)
3689 if(bit_pos != 0) dst_pixel++;
3690 memset(dst_pixel, 0, pad_size);
3692 dst_start += dst->stride;
3693 src_start += src->stride;
3695 break;
3698 case 4:
3700 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3702 for(y = src_rect->top; y < src_rect->bottom; y++)
3704 dst_pixel = dst_start;
3705 src_pixel = src_start;
3706 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3708 RGBQUAD rgb;
3709 if(x & 1)
3710 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3711 else
3712 rgb = colortable_entry( src, *src_pixel >> 4 );
3713 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3715 if(bit_pos == 0) *dst_pixel = 0;
3716 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3718 if(++bit_pos == 8)
3720 dst_pixel++;
3721 bit_pos = 0;
3724 if(pad_size)
3726 if(bit_pos != 0) dst_pixel++;
3727 memset(dst_pixel, 0, pad_size);
3729 dst_start += dst->stride;
3730 src_start += src->stride;
3732 break;
3735 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3736 uses text/bkgnd colours instead of the dib's colour table, this
3737 doesn't appear to be the case for a dc backed by a
3738 dibsection. */
3740 case 1:
3742 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3743 for(y = src_rect->top; y < src_rect->bottom; y++)
3745 dst_pixel = dst_start;
3746 src_pixel = src_start;
3747 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3749 RGBQUAD rgb;
3750 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3751 if((x % 8) == 7) src_pixel++;
3752 rgb = src->color_table[src_val];
3753 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3755 if(bit_pos == 0) *dst_pixel = 0;
3756 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3758 if(++bit_pos == 8)
3760 dst_pixel++;
3761 bit_pos = 0;
3764 if(pad_size)
3766 if(bit_pos != 0) dst_pixel++;
3767 memset(dst_pixel, 0, pad_size);
3769 dst_start += dst->stride;
3770 src_start += src->stride;
3772 break;
3777 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3781 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3783 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3786 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3788 return (blend_color( dst, src, alpha ) |
3789 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3790 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3791 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3794 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3796 BYTE b = ((BYTE)src * alpha + 127) / 255;
3797 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3798 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3799 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3800 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3801 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3802 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3803 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3806 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3808 if (blend.AlphaFormat & AC_SRC_ALPHA)
3810 DWORD alpha = blend.SourceConstantAlpha;
3811 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3812 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3813 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3814 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3815 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3816 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3817 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3819 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3820 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3821 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3824 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3825 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3827 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3828 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3829 int x, y;
3831 if (blend.AlphaFormat & AC_SRC_ALPHA)
3832 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3833 for (x = 0; x < rc->right - rc->left; x++)
3834 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3835 else
3836 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3837 for (x = 0; x < rc->right - rc->left; x++)
3838 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3841 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3842 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3844 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3845 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3846 int x, y;
3848 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3850 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3852 for (x = 0; x < rc->right - rc->left; x++)
3854 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3855 dst_ptr[x] >> dst->green_shift,
3856 dst_ptr[x] >> dst->blue_shift,
3857 src_ptr[x], blend );
3858 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3859 (((val >> 8) & 0xff) << dst->green_shift) |
3860 (((val >> 16) & 0xff) << dst->red_shift));
3864 else
3866 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3868 for (x = 0; x < rc->right - rc->left; x++)
3870 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3871 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3872 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3873 src_ptr[x], blend );
3874 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3875 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3876 put_field( val, dst->blue_shift, dst->blue_len ));
3882 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3883 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3885 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3886 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3887 int x, y;
3889 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3891 for (x = 0; x < rc->right - rc->left; x++)
3893 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3894 src_ptr[x], blend );
3895 dst_ptr[x * 3] = val;
3896 dst_ptr[x * 3 + 1] = val >> 8;
3897 dst_ptr[x * 3 + 2] = val >> 16;
3902 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3903 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3905 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3906 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3907 int x, y;
3909 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3911 for (x = 0; x < rc->right - rc->left; x++)
3913 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3914 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3915 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3916 src_ptr[x], blend );
3917 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3922 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3923 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3925 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3926 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3927 int x, y;
3929 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3931 for (x = 0; x < rc->right - rc->left; x++)
3933 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3934 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3935 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3936 src_ptr[x], blend );
3937 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3938 put_field((val >> 8), dst->green_shift, dst->green_len) |
3939 put_field( val, dst->blue_shift, dst->blue_len));
3944 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3945 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3947 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3948 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3949 int x, y;
3951 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3953 for (x = 0; x < rc->right - rc->left; x++)
3955 RGBQUAD rgb = colortable_entry( dst, dst_ptr[x] );
3956 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3957 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3962 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3963 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3965 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3966 BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3967 int x, y;
3969 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3971 for (x = rc->left; x < rc->right; x++)
3973 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3974 RGBQUAD rgb = colortable_entry( dst, val );
3975 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3976 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3977 if (x & 1)
3978 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3979 else
3980 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3985 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3986 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3988 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3989 BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
3990 int x, y;
3992 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3994 for (x = rc->left; x < rc->right; x++)
3996 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3997 RGBQUAD rgb = dst->color_table[val];
3998 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3999 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
4000 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4005 static void blend_rect_null(const dib_info *dst, const RECT *rc,
4006 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4010 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4012 BYTE r, g, b, a;
4013 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4014 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4015 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4016 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4017 return a << 24 | r << 16 | g << 8 | b;
4020 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4022 BYTE r, g, b;
4023 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4024 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4025 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4026 return r << 16 | g << 8 | b;
4029 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4030 unsigned int x, unsigned int y )
4032 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4033 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4034 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4035 r = min( 31, max( 0, r / 16 ));
4036 g = min( 31, max( 0, g / 16 ));
4037 b = min( 31, max( 0, b / 16 ));
4038 return (r << 10) | (g << 5) | b;
4041 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4042 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4044 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4045 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4046 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4047 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4050 /* compute the left/right triangle limit for row y */
4051 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4053 int x1, x2;
4055 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4056 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4058 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4060 *left = max( rc->left, min( x1, x2 ) );
4061 *right = min( rc->right, max( x1, x2 ) );
4064 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4065 static inline int triangle_det( const TRIVERTEX *v )
4067 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);
4070 /* compute the barycentric weights for a given point inside the triangle */
4071 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4073 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4074 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4077 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4079 INT64 l1, l2;
4080 BYTE r, g, b, a;
4082 triangle_weights( v, x, y, &l1, &l2 );
4083 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4084 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4085 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4086 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4087 return a << 24 | r << 16 | g << 8 | b;
4090 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4092 INT64 l1, l2;
4093 BYTE r, g, b;
4095 triangle_weights( v, x, y, &l1, &l2 );
4096 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4097 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4098 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4099 return r << 16 | g << 8 | b;
4102 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4104 INT64 l1, l2;
4105 int r, g, b;
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 / 128 + bayer_4x4[y % 4][x % 4];
4109 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4110 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4111 r = min( 31, max( 0, r / 16 ));
4112 g = min( 31, max( 0, g / 16 ));
4113 b = min( 31, max( 0, b / 16 ));
4114 return (r << 10) | (g << 5) | b;
4117 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4119 INT64 l1, l2;
4120 BYTE r, g, b;
4122 triangle_weights( v, x, y, &l1, &l2 );
4123 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4124 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4125 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4126 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4129 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4131 DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4132 int x, y, left, right, det;
4134 switch (mode)
4136 case GRADIENT_FILL_RECT_H:
4137 for (x = rc->left; x < rc->right; x++)
4138 ptr[x] = gradient_rgb_8888( v, x - v[0].x, v[1].x - v[0].x );
4140 for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4141 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4142 break;
4144 case GRADIENT_FILL_RECT_V:
4145 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4147 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4148 for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4150 break;
4152 case GRADIENT_FILL_TRIANGLE:
4153 if (!(det = triangle_det( v ))) return FALSE;
4154 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4156 triangle_coords( v, rc, y, &left, &right );
4157 for (x = left; x < right; x++) ptr[x] = gradient_triangle_8888( v, x, y, det );
4159 break;
4161 return TRUE;
4164 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4166 DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4167 int x, y, left, right, det;
4169 switch (mode)
4171 case GRADIENT_FILL_RECT_H:
4172 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4174 for (x = rc->left; x < rc->right; x++)
4176 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4177 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4178 (((val >> 8) & 0xff) << dib->green_shift) |
4179 (((val >> 16) & 0xff) << dib->red_shift));
4182 else
4184 for (x = rc->left; x < rc->right; x++)
4186 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4187 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4188 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4189 put_field( val, dib->blue_shift, dib->blue_len ));
4193 for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4194 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4195 break;
4197 case GRADIENT_FILL_RECT_V:
4198 for (y = rc->top; y < rc->bottom; y++)
4200 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4201 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4202 val = ((( val & 0xff) << dib->blue_shift) |
4203 (((val >> 8) & 0xff) << dib->green_shift) |
4204 (((val >> 16) & 0xff) << dib->red_shift));
4205 else
4206 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4207 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4208 put_field( val, dib->blue_shift, dib->blue_len ));
4210 for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4211 ptr += dib->stride / 4;
4213 break;
4215 case GRADIENT_FILL_TRIANGLE:
4216 if (!(det = triangle_det( v ))) return FALSE;
4217 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4219 triangle_coords( v, rc, y, &left, &right );
4221 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4222 for (x = left; x < right; x++)
4224 DWORD val = gradient_triangle_24( v, x, y, det );
4225 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4226 (((val >> 8) & 0xff) << dib->green_shift) |
4227 (((val >> 16) & 0xff) << dib->red_shift));
4229 else
4230 for (x = left; x < right; x++)
4232 DWORD val = gradient_triangle_24( v, x, y, det );
4233 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4234 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4235 put_field( val, dib->blue_shift, dib->blue_len ));
4238 break;
4240 return TRUE;
4243 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4245 BYTE *ptr = get_pixel_ptr_24( dib, 0, rc->top );
4246 int x, y, left, right, det;
4248 switch (mode)
4250 case GRADIENT_FILL_RECT_H:
4251 for (x = rc->left; x < rc->right; x++)
4253 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4254 ptr[x * 3] = val;
4255 ptr[x * 3 + 1] = val >> 8;
4256 ptr[x * 3 + 2] = val >> 16;
4259 for (y = rc->top + 1, ptr += rc->left * 3; y < rc->bottom; y++, ptr += dib->stride)
4260 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4261 break;
4263 case GRADIENT_FILL_RECT_V:
4264 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4266 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4267 for (x = rc->left; x < rc->right; x++)
4269 ptr[x * 3] = val;
4270 ptr[x * 3 + 1] = val >> 8;
4271 ptr[x * 3 + 2] = val >> 16;
4274 break;
4276 case GRADIENT_FILL_TRIANGLE:
4277 if (!(det = triangle_det( v ))) return FALSE;
4278 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4280 triangle_coords( v, rc, y, &left, &right );
4281 for (x = left; x < right; x++)
4283 DWORD val = gradient_triangle_24( v, x, y, det );
4284 ptr[x * 3] = val;
4285 ptr[x * 3 + 1] = val >> 8;
4286 ptr[x * 3 + 2] = val >> 16;
4289 break;
4291 return TRUE;
4294 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4296 WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4297 int x, y, left, right, det;
4299 switch (mode)
4301 case GRADIENT_FILL_RECT_H:
4302 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4303 for (x = rc->left; x < rc->right; x++)
4304 ptr[x] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4305 for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4306 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4307 break;
4309 case GRADIENT_FILL_RECT_V:
4310 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4312 WORD values[4];
4313 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4314 for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4316 break;
4318 case GRADIENT_FILL_TRIANGLE:
4319 if (!(det = triangle_det( v ))) return FALSE;
4320 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4322 triangle_coords( v, rc, y, &left, &right );
4323 for (x = left; x < right; x++) ptr[x] = gradient_triangle_555( v, x, y, det );
4325 break;
4327 return TRUE;
4330 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4332 WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4333 int x, y, left, right, det;
4335 switch (mode)
4337 case GRADIENT_FILL_RECT_H:
4338 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4339 for (x = rc->left; x < rc->right; x++)
4341 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4342 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4343 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4344 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4346 for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4347 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4348 break;
4350 case GRADIENT_FILL_RECT_V:
4351 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4353 WORD values[4];
4354 for (x = 0; x < 4; x++)
4356 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4357 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4358 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4359 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4361 for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4363 break;
4365 case GRADIENT_FILL_TRIANGLE:
4366 if (!(det = triangle_det( v ))) return FALSE;
4367 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4369 triangle_coords( v, rc, y, &left, &right );
4370 for (x = left; x < right; x++)
4372 WORD val = gradient_triangle_555( v, x, y, det );
4373 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4374 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4375 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4378 break;
4380 return TRUE;
4383 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4385 BYTE *ptr = get_pixel_ptr_8( dib, 0, rc->top );
4386 int x, y, left, right, det;
4388 switch (mode)
4390 case GRADIENT_FILL_RECT_H:
4391 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4392 for (x = rc->left; x < rc->right; x++)
4393 ptr[x] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4394 for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride)
4395 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4396 break;
4398 case GRADIENT_FILL_RECT_V:
4399 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4401 BYTE values[16];
4402 for (x = 0; x < 16; x++)
4403 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4404 for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 16];
4406 break;
4408 case GRADIENT_FILL_TRIANGLE:
4409 if (!(det = triangle_det( v ))) return FALSE;
4410 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4412 triangle_coords( v, rc, y, &left, &right );
4413 for (x = left; x < right; x++) ptr[x] = gradient_triangle_8( dib, v, x, y, det );
4415 break;
4417 return TRUE;
4420 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4422 BYTE *ptr = get_pixel_ptr_4( dib, 0, rc->top );
4423 int x, y, left, right, det;
4425 switch (mode)
4427 case GRADIENT_FILL_RECT_H:
4428 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4430 for (x = rc->left; x < rc->right; x++)
4432 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4433 if (x & 1)
4434 ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4435 else
4436 ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4439 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4441 x = rc->left;
4442 if (x & 1)
4444 ptr[x / 2] = (ptr[x / 2 - 16 * dib->stride] & 0x0f) | (ptr[x / 2] & 0xf0);
4445 x++;
4447 for (; x < rc->right - 1; x += 2) ptr[x / 2] = ptr[x / 2 - 16 * dib->stride];
4448 if (x < rc->right)
4449 ptr[x / 2] = (ptr[x / 2] & 0x0f) | (ptr[x / 2 - 16 * dib->stride] & 0xf0);
4451 break;
4453 case GRADIENT_FILL_RECT_V:
4454 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4456 BYTE values[16];
4457 for (x = 0; x < 16; x++)
4458 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4459 for (x = rc->left; x < rc->right; x++)
4460 if (x & 1)
4461 ptr[x / 2] = values[x % 16] | (ptr[x / 2] & 0xf0);
4462 else
4463 ptr[x / 2] = (values[x % 16] << 4) | (ptr[x / 2] & 0x0f);
4465 break;
4467 case GRADIENT_FILL_TRIANGLE:
4468 if (!(det = triangle_det( v ))) return FALSE;
4469 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4471 triangle_coords( v, rc, y, &left, &right );
4472 for (x = left; x < right; x++)
4474 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4475 if (x & 1)
4476 ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4477 else
4478 ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4481 break;
4483 return TRUE;
4486 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4488 BYTE *ptr = get_pixel_ptr_1( dib, 0, rc->top );
4489 int x, y, left, right, det;
4491 switch (mode)
4493 case GRADIENT_FILL_RECT_H:
4494 for (x = rc->left; x < rc->right; x++)
4496 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4497 val = rgb_to_pixel_colortable( dib, val >> 16, val >> 8, val ) ? 0xff : 0;
4498 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4501 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4502 for (x = rc->left; x < rc->right; x++)
4503 ptr[dib->stride + x / 8] = (ptr[dib->stride + x / 8] & ~pixel_masks_1[x % 8]) |
4504 (ptr[x / 8] & pixel_masks_1[x % 8]);
4505 break;
4507 case GRADIENT_FILL_RECT_V:
4508 for (y = rc->top; y < rc->bottom; y++)
4510 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4511 val = rgb_to_pixel_colortable( dib, val >> 16, val >> 8, val ) ? 0xff : 0;
4512 for (x = rc->left; x < rc->right; x++)
4513 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4514 ptr += dib->stride;
4516 break;
4518 case GRADIENT_FILL_TRIANGLE:
4519 if (!(det = triangle_det( v ))) return FALSE;
4520 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4522 triangle_coords( v, rc, y, &left, &right );
4523 for (x = left; x < right; x++)
4525 DWORD val = gradient_triangle_24( v, x, y, det );
4526 val = rgb_to_pixel_colortable( dib, val >> 16, val >> 8, val ) ? 0xff : 0;
4527 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4530 break;
4532 return TRUE;
4535 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4537 return TRUE;
4540 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4542 if (dst == text) return dst;
4544 if (dst > text)
4546 DWORD diff = dst - text;
4547 DWORD range = max_comp - text;
4548 dst = text + (diff * range ) / (0xff - text);
4549 return dst;
4551 else
4553 DWORD diff = text - dst;
4554 DWORD range = text - min_comp;
4555 dst = text - (diff * range) / text;
4556 return dst;
4560 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4562 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4563 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4564 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4567 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4568 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4570 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4571 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4572 int x, y;
4574 for (y = rect->top; y < rect->bottom; y++)
4576 for (x = 0; x < rect->right - rect->left; x++)
4578 if (glyph_ptr[x] <= 1) continue;
4579 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4580 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4582 dst_ptr += dib->stride / 4;
4583 glyph_ptr += glyph->stride;
4587 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4588 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4590 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4591 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4592 int x, y;
4593 DWORD text, val;
4595 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4596 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4597 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4599 for (y = rect->top; y < rect->bottom; y++)
4601 for (x = 0; x < rect->right - rect->left; x++)
4603 if (glyph_ptr[x] <= 1) continue;
4604 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4605 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4606 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4607 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4608 text, ranges + glyph_ptr[x] );
4609 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4610 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4611 put_field( val, dib->blue_shift, dib->blue_len ));
4613 dst_ptr += dib->stride / 4;
4614 glyph_ptr += glyph->stride;
4618 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4619 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4621 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4622 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4623 int x, y;
4624 DWORD val;
4626 for (y = rect->top; y < rect->bottom; y++)
4628 for (x = 0; x < rect->right - rect->left; x++)
4630 if (glyph_ptr[x] <= 1) continue;
4631 if (glyph_ptr[x] >= 16)
4632 val = text_pixel;
4633 else
4634 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4635 text_pixel, ranges + glyph_ptr[x] );
4636 dst_ptr[x * 3] = val;
4637 dst_ptr[x * 3 + 1] = val >> 8;
4638 dst_ptr[x * 3 + 2] = val >> 16;
4640 dst_ptr += dib->stride;
4641 glyph_ptr += glyph->stride;
4645 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4646 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4648 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4649 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4650 int x, y;
4651 DWORD text, val;
4653 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4654 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4655 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4657 for (y = rect->top; y < rect->bottom; y++)
4659 for (x = 0; x < rect->right - rect->left; x++)
4661 if (glyph_ptr[x] <= 1) continue;
4662 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4663 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4664 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4665 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4666 text, ranges + glyph_ptr[x] );
4667 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4669 dst_ptr += dib->stride / 2;
4670 glyph_ptr += glyph->stride;
4674 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4675 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4677 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4678 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4679 int x, y;
4680 DWORD text, val;
4682 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4683 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4684 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4686 for (y = rect->top; y < rect->bottom; y++)
4688 for (x = 0; x < rect->right - rect->left; x++)
4690 if (glyph_ptr[x] <= 1) continue;
4691 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4692 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4693 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4694 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4695 text, ranges + glyph_ptr[x] );
4696 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4697 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4698 put_field( val, dib->blue_shift, dib->blue_len ));
4700 dst_ptr += dib->stride / 2;
4701 glyph_ptr += glyph->stride;
4705 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4706 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4708 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4709 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4710 int x, y;
4712 for (y = rect->top; y < rect->bottom; y++)
4714 for (x = 0; x < rect->right - rect->left; x++)
4716 /* no antialiasing, glyph should only contain 0 or 16. */
4717 if (glyph_ptr[x] >= 16)
4718 dst_ptr[x] = text_pixel;
4720 dst_ptr += dib->stride;
4721 glyph_ptr += glyph->stride;
4725 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4726 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4728 BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
4729 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4730 int x, y;
4732 for (y = rect->top; y < rect->bottom; y++)
4734 for (x = rect->left; x < rect->right; x++)
4736 /* no antialiasing, glyph should only contain 0 or 16. */
4737 if (glyph_ptr[x] >= 16)
4739 if (x & 1)
4740 dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
4741 else
4742 dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
4745 dst_ptr += dib->stride;
4746 glyph_ptr += glyph->stride;
4750 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4751 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4753 BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
4754 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4755 int x, y;
4756 BYTE text = (text_pixel & 1) ? 0xff : 0;
4758 for (y = rect->top; y < rect->bottom; y++)
4760 for (x = rect->left; x < rect->right; x++)
4762 /* no antialiasing, glyph should only contain 0 or 16. */
4763 if (glyph_ptr[x] >= 16)
4764 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
4766 dst_ptr += dib->stride;
4767 glyph_ptr += glyph->stride;
4771 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4772 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4774 return;
4777 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)
4779 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4780 DWORD mask_start = 0, mask_offset;
4781 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4782 int x, y;
4784 for(y = 0; y < hatch->height; y++)
4786 hatch_ptr = hatch_start;
4787 mask_offset = mask_start;
4788 for(x = 0; x < hatch->width; x++)
4790 if(*hatch_ptr & pixel_masks_1[x % 8])
4792 and_bits[mask_offset] = fg->and;
4793 xor_bits[mask_offset] = fg->xor;
4795 else
4797 and_bits[mask_offset] = bg->and;
4798 xor_bits[mask_offset] = bg->xor;
4800 if(x % 8 == 7) hatch_ptr++;
4801 mask_offset++;
4803 hatch_start += hatch->stride;
4804 mask_start += dib->stride / 4;
4807 return TRUE;
4810 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)
4812 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4813 DWORD mask_start = 0, mask_offset;
4814 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4815 int x, y;
4817 for(y = 0; y < hatch->height; y++)
4819 hatch_ptr = hatch_start;
4820 mask_offset = mask_start;
4821 for(x = 0; x < hatch->width; x++)
4823 if(*hatch_ptr & pixel_masks_1[x % 8])
4825 and_bits[mask_offset] = fg->and & 0xff;
4826 xor_bits[mask_offset++] = fg->xor & 0xff;
4827 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4828 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4829 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4830 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4832 else
4834 and_bits[mask_offset] = bg->and & 0xff;
4835 xor_bits[mask_offset++] = bg->xor & 0xff;
4836 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4837 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4838 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4839 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4841 if(x % 8 == 7) hatch_ptr++;
4843 hatch_start += hatch->stride;
4844 mask_start += dib->stride;
4847 return TRUE;
4850 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)
4852 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4853 DWORD mask_start = 0, mask_offset;
4854 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4855 int x, y;
4857 for(y = 0; y < hatch->height; y++)
4859 hatch_ptr = hatch_start;
4860 mask_offset = mask_start;
4861 for(x = 0; x < hatch->width; x++)
4863 if(*hatch_ptr & pixel_masks_1[x % 8])
4865 and_bits[mask_offset] = fg->and;
4866 xor_bits[mask_offset] = fg->xor;
4868 else
4870 and_bits[mask_offset] = bg->and;
4871 xor_bits[mask_offset] = bg->xor;
4873 if(x % 8 == 7) hatch_ptr++;
4874 mask_offset++;
4876 hatch_start += hatch->stride;
4877 mask_start += dib->stride / 2;
4880 return TRUE;
4883 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)
4885 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4886 DWORD mask_start = 0, mask_offset;
4887 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4888 int x, y;
4890 for(y = 0; y < hatch->height; y++)
4892 hatch_ptr = hatch_start;
4893 mask_offset = mask_start;
4894 for(x = 0; x < hatch->width; x++)
4896 if(*hatch_ptr & pixel_masks_1[x % 8])
4898 and_bits[mask_offset] = fg->and;
4899 xor_bits[mask_offset] = fg->xor;
4901 else
4903 and_bits[mask_offset] = bg->and;
4904 xor_bits[mask_offset] = bg->xor;
4906 if(x % 8 == 7) hatch_ptr++;
4907 mask_offset++;
4909 hatch_start += hatch->stride;
4910 mask_start += dib->stride;
4913 return TRUE;
4916 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)
4918 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4919 DWORD mask_start = 0, mask_offset;
4920 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4921 const rop_mask *rop_mask;
4922 int x, y;
4924 for(y = 0; y < hatch->height; y++)
4926 hatch_ptr = hatch_start;
4927 mask_offset = mask_start;
4928 for(x = 0; x < hatch->width; x++)
4930 if(*hatch_ptr & pixel_masks_1[x % 8])
4931 rop_mask = fg;
4932 else
4933 rop_mask = bg;
4935 if(x & 1)
4937 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4938 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4939 mask_offset++;
4941 else
4943 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4944 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4947 if(x % 8 == 7) hatch_ptr++;
4949 hatch_start += hatch->stride;
4950 mask_start += dib->stride;
4953 return TRUE;
4956 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)
4958 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4959 DWORD mask_start = 0, mask_offset;
4960 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4961 rop_mask rop_mask;
4962 int x, y, bit_pos;
4964 for(y = 0; y < hatch->height; y++)
4966 hatch_ptr = hatch_start;
4967 mask_offset = mask_start;
4968 for(x = 0, bit_pos = 0; x < hatch->width; x++)
4970 if(*hatch_ptr & pixel_masks_1[x % 8])
4972 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4973 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4975 else
4977 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4978 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4981 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4983 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4984 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4986 if(++bit_pos == 8)
4988 mask_offset++;
4989 hatch_ptr++;
4990 bit_pos = 0;
4993 hatch_start += hatch->stride;
4994 mask_start += dib->stride;
4997 return TRUE;
5000 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)
5002 return FALSE;
5005 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5007 switch (mode)
5009 default:
5010 case STRETCH_DELETESCANS:
5011 get_rop_codes( R2_COPYPEN, codes );
5012 break;
5013 case STRETCH_ORSCANS:
5014 get_rop_codes( R2_MERGEPEN, codes );
5015 break;
5016 case STRETCH_ANDSCANS:
5017 get_rop_codes( R2_MASKPEN, codes );
5018 break;
5020 return;
5023 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5024 const dib_info *src_dib, const POINT *src_start,
5025 const struct stretch_params *params, int mode,
5026 BOOL keep_dst)
5028 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5029 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5030 int err = params->err_start;
5031 int width;
5032 struct rop_codes codes;
5034 rop_codes_from_stretch_mode( mode, &codes );
5035 for (width = params->length; width; width--)
5037 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5038 dst_ptr += params->dst_inc;
5039 if (err > 0)
5041 src_ptr += params->src_inc;
5042 err += params->err_add_1;
5044 else err += params->err_add_2;
5048 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5049 const dib_info *src_dib, const POINT *src_start,
5050 const struct stretch_params *params, int mode,
5051 BOOL keep_dst)
5053 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5054 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5055 int err = params->err_start;
5056 int width;
5057 struct rop_codes codes;
5059 rop_codes_from_stretch_mode( mode, &codes );
5060 for (width = params->length; width; width--)
5062 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5063 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5064 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5065 dst_ptr += 3 * params->dst_inc;
5066 if (err > 0)
5068 src_ptr += 3 * params->src_inc;
5069 err += params->err_add_1;
5071 else err += params->err_add_2;
5075 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5076 const dib_info *src_dib, const POINT *src_start,
5077 const struct stretch_params *params, int mode,
5078 BOOL keep_dst)
5080 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5081 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5082 int err = params->err_start;
5083 int width;
5084 struct rop_codes codes;
5086 rop_codes_from_stretch_mode( mode, &codes );
5087 for (width = params->length; width; width--)
5089 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5090 dst_ptr += params->dst_inc;
5091 if (err > 0)
5093 src_ptr += params->src_inc;
5094 err += params->err_add_1;
5096 else err += params->err_add_2;
5100 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5101 const dib_info *src_dib, const POINT *src_start,
5102 const struct stretch_params *params, int mode,
5103 BOOL keep_dst)
5105 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5106 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5107 int err = params->err_start;
5108 int width;
5109 struct rop_codes codes;
5111 rop_codes_from_stretch_mode( mode, &codes );
5112 for (width = params->length; width; width--)
5114 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5115 dst_ptr += params->dst_inc;
5116 if (err > 0)
5118 src_ptr += params->src_inc;
5119 err += params->err_add_1;
5121 else err += params->err_add_2;
5125 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5126 const dib_info *src_dib, const POINT *src_start,
5127 const struct stretch_params *params, int mode,
5128 BOOL keep_dst)
5130 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5131 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5132 int err = params->err_start;
5133 int width, dst_x = dst_start->x, src_x = src_start->x;
5134 struct rop_codes codes;
5135 BYTE src_val;
5137 rop_codes_from_stretch_mode( mode, &codes );
5138 for (width = params->length; width; width--)
5140 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5141 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5143 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5145 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5146 dst_ptr += params->dst_inc;
5147 dst_x += params->dst_inc;
5149 if (err > 0)
5151 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5152 src_ptr += params->src_inc;
5153 src_x += params->src_inc;
5154 err += params->err_add_1;
5156 else err += params->err_add_2;
5160 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5161 const dib_info *src_dib, const POINT *src_start,
5162 const struct stretch_params *params, int mode,
5163 BOOL keep_dst)
5165 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5166 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5167 int err = params->err_start;
5168 int width, dst_x = dst_start->x, src_x = src_start->x;
5169 struct rop_codes codes;
5170 BYTE src_val;
5172 rop_codes_from_stretch_mode( mode, &codes );
5173 for (width = params->length; width; width--)
5175 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5176 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5178 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5179 dst_ptr += params->dst_inc;
5180 dst_x += params->dst_inc;
5182 if (err > 0)
5184 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5185 src_ptr += params->src_inc;
5186 src_x += params->src_inc;
5187 err += params->err_add_1;
5189 else err += params->err_add_2;
5193 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5194 const dib_info *src_dib, const POINT *src_start,
5195 const struct stretch_params *params, int mode,
5196 BOOL keep_dst)
5198 FIXME("bit count %d\n", dst_dib->bit_count);
5199 return;
5202 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5203 const dib_info *src_dib, const POINT *src_start,
5204 const struct stretch_params *params, int mode,
5205 BOOL keep_dst)
5207 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5208 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5209 int err = params->err_start;
5210 int width;
5211 struct rop_codes codes;
5212 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5213 BOOL new_pix = TRUE;
5215 rop_codes_from_stretch_mode( mode, &codes );
5216 for (width = params->length; width; width--)
5218 if (new_pix && !keep_dst) *dst_ptr = init_val;
5219 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5220 new_pix = FALSE;
5221 src_ptr += params->src_inc;
5222 if (err > 0)
5224 dst_ptr += params->dst_inc;
5225 new_pix = TRUE;
5226 err += params->err_add_1;
5228 else err += params->err_add_2;
5232 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5233 const dib_info *src_dib, const POINT *src_start,
5234 const struct stretch_params *params, int mode,
5235 BOOL keep_dst)
5237 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5238 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5239 int err = params->err_start;
5240 int width;
5241 struct rop_codes codes;
5242 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5243 BOOL new_pix = TRUE;
5245 rop_codes_from_stretch_mode( mode, &codes );
5246 for (width = params->length; width; width--)
5248 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5249 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5250 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5251 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5252 new_pix = FALSE;
5253 src_ptr += 3 * params->src_inc;
5254 if (err > 0)
5256 dst_ptr += 3 * params->dst_inc;
5257 new_pix = TRUE;
5258 err += params->err_add_1;
5260 else err += params->err_add_2;
5264 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5265 const dib_info *src_dib, const POINT *src_start,
5266 const struct stretch_params *params, int mode,
5267 BOOL keep_dst)
5269 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5270 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5271 int err = params->err_start;
5272 int width;
5273 struct rop_codes codes;
5274 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5275 BOOL new_pix = TRUE;
5277 rop_codes_from_stretch_mode( mode, &codes );
5278 for (width = params->length; width; width--)
5280 if (new_pix && !keep_dst) *dst_ptr = init_val;
5281 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5282 new_pix = FALSE;
5283 src_ptr += params->src_inc;
5284 if (err > 0)
5286 dst_ptr += params->dst_inc;
5287 new_pix = TRUE;
5288 err += params->err_add_1;
5290 else err += params->err_add_2;
5294 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5295 const dib_info *src_dib, const POINT *src_start,
5296 const struct stretch_params *params, int mode,
5297 BOOL keep_dst)
5299 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5300 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5301 int err = params->err_start;
5302 int width;
5303 struct rop_codes codes;
5304 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5305 BOOL new_pix = TRUE;
5307 rop_codes_from_stretch_mode( mode, &codes );
5308 for (width = params->length; width; width--)
5310 if (new_pix && !keep_dst) *dst_ptr = init_val;
5311 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5312 new_pix = FALSE;
5313 src_ptr += params->src_inc;
5314 if (err > 0)
5316 dst_ptr += params->dst_inc;
5317 new_pix = TRUE;
5318 err += params->err_add_1;
5320 else err += params->err_add_2;
5324 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5325 const dib_info *src_dib, const POINT *src_start,
5326 const struct stretch_params *params, int mode,
5327 BOOL keep_dst)
5329 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5330 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5331 int err = params->err_start;
5332 int width, dst_x = dst_start->x, src_x = src_start->x;
5333 struct rop_codes codes;
5334 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5335 BOOL new_pix = TRUE;
5337 rop_codes_from_stretch_mode( mode, &codes );
5338 for (width = params->length; width; width--)
5340 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
5342 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5343 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5345 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
5346 new_pix = FALSE;
5348 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5349 src_ptr += params->src_inc;
5350 src_x += params->src_inc;
5352 if (err > 0)
5354 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5355 dst_ptr += params->dst_inc;
5356 dst_x += params->dst_inc;
5357 new_pix = TRUE;
5358 err += params->err_add_1;
5360 else err += params->err_add_2;
5364 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5365 const dib_info *src_dib, const POINT *src_start,
5366 const struct stretch_params *params, int mode,
5367 BOOL keep_dst)
5369 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5370 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5371 int err = params->err_start;
5372 int width, dst_x = dst_start->x, src_x = src_start->x;
5373 struct rop_codes codes;
5374 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5375 BOOL new_pix = TRUE;
5377 rop_codes_from_stretch_mode( mode, &codes );
5378 for (width = params->length; width; width--)
5380 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5381 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5382 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5383 new_pix = FALSE;
5385 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5386 src_ptr += params->src_inc;
5387 src_x += params->src_inc;
5389 if (err > 0)
5391 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5392 dst_ptr += params->dst_inc;
5393 dst_x += params->dst_inc;
5394 new_pix = TRUE;
5395 err += params->err_add_1;
5397 else err += params->err_add_2;
5401 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5402 const dib_info *src_dib, const POINT *src_start,
5403 const struct stretch_params *params, int mode,
5404 BOOL keep_dst)
5406 FIXME("bit count %d\n", dst_dib->bit_count);
5407 return;
5410 const primitive_funcs funcs_8888 =
5412 solid_rects_32,
5413 solid_line_32,
5414 pattern_rects_32,
5415 copy_rect_32,
5416 blend_rect_8888,
5417 gradient_rect_8888,
5418 draw_glyph_8888,
5419 get_pixel_32,
5420 colorref_to_pixel_888,
5421 pixel_to_colorref_888,
5422 convert_to_8888,
5423 create_rop_masks_32,
5424 stretch_row_32,
5425 shrink_row_32
5428 const primitive_funcs funcs_32 =
5430 solid_rects_32,
5431 solid_line_32,
5432 pattern_rects_32,
5433 copy_rect_32,
5434 blend_rect_32,
5435 gradient_rect_32,
5436 draw_glyph_32,
5437 get_pixel_32,
5438 colorref_to_pixel_masks,
5439 pixel_to_colorref_masks,
5440 convert_to_32,
5441 create_rop_masks_32,
5442 stretch_row_32,
5443 shrink_row_32
5446 const primitive_funcs funcs_24 =
5448 solid_rects_24,
5449 solid_line_24,
5450 pattern_rects_24,
5451 copy_rect_24,
5452 blend_rect_24,
5453 gradient_rect_24,
5454 draw_glyph_24,
5455 get_pixel_24,
5456 colorref_to_pixel_888,
5457 pixel_to_colorref_888,
5458 convert_to_24,
5459 create_rop_masks_24,
5460 stretch_row_24,
5461 shrink_row_24
5464 const primitive_funcs funcs_555 =
5466 solid_rects_16,
5467 solid_line_16,
5468 pattern_rects_16,
5469 copy_rect_16,
5470 blend_rect_555,
5471 gradient_rect_555,
5472 draw_glyph_555,
5473 get_pixel_16,
5474 colorref_to_pixel_555,
5475 pixel_to_colorref_555,
5476 convert_to_555,
5477 create_rop_masks_16,
5478 stretch_row_16,
5479 shrink_row_16
5482 const primitive_funcs funcs_16 =
5484 solid_rects_16,
5485 solid_line_16,
5486 pattern_rects_16,
5487 copy_rect_16,
5488 blend_rect_16,
5489 gradient_rect_16,
5490 draw_glyph_16,
5491 get_pixel_16,
5492 colorref_to_pixel_masks,
5493 pixel_to_colorref_masks,
5494 convert_to_16,
5495 create_rop_masks_16,
5496 stretch_row_16,
5497 shrink_row_16
5500 const primitive_funcs funcs_8 =
5502 solid_rects_8,
5503 solid_line_8,
5504 pattern_rects_8,
5505 copy_rect_8,
5506 blend_rect_8,
5507 gradient_rect_8,
5508 draw_glyph_8,
5509 get_pixel_8,
5510 colorref_to_pixel_colortable,
5511 pixel_to_colorref_colortable,
5512 convert_to_8,
5513 create_rop_masks_8,
5514 stretch_row_8,
5515 shrink_row_8
5518 const primitive_funcs funcs_4 =
5520 solid_rects_4,
5521 solid_line_4,
5522 pattern_rects_4,
5523 copy_rect_4,
5524 blend_rect_4,
5525 gradient_rect_4,
5526 draw_glyph_4,
5527 get_pixel_4,
5528 colorref_to_pixel_colortable,
5529 pixel_to_colorref_colortable,
5530 convert_to_4,
5531 create_rop_masks_4,
5532 stretch_row_4,
5533 shrink_row_4
5536 const primitive_funcs funcs_1 =
5538 solid_rects_1,
5539 solid_line_1,
5540 pattern_rects_1,
5541 copy_rect_1,
5542 blend_rect_1,
5543 gradient_rect_1,
5544 draw_glyph_1,
5545 get_pixel_1,
5546 colorref_to_pixel_colortable,
5547 pixel_to_colorref_colortable,
5548 convert_to_1,
5549 create_rop_masks_1,
5550 stretch_row_1,
5551 shrink_row_1
5554 const primitive_funcs funcs_null =
5556 solid_rects_null,
5557 solid_line_null,
5558 pattern_rects_null,
5559 copy_rect_null,
5560 blend_rect_null,
5561 gradient_rect_null,
5562 draw_glyph_null,
5563 get_pixel_null,
5564 colorref_to_pixel_null,
5565 pixel_to_colorref_null,
5566 convert_to_null,
5567 create_rop_masks_null,
5568 stretch_row_null,
5569 shrink_row_null