ntdll: Add support for rep;ret instruction in function epilogs.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blob55c17b74865312215f176d1f71c5b0d1226c5f14
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, int x, int y)
1281 DWORD *ptr = get_pixel_ptr_32( dib, x, y );
1282 return *ptr;
1285 static DWORD get_pixel_24(const dib_info *dib, int x, int y)
1287 BYTE *ptr = get_pixel_ptr_24( dib, x, y );
1288 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1291 static DWORD get_pixel_16(const dib_info *dib, int x, int y)
1293 WORD *ptr = get_pixel_ptr_16( dib, x, y );
1294 return *ptr;
1297 static DWORD get_pixel_8(const dib_info *dib, int x, int y)
1299 BYTE *ptr = get_pixel_ptr_8( dib, x, y );
1300 return *ptr;
1303 static DWORD get_pixel_4(const dib_info *dib, int x, int y)
1305 BYTE *ptr = get_pixel_ptr_4( dib, x, y );
1307 if (x & 1)
1308 return *ptr & 0x0f;
1309 else
1310 return (*ptr >> 4) & 0x0f;
1313 static DWORD get_pixel_1(const dib_info *dib, int x, int y)
1315 BYTE *ptr = get_pixel_ptr_1( dib, x, y );
1316 return (*ptr & pixel_masks_1[x & 0x7]) ? 1 : 0;
1319 static DWORD get_pixel_null(const dib_info *dib, int x, int y)
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 const 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 COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1426 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1429 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1431 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1432 get_field( pixel, dib->green_shift, dib->green_len ),
1433 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1436 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1438 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1439 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1440 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1443 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1445 if (pixel < dib->color_table_size)
1447 RGBQUAD quad = dib->color_table[pixel];
1448 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1450 return 0;
1453 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1455 return 0;
1458 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1460 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1462 return d1->red_mask == d2->red_mask &&
1463 d1->green_mask == d2->green_mask &&
1464 d1->blue_mask == d2->blue_mask;
1467 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1469 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1470 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1472 switch(src->bit_count)
1474 case 32:
1476 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1477 if(src->funcs == &funcs_8888)
1479 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1480 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1481 else
1483 for(y = src_rect->top; y < src_rect->bottom; y++)
1485 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1486 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1487 dst_start += dst->stride / 4;
1488 src_start += src->stride / 4;
1492 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1494 for(y = src_rect->top; y < src_rect->bottom; y++)
1496 dst_pixel = dst_start;
1497 src_pixel = src_start;
1498 for(x = src_rect->left; x < src_rect->right; x++)
1500 src_val = *src_pixel++;
1501 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1502 (((src_val >> src->green_shift) & 0xff) << 8) |
1503 ((src_val >> src->blue_shift) & 0xff);
1505 if(pad_size) memset(dst_pixel, 0, pad_size);
1506 dst_start += dst->stride / 4;
1507 src_start += src->stride / 4;
1510 else
1512 for(y = src_rect->top; y < src_rect->bottom; y++)
1514 dst_pixel = dst_start;
1515 src_pixel = src_start;
1516 for(x = src_rect->left; x < src_rect->right; x++)
1518 src_val = *src_pixel++;
1519 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1520 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1521 get_field( src_val, src->blue_shift, src->blue_len ));
1523 if(pad_size) memset(dst_pixel, 0, pad_size);
1524 dst_start += dst->stride / 4;
1525 src_start += src->stride / 4;
1528 break;
1531 case 24:
1533 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1535 for(y = src_rect->top; y < src_rect->bottom; y++)
1537 dst_pixel = dst_start;
1538 src_pixel = src_start;
1539 for(x = src_rect->left; x < src_rect->right; x++)
1541 RGBQUAD rgb;
1542 rgb.rgbBlue = *src_pixel++;
1543 rgb.rgbGreen = *src_pixel++;
1544 rgb.rgbRed = *src_pixel++;
1546 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1548 if(pad_size) memset(dst_pixel, 0, pad_size);
1549 dst_start += dst->stride / 4;
1550 src_start += src->stride;
1552 break;
1555 case 16:
1557 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1558 if(src->funcs == &funcs_555)
1560 for(y = src_rect->top; y < src_rect->bottom; y++)
1562 dst_pixel = dst_start;
1563 src_pixel = src_start;
1564 for(x = src_rect->left; x < src_rect->right; x++)
1566 src_val = *src_pixel++;
1567 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1568 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1569 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1571 if(pad_size) memset(dst_pixel, 0, pad_size);
1572 dst_start += dst->stride / 4;
1573 src_start += src->stride / 2;
1576 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1578 for(y = src_rect->top; y < src_rect->bottom; y++)
1580 dst_pixel = dst_start;
1581 src_pixel = src_start;
1582 for(x = src_rect->left; x < src_rect->right; x++)
1584 src_val = *src_pixel++;
1585 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1586 (((src_val >> src->red_shift) << 14) & 0x070000) |
1587 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1588 (((src_val >> src->green_shift) << 6) & 0x000700) |
1589 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1590 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1592 if(pad_size) memset(dst_pixel, 0, pad_size);
1593 dst_start += dst->stride / 4;
1594 src_start += src->stride / 2;
1597 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1599 for(y = src_rect->top; y < src_rect->bottom; y++)
1601 dst_pixel = dst_start;
1602 src_pixel = src_start;
1603 for(x = src_rect->left; x < src_rect->right; x++)
1605 src_val = *src_pixel++;
1606 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1607 (((src_val >> src->red_shift) << 14) & 0x070000) |
1608 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1609 (((src_val >> src->green_shift) << 4) & 0x000300) |
1610 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1611 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1613 if(pad_size) memset(dst_pixel, 0, pad_size);
1614 dst_start += dst->stride / 4;
1615 src_start += src->stride / 2;
1618 else
1620 for(y = src_rect->top; y < src_rect->bottom; y++)
1622 dst_pixel = dst_start;
1623 src_pixel = src_start;
1624 for(x = src_rect->left; x < src_rect->right; x++)
1626 src_val = *src_pixel++;
1627 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1628 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1629 get_field( src_val, src->blue_shift, src->blue_len ));
1631 if(pad_size) memset(dst_pixel, 0, pad_size);
1632 dst_start += dst->stride / 4;
1633 src_start += src->stride / 2;
1636 break;
1639 case 8:
1641 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1642 for(y = src_rect->top; y < src_rect->bottom; y++)
1644 dst_pixel = dst_start;
1645 src_pixel = src_start;
1646 for(x = src_rect->left; x < src_rect->right; x++)
1648 RGBQUAD rgb = src->color_table[*src_pixel++];
1649 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1651 if(pad_size) memset(dst_pixel, 0, pad_size);
1652 dst_start += dst->stride / 4;
1653 src_start += src->stride;
1655 break;
1658 case 4:
1660 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1661 for(y = src_rect->top; y < src_rect->bottom; y++)
1663 dst_pixel = dst_start;
1664 src_pixel = src_start;
1665 for(x = src_rect->left; x < src_rect->right; x++)
1667 RGBQUAD rgb;
1668 if(x & 1)
1669 rgb = src->color_table[*src_pixel++ & 0xf];
1670 else
1671 rgb = src->color_table[*src_pixel >> 4];
1672 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1674 if(pad_size) memset(dst_pixel, 0, pad_size);
1675 dst_start += dst->stride / 4;
1676 src_start += src->stride;
1678 break;
1681 case 1:
1683 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1684 for(y = src_rect->top; y < src_rect->bottom; y++)
1686 dst_pixel = dst_start;
1687 src_pixel = src_start;
1688 for(x = src_rect->left; x < src_rect->right; x++)
1690 RGBQUAD rgb;
1691 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1692 if((x % 8) == 7) src_pixel++;
1693 rgb = src->color_table[src_val];
1694 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1696 if(pad_size) memset(dst_pixel, 0, pad_size);
1697 dst_start += dst->stride / 4;
1698 src_start += src->stride;
1700 break;
1705 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1707 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1708 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1710 switch(src->bit_count)
1712 case 32:
1714 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1716 if(src->funcs == &funcs_8888)
1718 for(y = src_rect->top; y < src_rect->bottom; y++)
1720 dst_pixel = dst_start;
1721 src_pixel = src_start;
1722 for(x = src_rect->left; x < src_rect->right; x++)
1724 src_val = *src_pixel++;
1725 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1726 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1727 put_field(src_val, dst->blue_shift, dst->blue_len);
1729 if(pad_size) memset(dst_pixel, 0, pad_size);
1730 dst_start += dst->stride / 4;
1731 src_start += src->stride / 4;
1734 else if(bit_fields_match(src, dst))
1736 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1737 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1738 else
1740 for(y = src_rect->top; y < src_rect->bottom; y++)
1742 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1743 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1744 dst_start += dst->stride / 4;
1745 src_start += src->stride / 4;
1749 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1750 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1752 for(y = src_rect->top; y < src_rect->bottom; y++)
1754 dst_pixel = dst_start;
1755 src_pixel = src_start;
1756 for(x = src_rect->left; x < src_rect->right; x++)
1758 src_val = *src_pixel++;
1759 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1760 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1761 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1763 if(pad_size) memset(dst_pixel, 0, pad_size);
1764 dst_start += dst->stride / 4;
1765 src_start += src->stride / 4;
1768 else
1770 for(y = src_rect->top; y < src_rect->bottom; y++)
1772 dst_pixel = dst_start;
1773 src_pixel = src_start;
1774 for(x = src_rect->left; x < src_rect->right; x++)
1776 src_val = *src_pixel++;
1777 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1778 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1779 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1781 if(pad_size) memset(dst_pixel, 0, pad_size);
1782 dst_start += dst->stride / 4;
1783 src_start += src->stride / 4;
1786 break;
1789 case 24:
1791 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1793 for(y = src_rect->top; y < src_rect->bottom; y++)
1795 dst_pixel = dst_start;
1796 src_pixel = src_start;
1797 for(x = src_rect->left; x < src_rect->right; x++)
1799 RGBQUAD rgb;
1800 rgb.rgbBlue = *src_pixel++;
1801 rgb.rgbGreen = *src_pixel++;
1802 rgb.rgbRed = *src_pixel++;
1804 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1805 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1806 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1808 if(pad_size) memset(dst_pixel, 0, pad_size);
1809 dst_start += dst->stride / 4;
1810 src_start += src->stride;
1812 break;
1815 case 16:
1817 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1818 if(src->funcs == &funcs_555)
1820 for(y = src_rect->top; y < src_rect->bottom; y++)
1822 dst_pixel = dst_start;
1823 src_pixel = src_start;
1824 for(x = src_rect->left; x < src_rect->right; x++)
1826 src_val = *src_pixel++;
1827 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1828 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1829 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1831 if(pad_size) memset(dst_pixel, 0, pad_size);
1832 dst_start += dst->stride / 4;
1833 src_start += src->stride / 2;
1836 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1838 for(y = src_rect->top; y < src_rect->bottom; y++)
1840 dst_pixel = dst_start;
1841 src_pixel = src_start;
1842 for(x = src_rect->left; x < src_rect->right; x++)
1844 src_val = *src_pixel++;
1845 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1846 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1847 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1848 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1849 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1850 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1852 if(pad_size) memset(dst_pixel, 0, pad_size);
1853 dst_start += dst->stride / 4;
1854 src_start += src->stride / 2;
1857 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1859 for(y = src_rect->top; y < src_rect->bottom; y++)
1861 dst_pixel = dst_start;
1862 src_pixel = src_start;
1863 for(x = src_rect->left; x < src_rect->right; x++)
1865 src_val = *src_pixel++;
1866 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1867 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1868 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1869 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1870 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1871 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1873 if(pad_size) memset(dst_pixel, 0, pad_size);
1874 dst_start += dst->stride / 4;
1875 src_start += src->stride / 2;
1878 else
1880 for(y = src_rect->top; y < src_rect->bottom; y++)
1882 dst_pixel = dst_start;
1883 src_pixel = src_start;
1884 for(x = src_rect->left; x < src_rect->right; x++)
1886 src_val = *src_pixel++;
1887 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1888 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1889 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1891 if(pad_size) memset(dst_pixel, 0, pad_size);
1892 dst_start += dst->stride / 4;
1893 src_start += src->stride / 2;
1896 break;
1899 case 8:
1901 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1902 for(y = src_rect->top; y < src_rect->bottom; y++)
1904 dst_pixel = dst_start;
1905 src_pixel = src_start;
1906 for(x = src_rect->left; x < src_rect->right; x++)
1908 RGBQUAD rgb = src->color_table[*src_pixel++];
1909 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1910 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1911 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1913 if(pad_size) memset(dst_pixel, 0, pad_size);
1914 dst_start += dst->stride / 4;
1915 src_start += src->stride;
1917 break;
1920 case 4:
1922 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1923 for(y = src_rect->top; y < src_rect->bottom; y++)
1925 dst_pixel = dst_start;
1926 src_pixel = src_start;
1927 for(x = src_rect->left; x < src_rect->right; x++)
1929 RGBQUAD rgb;
1930 if(x & 1)
1931 rgb = src->color_table[*src_pixel++ & 0xf];
1932 else
1933 rgb = src->color_table[*src_pixel >> 4];
1934 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1935 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1936 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1938 if(pad_size) memset(dst_pixel, 0, pad_size);
1939 dst_start += dst->stride / 4;
1940 src_start += src->stride;
1942 break;
1945 case 1:
1947 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1948 for(y = src_rect->top; y < src_rect->bottom; y++)
1950 dst_pixel = dst_start;
1951 src_pixel = src_start;
1952 for(x = src_rect->left; x < src_rect->right; x++)
1954 RGBQUAD rgb;
1955 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1956 if((x % 8) == 7) src_pixel++;
1957 rgb = src->color_table[src_val];
1958 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1959 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1960 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1962 if(pad_size) memset(dst_pixel, 0, pad_size);
1963 dst_start += dst->stride / 4;
1964 src_start += src->stride;
1966 break;
1971 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1973 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1974 DWORD src_val;
1975 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1977 switch(src->bit_count)
1979 case 32:
1981 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1982 if(src->funcs == &funcs_8888)
1984 for(y = src_rect->top; y < src_rect->bottom; y++)
1986 dst_pixel = dst_start;
1987 src_pixel = src_start;
1988 for(x = src_rect->left; x < src_rect->right; x++)
1990 src_val = *src_pixel++;
1991 *dst_pixel++ = src_val & 0xff;
1992 *dst_pixel++ = (src_val >> 8) & 0xff;
1993 *dst_pixel++ = (src_val >> 16) & 0xff;
1995 if(pad_size) memset(dst_pixel, 0, pad_size);
1996 dst_start += dst->stride;
1997 src_start += src->stride / 4;
2000 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2002 for(y = src_rect->top; y < src_rect->bottom; y++)
2004 dst_pixel = dst_start;
2005 src_pixel = src_start;
2006 for(x = src_rect->left; x < src_rect->right; x++)
2008 src_val = *src_pixel++;
2009 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
2010 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
2011 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
2013 if(pad_size) memset(dst_pixel, 0, pad_size);
2014 dst_start += dst->stride;
2015 src_start += src->stride / 4;
2018 else
2020 for(y = src_rect->top; y < src_rect->bottom; y++)
2022 dst_pixel = dst_start;
2023 src_pixel = src_start;
2024 for(x = src_rect->left; x < src_rect->right; x++)
2026 src_val = *src_pixel++;
2027 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2028 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2029 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2031 if(pad_size) memset(dst_pixel, 0, pad_size);
2032 dst_start += dst->stride;
2033 src_start += src->stride / 4;
2036 break;
2039 case 24:
2041 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2043 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2044 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2045 else
2047 for(y = src_rect->top; y < src_rect->bottom; y++)
2049 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2050 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2051 dst_start += dst->stride;
2052 src_start += src->stride;
2055 break;
2058 case 16:
2060 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2061 if(src->funcs == &funcs_555)
2063 for(y = src_rect->top; y < src_rect->bottom; y++)
2065 dst_pixel = dst_start;
2066 src_pixel = src_start;
2067 for(x = src_rect->left; x < src_rect->right; x++)
2069 src_val = *src_pixel++;
2070 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2071 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2072 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2074 if(pad_size) memset(dst_pixel, 0, pad_size);
2075 dst_start += dst->stride;
2076 src_start += src->stride / 2;
2079 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2081 for(y = src_rect->top; y < src_rect->bottom; y++)
2083 dst_pixel = dst_start;
2084 src_pixel = src_start;
2085 for(x = src_rect->left; x < src_rect->right; x++)
2087 src_val = *src_pixel++;
2088 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2089 (((src_val >> src->blue_shift) >> 2) & 0x07);
2090 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2091 (((src_val >> src->green_shift) >> 2) & 0x07);
2092 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2093 (((src_val >> src->red_shift) >> 2) & 0x07);
2095 if(pad_size) memset(dst_pixel, 0, pad_size);
2096 dst_start += dst->stride;
2097 src_start += src->stride / 2;
2100 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2102 for(y = src_rect->top; y < src_rect->bottom; y++)
2104 dst_pixel = dst_start;
2105 src_pixel = src_start;
2106 for(x = src_rect->left; x < src_rect->right; x++)
2108 src_val = *src_pixel++;
2109 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2110 (((src_val >> src->blue_shift) >> 2) & 0x07);
2111 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2112 (((src_val >> src->green_shift) >> 4) & 0x03);
2113 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2114 (((src_val >> src->red_shift) >> 2) & 0x07);
2116 if(pad_size) memset(dst_pixel, 0, pad_size);
2117 dst_start += dst->stride;
2118 src_start += src->stride / 2;
2121 else
2123 for(y = src_rect->top; y < src_rect->bottom; y++)
2125 dst_pixel = dst_start;
2126 src_pixel = src_start;
2127 for(x = src_rect->left; x < src_rect->right; x++)
2129 src_val = *src_pixel++;
2130 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2131 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2132 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2134 if(pad_size) memset(dst_pixel, 0, pad_size);
2135 dst_start += dst->stride;
2136 src_start += src->stride / 2;
2139 break;
2142 case 8:
2144 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2145 for(y = src_rect->top; y < src_rect->bottom; y++)
2147 dst_pixel = dst_start;
2148 src_pixel = src_start;
2149 for(x = src_rect->left; x < src_rect->right; x++)
2151 RGBQUAD rgb = src->color_table[*src_pixel++];
2152 *dst_pixel++ = rgb.rgbBlue;
2153 *dst_pixel++ = rgb.rgbGreen;
2154 *dst_pixel++ = rgb.rgbRed;
2156 if(pad_size) memset(dst_pixel, 0, pad_size);
2157 dst_start += dst->stride;
2158 src_start += src->stride;
2160 break;
2163 case 4:
2165 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2166 for(y = src_rect->top; y < src_rect->bottom; y++)
2168 dst_pixel = dst_start;
2169 src_pixel = src_start;
2170 for(x = src_rect->left; x < src_rect->right; x++)
2172 RGBQUAD rgb;
2173 if(x & 1)
2174 rgb = src->color_table[*src_pixel++ & 0xf];
2175 else
2176 rgb = src->color_table[*src_pixel >> 4];
2177 *dst_pixel++ = rgb.rgbBlue;
2178 *dst_pixel++ = rgb.rgbGreen;
2179 *dst_pixel++ = rgb.rgbRed;
2181 if(pad_size) memset(dst_pixel, 0, pad_size);
2182 dst_start += dst->stride;
2183 src_start += src->stride;
2185 break;
2188 case 1:
2190 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2191 for(y = src_rect->top; y < src_rect->bottom; y++)
2193 dst_pixel = dst_start;
2194 src_pixel = src_start;
2195 for(x = src_rect->left; x < src_rect->right; x++)
2197 RGBQUAD rgb;
2198 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2199 if((x % 8) == 7) src_pixel++;
2200 rgb = src->color_table[src_val];
2201 *dst_pixel++ = rgb.rgbBlue;
2202 *dst_pixel++ = rgb.rgbGreen;
2203 *dst_pixel++ = rgb.rgbRed;
2205 if(pad_size) memset(dst_pixel, 0, pad_size);
2206 dst_start += dst->stride;
2207 src_start += src->stride;
2209 break;
2214 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
2216 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2217 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2218 DWORD src_val;
2220 switch(src->bit_count)
2222 case 32:
2224 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2226 if(src->funcs == &funcs_8888)
2228 for(y = src_rect->top; y < src_rect->bottom; y++)
2230 dst_pixel = dst_start;
2231 src_pixel = src_start;
2232 for(x = src_rect->left; x < src_rect->right; x++)
2234 src_val = *src_pixel++;
2235 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2236 ((src_val >> 6) & 0x03e0) |
2237 ((src_val >> 3) & 0x001f);
2239 if(pad_size) memset(dst_pixel, 0, pad_size);
2240 dst_start += dst->stride / 2;
2241 src_start += src->stride / 4;
2244 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2246 for(y = src_rect->top; y < src_rect->bottom; y++)
2248 dst_pixel = dst_start;
2249 src_pixel = src_start;
2250 for(x = src_rect->left; x < src_rect->right; x++)
2252 src_val = *src_pixel++;
2253 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2254 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2255 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2257 if(pad_size) memset(dst_pixel, 0, pad_size);
2258 dst_start += dst->stride / 2;
2259 src_start += src->stride / 4;
2262 else
2264 for(y = src_rect->top; y < src_rect->bottom; y++)
2266 dst_pixel = dst_start;
2267 src_pixel = src_start;
2268 for(x = src_rect->left; x < src_rect->right; x++)
2270 src_val = *src_pixel++;
2271 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2272 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2273 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2275 if(pad_size) memset(dst_pixel, 0, pad_size);
2276 dst_start += dst->stride / 2;
2277 src_start += src->stride / 4;
2280 break;
2283 case 24:
2285 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2287 for(y = src_rect->top; y < src_rect->bottom; y++)
2289 dst_pixel = dst_start;
2290 src_pixel = src_start;
2291 for(x = src_rect->left; x < src_rect->right; x++)
2293 RGBQUAD rgb;
2294 rgb.rgbBlue = *src_pixel++;
2295 rgb.rgbGreen = *src_pixel++;
2296 rgb.rgbRed = *src_pixel++;
2298 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2299 ((rgb.rgbGreen << 2) & 0x03e0) |
2300 ((rgb.rgbBlue >> 3) & 0x001f);
2302 if(pad_size) memset(dst_pixel, 0, pad_size);
2303 dst_start += dst->stride / 2;
2304 src_start += src->stride;
2306 break;
2309 case 16:
2311 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2312 if(src->funcs == &funcs_555)
2314 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2315 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2316 else
2318 for(y = src_rect->top; y < src_rect->bottom; y++)
2320 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2321 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2322 dst_start += dst->stride / 2;
2323 src_start += src->stride / 2;
2327 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2329 for(y = src_rect->top; y < src_rect->bottom; y++)
2331 dst_pixel = dst_start;
2332 src_pixel = src_start;
2333 for(x = src_rect->left; x < src_rect->right; x++)
2335 src_val = *src_pixel++;
2336 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2337 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2338 ( (src_val >> src->blue_shift) & 0x001f);
2340 if(pad_size) memset(dst_pixel, 0, pad_size);
2341 dst_start += dst->stride / 2;
2342 src_start += src->stride / 2;
2345 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2347 for(y = src_rect->top; y < src_rect->bottom; y++)
2349 dst_pixel = dst_start;
2350 src_pixel = src_start;
2351 for(x = src_rect->left; x < src_rect->right; x++)
2353 src_val = *src_pixel++;
2354 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2355 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2356 ( (src_val >> src->blue_shift) & 0x001f);
2358 if(pad_size) memset(dst_pixel, 0, pad_size);
2359 dst_start += dst->stride / 2;
2360 src_start += src->stride / 2;
2363 else
2365 for(y = src_rect->top; y < src_rect->bottom; y++)
2367 dst_pixel = dst_start;
2368 src_pixel = src_start;
2369 for(x = src_rect->left; x < src_rect->right; x++)
2371 src_val = *src_pixel++;
2372 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2373 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2374 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2376 if(pad_size) memset(dst_pixel, 0, pad_size);
2377 dst_start += dst->stride / 2;
2378 src_start += src->stride / 2;
2381 break;
2384 case 8:
2386 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2387 for(y = src_rect->top; y < src_rect->bottom; y++)
2389 dst_pixel = dst_start;
2390 src_pixel = src_start;
2391 for(x = src_rect->left; x < src_rect->right; x++)
2393 RGBQUAD rgb = src->color_table[*src_pixel++];
2394 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2395 ((rgb.rgbGreen << 2) & 0x03e0) |
2396 ((rgb.rgbBlue >> 3) & 0x001f);
2398 if(pad_size) memset(dst_pixel, 0, pad_size);
2399 dst_start += dst->stride / 2;
2400 src_start += src->stride;
2402 break;
2405 case 4:
2407 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2408 for(y = src_rect->top; y < src_rect->bottom; y++)
2410 dst_pixel = dst_start;
2411 src_pixel = src_start;
2412 for(x = src_rect->left; x < src_rect->right; x++)
2414 RGBQUAD rgb;
2415 if(x & 1)
2416 rgb = src->color_table[*src_pixel++ & 0xf];
2417 else
2418 rgb = src->color_table[*src_pixel >> 4];
2419 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2420 ((rgb.rgbGreen << 2) & 0x03e0) |
2421 ((rgb.rgbBlue >> 3) & 0x001f);
2423 if(pad_size) memset(dst_pixel, 0, pad_size);
2424 dst_start += dst->stride / 2;
2425 src_start += src->stride;
2427 break;
2430 case 1:
2432 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2433 for(y = src_rect->top; y < src_rect->bottom; y++)
2435 dst_pixel = dst_start;
2436 src_pixel = src_start;
2437 for(x = src_rect->left; x < src_rect->right; x++)
2439 RGBQUAD rgb;
2440 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2441 if((x % 8) == 7) src_pixel++;
2442 rgb = src->color_table[src_val];
2443 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2444 ((rgb.rgbGreen << 2) & 0x03e0) |
2445 ((rgb.rgbBlue >> 3) & 0x001f);
2447 if(pad_size) memset(dst_pixel, 0, pad_size);
2448 dst_start += dst->stride / 2;
2449 src_start += src->stride;
2451 break;
2456 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2458 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2459 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2460 DWORD src_val;
2462 switch(src->bit_count)
2464 case 32:
2466 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2468 if(src->funcs == &funcs_8888)
2470 for(y = src_rect->top; y < src_rect->bottom; y++)
2472 dst_pixel = dst_start;
2473 src_pixel = src_start;
2474 for(x = src_rect->left; x < src_rect->right; x++)
2476 src_val = *src_pixel++;
2477 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2478 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2479 put_field(src_val, dst->blue_shift, dst->blue_len);
2481 if(pad_size) memset(dst_pixel, 0, pad_size);
2482 dst_start += dst->stride / 2;
2483 src_start += src->stride / 4;
2486 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2488 for(y = src_rect->top; y < src_rect->bottom; y++)
2490 dst_pixel = dst_start;
2491 src_pixel = src_start;
2492 for(x = src_rect->left; x < src_rect->right; x++)
2494 src_val = *src_pixel++;
2495 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2496 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2497 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2499 if(pad_size) memset(dst_pixel, 0, pad_size);
2500 dst_start += dst->stride / 2;
2501 src_start += src->stride / 4;
2504 else
2506 for(y = src_rect->top; y < src_rect->bottom; y++)
2508 dst_pixel = dst_start;
2509 src_pixel = src_start;
2510 for(x = src_rect->left; x < src_rect->right; x++)
2512 src_val = *src_pixel++;
2513 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2514 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2515 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2517 if(pad_size) memset(dst_pixel, 0, pad_size);
2518 dst_start += dst->stride / 2;
2519 src_start += src->stride / 4;
2522 break;
2525 case 24:
2527 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2529 for(y = src_rect->top; y < src_rect->bottom; y++)
2531 dst_pixel = dst_start;
2532 src_pixel = src_start;
2533 for(x = src_rect->left; x < src_rect->right; x++)
2535 RGBQUAD rgb;
2536 rgb.rgbBlue = *src_pixel++;
2537 rgb.rgbGreen = *src_pixel++;
2538 rgb.rgbRed = *src_pixel++;
2540 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2541 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2542 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2544 if(pad_size) memset(dst_pixel, 0, pad_size);
2545 dst_start += dst->stride / 2;
2546 src_start += src->stride;
2548 break;
2551 case 16:
2553 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2554 if(src->funcs == &funcs_555)
2556 for(y = src_rect->top; y < src_rect->bottom; y++)
2558 dst_pixel = dst_start;
2559 src_pixel = src_start;
2560 for(x = src_rect->left; x < src_rect->right; x++)
2562 src_val = *src_pixel++;
2563 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2564 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2565 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2567 if(pad_size) memset(dst_pixel, 0, pad_size);
2568 dst_start += dst->stride / 2;
2569 src_start += src->stride / 2;
2572 else if(bit_fields_match(src, dst))
2574 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2575 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2576 else
2578 for(y = src_rect->top; y < src_rect->bottom; y++)
2580 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2581 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2582 dst_start += dst->stride / 2;
2583 src_start += src->stride / 2;
2587 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2589 for(y = src_rect->top; y < src_rect->bottom; y++)
2591 dst_pixel = dst_start;
2592 src_pixel = src_start;
2593 for(x = src_rect->left; x < src_rect->right; x++)
2595 src_val = *src_pixel++;
2596 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2597 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2598 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2599 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2600 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2601 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2603 if(pad_size) memset(dst_pixel, 0, pad_size);
2604 dst_start += dst->stride / 2;
2605 src_start += src->stride / 2;
2608 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2610 for(y = src_rect->top; y < src_rect->bottom; y++)
2612 dst_pixel = dst_start;
2613 src_pixel = src_start;
2614 for(x = src_rect->left; x < src_rect->right; x++)
2616 src_val = *src_pixel++;
2617 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2618 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2619 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2620 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2621 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2622 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2624 if(pad_size) memset(dst_pixel, 0, pad_size);
2625 dst_start += dst->stride / 2;
2626 src_start += src->stride / 2;
2629 else
2631 for(y = src_rect->top; y < src_rect->bottom; y++)
2633 dst_pixel = dst_start;
2634 src_pixel = src_start;
2635 for(x = src_rect->left; x < src_rect->right; x++)
2637 src_val = *src_pixel++;
2638 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2639 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2640 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2642 if(pad_size) memset(dst_pixel, 0, pad_size);
2643 dst_start += dst->stride / 2;
2644 src_start += src->stride / 2;
2647 break;
2650 case 8:
2652 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2653 for(y = src_rect->top; y < src_rect->bottom; y++)
2655 dst_pixel = dst_start;
2656 src_pixel = src_start;
2657 for(x = src_rect->left; x < src_rect->right; x++)
2659 RGBQUAD rgb = src->color_table[*src_pixel++];
2660 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2661 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2662 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2664 if(pad_size) memset(dst_pixel, 0, pad_size);
2665 dst_start += dst->stride / 2;
2666 src_start += src->stride;
2668 break;
2671 case 4:
2673 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2674 for(y = src_rect->top; y < src_rect->bottom; y++)
2676 dst_pixel = dst_start;
2677 src_pixel = src_start;
2678 for(x = src_rect->left; x < src_rect->right; x++)
2680 RGBQUAD rgb;
2681 if(x & 1)
2682 rgb = src->color_table[*src_pixel++ & 0xf];
2683 else
2684 rgb = src->color_table[*src_pixel >> 4];
2685 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2686 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2687 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2689 if(pad_size) memset(dst_pixel, 0, pad_size);
2690 dst_start += dst->stride / 2;
2691 src_start += src->stride;
2693 break;
2696 case 1:
2698 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2699 for(y = src_rect->top; y < src_rect->bottom; y++)
2701 dst_pixel = dst_start;
2702 src_pixel = src_start;
2703 for(x = src_rect->left; x < src_rect->right; x++)
2705 RGBQUAD rgb;
2706 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2707 if((x % 8) == 7) src_pixel++;
2708 rgb = src->color_table[src_val];
2709 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2710 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2711 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2713 if(pad_size) memset(dst_pixel, 0, pad_size);
2714 dst_start += dst->stride / 2;
2715 src_start += src->stride;
2717 break;
2722 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2724 return !memcmp(d1->color_table, d2->color_table, (1 << d1->bit_count) * sizeof(d1->color_table[0]));
2727 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2729 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2730 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2733 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2735 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2736 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2737 DWORD src_val;
2739 switch(src->bit_count)
2741 case 32:
2743 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2745 if(src->funcs == &funcs_8888)
2747 for(y = src_rect->top; y < src_rect->bottom; y++)
2749 dst_pixel = dst_start;
2750 src_pixel = src_start;
2751 for(x = src_rect->left; x < src_rect->right; x++)
2753 src_val = *src_pixel++;
2754 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2756 if(pad_size) memset(dst_pixel, 0, pad_size);
2757 dst_start += dst->stride;
2758 src_start += src->stride / 4;
2761 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2763 for(y = src_rect->top; y < src_rect->bottom; y++)
2765 dst_pixel = dst_start;
2766 src_pixel = src_start;
2767 for(x = src_rect->left; x < src_rect->right; x++)
2769 src_val = *src_pixel++;
2770 *dst_pixel++ = rgb_lookup_colortable(dst,
2771 src_val >> src->red_shift,
2772 src_val >> src->green_shift,
2773 src_val >> src->blue_shift );
2775 if(pad_size) memset(dst_pixel, 0, pad_size);
2776 dst_start += dst->stride;
2777 src_start += src->stride / 4;
2780 else
2782 for(y = src_rect->top; y < src_rect->bottom; y++)
2784 dst_pixel = dst_start;
2785 src_pixel = src_start;
2786 for(x = src_rect->left; x < src_rect->right; x++)
2788 src_val = *src_pixel++;
2789 *dst_pixel++ = rgb_lookup_colortable(dst,
2790 get_field(src_val, src->red_shift, src->red_len),
2791 get_field(src_val, src->green_shift, src->green_len),
2792 get_field(src_val, src->blue_shift, src->blue_len));
2794 if(pad_size) memset(dst_pixel, 0, pad_size);
2795 dst_start += dst->stride;
2796 src_start += src->stride / 4;
2799 break;
2802 case 24:
2804 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2806 for(y = src_rect->top; y < src_rect->bottom; y++)
2808 dst_pixel = dst_start;
2809 src_pixel = src_start;
2810 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2812 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2814 if(pad_size) memset(dst_pixel, 0, pad_size);
2815 dst_start += dst->stride;
2816 src_start += src->stride;
2818 break;
2821 case 16:
2823 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2824 if(src->funcs == &funcs_555)
2826 for(y = src_rect->top; y < src_rect->bottom; y++)
2828 dst_pixel = dst_start;
2829 src_pixel = src_start;
2830 for(x = src_rect->left; x < src_rect->right; x++)
2832 src_val = *src_pixel++;
2833 *dst_pixel++ = rgb_lookup_colortable(dst,
2834 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2835 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2836 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2838 if(pad_size) memset(dst_pixel, 0, pad_size);
2839 dst_start += dst->stride;
2840 src_start += src->stride / 2;
2843 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2845 for(y = src_rect->top; y < src_rect->bottom; y++)
2847 dst_pixel = dst_start;
2848 src_pixel = src_start;
2849 for(x = src_rect->left; x < src_rect->right; x++)
2851 src_val = *src_pixel++;
2852 *dst_pixel++ = rgb_lookup_colortable(dst,
2853 (((src_val >> src->red_shift) << 3) & 0xf8) |
2854 (((src_val >> src->red_shift) >> 2) & 0x07),
2855 (((src_val >> src->green_shift) << 3) & 0xf8) |
2856 (((src_val >> src->green_shift) >> 2) & 0x07),
2857 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2858 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2860 if(pad_size) memset(dst_pixel, 0, pad_size);
2861 dst_start += dst->stride;
2862 src_start += src->stride / 2;
2865 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2867 for(y = src_rect->top; y < src_rect->bottom; y++)
2869 dst_pixel = dst_start;
2870 src_pixel = src_start;
2871 for(x = src_rect->left; x < src_rect->right; x++)
2873 src_val = *src_pixel++;
2874 *dst_pixel++ = rgb_lookup_colortable(dst,
2875 (((src_val >> src->red_shift) << 3) & 0xf8) |
2876 (((src_val >> src->red_shift) >> 2) & 0x07),
2877 (((src_val >> src->green_shift) << 2) & 0xfc) |
2878 (((src_val >> src->green_shift) >> 4) & 0x03),
2879 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2880 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2882 if(pad_size) memset(dst_pixel, 0, pad_size);
2883 dst_start += dst->stride;
2884 src_start += src->stride / 2;
2887 else
2889 for(y = src_rect->top; y < src_rect->bottom; y++)
2891 dst_pixel = dst_start;
2892 src_pixel = src_start;
2893 for(x = src_rect->left; x < src_rect->right; x++)
2895 src_val = *src_pixel++;
2896 *dst_pixel++ = rgb_lookup_colortable(dst,
2897 get_field(src_val, src->red_shift, src->red_len),
2898 get_field(src_val, src->green_shift, src->green_len),
2899 get_field(src_val, src->blue_shift, src->blue_len));
2901 if(pad_size) memset(dst_pixel, 0, pad_size);
2902 dst_start += dst->stride;
2903 src_start += src->stride / 2;
2906 break;
2909 case 8:
2911 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2913 if(color_tables_match(dst, src))
2915 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2916 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2917 else
2919 for(y = src_rect->top; y < src_rect->bottom; y++)
2921 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2922 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2923 dst_start += dst->stride;
2924 src_start += src->stride;
2928 else
2930 for(y = src_rect->top; y < src_rect->bottom; y++)
2932 dst_pixel = dst_start;
2933 src_pixel = src_start;
2934 for(x = src_rect->left; x < src_rect->right; x++)
2936 RGBQUAD rgb = src->color_table[*src_pixel++];
2937 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2939 if(pad_size) memset(dst_pixel, 0, pad_size);
2940 dst_start += dst->stride;
2941 src_start += src->stride;
2944 break;
2947 case 4:
2949 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2950 for(y = src_rect->top; y < src_rect->bottom; y++)
2952 dst_pixel = dst_start;
2953 src_pixel = src_start;
2954 for(x = src_rect->left; x < src_rect->right; x++)
2956 RGBQUAD rgb;
2957 if(x & 1)
2958 rgb = src->color_table[*src_pixel++ & 0xf];
2959 else
2960 rgb = src->color_table[*src_pixel >> 4];
2961 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2963 if(pad_size) memset(dst_pixel, 0, pad_size);
2964 dst_start += dst->stride;
2965 src_start += src->stride;
2967 break;
2970 case 1:
2972 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2973 for(y = src_rect->top; y < src_rect->bottom; y++)
2975 dst_pixel = dst_start;
2976 src_pixel = src_start;
2977 for(x = src_rect->left; x < src_rect->right; x++)
2979 RGBQUAD rgb;
2980 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2981 if((x % 8) == 7) src_pixel++;
2982 rgb = src->color_table[src_val];
2983 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2985 if(pad_size) memset(dst_pixel, 0, pad_size);
2986 dst_start += dst->stride;
2987 src_start += src->stride;
2989 break;
2994 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2996 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2997 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2998 DWORD src_val;
3000 switch(src->bit_count)
3002 case 32:
3004 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3006 if(src->funcs == &funcs_8888)
3008 for(y = src_rect->top; y < src_rect->bottom; y++)
3010 dst_pixel = dst_start;
3011 src_pixel = src_start;
3012 for(x = src_rect->left; x < src_rect->right; x++)
3014 src_val = *src_pixel++;
3015 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
3016 if((x - src_rect->left) & 1)
3018 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3019 dst_pixel++;
3021 else
3022 *dst_pixel = (dst_val << 4) & 0xf0;
3024 if(pad_size)
3026 if((x - src_rect->left) & 1) dst_pixel++;
3027 memset(dst_pixel, 0, pad_size);
3029 dst_start += dst->stride;
3030 src_start += src->stride / 4;
3033 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3035 for(y = src_rect->top; y < src_rect->bottom; y++)
3037 dst_pixel = dst_start;
3038 src_pixel = src_start;
3039 for(x = src_rect->left; x < src_rect->right; x++)
3041 src_val = *src_pixel++;
3042 dst_val = rgb_to_pixel_colortable(dst,
3043 src_val >> src->red_shift,
3044 src_val >> src->green_shift,
3045 src_val >> src->blue_shift);
3046 if((x - src_rect->left) & 1)
3048 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3049 dst_pixel++;
3051 else
3052 *dst_pixel = (dst_val << 4) & 0xf0;
3054 if(pad_size)
3056 if((x - src_rect->left) & 1) dst_pixel++;
3057 memset(dst_pixel, 0, pad_size);
3059 dst_start += dst->stride;
3060 src_start += src->stride / 4;
3063 else
3065 for(y = src_rect->top; y < src_rect->bottom; y++)
3067 dst_pixel = dst_start;
3068 src_pixel = src_start;
3069 for(x = src_rect->left; x < src_rect->right; x++)
3071 src_val = *src_pixel++;
3072 dst_val = rgb_to_pixel_colortable(dst,
3073 get_field(src_val, src->red_shift, src->red_len),
3074 get_field(src_val, src->green_shift, src->green_len),
3075 get_field(src_val, src->blue_shift, src->blue_len));
3076 if((x - src_rect->left) & 1)
3078 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3079 dst_pixel++;
3081 else
3082 *dst_pixel = (dst_val << 4) & 0xf0;
3084 if(pad_size)
3086 if((x - src_rect->left) & 1) dst_pixel++;
3087 memset(dst_pixel, 0, pad_size);
3089 dst_start += dst->stride;
3090 src_start += src->stride / 4;
3093 break;
3096 case 24:
3098 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3100 for(y = src_rect->top; y < src_rect->bottom; y++)
3102 dst_pixel = dst_start;
3103 src_pixel = src_start;
3104 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3106 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3108 if((x - src_rect->left) & 1)
3110 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3111 dst_pixel++;
3113 else
3114 *dst_pixel = (dst_val << 4) & 0xf0;
3116 if(pad_size)
3118 if((x - src_rect->left) & 1) dst_pixel++;
3119 memset(dst_pixel, 0, pad_size);
3121 dst_start += dst->stride;
3122 src_start += src->stride;
3124 break;
3127 case 16:
3129 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3130 if(src->funcs == &funcs_555)
3132 for(y = src_rect->top; y < src_rect->bottom; y++)
3134 dst_pixel = dst_start;
3135 src_pixel = src_start;
3136 for(x = src_rect->left; x < src_rect->right; x++)
3138 src_val = *src_pixel++;
3139 dst_val = rgb_to_pixel_colortable(dst,
3140 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3141 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3142 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3143 if((x - src_rect->left) & 1)
3145 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3146 dst_pixel++;
3148 else
3149 *dst_pixel = (dst_val << 4) & 0xf0;
3151 if(pad_size)
3153 if((x - src_rect->left) & 1) dst_pixel++;
3154 memset(dst_pixel, 0, pad_size);
3156 dst_start += dst->stride;
3157 src_start += src->stride / 2;
3160 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3162 for(y = src_rect->top; y < src_rect->bottom; y++)
3164 dst_pixel = dst_start;
3165 src_pixel = src_start;
3166 for(x = src_rect->left; x < src_rect->right; x++)
3168 src_val = *src_pixel++;
3169 dst_val = rgb_to_pixel_colortable(dst,
3170 (((src_val >> src->red_shift) << 3) & 0xf8) |
3171 (((src_val >> src->red_shift) >> 2) & 0x07),
3172 (((src_val >> src->green_shift) << 3) & 0xf8) |
3173 (((src_val >> src->green_shift) >> 2) & 0x07),
3174 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3175 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3176 if((x - src_rect->left) & 1)
3178 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3179 dst_pixel++;
3181 else
3182 *dst_pixel = (dst_val << 4) & 0xf0;
3184 if(pad_size)
3186 if((x - src_rect->left) & 1) dst_pixel++;
3187 memset(dst_pixel, 0, pad_size);
3189 dst_start += dst->stride;
3190 src_start += src->stride / 2;
3193 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3195 for(y = src_rect->top; y < src_rect->bottom; y++)
3197 dst_pixel = dst_start;
3198 src_pixel = src_start;
3199 for(x = src_rect->left; x < src_rect->right; x++)
3201 src_val = *src_pixel++;
3202 dst_val = rgb_to_pixel_colortable(dst,
3203 (((src_val >> src->red_shift) << 3) & 0xf8) |
3204 (((src_val >> src->red_shift) >> 2) & 0x07),
3205 (((src_val >> src->green_shift) << 2) & 0xfc) |
3206 (((src_val >> src->green_shift) >> 4) & 0x03),
3207 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3208 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3209 if((x - src_rect->left) & 1)
3211 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3212 dst_pixel++;
3214 else
3215 *dst_pixel = (dst_val << 4) & 0xf0;
3217 if(pad_size)
3219 if((x - src_rect->left) & 1) dst_pixel++;
3220 memset(dst_pixel, 0, pad_size);
3222 dst_start += dst->stride;
3223 src_start += src->stride / 2;
3226 else
3228 for(y = src_rect->top; y < src_rect->bottom; y++)
3230 dst_pixel = dst_start;
3231 src_pixel = src_start;
3232 for(x = src_rect->left; x < src_rect->right; x++)
3234 src_val = *src_pixel++;
3235 dst_val = rgb_to_pixel_colortable(dst,
3236 get_field(src_val, src->red_shift, src->red_len),
3237 get_field(src_val, src->green_shift, src->green_len),
3238 get_field(src_val, src->blue_shift, src->blue_len));
3239 if((x - src_rect->left) & 1)
3241 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3242 dst_pixel++;
3244 else
3245 *dst_pixel = (dst_val << 4) & 0xf0;
3247 if(pad_size)
3249 if((x - src_rect->left) & 1) dst_pixel++;
3250 memset(dst_pixel, 0, pad_size);
3252 dst_start += dst->stride;
3253 src_start += src->stride / 2;
3256 break;
3259 case 8:
3261 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3263 for(y = src_rect->top; y < src_rect->bottom; y++)
3265 dst_pixel = dst_start;
3266 src_pixel = src_start;
3267 for(x = src_rect->left; x < src_rect->right; x++)
3269 RGBQUAD rgb = src->color_table[*src_pixel++];
3270 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3271 if((x - src_rect->left) & 1)
3273 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3274 dst_pixel++;
3276 else
3277 *dst_pixel = (dst_val << 4) & 0xf0;
3279 if(pad_size)
3281 if((x - src_rect->left) & 1) dst_pixel++;
3282 memset(dst_pixel, 0, pad_size);
3284 dst_start += dst->stride;
3285 src_start += src->stride;
3287 break;
3290 case 4:
3292 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3294 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
3296 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
3297 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3298 else
3300 for(y = src_rect->top; y < src_rect->bottom; y++)
3302 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3303 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3304 dst_start += dst->stride;
3305 src_start += src->stride;
3309 else
3311 for(y = src_rect->top; y < src_rect->bottom; y++)
3313 dst_pixel = dst_start;
3314 src_pixel = src_start;
3315 for(x = src_rect->left; x < src_rect->right; x++)
3317 RGBQUAD rgb;
3318 if(x & 1)
3319 rgb = src->color_table[*src_pixel++ & 0xf];
3320 else
3321 rgb = src->color_table[*src_pixel >> 4];
3322 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3323 if((x - src_rect->left) & 1)
3325 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3326 dst_pixel++;
3328 else
3329 *dst_pixel = (dst_val << 4) & 0xf0;
3331 if(pad_size)
3333 if((x - src_rect->left) & 1) dst_pixel++;
3334 memset(dst_pixel, 0, pad_size);
3336 dst_start += dst->stride;
3337 src_start += src->stride;
3340 break;
3343 case 1:
3345 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3346 for(y = src_rect->top; y < src_rect->bottom; y++)
3348 dst_pixel = dst_start;
3349 src_pixel = src_start;
3350 for(x = src_rect->left; x < src_rect->right; x++)
3352 RGBQUAD rgb;
3353 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3354 if((x % 8) == 7) src_pixel++;
3355 rgb = src->color_table[src_val];
3356 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3357 if((x - src_rect->left) & 1)
3359 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3360 dst_pixel++;
3362 else
3363 *dst_pixel = (dst_val << 4) & 0xf0;
3365 if(pad_size)
3367 if((x - src_rect->left) & 1) dst_pixel++;
3368 memset(dst_pixel, 0, pad_size);
3370 dst_start += dst->stride;
3371 src_start += src->stride;
3373 break;
3378 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3380 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3381 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3382 DWORD src_val;
3383 int bit_pos;
3385 /* FIXME: Brushes should be dithered. */
3387 switch(src->bit_count)
3389 case 32:
3391 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3393 if(src->funcs == &funcs_8888)
3395 for(y = src_rect->top; y < src_rect->bottom; y++)
3397 dst_pixel = dst_start;
3398 src_pixel = src_start;
3399 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3401 src_val = *src_pixel++;
3402 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3404 if(bit_pos == 0) *dst_pixel = 0;
3405 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3407 if(++bit_pos == 8)
3409 dst_pixel++;
3410 bit_pos = 0;
3413 if(pad_size)
3415 if(bit_pos != 0) dst_pixel++;
3416 memset(dst_pixel, 0, pad_size);
3418 dst_start += dst->stride;
3419 src_start += src->stride / 4;
3422 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3424 for(y = src_rect->top; y < src_rect->bottom; y++)
3426 dst_pixel = dst_start;
3427 src_pixel = src_start;
3428 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3430 src_val = *src_pixel++;
3431 dst_val = rgb_to_pixel_colortable(dst,
3432 src_val >> src->red_shift,
3433 src_val >> src->green_shift,
3434 src_val >> src->blue_shift) ? 0xff : 0;
3436 if(bit_pos == 0) *dst_pixel = 0;
3437 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3439 if(++bit_pos == 8)
3441 dst_pixel++;
3442 bit_pos = 0;
3445 if(pad_size)
3447 if(bit_pos != 0) dst_pixel++;
3448 memset(dst_pixel, 0, pad_size);
3450 dst_start += dst->stride;
3451 src_start += src->stride / 4;
3454 else
3456 for(y = src_rect->top; y < src_rect->bottom; y++)
3458 dst_pixel = dst_start;
3459 src_pixel = src_start;
3460 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3462 src_val = *src_pixel++;
3463 dst_val = rgb_to_pixel_colortable(dst,
3464 get_field(src_val, src->red_shift, src->red_len),
3465 get_field(src_val, src->green_shift, src->green_len),
3466 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3468 if(bit_pos == 0) *dst_pixel = 0;
3469 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3471 if(++bit_pos == 8)
3473 dst_pixel++;
3474 bit_pos = 0;
3477 if(pad_size)
3479 if(bit_pos != 0) dst_pixel++;
3480 memset(dst_pixel, 0, pad_size);
3482 dst_start += dst->stride;
3483 src_start += src->stride / 4;
3486 break;
3489 case 24:
3491 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3493 for(y = src_rect->top; y < src_rect->bottom; y++)
3495 dst_pixel = dst_start;
3496 src_pixel = src_start;
3497 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3499 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3501 if(bit_pos == 0) *dst_pixel = 0;
3502 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3504 if(++bit_pos == 8)
3506 dst_pixel++;
3507 bit_pos = 0;
3510 if(pad_size)
3512 if(bit_pos != 0) dst_pixel++;
3513 memset(dst_pixel, 0, pad_size);
3515 dst_start += dst->stride;
3516 src_start += src->stride;
3518 break;
3521 case 16:
3523 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3524 if(src->funcs == &funcs_555)
3526 for(y = src_rect->top; y < src_rect->bottom; y++)
3528 dst_pixel = dst_start;
3529 src_pixel = src_start;
3530 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3532 src_val = *src_pixel++;
3533 dst_val = rgb_to_pixel_colortable(dst,
3534 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3535 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3536 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3538 if(bit_pos == 0) *dst_pixel = 0;
3539 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3541 if(++bit_pos == 8)
3543 dst_pixel++;
3544 bit_pos = 0;
3547 if(pad_size)
3549 if(bit_pos != 0) dst_pixel++;
3550 memset(dst_pixel, 0, pad_size);
3552 dst_start += dst->stride;
3553 src_start += src->stride / 2;
3556 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3558 for(y = src_rect->top; y < src_rect->bottom; y++)
3560 dst_pixel = dst_start;
3561 src_pixel = src_start;
3562 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3564 src_val = *src_pixel++;
3565 dst_val = rgb_to_pixel_colortable(dst,
3566 (((src_val >> src->red_shift) << 3) & 0xf8) |
3567 (((src_val >> src->red_shift) >> 2) & 0x07),
3568 (((src_val >> src->green_shift) << 3) & 0xf8) |
3569 (((src_val >> src->green_shift) >> 2) & 0x07),
3570 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3571 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3572 if(bit_pos == 0) *dst_pixel = 0;
3573 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3575 if(++bit_pos == 8)
3577 dst_pixel++;
3578 bit_pos = 0;
3581 if(pad_size)
3583 if(bit_pos != 0) dst_pixel++;
3584 memset(dst_pixel, 0, pad_size);
3586 dst_start += dst->stride;
3587 src_start += src->stride / 2;
3590 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3592 for(y = src_rect->top; y < src_rect->bottom; y++)
3594 dst_pixel = dst_start;
3595 src_pixel = src_start;
3596 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3598 src_val = *src_pixel++;
3599 dst_val = rgb_to_pixel_colortable(dst,
3600 (((src_val >> src->red_shift) << 3) & 0xf8) |
3601 (((src_val >> src->red_shift) >> 2) & 0x07),
3602 (((src_val >> src->green_shift) << 2) & 0xfc) |
3603 (((src_val >> src->green_shift) >> 4) & 0x03),
3604 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3605 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3606 if(bit_pos == 0) *dst_pixel = 0;
3607 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3609 if(++bit_pos == 8)
3611 dst_pixel++;
3612 bit_pos = 0;
3615 if(pad_size)
3617 if(bit_pos != 0) dst_pixel++;
3618 memset(dst_pixel, 0, pad_size);
3620 dst_start += dst->stride;
3621 src_start += src->stride / 2;
3624 else
3626 for(y = src_rect->top; y < src_rect->bottom; y++)
3628 dst_pixel = dst_start;
3629 src_pixel = src_start;
3630 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3632 src_val = *src_pixel++;
3633 dst_val = rgb_to_pixel_colortable(dst,
3634 get_field(src_val, src->red_shift, src->red_len),
3635 get_field(src_val, src->green_shift, src->green_len),
3636 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3637 if(bit_pos == 0) *dst_pixel = 0;
3638 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3640 if(++bit_pos == 8)
3642 dst_pixel++;
3643 bit_pos = 0;
3646 if(pad_size)
3648 if(bit_pos != 0) dst_pixel++;
3649 memset(dst_pixel, 0, pad_size);
3651 dst_start += dst->stride;
3652 src_start += src->stride / 2;
3655 break;
3658 case 8:
3660 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3662 for(y = src_rect->top; y < src_rect->bottom; y++)
3664 dst_pixel = dst_start;
3665 src_pixel = src_start;
3666 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3668 RGBQUAD rgb = src->color_table[*src_pixel++];
3669 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3671 if(bit_pos == 0) *dst_pixel = 0;
3672 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3674 if(++bit_pos == 8)
3676 dst_pixel++;
3677 bit_pos = 0;
3680 if(pad_size)
3682 if(bit_pos != 0) dst_pixel++;
3683 memset(dst_pixel, 0, pad_size);
3685 dst_start += dst->stride;
3686 src_start += src->stride;
3688 break;
3691 case 4:
3693 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3695 for(y = src_rect->top; y < src_rect->bottom; y++)
3697 dst_pixel = dst_start;
3698 src_pixel = src_start;
3699 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3701 RGBQUAD rgb;
3702 if(x & 1)
3703 rgb = src->color_table[*src_pixel++ & 0xf];
3704 else
3705 rgb = src->color_table[*src_pixel >> 4];
3706 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3708 if(bit_pos == 0) *dst_pixel = 0;
3709 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3711 if(++bit_pos == 8)
3713 dst_pixel++;
3714 bit_pos = 0;
3717 if(pad_size)
3719 if(bit_pos != 0) dst_pixel++;
3720 memset(dst_pixel, 0, pad_size);
3722 dst_start += dst->stride;
3723 src_start += src->stride;
3725 break;
3728 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3729 uses text/bkgnd colours instead of the dib's colour table, this
3730 doesn't appear to be the case for a dc backed by a
3731 dibsection. */
3733 case 1:
3735 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3736 for(y = src_rect->top; y < src_rect->bottom; y++)
3738 dst_pixel = dst_start;
3739 src_pixel = src_start;
3740 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3742 RGBQUAD rgb;
3743 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3744 if((x % 8) == 7) src_pixel++;
3745 rgb = src->color_table[src_val];
3746 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3748 if(bit_pos == 0) *dst_pixel = 0;
3749 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3751 if(++bit_pos == 8)
3753 dst_pixel++;
3754 bit_pos = 0;
3757 if(pad_size)
3759 if(bit_pos != 0) dst_pixel++;
3760 memset(dst_pixel, 0, pad_size);
3762 dst_start += dst->stride;
3763 src_start += src->stride;
3765 break;
3770 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3774 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3776 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3779 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3781 return (blend_color( dst, src, alpha ) |
3782 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3783 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3784 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3787 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3789 BYTE b = ((BYTE)src * alpha + 127) / 255;
3790 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3791 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3792 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3793 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3794 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3795 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3796 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3799 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3801 if (blend.AlphaFormat & AC_SRC_ALPHA)
3803 DWORD alpha = blend.SourceConstantAlpha;
3804 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3805 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3806 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3807 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3808 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3809 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3810 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3812 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3813 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3814 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3817 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3818 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3820 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3821 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3822 int x, y;
3824 if (blend.AlphaFormat & AC_SRC_ALPHA)
3825 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3826 for (x = 0; x < rc->right - rc->left; x++)
3827 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3828 else
3829 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3830 for (x = 0; x < rc->right - rc->left; x++)
3831 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3834 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3835 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3837 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3838 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3839 int x, y;
3841 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3843 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3845 for (x = 0; x < rc->right - rc->left; x++)
3847 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3848 dst_ptr[x] >> dst->green_shift,
3849 dst_ptr[x] >> dst->blue_shift,
3850 src_ptr[x], blend );
3851 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3852 (((val >> 8) & 0xff) << dst->green_shift) |
3853 (((val >> 16) & 0xff) << dst->red_shift));
3857 else
3859 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3861 for (x = 0; x < rc->right - rc->left; x++)
3863 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3864 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3865 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3866 src_ptr[x], blend );
3867 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3868 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3869 put_field( val, dst->blue_shift, dst->blue_len ));
3875 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3876 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3878 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3879 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3880 int x, y;
3882 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3884 for (x = 0; x < rc->right - rc->left; x++)
3886 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3887 src_ptr[x], blend );
3888 dst_ptr[x * 3] = val;
3889 dst_ptr[x * 3 + 1] = val >> 8;
3890 dst_ptr[x * 3 + 2] = val >> 16;
3895 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3896 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3898 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3899 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3900 int x, y;
3902 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3904 for (x = 0; x < rc->right - rc->left; x++)
3906 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3907 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3908 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3909 src_ptr[x], blend );
3910 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3915 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3916 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3918 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3919 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3920 int x, y;
3922 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3924 for (x = 0; x < rc->right - rc->left; x++)
3926 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3927 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3928 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3929 src_ptr[x], blend );
3930 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3931 put_field((val >> 8), dst->green_shift, dst->green_len) |
3932 put_field( val, dst->blue_shift, dst->blue_len));
3937 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3938 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3940 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3941 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3942 int x, y;
3944 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3946 for (x = 0; x < rc->right - rc->left; x++)
3948 RGBQUAD rgb = dst->color_table[dst_ptr[x]];
3949 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3950 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3955 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3956 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3958 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3959 BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3960 int x, y;
3962 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3964 for (x = rc->left; x < rc->right; x++)
3966 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3967 RGBQUAD rgb = dst->color_table[val];
3968 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3969 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3970 if (x & 1)
3971 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3972 else
3973 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3978 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3979 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3981 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3982 BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
3983 int x, y;
3985 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3987 for (x = rc->left; x < rc->right; x++)
3989 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3990 RGBQUAD rgb = dst->color_table[val];
3991 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3992 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
3993 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
3998 static void blend_rect_null(const dib_info *dst, const RECT *rc,
3999 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
4003 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4005 BYTE r, g, b, a;
4006 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4007 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4008 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4009 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
4010 return a << 24 | r << 16 | g << 8 | b;
4013 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
4015 BYTE r, g, b;
4016 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
4017 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
4018 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
4019 return r << 16 | g << 8 | b;
4022 static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
4023 unsigned int x, unsigned int y )
4025 int r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4026 int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4027 int b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_4x4[y % 4][x % 4];
4028 r = min( 31, max( 0, r / 16 ));
4029 g = min( 31, max( 0, g / 16 ));
4030 b = min( 31, max( 0, b / 16 ));
4031 return (r << 10) | (g << 5) | b;
4034 static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
4035 unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
4037 BYTE r = ((v[0].Red * (len - pos) + v[1].Red * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4038 BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4039 BYTE b = ((v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4040 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4043 /* compute the left/right triangle limit for row y */
4044 static inline void triangle_coords( const TRIVERTEX *v, const RECT *rc, int y, int *left, int *right )
4046 int x1, x2;
4048 if (y < v[1].y) x1 = edge_coord( y, v[0].x, v[0].y, v[1].x, v[1].y );
4049 else x1 = edge_coord( y, v[1].x, v[1].y, v[2].x, v[2].y );
4051 x2 = edge_coord( y, v[0].x, v[0].y, v[2].x, v[2].y );
4053 *left = max( rc->left, min( x1, x2 ) );
4054 *right = min( rc->right, max( x1, x2 ) );
4057 /* compute the matrix determinant for triangular barycentric coordinates (constant across the triangle) */
4058 static inline int triangle_det( const TRIVERTEX *v )
4060 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);
4063 /* compute the barycentric weights for a given point inside the triangle */
4064 static inline void triangle_weights( const TRIVERTEX *v, int x, int y, INT64 *l1, INT64 *l2 )
4066 *l1 = (v[1].y - v[2].y) * (x - v[2].x) - (v[1].x - v[2].x) * (y - v[2].y);
4067 *l2 = (v[2].y - v[0].y) * (x - v[2].x) - (v[2].x - v[0].x) * (y - v[2].y);
4070 static inline DWORD gradient_triangle_8888( const TRIVERTEX *v, int x, int y, int det )
4072 INT64 l1, l2;
4073 BYTE r, g, b, a;
4075 triangle_weights( v, x, y, &l1, &l2 );
4076 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4077 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4078 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4079 a = (v[0].Alpha * l1 + v[1].Alpha * l2 + v[2].Alpha * (det - l1 - l2)) / det / 256;
4080 return a << 24 | r << 16 | g << 8 | b;
4083 static inline DWORD gradient_triangle_24( const TRIVERTEX *v, int x, int y, int det )
4085 INT64 l1, l2;
4086 BYTE r, g, b;
4088 triangle_weights( v, x, y, &l1, &l2 );
4089 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 256;
4090 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 256;
4091 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 256;
4092 return r << 16 | g << 8 | b;
4095 static inline DWORD gradient_triangle_555( const TRIVERTEX *v, int x, int y, int det )
4097 INT64 l1, l2;
4098 int r, g, b;
4100 triangle_weights( v, x, y, &l1, &l2 );
4101 r = (v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4102 g = (v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4103 b = (v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_4x4[y % 4][x % 4];
4104 r = min( 31, max( 0, r / 16 ));
4105 g = min( 31, max( 0, g / 16 ));
4106 b = min( 31, max( 0, b / 16 ));
4107 return (r << 10) | (g << 5) | b;
4110 static inline DWORD gradient_triangle_8( const dib_info *dib, const TRIVERTEX *v, int x, int y, int det )
4112 INT64 l1, l2;
4113 BYTE r, g, b;
4115 triangle_weights( v, x, y, &l1, &l2 );
4116 r = ((v[0].Red * l1 + v[1].Red * l2 + v[2].Red * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4117 g = ((v[0].Green * l1 + v[1].Green * l2 + v[2].Green * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4118 b = ((v[0].Blue * l1 + v[1].Blue * l2 + v[2].Blue * (det - l1 - l2)) / det / 128 + bayer_16x16[y % 16][x % 16]) / 256;
4119 return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
4122 static BOOL gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4124 DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4125 int x, y, left, right, det;
4127 switch (mode)
4129 case GRADIENT_FILL_RECT_H:
4130 for (x = rc->left; x < rc->right; x++)
4131 ptr[x] = gradient_rgb_8888( v, x - v[0].x, v[1].x - v[0].x );
4133 for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4134 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4135 break;
4137 case GRADIENT_FILL_RECT_V:
4138 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4140 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4141 for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4143 break;
4145 case GRADIENT_FILL_TRIANGLE:
4146 if (!(det = triangle_det( v ))) return FALSE;
4147 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4149 triangle_coords( v, rc, y, &left, &right );
4150 for (x = left; x < right; x++) ptr[x] = gradient_triangle_8888( v, x, y, det );
4152 break;
4154 return TRUE;
4157 static BOOL gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4159 DWORD *ptr = get_pixel_ptr_32( dib, 0, rc->top );
4160 int x, y, left, right, det;
4162 switch (mode)
4164 case GRADIENT_FILL_RECT_H:
4165 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4167 for (x = rc->left; x < rc->right; x++)
4169 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4170 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4171 (((val >> 8) & 0xff) << dib->green_shift) |
4172 (((val >> 16) & 0xff) << dib->red_shift));
4175 else
4177 for (x = rc->left; x < rc->right; x++)
4179 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4180 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4181 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4182 put_field( val, dib->blue_shift, dib->blue_len ));
4186 for (y = rc->top + 1, ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 4)
4187 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4188 break;
4190 case GRADIENT_FILL_RECT_V:
4191 for (y = rc->top; y < rc->bottom; y++)
4193 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4194 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4195 val = ((( val & 0xff) << dib->blue_shift) |
4196 (((val >> 8) & 0xff) << dib->green_shift) |
4197 (((val >> 16) & 0xff) << dib->red_shift));
4198 else
4199 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4200 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4201 put_field( val, dib->blue_shift, dib->blue_len ));
4203 for (x = rc->left; x < rc->right; x++) ptr[x] = val;
4204 ptr += dib->stride / 4;
4206 break;
4208 case GRADIENT_FILL_TRIANGLE:
4209 if (!(det = triangle_det( v ))) return FALSE;
4210 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 4)
4212 triangle_coords( v, rc, y, &left, &right );
4214 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4215 for (x = left; x < right; x++)
4217 DWORD val = gradient_triangle_24( v, x, y, det );
4218 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4219 (((val >> 8) & 0xff) << dib->green_shift) |
4220 (((val >> 16) & 0xff) << dib->red_shift));
4222 else
4223 for (x = left; x < right; x++)
4225 DWORD val = gradient_triangle_24( v, x, y, det );
4226 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4227 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4228 put_field( val, dib->blue_shift, dib->blue_len ));
4231 break;
4233 return TRUE;
4236 static BOOL gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4238 BYTE *ptr = get_pixel_ptr_24( dib, 0, rc->top );
4239 int x, y, left, right, det;
4241 switch (mode)
4243 case GRADIENT_FILL_RECT_H:
4244 for (x = rc->left; x < rc->right; x++)
4246 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4247 ptr[x * 3] = val;
4248 ptr[x * 3 + 1] = val >> 8;
4249 ptr[x * 3 + 2] = val >> 16;
4252 for (y = rc->top + 1, ptr += rc->left * 3; y < rc->bottom; y++, ptr += dib->stride)
4253 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4254 break;
4256 case GRADIENT_FILL_RECT_V:
4257 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4259 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4260 for (x = rc->left; x < rc->right; x++)
4262 ptr[x * 3] = val;
4263 ptr[x * 3 + 1] = val >> 8;
4264 ptr[x * 3 + 2] = val >> 16;
4267 break;
4269 case GRADIENT_FILL_TRIANGLE:
4270 if (!(det = triangle_det( v ))) return FALSE;
4271 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4273 triangle_coords( v, rc, y, &left, &right );
4274 for (x = left; x < right; x++)
4276 DWORD val = gradient_triangle_24( v, x, y, det );
4277 ptr[x * 3] = val;
4278 ptr[x * 3 + 1] = val >> 8;
4279 ptr[x * 3 + 2] = val >> 16;
4282 break;
4284 return TRUE;
4287 static BOOL gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4289 WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4290 int x, y, left, right, det;
4292 switch (mode)
4294 case GRADIENT_FILL_RECT_H:
4295 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4296 for (x = rc->left; x < rc->right; x++)
4297 ptr[x] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4298 for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4299 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4300 break;
4302 case GRADIENT_FILL_RECT_V:
4303 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4305 WORD values[4];
4306 for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4307 for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4309 break;
4311 case GRADIENT_FILL_TRIANGLE:
4312 if (!(det = triangle_det( v ))) return FALSE;
4313 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4315 triangle_coords( v, rc, y, &left, &right );
4316 for (x = left; x < right; x++) ptr[x] = gradient_triangle_555( v, x, y, det );
4318 break;
4320 return TRUE;
4323 static BOOL gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4325 WORD *ptr = get_pixel_ptr_16( dib, 0, rc->top );
4326 int x, y, left, right, det;
4328 switch (mode)
4330 case GRADIENT_FILL_RECT_H:
4331 for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
4332 for (x = rc->left; x < rc->right; x++)
4334 WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
4335 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4336 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4337 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4339 for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
4340 memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
4341 break;
4343 case GRADIENT_FILL_RECT_V:
4344 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4346 WORD values[4];
4347 for (x = 0; x < 4; x++)
4349 WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
4350 values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4351 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4352 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4354 for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
4356 break;
4358 case GRADIENT_FILL_TRIANGLE:
4359 if (!(det = triangle_det( v ))) return FALSE;
4360 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride / 2)
4362 triangle_coords( v, rc, y, &left, &right );
4363 for (x = left; x < right; x++)
4365 WORD val = gradient_triangle_555( v, x, y, det );
4366 ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) |
4367 put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) |
4368 put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len));
4371 break;
4373 return TRUE;
4376 static BOOL gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4378 BYTE *ptr = get_pixel_ptr_8( dib, 0, rc->top );
4379 int x, y, left, right, det;
4381 switch (mode)
4383 case GRADIENT_FILL_RECT_H:
4384 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4385 for (x = rc->left; x < rc->right; x++)
4386 ptr[x] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4387 for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride)
4388 memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
4389 break;
4391 case GRADIENT_FILL_RECT_V:
4392 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4394 BYTE values[16];
4395 for (x = 0; x < 16; x++)
4396 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4397 for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 16];
4399 break;
4401 case GRADIENT_FILL_TRIANGLE:
4402 if (!(det = triangle_det( v ))) return FALSE;
4403 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4405 triangle_coords( v, rc, y, &left, &right );
4406 for (x = left; x < right; x++) ptr[x] = gradient_triangle_8( dib, v, x, y, det );
4408 break;
4410 return TRUE;
4413 static BOOL gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4415 BYTE *ptr = get_pixel_ptr_4( dib, 0, rc->top );
4416 int x, y, left, right, det;
4418 switch (mode)
4420 case GRADIENT_FILL_RECT_H:
4421 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4423 for (x = rc->left; x < rc->right; x++)
4425 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
4426 if (x & 1)
4427 ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4428 else
4429 ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4432 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4434 x = rc->left;
4435 if (x & 1)
4437 ptr[x / 2] = (ptr[x / 2 - 16 * dib->stride] & 0x0f) | (ptr[x / 2] & 0xf0);
4438 x++;
4440 for (; x < rc->right - 1; x += 2) ptr[x / 2] = ptr[x / 2 - 16 * dib->stride];
4441 if (x < rc->right)
4442 ptr[x / 2] = (ptr[x / 2] & 0x0f) | (ptr[x / 2 - 16 * dib->stride] & 0xf0);
4444 break;
4446 case GRADIENT_FILL_RECT_V:
4447 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4449 BYTE values[16];
4450 for (x = 0; x < 16; x++)
4451 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
4452 for (x = rc->left; x < rc->right; x++)
4453 if (x & 1)
4454 ptr[x / 2] = values[x % 16] | (ptr[x / 2] & 0xf0);
4455 else
4456 ptr[x / 2] = (values[x % 16] << 4) | (ptr[x / 2] & 0x0f);
4458 break;
4460 case GRADIENT_FILL_TRIANGLE:
4461 if (!(det = triangle_det( v ))) return FALSE;
4462 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4464 triangle_coords( v, rc, y, &left, &right );
4465 for (x = left; x < right; x++)
4467 BYTE val = gradient_triangle_8( dib, v, x, y, det );
4468 if (x & 1)
4469 ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4470 else
4471 ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4474 break;
4476 return TRUE;
4479 static BOOL gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4481 BYTE *ptr = get_pixel_ptr_1( dib, 0, rc->top );
4482 int x, y, left, right, det;
4484 switch (mode)
4486 case GRADIENT_FILL_RECT_H:
4487 for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
4489 for (x = rc->left; x < rc->right; x++)
4491 BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y ) ? 0xff : 0;
4492 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4495 for ( ; y < rc->bottom; y++, ptr += dib->stride)
4496 for (x = rc->left; x < rc->right; x++)
4497 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) |
4498 (ptr[x / 8 - 16 * dib->stride] & pixel_masks_1[x % 8]);
4499 break;
4501 case GRADIENT_FILL_RECT_V:
4502 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4504 BYTE values[16];
4505 for (x = 0; x < 16; x++)
4506 values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y ) ? 0xff : 0;
4507 for (x = rc->left; x < rc->right; x++)
4508 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (values[x % 16] & pixel_masks_1[x % 8]);
4510 break;
4512 case GRADIENT_FILL_TRIANGLE:
4513 if (!(det = triangle_det( v ))) return FALSE;
4514 for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
4516 triangle_coords( v, rc, y, &left, &right );
4517 for (x = left; x < right; x++)
4519 BYTE val = gradient_triangle_8( dib, v, x, y, det ) ? 0xff : 0;
4520 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4523 break;
4525 return TRUE;
4528 static BOOL gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4530 return TRUE;
4533 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4535 if (dst == text) return dst;
4537 if (dst > text)
4539 DWORD diff = dst - text;
4540 DWORD range = max_comp - text;
4541 dst = text + (diff * range ) / (0xff - text);
4542 return dst;
4544 else
4546 DWORD diff = text - dst;
4547 DWORD range = text - min_comp;
4548 dst = text - (diff * range) / text;
4549 return dst;
4553 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4555 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4556 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4557 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4560 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4561 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4563 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4564 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4565 int x, y;
4567 for (y = rect->top; y < rect->bottom; y++)
4569 for (x = 0; x < rect->right - rect->left; x++)
4571 if (glyph_ptr[x] <= 1) continue;
4572 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4573 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4575 dst_ptr += dib->stride / 4;
4576 glyph_ptr += glyph->stride;
4580 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4581 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4583 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4584 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4585 int x, y;
4586 DWORD text, val;
4588 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4589 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4590 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4592 for (y = rect->top; y < rect->bottom; y++)
4594 for (x = 0; x < rect->right - rect->left; x++)
4596 if (glyph_ptr[x] <= 1) continue;
4597 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4598 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4599 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4600 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4601 text, ranges + glyph_ptr[x] );
4602 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4603 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4604 put_field( val, dib->blue_shift, dib->blue_len ));
4606 dst_ptr += dib->stride / 4;
4607 glyph_ptr += glyph->stride;
4611 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4612 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4614 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4615 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4616 int x, y;
4617 DWORD val;
4619 for (y = rect->top; y < rect->bottom; y++)
4621 for (x = 0; x < rect->right - rect->left; x++)
4623 if (glyph_ptr[x] <= 1) continue;
4624 if (glyph_ptr[x] >= 16)
4625 val = text_pixel;
4626 else
4627 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4628 text_pixel, ranges + glyph_ptr[x] );
4629 dst_ptr[x * 3] = val;
4630 dst_ptr[x * 3 + 1] = val >> 8;
4631 dst_ptr[x * 3 + 2] = val >> 16;
4633 dst_ptr += dib->stride;
4634 glyph_ptr += glyph->stride;
4638 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4639 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4641 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4642 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4643 int x, y;
4644 DWORD text, val;
4646 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4647 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4648 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4650 for (y = rect->top; y < rect->bottom; y++)
4652 for (x = 0; x < rect->right - rect->left; x++)
4654 if (glyph_ptr[x] <= 1) continue;
4655 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4656 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4657 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4658 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4659 text, ranges + glyph_ptr[x] );
4660 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4662 dst_ptr += dib->stride / 2;
4663 glyph_ptr += glyph->stride;
4667 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4668 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4670 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4671 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4672 int x, y;
4673 DWORD text, val;
4675 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4676 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4677 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4679 for (y = rect->top; y < rect->bottom; y++)
4681 for (x = 0; x < rect->right - rect->left; x++)
4683 if (glyph_ptr[x] <= 1) continue;
4684 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4685 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4686 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4687 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4688 text, ranges + glyph_ptr[x] );
4689 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4690 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4691 put_field( val, dib->blue_shift, dib->blue_len ));
4693 dst_ptr += dib->stride / 2;
4694 glyph_ptr += glyph->stride;
4698 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4699 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4701 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4702 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4703 int x, y;
4705 for (y = rect->top; y < rect->bottom; y++)
4707 for (x = 0; x < rect->right - rect->left; x++)
4709 /* no antialiasing, glyph should only contain 0 or 16. */
4710 if (glyph_ptr[x] >= 16)
4711 dst_ptr[x] = text_pixel;
4713 dst_ptr += dib->stride;
4714 glyph_ptr += glyph->stride;
4718 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4719 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4721 BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
4722 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4723 int x, y;
4725 for (y = rect->top; y < rect->bottom; y++)
4727 for (x = rect->left; x < rect->right; x++)
4729 /* no antialiasing, glyph should only contain 0 or 16. */
4730 if (glyph_ptr[x] >= 16)
4732 if (x & 1)
4733 dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
4734 else
4735 dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
4738 dst_ptr += dib->stride;
4739 glyph_ptr += glyph->stride;
4743 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4744 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4746 BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
4747 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4748 int x, y;
4749 BYTE text = (text_pixel & 1) ? 0xff : 0;
4751 for (y = rect->top; y < rect->bottom; y++)
4753 for (x = rect->left; x < rect->right; x++)
4755 /* no antialiasing, glyph should only contain 0 or 16. */
4756 if (glyph_ptr[x] >= 16)
4757 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
4759 dst_ptr += dib->stride;
4760 glyph_ptr += glyph->stride;
4764 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4765 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4767 return;
4770 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)
4772 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4773 DWORD mask_start = 0, mask_offset;
4774 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4775 int x, y;
4777 for(y = 0; y < hatch->height; y++)
4779 hatch_ptr = hatch_start;
4780 mask_offset = mask_start;
4781 for(x = 0; x < hatch->width; x++)
4783 if(*hatch_ptr & pixel_masks_1[x % 8])
4785 and_bits[mask_offset] = fg->and;
4786 xor_bits[mask_offset] = fg->xor;
4788 else
4790 and_bits[mask_offset] = bg->and;
4791 xor_bits[mask_offset] = bg->xor;
4793 if(x % 8 == 7) hatch_ptr++;
4794 mask_offset++;
4796 hatch_start += hatch->stride;
4797 mask_start += dib->stride / 4;
4800 return TRUE;
4803 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)
4805 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4806 DWORD mask_start = 0, mask_offset;
4807 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4808 int x, y;
4810 for(y = 0; y < hatch->height; y++)
4812 hatch_ptr = hatch_start;
4813 mask_offset = mask_start;
4814 for(x = 0; x < hatch->width; x++)
4816 if(*hatch_ptr & pixel_masks_1[x % 8])
4818 and_bits[mask_offset] = fg->and & 0xff;
4819 xor_bits[mask_offset++] = fg->xor & 0xff;
4820 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4821 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4822 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4823 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4825 else
4827 and_bits[mask_offset] = bg->and & 0xff;
4828 xor_bits[mask_offset++] = bg->xor & 0xff;
4829 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4830 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4831 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4832 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4834 if(x % 8 == 7) hatch_ptr++;
4836 hatch_start += hatch->stride;
4837 mask_start += dib->stride;
4840 return TRUE;
4843 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)
4845 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4846 DWORD mask_start = 0, mask_offset;
4847 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4848 int x, y;
4850 for(y = 0; y < hatch->height; y++)
4852 hatch_ptr = hatch_start;
4853 mask_offset = mask_start;
4854 for(x = 0; x < hatch->width; x++)
4856 if(*hatch_ptr & pixel_masks_1[x % 8])
4858 and_bits[mask_offset] = fg->and;
4859 xor_bits[mask_offset] = fg->xor;
4861 else
4863 and_bits[mask_offset] = bg->and;
4864 xor_bits[mask_offset] = bg->xor;
4866 if(x % 8 == 7) hatch_ptr++;
4867 mask_offset++;
4869 hatch_start += hatch->stride;
4870 mask_start += dib->stride / 2;
4873 return TRUE;
4876 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)
4878 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4879 DWORD mask_start = 0, mask_offset;
4880 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4881 int x, y;
4883 for(y = 0; y < hatch->height; y++)
4885 hatch_ptr = hatch_start;
4886 mask_offset = mask_start;
4887 for(x = 0; x < hatch->width; x++)
4889 if(*hatch_ptr & pixel_masks_1[x % 8])
4891 and_bits[mask_offset] = fg->and;
4892 xor_bits[mask_offset] = fg->xor;
4894 else
4896 and_bits[mask_offset] = bg->and;
4897 xor_bits[mask_offset] = bg->xor;
4899 if(x % 8 == 7) hatch_ptr++;
4900 mask_offset++;
4902 hatch_start += hatch->stride;
4903 mask_start += dib->stride;
4906 return TRUE;
4909 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)
4911 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4912 DWORD mask_start = 0, mask_offset;
4913 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4914 const rop_mask *rop_mask;
4915 int x, y;
4917 for(y = 0; y < hatch->height; y++)
4919 hatch_ptr = hatch_start;
4920 mask_offset = mask_start;
4921 for(x = 0; x < hatch->width; x++)
4923 if(*hatch_ptr & pixel_masks_1[x % 8])
4924 rop_mask = fg;
4925 else
4926 rop_mask = bg;
4928 if(x & 1)
4930 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4931 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4932 mask_offset++;
4934 else
4936 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4937 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4940 if(x % 8 == 7) hatch_ptr++;
4942 hatch_start += hatch->stride;
4943 mask_start += dib->stride;
4946 return TRUE;
4949 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)
4951 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4952 DWORD mask_start = 0, mask_offset;
4953 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4954 rop_mask rop_mask;
4955 int x, y, bit_pos;
4957 for(y = 0; y < hatch->height; y++)
4959 hatch_ptr = hatch_start;
4960 mask_offset = mask_start;
4961 for(x = 0, bit_pos = 0; x < hatch->width; x++)
4963 if(*hatch_ptr & pixel_masks_1[x % 8])
4965 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4966 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4968 else
4970 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4971 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4974 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4976 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4977 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4979 if(++bit_pos == 8)
4981 mask_offset++;
4982 hatch_ptr++;
4983 bit_pos = 0;
4986 hatch_start += hatch->stride;
4987 mask_start += dib->stride;
4990 return TRUE;
4993 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)
4995 return FALSE;
4998 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
5000 switch (mode)
5002 default:
5003 case STRETCH_DELETESCANS:
5004 get_rop_codes( R2_COPYPEN, codes );
5005 break;
5006 case STRETCH_ORSCANS:
5007 get_rop_codes( R2_MERGEPEN, codes );
5008 break;
5009 case STRETCH_ANDSCANS:
5010 get_rop_codes( R2_MASKPEN, codes );
5011 break;
5013 return;
5016 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
5017 const dib_info *src_dib, const POINT *src_start,
5018 const struct stretch_params *params, int mode,
5019 BOOL keep_dst)
5021 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5022 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5023 int err = params->err_start;
5024 int width;
5025 struct rop_codes codes;
5027 rop_codes_from_stretch_mode( mode, &codes );
5028 for (width = params->length; width; width--)
5030 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5031 dst_ptr += params->dst_inc;
5032 if (err > 0)
5034 src_ptr += params->src_inc;
5035 err += params->err_add_1;
5037 else err += params->err_add_2;
5041 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
5042 const dib_info *src_dib, const POINT *src_start,
5043 const struct stretch_params *params, int mode,
5044 BOOL keep_dst)
5046 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5047 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5048 int err = params->err_start;
5049 int width;
5050 struct rop_codes codes;
5052 rop_codes_from_stretch_mode( mode, &codes );
5053 for (width = params->length; width; width--)
5055 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5056 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5057 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5058 dst_ptr += 3 * params->dst_inc;
5059 if (err > 0)
5061 src_ptr += 3 * params->src_inc;
5062 err += params->err_add_1;
5064 else err += params->err_add_2;
5068 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
5069 const dib_info *src_dib, const POINT *src_start,
5070 const struct stretch_params *params, int mode,
5071 BOOL keep_dst)
5073 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5074 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5075 int err = params->err_start;
5076 int width;
5077 struct rop_codes codes;
5079 rop_codes_from_stretch_mode( mode, &codes );
5080 for (width = params->length; width; width--)
5082 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5083 dst_ptr += params->dst_inc;
5084 if (err > 0)
5086 src_ptr += params->src_inc;
5087 err += params->err_add_1;
5089 else err += params->err_add_2;
5093 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
5094 const dib_info *src_dib, const POINT *src_start,
5095 const struct stretch_params *params, int mode,
5096 BOOL keep_dst)
5098 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5099 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5100 int err = params->err_start;
5101 int width;
5102 struct rop_codes codes;
5104 rop_codes_from_stretch_mode( mode, &codes );
5105 for (width = params->length; width; width--)
5107 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5108 dst_ptr += params->dst_inc;
5109 if (err > 0)
5111 src_ptr += params->src_inc;
5112 err += params->err_add_1;
5114 else err += params->err_add_2;
5118 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
5119 const dib_info *src_dib, const POINT *src_start,
5120 const struct stretch_params *params, int mode,
5121 BOOL keep_dst)
5123 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
5124 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
5125 int err = params->err_start;
5126 int width, dst_x = dst_start->x, src_x = src_start->x;
5127 struct rop_codes codes;
5128 BYTE src_val;
5130 rop_codes_from_stretch_mode( mode, &codes );
5131 for (width = params->length; width; width--)
5133 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5134 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5136 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
5138 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5139 dst_ptr += params->dst_inc;
5140 dst_x += params->dst_inc;
5142 if (err > 0)
5144 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5145 src_ptr += params->src_inc;
5146 src_x += params->src_inc;
5147 err += params->err_add_1;
5149 else err += params->err_add_2;
5153 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
5154 const dib_info *src_dib, const POINT *src_start,
5155 const struct stretch_params *params, int mode,
5156 BOOL keep_dst)
5158 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5159 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5160 int err = params->err_start;
5161 int width, dst_x = dst_start->x, src_x = src_start->x;
5162 struct rop_codes codes;
5163 BYTE src_val;
5165 rop_codes_from_stretch_mode( mode, &codes );
5166 for (width = params->length; width; width--)
5168 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5169 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5171 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5172 dst_ptr += params->dst_inc;
5173 dst_x += params->dst_inc;
5175 if (err > 0)
5177 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5178 src_ptr += params->src_inc;
5179 src_x += params->src_inc;
5180 err += params->err_add_1;
5182 else err += params->err_add_2;
5186 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
5187 const dib_info *src_dib, const POINT *src_start,
5188 const struct stretch_params *params, int mode,
5189 BOOL keep_dst)
5191 FIXME("bit count %d\n", dst_dib->bit_count);
5192 return;
5195 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
5196 const dib_info *src_dib, const POINT *src_start,
5197 const struct stretch_params *params, int mode,
5198 BOOL keep_dst)
5200 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
5201 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
5202 int err = params->err_start;
5203 int width;
5204 struct rop_codes codes;
5205 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5206 BOOL new_pix = TRUE;
5208 rop_codes_from_stretch_mode( mode, &codes );
5209 for (width = params->length; width; width--)
5211 if (new_pix && !keep_dst) *dst_ptr = init_val;
5212 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
5213 new_pix = FALSE;
5214 src_ptr += params->src_inc;
5215 if (err > 0)
5217 dst_ptr += params->dst_inc;
5218 new_pix = TRUE;
5219 err += params->err_add_1;
5221 else err += params->err_add_2;
5225 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
5226 const dib_info *src_dib, const POINT *src_start,
5227 const struct stretch_params *params, int mode,
5228 BOOL keep_dst)
5230 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
5231 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
5232 int err = params->err_start;
5233 int width;
5234 struct rop_codes codes;
5235 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5236 BOOL new_pix = TRUE;
5238 rop_codes_from_stretch_mode( mode, &codes );
5239 for (width = params->length; width; width--)
5241 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5242 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5243 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5244 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5245 new_pix = FALSE;
5246 src_ptr += 3 * params->src_inc;
5247 if (err > 0)
5249 dst_ptr += 3 * params->dst_inc;
5250 new_pix = TRUE;
5251 err += params->err_add_1;
5253 else err += params->err_add_2;
5257 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5258 const dib_info *src_dib, const POINT *src_start,
5259 const struct stretch_params *params, int mode,
5260 BOOL keep_dst)
5262 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5263 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5264 int err = params->err_start;
5265 int width;
5266 struct rop_codes codes;
5267 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5268 BOOL new_pix = TRUE;
5270 rop_codes_from_stretch_mode( mode, &codes );
5271 for (width = params->length; width; width--)
5273 if (new_pix && !keep_dst) *dst_ptr = init_val;
5274 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5275 new_pix = FALSE;
5276 src_ptr += params->src_inc;
5277 if (err > 0)
5279 dst_ptr += params->dst_inc;
5280 new_pix = TRUE;
5281 err += params->err_add_1;
5283 else err += params->err_add_2;
5287 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5288 const dib_info *src_dib, const POINT *src_start,
5289 const struct stretch_params *params, int mode,
5290 BOOL keep_dst)
5292 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5293 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5294 int err = params->err_start;
5295 int width;
5296 struct rop_codes codes;
5297 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5298 BOOL new_pix = TRUE;
5300 rop_codes_from_stretch_mode( mode, &codes );
5301 for (width = params->length; width; width--)
5303 if (new_pix && !keep_dst) *dst_ptr = init_val;
5304 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5305 new_pix = FALSE;
5306 src_ptr += params->src_inc;
5307 if (err > 0)
5309 dst_ptr += params->dst_inc;
5310 new_pix = TRUE;
5311 err += params->err_add_1;
5313 else err += params->err_add_2;
5317 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5318 const dib_info *src_dib, const POINT *src_start,
5319 const struct stretch_params *params, int mode,
5320 BOOL keep_dst)
5322 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5323 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5324 int err = params->err_start;
5325 int width, dst_x = dst_start->x, src_x = src_start->x;
5326 struct rop_codes codes;
5327 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5328 BOOL new_pix = TRUE;
5330 rop_codes_from_stretch_mode( mode, &codes );
5331 for (width = params->length; width; width--)
5333 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
5335 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5336 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5338 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
5339 new_pix = FALSE;
5341 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5342 src_ptr += params->src_inc;
5343 src_x += params->src_inc;
5345 if (err > 0)
5347 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5348 dst_ptr += params->dst_inc;
5349 dst_x += params->dst_inc;
5350 new_pix = TRUE;
5351 err += params->err_add_1;
5353 else err += params->err_add_2;
5357 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5358 const dib_info *src_dib, const POINT *src_start,
5359 const struct stretch_params *params, int mode,
5360 BOOL keep_dst)
5362 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5363 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5364 int err = params->err_start;
5365 int width, dst_x = dst_start->x, src_x = src_start->x;
5366 struct rop_codes codes;
5367 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5368 BOOL new_pix = TRUE;
5370 rop_codes_from_stretch_mode( mode, &codes );
5371 for (width = params->length; width; width--)
5373 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5374 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5375 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5376 new_pix = FALSE;
5378 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5379 src_ptr += params->src_inc;
5380 src_x += params->src_inc;
5382 if (err > 0)
5384 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5385 dst_ptr += params->dst_inc;
5386 dst_x += params->dst_inc;
5387 new_pix = TRUE;
5388 err += params->err_add_1;
5390 else err += params->err_add_2;
5394 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5395 const dib_info *src_dib, const POINT *src_start,
5396 const struct stretch_params *params, int mode,
5397 BOOL keep_dst)
5399 FIXME("bit count %d\n", dst_dib->bit_count);
5400 return;
5403 const primitive_funcs funcs_8888 =
5405 solid_rects_32,
5406 solid_line_32,
5407 pattern_rects_32,
5408 copy_rect_32,
5409 blend_rect_8888,
5410 gradient_rect_8888,
5411 draw_glyph_8888,
5412 get_pixel_32,
5413 colorref_to_pixel_888,
5414 pixel_to_colorref_888,
5415 convert_to_8888,
5416 create_rop_masks_32,
5417 stretch_row_32,
5418 shrink_row_32
5421 const primitive_funcs funcs_32 =
5423 solid_rects_32,
5424 solid_line_32,
5425 pattern_rects_32,
5426 copy_rect_32,
5427 blend_rect_32,
5428 gradient_rect_32,
5429 draw_glyph_32,
5430 get_pixel_32,
5431 colorref_to_pixel_masks,
5432 pixel_to_colorref_masks,
5433 convert_to_32,
5434 create_rop_masks_32,
5435 stretch_row_32,
5436 shrink_row_32
5439 const primitive_funcs funcs_24 =
5441 solid_rects_24,
5442 solid_line_24,
5443 pattern_rects_24,
5444 copy_rect_24,
5445 blend_rect_24,
5446 gradient_rect_24,
5447 draw_glyph_24,
5448 get_pixel_24,
5449 colorref_to_pixel_888,
5450 pixel_to_colorref_888,
5451 convert_to_24,
5452 create_rop_masks_24,
5453 stretch_row_24,
5454 shrink_row_24
5457 const primitive_funcs funcs_555 =
5459 solid_rects_16,
5460 solid_line_16,
5461 pattern_rects_16,
5462 copy_rect_16,
5463 blend_rect_555,
5464 gradient_rect_555,
5465 draw_glyph_555,
5466 get_pixel_16,
5467 colorref_to_pixel_555,
5468 pixel_to_colorref_555,
5469 convert_to_555,
5470 create_rop_masks_16,
5471 stretch_row_16,
5472 shrink_row_16
5475 const primitive_funcs funcs_16 =
5477 solid_rects_16,
5478 solid_line_16,
5479 pattern_rects_16,
5480 copy_rect_16,
5481 blend_rect_16,
5482 gradient_rect_16,
5483 draw_glyph_16,
5484 get_pixel_16,
5485 colorref_to_pixel_masks,
5486 pixel_to_colorref_masks,
5487 convert_to_16,
5488 create_rop_masks_16,
5489 stretch_row_16,
5490 shrink_row_16
5493 const primitive_funcs funcs_8 =
5495 solid_rects_8,
5496 solid_line_8,
5497 pattern_rects_8,
5498 copy_rect_8,
5499 blend_rect_8,
5500 gradient_rect_8,
5501 draw_glyph_8,
5502 get_pixel_8,
5503 colorref_to_pixel_colortable,
5504 pixel_to_colorref_colortable,
5505 convert_to_8,
5506 create_rop_masks_8,
5507 stretch_row_8,
5508 shrink_row_8
5511 const primitive_funcs funcs_4 =
5513 solid_rects_4,
5514 solid_line_4,
5515 pattern_rects_4,
5516 copy_rect_4,
5517 blend_rect_4,
5518 gradient_rect_4,
5519 draw_glyph_4,
5520 get_pixel_4,
5521 colorref_to_pixel_colortable,
5522 pixel_to_colorref_colortable,
5523 convert_to_4,
5524 create_rop_masks_4,
5525 stretch_row_4,
5526 shrink_row_4
5529 const primitive_funcs funcs_1 =
5531 solid_rects_1,
5532 solid_line_1,
5533 pattern_rects_1,
5534 copy_rect_1,
5535 blend_rect_1,
5536 gradient_rect_1,
5537 draw_glyph_1,
5538 get_pixel_1,
5539 colorref_to_pixel_colortable,
5540 pixel_to_colorref_colortable,
5541 convert_to_1,
5542 create_rop_masks_1,
5543 stretch_row_1,
5544 shrink_row_1
5547 const primitive_funcs funcs_null =
5549 solid_rects_null,
5550 solid_line_null,
5551 pattern_rects_null,
5552 copy_rect_null,
5553 blend_rect_null,
5554 gradient_rect_null,
5555 draw_glyph_null,
5556 get_pixel_null,
5557 colorref_to_pixel_null,
5558 pixel_to_colorref_null,
5559 convert_to_null,
5560 create_rop_masks_null,
5561 stretch_row_null,
5562 shrink_row_null