gdi32: Implement rectangular gradients in the DIB engine.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blobe882b8ac1d85f809ce8e2d74b9987261a7441785
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 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
32 return (DWORD *)((BYTE*)dib->bits.ptr + y * dib->stride + x * 4);
35 static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
37 return (DWORD *)((BYTE*)dib->bits.ptr + y * dib->stride) + x * 3 / 4;
40 static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
42 return (BYTE*)dib->bits.ptr + y * dib->stride + x * 3;
45 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
47 return (WORD *)((BYTE*)dib->bits.ptr + y * dib->stride + x * 2);
50 static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
52 return (BYTE*)dib->bits.ptr + y * dib->stride + x;
55 static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
57 return (BYTE*)dib->bits.ptr + y * dib->stride + x / 2;
60 static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
62 return (BYTE*)dib->bits.ptr + y * dib->stride + x / 8;
65 static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
66 static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
68 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
70 *ptr = (*ptr & and) ^ xor;
73 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
75 *ptr = (*ptr & and) ^ xor;
78 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
80 *ptr = (*ptr & and) ^ xor;
83 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
85 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
88 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
90 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
93 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
95 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
98 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
100 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
103 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
105 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
108 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
110 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
113 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
115 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
116 do_rop_codes_32( dst, *src, codes );
119 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
121 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
124 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
126 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
127 do_rop_codes_16( dst, *src, codes );
130 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
132 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
135 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
137 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
138 do_rop_codes_8( dst, *src, codes );
141 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
142 struct rop_codes *codes, int len)
144 BYTE src_val;
146 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
148 if (dst_x & 1)
150 if (src_x & 1) src_val = *src++;
151 else src_val = *src >> 4;
152 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
154 else
156 if (src_x & 1) src_val = *src++ << 4;
157 else src_val = *src;
158 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
163 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
164 struct rop_codes *codes, int len)
166 BYTE src_val;
168 src_x += len - 1;
169 dst_x += len - 1;
170 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
172 if (dst_x & 1)
174 if (src_x & 1) src_val = *src;
175 else src_val = *src-- >> 4;
176 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
178 else
180 if (src_x & 1) src_val = *src << 4;
181 else src_val = *src--;
182 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
187 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
188 struct rop_codes *codes, int len)
190 BYTE src_val;
192 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
194 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
195 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
196 if ((src_x & 7) == 7) src++;
197 if ((dst_x & 7) == 7) dst++;
201 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
202 struct rop_codes *codes, int len)
204 BYTE src_val;
206 src_x += len - 1;
207 dst_x += len - 1;
208 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
210 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
211 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
212 if ((src_x & 7) == 0) src--;
213 if ((dst_x & 7) == 0) dst--;
217 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
219 DWORD *ptr, *start;
220 int x, y, i;
222 for(i = 0; i < num; i++, rc++)
224 start = get_pixel_ptr_32(dib, rc->left, rc->top);
225 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
226 for(x = rc->left, ptr = start; x < rc->right; x++)
227 do_rop_32(ptr++, and, xor);
231 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
233 DWORD *ptr, *start;
234 BYTE *byte_ptr, *byte_start;
235 int x, y, i;
236 DWORD and_masks[3], xor_masks[3];
238 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
239 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
240 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
241 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
242 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
243 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
245 for(i = 0; i < num; i++, rc++)
247 if(rc->left >= rc->right) continue;
249 if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
251 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
252 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
254 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
256 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
257 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
258 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
262 else
264 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
265 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
267 ptr = start;
269 switch(rc->left & 3)
271 case 1:
272 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
273 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
274 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
275 break;
276 case 2:
277 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
278 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
279 break;
280 case 3:
281 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
282 break;
285 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
287 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
288 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
289 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
292 switch(rc->right & 3)
294 case 1:
295 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
296 break;
297 case 2:
298 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
299 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
300 break;
301 case 3:
302 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
303 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
304 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
305 break;
312 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
314 WORD *ptr, *start;
315 int x, y, i;
317 for(i = 0; i < num; i++, rc++)
319 start = get_pixel_ptr_16(dib, rc->left, rc->top);
320 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
321 for(x = rc->left, ptr = start; x < rc->right; x++)
322 do_rop_16(ptr++, and, xor);
326 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
328 BYTE *ptr, *start;
329 int x, y, i;
331 for(i = 0; i < num; i++, rc++)
333 start = get_pixel_ptr_8(dib, rc->left, rc->top);
334 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
335 for(x = rc->left, ptr = start; x < rc->right; x++)
336 do_rop_8(ptr++, and, xor);
340 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
342 BYTE *ptr, *start;
343 int x, y, i;
344 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
345 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
347 for(i = 0; i < num; i++, rc++)
349 if(rc->left >= rc->right) continue;
350 start = get_pixel_ptr_4(dib, rc->left, rc->top);
351 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
353 ptr = start;
354 if(rc->left & 1) /* upper nibble untouched */
355 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
357 for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
358 do_rop_8(ptr++, byte_and, byte_xor);
360 if(rc->right & 1) /* lower nibble untouched */
361 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
366 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
368 BYTE *ptr, *start;
369 int x, y, i;
370 BYTE byte_and = (and & 1) ? 0xff : 0;
371 BYTE byte_xor = (xor & 1) ? 0xff : 0;
372 BYTE start_and, start_xor, end_and, end_xor, mask;
373 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
375 for(i = 0; i < num; i++, rc++)
377 if(rc->left >= rc->right) continue;
379 start = get_pixel_ptr_1(dib, rc->left, rc->top);
381 if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
383 mask = masks[rc->left & 7] & ~masks[rc->right & 7];
385 start_and = byte_and | ~mask;
386 start_xor = byte_xor & mask;
387 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
389 do_rop_8(start, start_and, start_xor);
392 else
394 mask = masks[rc->left & 7];
395 start_and = byte_and | ~mask;
396 start_xor = byte_xor & mask;
398 mask = masks[rc->right & 7];
399 /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
400 end_and = byte_and | mask;
401 end_xor = byte_xor & ~mask;
403 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
405 ptr = start;
407 if(rc->left & 7)
408 do_rop_8(ptr++, start_and, start_xor);
410 for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
411 do_rop_8(ptr++, byte_and, byte_xor);
413 if(rc->right & 7)
414 do_rop_8(ptr, end_and, end_xor);
420 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
422 return;
425 static void solid_line_32(const dib_info *dib, const POINT *start, const struct line_params *params,
426 DWORD and, DWORD xor)
428 DWORD *ptr = get_pixel_ptr_32( dib, start->x, start->y );
429 int len = params->length, err = params->err_start;
430 int major_inc, minor_inc;
432 if (params->x_major)
434 major_inc = params->x_inc;
435 minor_inc = (dib->stride * params->y_inc) / 4;
437 else
439 major_inc = (dib->stride * params->y_inc) / 4;
440 minor_inc = params->x_inc;
443 while (len--)
445 do_rop_32( ptr, and, xor );
446 if (err + params->bias > 0)
448 ptr += minor_inc;
449 err += params->err_add_1;
451 else err += params->err_add_2;
452 ptr += major_inc;
456 static void solid_line_24(const dib_info *dib, const POINT *start, const struct line_params *params,
457 DWORD and, DWORD xor)
459 BYTE *ptr = get_pixel_ptr_24( dib, start->x, start->y );
460 int len = params->length, err = params->err_start;
461 int major_inc, minor_inc;
463 if (params->x_major)
465 major_inc = params->x_inc * 3;
466 minor_inc = dib->stride * params->y_inc;
468 else
470 major_inc = dib->stride * params->y_inc;
471 minor_inc = params->x_inc * 3;
474 while (len--)
476 do_rop_8( ptr, and, xor );
477 do_rop_8( ptr + 1, and >> 8, xor >> 8 );
478 do_rop_8( ptr + 2, and >> 16, xor >> 16 );
479 if (err + params->bias > 0)
481 ptr += minor_inc;
482 err += params->err_add_1;
484 else err += params->err_add_2;
485 ptr += major_inc;
489 static void solid_line_16(const dib_info *dib, const POINT *start, const struct line_params *params,
490 DWORD and, DWORD xor)
492 WORD *ptr = get_pixel_ptr_16( dib, start->x, start->y );
493 int len = params->length, err = params->err_start;
494 int major_inc, minor_inc;
496 if (params->x_major)
498 major_inc = params->x_inc;
499 minor_inc = (dib->stride * params->y_inc) / 2;
501 else
503 major_inc = (dib->stride * params->y_inc) / 2;
504 minor_inc = params->x_inc;
507 while (len--)
509 do_rop_16( ptr, and, xor );
510 if (err + params->bias > 0)
512 ptr += minor_inc;
513 err += params->err_add_1;
515 else err += params->err_add_2;
516 ptr += major_inc;
520 static void solid_line_8(const dib_info *dib, const POINT *start, const struct line_params *params,
521 DWORD and, DWORD xor)
523 BYTE *ptr = get_pixel_ptr_8( dib, start->x, start->y );
524 int len = params->length, err = params->err_start;
525 int major_inc, minor_inc;
527 if (params->x_major)
529 major_inc = params->x_inc;
530 minor_inc = dib->stride * params->y_inc;
532 else
534 major_inc = dib->stride * params->y_inc;
535 minor_inc = params->x_inc;
538 while (len--)
540 do_rop_8( ptr, and, xor );
541 if (err + params->bias > 0)
543 ptr += minor_inc;
544 err += params->err_add_1;
546 else err += params->err_add_2;
547 ptr += major_inc;
551 static void solid_line_4(const dib_info *dib, const POINT *start, const struct line_params *params,
552 DWORD and, DWORD xor)
554 BYTE *ptr = get_pixel_ptr_4( dib, start->x, start->y );
555 int len = params->length, err = params->err_start;
556 int x = start->x;
558 and = (and & 0x0f) | ((and << 4) & 0xf0);
559 xor = (xor & 0x0f) | ((xor << 4) & 0xf0);
561 if (params->x_major)
563 while (len--)
565 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
566 if (err + params->bias > 0)
568 ptr += dib->stride * params->y_inc;
569 err += params->err_add_1;
571 else err += params->err_add_2;
572 if ((x / 2) != ((x + params->x_inc) / 2))
573 ptr += params->x_inc;
574 x += params->x_inc;
577 else
579 while (len--)
581 do_rop_mask_8( ptr, and, xor, pixel_masks_4[ x % 2 ] );
582 if (err + params->bias > 0)
584 if ((x / 2) != ((x + params->x_inc) / 2))
585 ptr += params->x_inc;
586 x += params->x_inc;
587 err += params->err_add_1;
589 else err += params->err_add_2;
590 ptr += dib->stride * params->y_inc;
595 static void solid_line_1(const dib_info *dib, const POINT *start, const struct line_params *params,
596 DWORD and, DWORD xor)
598 BYTE *ptr = get_pixel_ptr_1( dib, start->x, start->y );
599 int len = params->length, err = params->err_start;
600 int x = start->x;
602 and = (and & 0x1) ? 0xff : 0;
603 xor = (xor & 0x1) ? 0xff : 0;
605 if (params->x_major)
607 while (len--)
609 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
610 if (err + params->bias > 0)
612 ptr += dib->stride * params->y_inc;
613 err += params->err_add_1;
615 else err += params->err_add_2;
616 if ((x / 8) != ((x + params->x_inc) / 8))
617 ptr += params->x_inc;
618 x += params->x_inc;
621 else
623 while (len--)
625 do_rop_mask_8( ptr, and, xor, pixel_masks_1[ x % 8 ] );
626 if (err + params->bias > 0)
628 if ((x / 8) != ((x + params->x_inc) / 8))
629 ptr += params->x_inc;
630 x += params->x_inc;
631 err += params->err_add_1;
633 else err += params->err_add_2;
634 ptr += dib->stride * params->y_inc;
639 static void solid_line_null(const dib_info *dib, const POINT *start, const struct line_params *params,
640 DWORD and, DWORD xor)
642 return;
645 static inline INT calc_offset(INT edge, INT size, INT origin)
647 INT offset;
649 if(edge - origin >= 0)
650 offset = (edge - origin) % size;
651 else
653 offset = (origin - edge) % size;
654 if(offset) offset = size - offset;
656 return offset;
659 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
661 POINT offset;
663 offset.x = calc_offset(rc->left, brush->width, origin->x);
664 offset.y = calc_offset(rc->top, brush->height, origin->y);
666 return offset;
669 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
670 const dib_info *brush, void *and_bits, void *xor_bits)
672 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
673 int x, y, i;
674 POINT offset;
676 for(i = 0; i < num; i++, rc++)
678 offset = calc_brush_offset(rc, brush, origin);
680 start = get_pixel_ptr_32(dib, rc->left, rc->top);
681 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
682 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
684 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
686 and_ptr = start_and + offset.x;
687 xor_ptr = start_xor + offset.x;
689 for(x = rc->left, ptr = start; x < rc->right; x++)
691 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
692 if(and_ptr == start_and + brush->width)
694 and_ptr = start_and;
695 xor_ptr = start_xor;
699 offset.y++;
700 if(offset.y == brush->height)
702 start_and = and_bits;
703 start_xor = xor_bits;
704 offset.y = 0;
706 else
708 start_and += brush->stride / 4;
709 start_xor += brush->stride / 4;
715 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
716 const dib_info *brush, void *and_bits, void *xor_bits)
718 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
719 int x, y, i;
720 POINT offset;
722 for(i = 0; i < num; i++, rc++)
724 offset = calc_brush_offset(rc, brush, origin);
726 start = get_pixel_ptr_24(dib, rc->left, rc->top);
727 start_and = (BYTE*)and_bits + offset.y * brush->stride;
728 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
730 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
732 and_ptr = start_and + offset.x * 3;
733 xor_ptr = start_xor + offset.x * 3;
735 for(x = rc->left, ptr = start; x < rc->right; x++)
737 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
738 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
739 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
740 if(and_ptr == start_and + brush->width * 3)
742 and_ptr = start_and;
743 xor_ptr = start_xor;
747 offset.y++;
748 if(offset.y == brush->height)
750 start_and = and_bits;
751 start_xor = xor_bits;
752 offset.y = 0;
754 else
756 start_and += brush->stride;
757 start_xor += brush->stride;
763 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
764 const dib_info *brush, void *and_bits, void *xor_bits)
766 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
767 int x, y, i;
768 POINT offset;
770 for(i = 0; i < num; i++, rc++)
772 offset = calc_brush_offset(rc, brush, origin);
774 start = get_pixel_ptr_16(dib, rc->left, rc->top);
775 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
776 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
778 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
780 and_ptr = start_and + offset.x;
781 xor_ptr = start_xor + offset.x;
783 for(x = rc->left, ptr = start; x < rc->right; x++)
785 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
786 if(and_ptr == start_and + brush->width)
788 and_ptr = start_and;
789 xor_ptr = start_xor;
793 offset.y++;
794 if(offset.y == brush->height)
796 start_and = and_bits;
797 start_xor = xor_bits;
798 offset.y = 0;
800 else
802 start_and += brush->stride / 2;
803 start_xor += brush->stride / 2;
809 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
810 const dib_info *brush, void *and_bits, void *xor_bits)
812 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
813 int x, y, i;
814 POINT offset;
816 for(i = 0; i < num; i++, rc++)
818 offset = calc_brush_offset(rc, brush, origin);
820 start = get_pixel_ptr_8(dib, rc->left, rc->top);
821 start_and = (BYTE*)and_bits + offset.y * brush->stride;
822 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
824 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
826 and_ptr = start_and + offset.x;
827 xor_ptr = start_xor + offset.x;
829 for(x = rc->left, ptr = start; x < rc->right; x++)
831 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
832 if(and_ptr == start_and + brush->width)
834 and_ptr = start_and;
835 xor_ptr = start_xor;
839 offset.y++;
840 if(offset.y == brush->height)
842 start_and = and_bits;
843 start_xor = xor_bits;
844 offset.y = 0;
846 else
848 start_and += brush->stride;
849 start_xor += brush->stride;
855 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
856 const dib_info *brush, void *and_bits, void *xor_bits)
858 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
859 int x, y, i;
860 POINT offset;
862 for(i = 0; i < num; i++, rc++)
864 offset = calc_brush_offset(rc, brush, origin);
866 start = get_pixel_ptr_4(dib, rc->left, rc->top);
867 start_and = (BYTE*)and_bits + offset.y * brush->stride;
868 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
870 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
872 INT brush_x = offset.x;
873 BYTE byte_and, byte_xor;
875 and_ptr = start_and + brush_x / 2;
876 xor_ptr = start_xor + brush_x / 2;
878 for(x = rc->left, ptr = start; x < rc->right; x++)
880 /* FIXME: Two pixels at a time */
881 if(x & 1) /* lower dst nibble */
883 if(brush_x & 1) /* lower pat nibble */
885 byte_and = *and_ptr++ | 0xf0;
886 byte_xor = *xor_ptr++ & 0x0f;
888 else /* upper pat nibble */
890 byte_and = (*and_ptr >> 4) | 0xf0;
891 byte_xor = (*xor_ptr >> 4) & 0x0f;
894 else /* upper dst nibble */
896 if(brush_x & 1) /* lower pat nibble */
898 byte_and = (*and_ptr++ << 4) | 0x0f;
899 byte_xor = (*xor_ptr++ << 4) & 0xf0;
901 else /* upper pat nibble */
903 byte_and = *and_ptr | 0x0f;
904 byte_xor = *xor_ptr & 0xf0;
907 do_rop_8(ptr, byte_and, byte_xor);
909 if(x & 1) ptr++;
911 if(++brush_x == brush->width)
913 brush_x = 0;
914 and_ptr = start_and;
915 xor_ptr = start_xor;
919 offset.y++;
920 if(offset.y == brush->height)
922 start_and = and_bits;
923 start_xor = xor_bits;
924 offset.y = 0;
926 else
928 start_and += brush->stride;
929 start_xor += brush->stride;
935 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
936 const dib_info *brush, void *and_bits, void *xor_bits)
938 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
939 int x, y, i;
940 POINT offset;
942 for(i = 0; i < num; i++, rc++)
944 offset = calc_brush_offset(rc, brush, origin);
946 start = get_pixel_ptr_1(dib, rc->left, rc->top);
947 start_and = (BYTE*)and_bits + offset.y * brush->stride;
948 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
950 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
952 INT brush_x = offset.x;
953 BYTE byte_and, byte_xor;
955 and_ptr = start_and + brush_x / 8;
956 xor_ptr = start_xor + brush_x / 8;
958 for(x = rc->left, ptr = start; x < rc->right; x++)
960 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
961 byte_and |= ~pixel_masks_1[x % 8];
962 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
963 byte_xor &= pixel_masks_1[x % 8];
965 do_rop_8(ptr, byte_and, byte_xor);
967 if((x & 7) == 7) ptr++;
969 if((brush_x & 7) == 7)
971 and_ptr++;
972 xor_ptr++;
975 if(++brush_x == brush->width)
977 brush_x = 0;
978 and_ptr = start_and;
979 xor_ptr = start_xor;
983 offset.y++;
984 if(offset.y == brush->height)
986 start_and = and_bits;
987 start_xor = xor_bits;
988 offset.y = 0;
990 else
992 start_and += brush->stride;
993 start_xor += brush->stride;
999 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
1000 const dib_info *brush, void *and_bits, void *xor_bits)
1002 return;
1005 static void copy_rect_32(const dib_info *dst, const RECT *rc,
1006 const dib_info *src, const POINT *origin, int rop2, int overlap)
1008 DWORD *dst_start, *src_start;
1009 struct rop_codes codes;
1010 int y, dst_stride, src_stride;
1012 if (overlap & OVERLAP_BELOW)
1014 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
1015 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1016 dst_stride = -dst->stride / 4;
1017 src_stride = -src->stride / 4;
1019 else
1021 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
1022 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
1023 dst_stride = dst->stride / 4;
1024 src_stride = src->stride / 4;
1027 if (rop2 == R2_COPYPEN)
1029 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1030 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
1031 return;
1034 get_rop_codes( rop2, &codes );
1035 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1037 if (overlap & OVERLAP_RIGHT)
1038 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
1039 else
1040 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
1044 static void copy_rect_24(const dib_info *dst, const RECT *rc,
1045 const dib_info *src, const POINT *origin, int rop2, int overlap)
1047 BYTE *dst_start, *src_start;
1048 int y, dst_stride, src_stride;
1049 struct rop_codes codes;
1051 if (overlap & OVERLAP_BELOW)
1053 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
1054 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1055 dst_stride = -dst->stride;
1056 src_stride = -src->stride;
1058 else
1060 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
1061 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
1062 dst_stride = dst->stride;
1063 src_stride = src->stride;
1066 if (rop2 == R2_COPYPEN)
1068 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1069 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
1070 return;
1073 get_rop_codes( rop2, &codes );
1074 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1076 if (overlap & OVERLAP_RIGHT)
1077 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1078 else
1079 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
1083 static void copy_rect_16(const dib_info *dst, const RECT *rc,
1084 const dib_info *src, const POINT *origin, int rop2, int overlap)
1086 WORD *dst_start, *src_start;
1087 int y, dst_stride, src_stride;
1088 struct rop_codes codes;
1090 if (overlap & OVERLAP_BELOW)
1092 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
1093 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1094 dst_stride = -dst->stride / 2;
1095 src_stride = -src->stride / 2;
1097 else
1099 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
1100 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
1101 dst_stride = dst->stride / 2;
1102 src_stride = src->stride / 2;
1105 if (rop2 == R2_COPYPEN)
1107 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1108 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
1109 return;
1112 get_rop_codes( rop2, &codes );
1113 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1115 if (overlap & OVERLAP_RIGHT)
1116 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
1117 else
1118 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
1122 static void copy_rect_8(const dib_info *dst, const RECT *rc,
1123 const dib_info *src, const POINT *origin, int rop2, int overlap)
1125 BYTE *dst_start, *src_start;
1126 int y, dst_stride, src_stride;
1127 struct rop_codes codes;
1129 if (overlap & OVERLAP_BELOW)
1131 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
1132 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
1133 dst_stride = -dst->stride;
1134 src_stride = -src->stride;
1136 else
1138 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
1139 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
1140 dst_stride = dst->stride;
1141 src_stride = src->stride;
1144 if (rop2 == R2_COPYPEN)
1146 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1147 memmove( dst_start, src_start, (rc->right - rc->left) );
1148 return;
1151 get_rop_codes( rop2, &codes );
1152 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1154 if (overlap & OVERLAP_RIGHT)
1155 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
1156 else
1157 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
1161 static void copy_rect_4(const dib_info *dst, const RECT *rc,
1162 const dib_info *src, const POINT *origin, int rop2, int overlap)
1164 BYTE *dst_start, *src_start;
1165 int y, dst_stride, src_stride;
1166 struct rop_codes codes;
1168 if (overlap & OVERLAP_BELOW)
1170 dst_start = get_pixel_ptr_4(dst, 0, rc->bottom - 1);
1171 src_start = get_pixel_ptr_4(src, 0, origin->y + rc->bottom - rc->top - 1);
1172 dst_stride = -dst->stride;
1173 src_stride = -src->stride;
1175 else
1177 dst_start = get_pixel_ptr_4(dst, 0, rc->top);
1178 src_start = get_pixel_ptr_4(src, 0, origin->y);
1179 dst_stride = dst->stride;
1180 src_stride = src->stride;
1183 if (rop2 == R2_COPYPEN && (rc->left & 1) == 0 && (origin->x & 1) == 0 && (rc->right & 1) == 0)
1185 dst_start += rc->left / 2;
1186 src_start += origin->x / 2;
1187 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1188 memmove( dst_start, src_start, (rc->right - rc->left) / 2 );
1189 return;
1192 get_rop_codes( rop2, &codes );
1193 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1195 if (overlap & OVERLAP_RIGHT)
1196 do_rop_codes_line_rev_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1197 else
1198 do_rop_codes_line_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1202 static void copy_rect_1(const dib_info *dst, const RECT *rc,
1203 const dib_info *src, const POINT *origin, int rop2, int overlap)
1205 BYTE *dst_start, *src_start;
1206 int y, dst_stride, src_stride;
1207 struct rop_codes codes;
1209 if (overlap & OVERLAP_BELOW)
1211 dst_start = get_pixel_ptr_1(dst, 0, rc->bottom - 1);
1212 src_start = get_pixel_ptr_1(src, 0, origin->y + rc->bottom - rc->top - 1);
1213 dst_stride = -dst->stride;
1214 src_stride = -src->stride;
1216 else
1218 dst_start = get_pixel_ptr_1(dst, 0, rc->top);
1219 src_start = get_pixel_ptr_1(src, 0, origin->y);
1220 dst_stride = dst->stride;
1221 src_stride = src->stride;
1224 if (rop2 == R2_COPYPEN && (rc->left & 7) == 0 && (origin->x & 7) == 0 && (rc->right & 7) == 0)
1226 dst_start += rc->left / 8;
1227 src_start += origin->x / 8;
1228 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1229 memmove( dst_start, src_start, (rc->right - rc->left) / 8 );
1230 return;
1233 get_rop_codes( rop2, &codes );
1234 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1236 if (overlap & OVERLAP_RIGHT)
1237 do_rop_codes_line_rev_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1238 else
1239 do_rop_codes_line_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1243 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1244 const dib_info *src, const POINT *origin, int rop2, int overlap)
1246 return;
1249 static DWORD get_pixel_32(const dib_info *dib, const POINT *pt)
1251 DWORD *ptr = get_pixel_ptr_32( dib, pt->x, pt->y );
1252 return *ptr;
1255 static DWORD get_pixel_24(const dib_info *dib, const POINT *pt)
1257 BYTE *ptr = get_pixel_ptr_24( dib, pt->x, pt->y );
1258 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1261 static DWORD get_pixel_16(const dib_info *dib, const POINT *pt)
1263 WORD *ptr = get_pixel_ptr_16( dib, pt->x, pt->y );
1264 return *ptr;
1267 static DWORD get_pixel_8(const dib_info *dib, const POINT *pt)
1269 BYTE *ptr = get_pixel_ptr_8( dib, pt->x, pt->y );
1270 return *ptr;
1273 static DWORD get_pixel_4(const dib_info *dib, const POINT *pt)
1275 BYTE *ptr = get_pixel_ptr_4( dib, pt->x, pt->y );
1277 if (pt->x & 1)
1278 return *ptr & 0x0f;
1279 else
1280 return (*ptr >> 4) & 0x0f;
1283 static DWORD get_pixel_1(const dib_info *dib, const POINT *pt)
1285 BYTE *ptr = get_pixel_ptr_1( dib, pt->x, pt->y );
1286 return (*ptr & pixel_masks_1[pt->x & 0x7]) ? 1 : 0;
1289 static DWORD get_pixel_null(const dib_info *dib, const POINT *pt)
1291 return 0;
1294 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1296 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1299 static const DWORD field_masks[33] =
1301 0x00, /* should never happen */
1302 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1303 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1304 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1305 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1308 static inline DWORD get_field(DWORD field, int shift, int len)
1310 shift = shift - (8 - len);
1311 if (shift < 0)
1312 field <<= -shift;
1313 else
1314 field >>= shift;
1315 field &= field_masks[len];
1316 field |= field >> len;
1317 return field;
1320 static inline DWORD put_field(DWORD field, int shift, int len)
1322 shift = shift - (8 - len);
1323 field &= field_masks[len];
1324 if (shift < 0)
1325 field >>= -shift;
1326 else
1327 field <<= shift;
1328 return field;
1331 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1333 DWORD r,g,b;
1335 r = GetRValue(colour);
1336 g = GetGValue(colour);
1337 b = GetBValue(colour);
1339 return put_field(r, dib->red_shift, dib->red_len) |
1340 put_field(g, dib->green_shift, dib->green_len) |
1341 put_field(b, dib->blue_shift, dib->blue_len);
1344 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1346 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1349 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1351 int i, best_index = 0;
1352 DWORD diff, best_diff = 0xffffffff;
1354 /* special case for conversion to 1-bpp without a color table:
1355 * we get a 1-entry table containing the background color
1357 if (dib->bit_count == 1 && dib->color_table_size == 1)
1358 return (r == dib->color_table[0].rgbRed &&
1359 g == dib->color_table[0].rgbGreen &&
1360 b == dib->color_table[0].rgbBlue);
1362 for(i = 0; i < dib->color_table_size; i++)
1364 RGBQUAD *cur = dib->color_table + i;
1365 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1366 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1367 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1369 if(diff == 0)
1371 best_index = i;
1372 break;
1375 if(diff < best_diff)
1377 best_diff = diff;
1378 best_index = i;
1381 return best_index;
1384 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1386 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1389 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1391 return 0;
1394 static inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1396 static const RGBQUAD default_rgb;
1397 if (index < dib->color_table_size) return dib->color_table[index];
1398 return default_rgb;
1401 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1403 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1406 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1408 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1409 get_field( pixel, dib->green_shift, dib->green_len ),
1410 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1413 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1415 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1416 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1417 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1420 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1422 RGBQUAD quad = colortable_entry( dib, pixel );
1424 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1427 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1429 return 0;
1432 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1434 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1436 return d1->red_mask == d2->red_mask &&
1437 d1->green_mask == d2->green_mask &&
1438 d1->blue_mask == d2->blue_mask;
1441 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1443 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1444 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1446 switch(src->bit_count)
1448 case 32:
1450 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1451 if(src->funcs == &funcs_8888)
1453 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1454 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1455 else
1457 for(y = src_rect->top; y < src_rect->bottom; y++)
1459 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1460 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1461 dst_start += dst->stride / 4;
1462 src_start += src->stride / 4;
1466 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1468 for(y = src_rect->top; y < src_rect->bottom; y++)
1470 dst_pixel = dst_start;
1471 src_pixel = src_start;
1472 for(x = src_rect->left; x < src_rect->right; x++)
1474 src_val = *src_pixel++;
1475 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1476 (((src_val >> src->green_shift) & 0xff) << 8) |
1477 ((src_val >> src->blue_shift) & 0xff);
1479 if(pad_size) memset(dst_pixel, 0, pad_size);
1480 dst_start += dst->stride / 4;
1481 src_start += src->stride / 4;
1484 else
1486 for(y = src_rect->top; y < src_rect->bottom; y++)
1488 dst_pixel = dst_start;
1489 src_pixel = src_start;
1490 for(x = src_rect->left; x < src_rect->right; x++)
1492 src_val = *src_pixel++;
1493 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1494 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1495 get_field( src_val, src->blue_shift, src->blue_len ));
1497 if(pad_size) memset(dst_pixel, 0, pad_size);
1498 dst_start += dst->stride / 4;
1499 src_start += src->stride / 4;
1502 break;
1505 case 24:
1507 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1509 for(y = src_rect->top; y < src_rect->bottom; y++)
1511 dst_pixel = dst_start;
1512 src_pixel = src_start;
1513 for(x = src_rect->left; x < src_rect->right; x++)
1515 RGBQUAD rgb;
1516 rgb.rgbBlue = *src_pixel++;
1517 rgb.rgbGreen = *src_pixel++;
1518 rgb.rgbRed = *src_pixel++;
1520 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1522 if(pad_size) memset(dst_pixel, 0, pad_size);
1523 dst_start += dst->stride / 4;
1524 src_start += src->stride;
1526 break;
1529 case 16:
1531 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1532 if(src->funcs == &funcs_555)
1534 for(y = src_rect->top; y < src_rect->bottom; y++)
1536 dst_pixel = dst_start;
1537 src_pixel = src_start;
1538 for(x = src_rect->left; x < src_rect->right; x++)
1540 src_val = *src_pixel++;
1541 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1542 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1543 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1545 if(pad_size) memset(dst_pixel, 0, pad_size);
1546 dst_start += dst->stride / 4;
1547 src_start += src->stride / 2;
1550 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1552 for(y = src_rect->top; y < src_rect->bottom; y++)
1554 dst_pixel = dst_start;
1555 src_pixel = src_start;
1556 for(x = src_rect->left; x < src_rect->right; x++)
1558 src_val = *src_pixel++;
1559 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1560 (((src_val >> src->red_shift) << 14) & 0x070000) |
1561 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1562 (((src_val >> src->green_shift) << 6) & 0x000700) |
1563 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1564 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1566 if(pad_size) memset(dst_pixel, 0, pad_size);
1567 dst_start += dst->stride / 4;
1568 src_start += src->stride / 2;
1571 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1573 for(y = src_rect->top; y < src_rect->bottom; y++)
1575 dst_pixel = dst_start;
1576 src_pixel = src_start;
1577 for(x = src_rect->left; x < src_rect->right; x++)
1579 src_val = *src_pixel++;
1580 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1581 (((src_val >> src->red_shift) << 14) & 0x070000) |
1582 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1583 (((src_val >> src->green_shift) << 4) & 0x000300) |
1584 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1585 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1587 if(pad_size) memset(dst_pixel, 0, pad_size);
1588 dst_start += dst->stride / 4;
1589 src_start += src->stride / 2;
1592 else
1594 for(y = src_rect->top; y < src_rect->bottom; y++)
1596 dst_pixel = dst_start;
1597 src_pixel = src_start;
1598 for(x = src_rect->left; x < src_rect->right; x++)
1600 src_val = *src_pixel++;
1601 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1602 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1603 get_field( src_val, src->blue_shift, src->blue_len ));
1605 if(pad_size) memset(dst_pixel, 0, pad_size);
1606 dst_start += dst->stride / 4;
1607 src_start += src->stride / 2;
1610 break;
1613 case 8:
1615 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1616 for(y = src_rect->top; y < src_rect->bottom; y++)
1618 dst_pixel = dst_start;
1619 src_pixel = src_start;
1620 for(x = src_rect->left; x < src_rect->right; x++)
1622 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1623 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1625 if(pad_size) memset(dst_pixel, 0, pad_size);
1626 dst_start += dst->stride / 4;
1627 src_start += src->stride;
1629 break;
1632 case 4:
1634 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1635 for(y = src_rect->top; y < src_rect->bottom; y++)
1637 dst_pixel = dst_start;
1638 src_pixel = src_start;
1639 for(x = src_rect->left; x < src_rect->right; x++)
1641 RGBQUAD rgb;
1642 if(x & 1)
1643 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1644 else
1645 rgb = colortable_entry( src, *src_pixel >> 4 );
1646 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1648 if(pad_size) memset(dst_pixel, 0, pad_size);
1649 dst_start += dst->stride / 4;
1650 src_start += src->stride;
1652 break;
1655 case 1:
1657 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1658 for(y = src_rect->top; y < src_rect->bottom; y++)
1660 dst_pixel = dst_start;
1661 src_pixel = src_start;
1662 for(x = src_rect->left; x < src_rect->right; x++)
1664 RGBQUAD rgb;
1665 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1666 if((x % 8) == 7) src_pixel++;
1667 rgb = src->color_table[src_val];
1668 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1670 if(pad_size) memset(dst_pixel, 0, pad_size);
1671 dst_start += dst->stride / 4;
1672 src_start += src->stride;
1674 break;
1679 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1681 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1682 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1684 switch(src->bit_count)
1686 case 32:
1688 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1690 if(src->funcs == &funcs_8888)
1692 for(y = src_rect->top; y < src_rect->bottom; y++)
1694 dst_pixel = dst_start;
1695 src_pixel = src_start;
1696 for(x = src_rect->left; x < src_rect->right; x++)
1698 src_val = *src_pixel++;
1699 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1700 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1701 put_field(src_val, dst->blue_shift, dst->blue_len);
1703 if(pad_size) memset(dst_pixel, 0, pad_size);
1704 dst_start += dst->stride / 4;
1705 src_start += src->stride / 4;
1708 else if(bit_fields_match(src, dst))
1710 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1711 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1712 else
1714 for(y = src_rect->top; y < src_rect->bottom; y++)
1716 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1717 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1718 dst_start += dst->stride / 4;
1719 src_start += src->stride / 4;
1723 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1724 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1726 for(y = src_rect->top; y < src_rect->bottom; y++)
1728 dst_pixel = dst_start;
1729 src_pixel = src_start;
1730 for(x = src_rect->left; x < src_rect->right; x++)
1732 src_val = *src_pixel++;
1733 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1734 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1735 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1737 if(pad_size) memset(dst_pixel, 0, pad_size);
1738 dst_start += dst->stride / 4;
1739 src_start += src->stride / 4;
1742 else
1744 for(y = src_rect->top; y < src_rect->bottom; y++)
1746 dst_pixel = dst_start;
1747 src_pixel = src_start;
1748 for(x = src_rect->left; x < src_rect->right; x++)
1750 src_val = *src_pixel++;
1751 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1752 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1753 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1755 if(pad_size) memset(dst_pixel, 0, pad_size);
1756 dst_start += dst->stride / 4;
1757 src_start += src->stride / 4;
1760 break;
1763 case 24:
1765 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1767 for(y = src_rect->top; y < src_rect->bottom; y++)
1769 dst_pixel = dst_start;
1770 src_pixel = src_start;
1771 for(x = src_rect->left; x < src_rect->right; x++)
1773 RGBQUAD rgb;
1774 rgb.rgbBlue = *src_pixel++;
1775 rgb.rgbGreen = *src_pixel++;
1776 rgb.rgbRed = *src_pixel++;
1778 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1779 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1780 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1782 if(pad_size) memset(dst_pixel, 0, pad_size);
1783 dst_start += dst->stride / 4;
1784 src_start += src->stride;
1786 break;
1789 case 16:
1791 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1792 if(src->funcs == &funcs_555)
1794 for(y = src_rect->top; y < src_rect->bottom; y++)
1796 dst_pixel = dst_start;
1797 src_pixel = src_start;
1798 for(x = src_rect->left; x < src_rect->right; x++)
1800 src_val = *src_pixel++;
1801 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1802 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1803 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1805 if(pad_size) memset(dst_pixel, 0, pad_size);
1806 dst_start += dst->stride / 4;
1807 src_start += src->stride / 2;
1810 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1812 for(y = src_rect->top; y < src_rect->bottom; y++)
1814 dst_pixel = dst_start;
1815 src_pixel = src_start;
1816 for(x = src_rect->left; x < src_rect->right; x++)
1818 src_val = *src_pixel++;
1819 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1820 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1821 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1822 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1823 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1824 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1826 if(pad_size) memset(dst_pixel, 0, pad_size);
1827 dst_start += dst->stride / 4;
1828 src_start += src->stride / 2;
1831 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1833 for(y = src_rect->top; y < src_rect->bottom; y++)
1835 dst_pixel = dst_start;
1836 src_pixel = src_start;
1837 for(x = src_rect->left; x < src_rect->right; x++)
1839 src_val = *src_pixel++;
1840 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1841 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1842 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1843 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1844 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1845 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1847 if(pad_size) memset(dst_pixel, 0, pad_size);
1848 dst_start += dst->stride / 4;
1849 src_start += src->stride / 2;
1852 else
1854 for(y = src_rect->top; y < src_rect->bottom; y++)
1856 dst_pixel = dst_start;
1857 src_pixel = src_start;
1858 for(x = src_rect->left; x < src_rect->right; x++)
1860 src_val = *src_pixel++;
1861 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1862 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1863 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1865 if(pad_size) memset(dst_pixel, 0, pad_size);
1866 dst_start += dst->stride / 4;
1867 src_start += src->stride / 2;
1870 break;
1873 case 8:
1875 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1876 for(y = src_rect->top; y < src_rect->bottom; y++)
1878 dst_pixel = dst_start;
1879 src_pixel = src_start;
1880 for(x = src_rect->left; x < src_rect->right; x++)
1882 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1883 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1884 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1885 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1887 if(pad_size) memset(dst_pixel, 0, pad_size);
1888 dst_start += dst->stride / 4;
1889 src_start += src->stride;
1891 break;
1894 case 4:
1896 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1897 for(y = src_rect->top; y < src_rect->bottom; y++)
1899 dst_pixel = dst_start;
1900 src_pixel = src_start;
1901 for(x = src_rect->left; x < src_rect->right; x++)
1903 RGBQUAD rgb;
1904 if(x & 1)
1905 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1906 else
1907 rgb = colortable_entry( src, *src_pixel >> 4 );
1908 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1909 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1910 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1912 if(pad_size) memset(dst_pixel, 0, pad_size);
1913 dst_start += dst->stride / 4;
1914 src_start += src->stride;
1916 break;
1919 case 1:
1921 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1922 for(y = src_rect->top; y < src_rect->bottom; y++)
1924 dst_pixel = dst_start;
1925 src_pixel = src_start;
1926 for(x = src_rect->left; x < src_rect->right; x++)
1928 RGBQUAD rgb;
1929 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1930 if((x % 8) == 7) src_pixel++;
1931 rgb = src->color_table[src_val];
1932 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1933 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1934 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1936 if(pad_size) memset(dst_pixel, 0, pad_size);
1937 dst_start += dst->stride / 4;
1938 src_start += src->stride;
1940 break;
1945 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1947 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1948 DWORD src_val;
1949 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1951 switch(src->bit_count)
1953 case 32:
1955 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1956 if(src->funcs == &funcs_8888)
1958 for(y = src_rect->top; y < src_rect->bottom; y++)
1960 dst_pixel = dst_start;
1961 src_pixel = src_start;
1962 for(x = src_rect->left; x < src_rect->right; x++)
1964 src_val = *src_pixel++;
1965 *dst_pixel++ = src_val & 0xff;
1966 *dst_pixel++ = (src_val >> 8) & 0xff;
1967 *dst_pixel++ = (src_val >> 16) & 0xff;
1969 if(pad_size) memset(dst_pixel, 0, pad_size);
1970 dst_start += dst->stride;
1971 src_start += src->stride / 4;
1974 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1976 for(y = src_rect->top; y < src_rect->bottom; y++)
1978 dst_pixel = dst_start;
1979 src_pixel = src_start;
1980 for(x = src_rect->left; x < src_rect->right; x++)
1982 src_val = *src_pixel++;
1983 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
1984 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1985 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
1987 if(pad_size) memset(dst_pixel, 0, pad_size);
1988 dst_start += dst->stride;
1989 src_start += src->stride / 4;
1992 else
1994 for(y = src_rect->top; y < src_rect->bottom; y++)
1996 dst_pixel = dst_start;
1997 src_pixel = src_start;
1998 for(x = src_rect->left; x < src_rect->right; x++)
2000 src_val = *src_pixel++;
2001 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
2002 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
2003 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
2005 if(pad_size) memset(dst_pixel, 0, pad_size);
2006 dst_start += dst->stride;
2007 src_start += src->stride / 4;
2010 break;
2013 case 24:
2015 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
2017 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2018 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2019 else
2021 for(y = src_rect->top; y < src_rect->bottom; y++)
2023 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
2024 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
2025 dst_start += dst->stride;
2026 src_start += src->stride;
2029 break;
2032 case 16:
2034 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2035 if(src->funcs == &funcs_555)
2037 for(y = src_rect->top; y < src_rect->bottom; y++)
2039 dst_pixel = dst_start;
2040 src_pixel = src_start;
2041 for(x = src_rect->left; x < src_rect->right; x++)
2043 src_val = *src_pixel++;
2044 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
2045 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
2046 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
2048 if(pad_size) memset(dst_pixel, 0, pad_size);
2049 dst_start += dst->stride;
2050 src_start += src->stride / 2;
2053 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2055 for(y = src_rect->top; y < src_rect->bottom; y++)
2057 dst_pixel = dst_start;
2058 src_pixel = src_start;
2059 for(x = src_rect->left; x < src_rect->right; x++)
2061 src_val = *src_pixel++;
2062 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2063 (((src_val >> src->blue_shift) >> 2) & 0x07);
2064 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
2065 (((src_val >> src->green_shift) >> 2) & 0x07);
2066 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2067 (((src_val >> src->red_shift) >> 2) & 0x07);
2069 if(pad_size) memset(dst_pixel, 0, pad_size);
2070 dst_start += dst->stride;
2071 src_start += src->stride / 2;
2074 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2076 for(y = src_rect->top; y < src_rect->bottom; y++)
2078 dst_pixel = dst_start;
2079 src_pixel = src_start;
2080 for(x = src_rect->left; x < src_rect->right; x++)
2082 src_val = *src_pixel++;
2083 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
2084 (((src_val >> src->blue_shift) >> 2) & 0x07);
2085 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
2086 (((src_val >> src->green_shift) >> 4) & 0x03);
2087 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
2088 (((src_val >> src->red_shift) >> 2) & 0x07);
2090 if(pad_size) memset(dst_pixel, 0, pad_size);
2091 dst_start += dst->stride;
2092 src_start += src->stride / 2;
2095 else
2097 for(y = src_rect->top; y < src_rect->bottom; y++)
2099 dst_pixel = dst_start;
2100 src_pixel = src_start;
2101 for(x = src_rect->left; x < src_rect->right; x++)
2103 src_val = *src_pixel++;
2104 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
2105 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
2106 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
2108 if(pad_size) memset(dst_pixel, 0, pad_size);
2109 dst_start += dst->stride;
2110 src_start += src->stride / 2;
2113 break;
2116 case 8:
2118 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2119 for(y = src_rect->top; y < src_rect->bottom; y++)
2121 dst_pixel = dst_start;
2122 src_pixel = src_start;
2123 for(x = src_rect->left; x < src_rect->right; x++)
2125 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2126 *dst_pixel++ = rgb.rgbBlue;
2127 *dst_pixel++ = rgb.rgbGreen;
2128 *dst_pixel++ = rgb.rgbRed;
2130 if(pad_size) memset(dst_pixel, 0, pad_size);
2131 dst_start += dst->stride;
2132 src_start += src->stride;
2134 break;
2137 case 4:
2139 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2140 for(y = src_rect->top; y < src_rect->bottom; y++)
2142 dst_pixel = dst_start;
2143 src_pixel = src_start;
2144 for(x = src_rect->left; x < src_rect->right; x++)
2146 RGBQUAD rgb;
2147 if(x & 1)
2148 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2149 else
2150 rgb = colortable_entry( src, *src_pixel >> 4 );
2151 *dst_pixel++ = rgb.rgbBlue;
2152 *dst_pixel++ = rgb.rgbGreen;
2153 *dst_pixel++ = rgb.rgbRed;
2155 if(pad_size) memset(dst_pixel, 0, pad_size);
2156 dst_start += dst->stride;
2157 src_start += src->stride;
2159 break;
2162 case 1:
2164 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2165 for(y = src_rect->top; y < src_rect->bottom; y++)
2167 dst_pixel = dst_start;
2168 src_pixel = src_start;
2169 for(x = src_rect->left; x < src_rect->right; x++)
2171 RGBQUAD rgb;
2172 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2173 if((x % 8) == 7) src_pixel++;
2174 rgb = src->color_table[src_val];
2175 *dst_pixel++ = rgb.rgbBlue;
2176 *dst_pixel++ = rgb.rgbGreen;
2177 *dst_pixel++ = rgb.rgbRed;
2179 if(pad_size) memset(dst_pixel, 0, pad_size);
2180 dst_start += dst->stride;
2181 src_start += src->stride;
2183 break;
2188 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
2190 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2191 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2192 DWORD src_val;
2194 switch(src->bit_count)
2196 case 32:
2198 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2200 if(src->funcs == &funcs_8888)
2202 for(y = src_rect->top; y < src_rect->bottom; y++)
2204 dst_pixel = dst_start;
2205 src_pixel = src_start;
2206 for(x = src_rect->left; x < src_rect->right; x++)
2208 src_val = *src_pixel++;
2209 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
2210 ((src_val >> 6) & 0x03e0) |
2211 ((src_val >> 3) & 0x001f);
2213 if(pad_size) memset(dst_pixel, 0, pad_size);
2214 dst_start += dst->stride / 2;
2215 src_start += src->stride / 4;
2218 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2220 for(y = src_rect->top; y < src_rect->bottom; y++)
2222 dst_pixel = dst_start;
2223 src_pixel = src_start;
2224 for(x = src_rect->left; x < src_rect->right; x++)
2226 src_val = *src_pixel++;
2227 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2228 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2229 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2231 if(pad_size) memset(dst_pixel, 0, pad_size);
2232 dst_start += dst->stride / 2;
2233 src_start += src->stride / 4;
2236 else
2238 for(y = src_rect->top; y < src_rect->bottom; y++)
2240 dst_pixel = dst_start;
2241 src_pixel = src_start;
2242 for(x = src_rect->left; x < src_rect->right; x++)
2244 src_val = *src_pixel++;
2245 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2246 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2247 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2249 if(pad_size) memset(dst_pixel, 0, pad_size);
2250 dst_start += dst->stride / 2;
2251 src_start += src->stride / 4;
2254 break;
2257 case 24:
2259 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2261 for(y = src_rect->top; y < src_rect->bottom; y++)
2263 dst_pixel = dst_start;
2264 src_pixel = src_start;
2265 for(x = src_rect->left; x < src_rect->right; x++)
2267 RGBQUAD rgb;
2268 rgb.rgbBlue = *src_pixel++;
2269 rgb.rgbGreen = *src_pixel++;
2270 rgb.rgbRed = *src_pixel++;
2272 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2273 ((rgb.rgbGreen << 2) & 0x03e0) |
2274 ((rgb.rgbBlue >> 3) & 0x001f);
2276 if(pad_size) memset(dst_pixel, 0, pad_size);
2277 dst_start += dst->stride / 2;
2278 src_start += src->stride;
2280 break;
2283 case 16:
2285 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2286 if(src->funcs == &funcs_555)
2288 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2289 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2290 else
2292 for(y = src_rect->top; y < src_rect->bottom; y++)
2294 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2295 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2296 dst_start += dst->stride / 2;
2297 src_start += src->stride / 2;
2301 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2303 for(y = src_rect->top; y < src_rect->bottom; y++)
2305 dst_pixel = dst_start;
2306 src_pixel = src_start;
2307 for(x = src_rect->left; x < src_rect->right; x++)
2309 src_val = *src_pixel++;
2310 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2311 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2312 ( (src_val >> src->blue_shift) & 0x001f);
2314 if(pad_size) memset(dst_pixel, 0, pad_size);
2315 dst_start += dst->stride / 2;
2316 src_start += src->stride / 2;
2319 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2321 for(y = src_rect->top; y < src_rect->bottom; y++)
2323 dst_pixel = dst_start;
2324 src_pixel = src_start;
2325 for(x = src_rect->left; x < src_rect->right; x++)
2327 src_val = *src_pixel++;
2328 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2329 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2330 ( (src_val >> src->blue_shift) & 0x001f);
2332 if(pad_size) memset(dst_pixel, 0, pad_size);
2333 dst_start += dst->stride / 2;
2334 src_start += src->stride / 2;
2337 else
2339 for(y = src_rect->top; y < src_rect->bottom; y++)
2341 dst_pixel = dst_start;
2342 src_pixel = src_start;
2343 for(x = src_rect->left; x < src_rect->right; x++)
2345 src_val = *src_pixel++;
2346 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2347 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2348 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2350 if(pad_size) memset(dst_pixel, 0, pad_size);
2351 dst_start += dst->stride / 2;
2352 src_start += src->stride / 2;
2355 break;
2358 case 8:
2360 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2361 for(y = src_rect->top; y < src_rect->bottom; y++)
2363 dst_pixel = dst_start;
2364 src_pixel = src_start;
2365 for(x = src_rect->left; x < src_rect->right; x++)
2367 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2368 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2369 ((rgb.rgbGreen << 2) & 0x03e0) |
2370 ((rgb.rgbBlue >> 3) & 0x001f);
2372 if(pad_size) memset(dst_pixel, 0, pad_size);
2373 dst_start += dst->stride / 2;
2374 src_start += src->stride;
2376 break;
2379 case 4:
2381 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2382 for(y = src_rect->top; y < src_rect->bottom; y++)
2384 dst_pixel = dst_start;
2385 src_pixel = src_start;
2386 for(x = src_rect->left; x < src_rect->right; x++)
2388 RGBQUAD rgb;
2389 if(x & 1)
2390 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2391 else
2392 rgb = colortable_entry( src, *src_pixel >> 4 );
2393 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2394 ((rgb.rgbGreen << 2) & 0x03e0) |
2395 ((rgb.rgbBlue >> 3) & 0x001f);
2397 if(pad_size) memset(dst_pixel, 0, pad_size);
2398 dst_start += dst->stride / 2;
2399 src_start += src->stride;
2401 break;
2404 case 1:
2406 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2407 for(y = src_rect->top; y < src_rect->bottom; y++)
2409 dst_pixel = dst_start;
2410 src_pixel = src_start;
2411 for(x = src_rect->left; x < src_rect->right; x++)
2413 RGBQUAD rgb;
2414 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2415 if((x % 8) == 7) src_pixel++;
2416 rgb = src->color_table[src_val];
2417 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2418 ((rgb.rgbGreen << 2) & 0x03e0) |
2419 ((rgb.rgbBlue >> 3) & 0x001f);
2421 if(pad_size) memset(dst_pixel, 0, pad_size);
2422 dst_start += dst->stride / 2;
2423 src_start += src->stride;
2425 break;
2430 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2432 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2433 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2434 DWORD src_val;
2436 switch(src->bit_count)
2438 case 32:
2440 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2442 if(src->funcs == &funcs_8888)
2444 for(y = src_rect->top; y < src_rect->bottom; y++)
2446 dst_pixel = dst_start;
2447 src_pixel = src_start;
2448 for(x = src_rect->left; x < src_rect->right; x++)
2450 src_val = *src_pixel++;
2451 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2452 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2453 put_field(src_val, dst->blue_shift, dst->blue_len);
2455 if(pad_size) memset(dst_pixel, 0, pad_size);
2456 dst_start += dst->stride / 2;
2457 src_start += src->stride / 4;
2460 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2462 for(y = src_rect->top; y < src_rect->bottom; y++)
2464 dst_pixel = dst_start;
2465 src_pixel = src_start;
2466 for(x = src_rect->left; x < src_rect->right; x++)
2468 src_val = *src_pixel++;
2469 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2470 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2471 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2473 if(pad_size) memset(dst_pixel, 0, pad_size);
2474 dst_start += dst->stride / 2;
2475 src_start += src->stride / 4;
2478 else
2480 for(y = src_rect->top; y < src_rect->bottom; y++)
2482 dst_pixel = dst_start;
2483 src_pixel = src_start;
2484 for(x = src_rect->left; x < src_rect->right; x++)
2486 src_val = *src_pixel++;
2487 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2488 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2489 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2491 if(pad_size) memset(dst_pixel, 0, pad_size);
2492 dst_start += dst->stride / 2;
2493 src_start += src->stride / 4;
2496 break;
2499 case 24:
2501 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2503 for(y = src_rect->top; y < src_rect->bottom; y++)
2505 dst_pixel = dst_start;
2506 src_pixel = src_start;
2507 for(x = src_rect->left; x < src_rect->right; x++)
2509 RGBQUAD rgb;
2510 rgb.rgbBlue = *src_pixel++;
2511 rgb.rgbGreen = *src_pixel++;
2512 rgb.rgbRed = *src_pixel++;
2514 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2515 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2516 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2518 if(pad_size) memset(dst_pixel, 0, pad_size);
2519 dst_start += dst->stride / 2;
2520 src_start += src->stride;
2522 break;
2525 case 16:
2527 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2528 if(src->funcs == &funcs_555)
2530 for(y = src_rect->top; y < src_rect->bottom; y++)
2532 dst_pixel = dst_start;
2533 src_pixel = src_start;
2534 for(x = src_rect->left; x < src_rect->right; x++)
2536 src_val = *src_pixel++;
2537 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2538 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2539 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2541 if(pad_size) memset(dst_pixel, 0, pad_size);
2542 dst_start += dst->stride / 2;
2543 src_start += src->stride / 2;
2546 else if(bit_fields_match(src, dst))
2548 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2549 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2550 else
2552 for(y = src_rect->top; y < src_rect->bottom; y++)
2554 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2555 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2556 dst_start += dst->stride / 2;
2557 src_start += src->stride / 2;
2561 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2563 for(y = src_rect->top; y < src_rect->bottom; y++)
2565 dst_pixel = dst_start;
2566 src_pixel = src_start;
2567 for(x = src_rect->left; x < src_rect->right; x++)
2569 src_val = *src_pixel++;
2570 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2571 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2572 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2573 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2574 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2575 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2577 if(pad_size) memset(dst_pixel, 0, pad_size);
2578 dst_start += dst->stride / 2;
2579 src_start += src->stride / 2;
2582 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2584 for(y = src_rect->top; y < src_rect->bottom; y++)
2586 dst_pixel = dst_start;
2587 src_pixel = src_start;
2588 for(x = src_rect->left; x < src_rect->right; x++)
2590 src_val = *src_pixel++;
2591 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2592 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2593 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2594 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2595 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2596 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2598 if(pad_size) memset(dst_pixel, 0, pad_size);
2599 dst_start += dst->stride / 2;
2600 src_start += src->stride / 2;
2603 else
2605 for(y = src_rect->top; y < src_rect->bottom; y++)
2607 dst_pixel = dst_start;
2608 src_pixel = src_start;
2609 for(x = src_rect->left; x < src_rect->right; x++)
2611 src_val = *src_pixel++;
2612 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2613 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2614 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2616 if(pad_size) memset(dst_pixel, 0, pad_size);
2617 dst_start += dst->stride / 2;
2618 src_start += src->stride / 2;
2621 break;
2624 case 8:
2626 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2627 for(y = src_rect->top; y < src_rect->bottom; y++)
2629 dst_pixel = dst_start;
2630 src_pixel = src_start;
2631 for(x = src_rect->left; x < src_rect->right; x++)
2633 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2634 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2635 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2636 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2638 if(pad_size) memset(dst_pixel, 0, pad_size);
2639 dst_start += dst->stride / 2;
2640 src_start += src->stride;
2642 break;
2645 case 4:
2647 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2648 for(y = src_rect->top; y < src_rect->bottom; y++)
2650 dst_pixel = dst_start;
2651 src_pixel = src_start;
2652 for(x = src_rect->left; x < src_rect->right; x++)
2654 RGBQUAD rgb;
2655 if(x & 1)
2656 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2657 else
2658 rgb = colortable_entry( src, *src_pixel >> 4 );
2659 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2660 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2661 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2663 if(pad_size) memset(dst_pixel, 0, pad_size);
2664 dst_start += dst->stride / 2;
2665 src_start += src->stride;
2667 break;
2670 case 1:
2672 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2673 for(y = src_rect->top; y < src_rect->bottom; y++)
2675 dst_pixel = dst_start;
2676 src_pixel = src_start;
2677 for(x = src_rect->left; x < src_rect->right; x++)
2679 RGBQUAD rgb;
2680 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2681 if((x % 8) == 7) src_pixel++;
2682 rgb = src->color_table[src_val];
2683 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2684 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2685 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2687 if(pad_size) memset(dst_pixel, 0, pad_size);
2688 dst_start += dst->stride / 2;
2689 src_start += src->stride;
2691 break;
2696 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2698 assert(d1->color_table_size && d2->color_table_size);
2700 if(d1->color_table_size != d2->color_table_size) return FALSE;
2701 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2704 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2706 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2707 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2710 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2712 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2713 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2714 DWORD src_val;
2716 switch(src->bit_count)
2718 case 32:
2720 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2722 if(src->funcs == &funcs_8888)
2724 for(y = src_rect->top; y < src_rect->bottom; y++)
2726 dst_pixel = dst_start;
2727 src_pixel = src_start;
2728 for(x = src_rect->left; x < src_rect->right; x++)
2730 src_val = *src_pixel++;
2731 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2733 if(pad_size) memset(dst_pixel, 0, pad_size);
2734 dst_start += dst->stride;
2735 src_start += src->stride / 4;
2738 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2740 for(y = src_rect->top; y < src_rect->bottom; y++)
2742 dst_pixel = dst_start;
2743 src_pixel = src_start;
2744 for(x = src_rect->left; x < src_rect->right; x++)
2746 src_val = *src_pixel++;
2747 *dst_pixel++ = rgb_lookup_colortable(dst,
2748 src_val >> src->red_shift,
2749 src_val >> src->green_shift,
2750 src_val >> src->blue_shift );
2752 if(pad_size) memset(dst_pixel, 0, pad_size);
2753 dst_start += dst->stride;
2754 src_start += src->stride / 4;
2757 else
2759 for(y = src_rect->top; y < src_rect->bottom; y++)
2761 dst_pixel = dst_start;
2762 src_pixel = src_start;
2763 for(x = src_rect->left; x < src_rect->right; x++)
2765 src_val = *src_pixel++;
2766 *dst_pixel++ = rgb_lookup_colortable(dst,
2767 get_field(src_val, src->red_shift, src->red_len),
2768 get_field(src_val, src->green_shift, src->green_len),
2769 get_field(src_val, src->blue_shift, src->blue_len));
2771 if(pad_size) memset(dst_pixel, 0, pad_size);
2772 dst_start += dst->stride;
2773 src_start += src->stride / 4;
2776 break;
2779 case 24:
2781 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2783 for(y = src_rect->top; y < src_rect->bottom; y++)
2785 dst_pixel = dst_start;
2786 src_pixel = src_start;
2787 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2789 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2791 if(pad_size) memset(dst_pixel, 0, pad_size);
2792 dst_start += dst->stride;
2793 src_start += src->stride;
2795 break;
2798 case 16:
2800 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2801 if(src->funcs == &funcs_555)
2803 for(y = src_rect->top; y < src_rect->bottom; y++)
2805 dst_pixel = dst_start;
2806 src_pixel = src_start;
2807 for(x = src_rect->left; x < src_rect->right; x++)
2809 src_val = *src_pixel++;
2810 *dst_pixel++ = rgb_lookup_colortable(dst,
2811 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2812 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2813 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2815 if(pad_size) memset(dst_pixel, 0, pad_size);
2816 dst_start += dst->stride;
2817 src_start += src->stride / 2;
2820 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2822 for(y = src_rect->top; y < src_rect->bottom; y++)
2824 dst_pixel = dst_start;
2825 src_pixel = src_start;
2826 for(x = src_rect->left; x < src_rect->right; x++)
2828 src_val = *src_pixel++;
2829 *dst_pixel++ = rgb_lookup_colortable(dst,
2830 (((src_val >> src->red_shift) << 3) & 0xf8) |
2831 (((src_val >> src->red_shift) >> 2) & 0x07),
2832 (((src_val >> src->green_shift) << 3) & 0xf8) |
2833 (((src_val >> src->green_shift) >> 2) & 0x07),
2834 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2835 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2837 if(pad_size) memset(dst_pixel, 0, pad_size);
2838 dst_start += dst->stride;
2839 src_start += src->stride / 2;
2842 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2844 for(y = src_rect->top; y < src_rect->bottom; y++)
2846 dst_pixel = dst_start;
2847 src_pixel = src_start;
2848 for(x = src_rect->left; x < src_rect->right; x++)
2850 src_val = *src_pixel++;
2851 *dst_pixel++ = rgb_lookup_colortable(dst,
2852 (((src_val >> src->red_shift) << 3) & 0xf8) |
2853 (((src_val >> src->red_shift) >> 2) & 0x07),
2854 (((src_val >> src->green_shift) << 2) & 0xfc) |
2855 (((src_val >> src->green_shift) >> 4) & 0x03),
2856 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2857 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2859 if(pad_size) memset(dst_pixel, 0, pad_size);
2860 dst_start += dst->stride;
2861 src_start += src->stride / 2;
2864 else
2866 for(y = src_rect->top; y < src_rect->bottom; y++)
2868 dst_pixel = dst_start;
2869 src_pixel = src_start;
2870 for(x = src_rect->left; x < src_rect->right; x++)
2872 src_val = *src_pixel++;
2873 *dst_pixel++ = rgb_lookup_colortable(dst,
2874 get_field(src_val, src->red_shift, src->red_len),
2875 get_field(src_val, src->green_shift, src->green_len),
2876 get_field(src_val, src->blue_shift, src->blue_len));
2878 if(pad_size) memset(dst_pixel, 0, pad_size);
2879 dst_start += dst->stride;
2880 src_start += src->stride / 2;
2883 break;
2886 case 8:
2888 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2890 if(color_tables_match(dst, src))
2892 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2893 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2894 else
2896 for(y = src_rect->top; y < src_rect->bottom; y++)
2898 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2899 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2900 dst_start += dst->stride;
2901 src_start += src->stride;
2905 else
2907 for(y = src_rect->top; y < src_rect->bottom; y++)
2909 dst_pixel = dst_start;
2910 src_pixel = src_start;
2911 for(x = src_rect->left; x < src_rect->right; x++)
2913 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2914 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2916 if(pad_size) memset(dst_pixel, 0, pad_size);
2917 dst_start += dst->stride;
2918 src_start += src->stride;
2921 break;
2924 case 4:
2926 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2927 for(y = src_rect->top; y < src_rect->bottom; y++)
2929 dst_pixel = dst_start;
2930 src_pixel = src_start;
2931 for(x = src_rect->left; x < src_rect->right; x++)
2933 RGBQUAD rgb;
2934 if(x & 1)
2935 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2936 else
2937 rgb = colortable_entry( src, *src_pixel >> 4 );
2938 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2940 if(pad_size) memset(dst_pixel, 0, pad_size);
2941 dst_start += dst->stride;
2942 src_start += src->stride;
2944 break;
2947 case 1:
2949 BYTE *src_start = get_pixel_ptr_1(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 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2958 if((x % 8) == 7) src_pixel++;
2959 rgb = src->color_table[src_val];
2960 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2962 if(pad_size) memset(dst_pixel, 0, pad_size);
2963 dst_start += dst->stride;
2964 src_start += src->stride;
2966 break;
2971 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2973 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2974 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2975 DWORD src_val;
2977 switch(src->bit_count)
2979 case 32:
2981 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2983 if(src->funcs == &funcs_8888)
2985 for(y = src_rect->top; y < src_rect->bottom; y++)
2987 dst_pixel = dst_start;
2988 src_pixel = src_start;
2989 for(x = src_rect->left; x < src_rect->right; x++)
2991 src_val = *src_pixel++;
2992 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
2993 if((x - src_rect->left) & 1)
2995 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2996 dst_pixel++;
2998 else
2999 *dst_pixel = (dst_val << 4) & 0xf0;
3001 if(pad_size)
3003 if((x - src_rect->left) & 1) dst_pixel++;
3004 memset(dst_pixel, 0, pad_size);
3006 dst_start += dst->stride;
3007 src_start += src->stride / 4;
3010 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3012 for(y = src_rect->top; y < src_rect->bottom; y++)
3014 dst_pixel = dst_start;
3015 src_pixel = src_start;
3016 for(x = src_rect->left; x < src_rect->right; x++)
3018 src_val = *src_pixel++;
3019 dst_val = rgb_to_pixel_colortable(dst,
3020 src_val >> src->red_shift,
3021 src_val >> src->green_shift,
3022 src_val >> src->blue_shift);
3023 if((x - src_rect->left) & 1)
3025 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3026 dst_pixel++;
3028 else
3029 *dst_pixel = (dst_val << 4) & 0xf0;
3031 if(pad_size)
3033 if((x - src_rect->left) & 1) dst_pixel++;
3034 memset(dst_pixel, 0, pad_size);
3036 dst_start += dst->stride;
3037 src_start += src->stride / 4;
3040 else
3042 for(y = src_rect->top; y < src_rect->bottom; y++)
3044 dst_pixel = dst_start;
3045 src_pixel = src_start;
3046 for(x = src_rect->left; x < src_rect->right; x++)
3048 src_val = *src_pixel++;
3049 dst_val = rgb_to_pixel_colortable(dst,
3050 get_field(src_val, src->red_shift, src->red_len),
3051 get_field(src_val, src->green_shift, src->green_len),
3052 get_field(src_val, src->blue_shift, src->blue_len));
3053 if((x - src_rect->left) & 1)
3055 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3056 dst_pixel++;
3058 else
3059 *dst_pixel = (dst_val << 4) & 0xf0;
3061 if(pad_size)
3063 if((x - src_rect->left) & 1) dst_pixel++;
3064 memset(dst_pixel, 0, pad_size);
3066 dst_start += dst->stride;
3067 src_start += src->stride / 4;
3070 break;
3073 case 24:
3075 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3077 for(y = src_rect->top; y < src_rect->bottom; y++)
3079 dst_pixel = dst_start;
3080 src_pixel = src_start;
3081 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
3083 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
3085 if((x - src_rect->left) & 1)
3087 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3088 dst_pixel++;
3090 else
3091 *dst_pixel = (dst_val << 4) & 0xf0;
3093 if(pad_size)
3095 if((x - src_rect->left) & 1) dst_pixel++;
3096 memset(dst_pixel, 0, pad_size);
3098 dst_start += dst->stride;
3099 src_start += src->stride;
3101 break;
3104 case 16:
3106 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3107 if(src->funcs == &funcs_555)
3109 for(y = src_rect->top; y < src_rect->bottom; y++)
3111 dst_pixel = dst_start;
3112 src_pixel = src_start;
3113 for(x = src_rect->left; x < src_rect->right; x++)
3115 src_val = *src_pixel++;
3116 dst_val = rgb_to_pixel_colortable(dst,
3117 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3118 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3119 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
3120 if((x - src_rect->left) & 1)
3122 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3123 dst_pixel++;
3125 else
3126 *dst_pixel = (dst_val << 4) & 0xf0;
3128 if(pad_size)
3130 if((x - src_rect->left) & 1) dst_pixel++;
3131 memset(dst_pixel, 0, pad_size);
3133 dst_start += dst->stride;
3134 src_start += src->stride / 2;
3137 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3139 for(y = src_rect->top; y < src_rect->bottom; y++)
3141 dst_pixel = dst_start;
3142 src_pixel = src_start;
3143 for(x = src_rect->left; x < src_rect->right; x++)
3145 src_val = *src_pixel++;
3146 dst_val = rgb_to_pixel_colortable(dst,
3147 (((src_val >> src->red_shift) << 3) & 0xf8) |
3148 (((src_val >> src->red_shift) >> 2) & 0x07),
3149 (((src_val >> src->green_shift) << 3) & 0xf8) |
3150 (((src_val >> src->green_shift) >> 2) & 0x07),
3151 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3152 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3153 if((x - src_rect->left) & 1)
3155 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3156 dst_pixel++;
3158 else
3159 *dst_pixel = (dst_val << 4) & 0xf0;
3161 if(pad_size)
3163 if((x - src_rect->left) & 1) dst_pixel++;
3164 memset(dst_pixel, 0, pad_size);
3166 dst_start += dst->stride;
3167 src_start += src->stride / 2;
3170 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3172 for(y = src_rect->top; y < src_rect->bottom; y++)
3174 dst_pixel = dst_start;
3175 src_pixel = src_start;
3176 for(x = src_rect->left; x < src_rect->right; x++)
3178 src_val = *src_pixel++;
3179 dst_val = rgb_to_pixel_colortable(dst,
3180 (((src_val >> src->red_shift) << 3) & 0xf8) |
3181 (((src_val >> src->red_shift) >> 2) & 0x07),
3182 (((src_val >> src->green_shift) << 2) & 0xfc) |
3183 (((src_val >> src->green_shift) >> 4) & 0x03),
3184 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3185 (((src_val >> src->blue_shift) >> 2) & 0x07) );
3186 if((x - src_rect->left) & 1)
3188 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3189 dst_pixel++;
3191 else
3192 *dst_pixel = (dst_val << 4) & 0xf0;
3194 if(pad_size)
3196 if((x - src_rect->left) & 1) dst_pixel++;
3197 memset(dst_pixel, 0, pad_size);
3199 dst_start += dst->stride;
3200 src_start += src->stride / 2;
3203 else
3205 for(y = src_rect->top; y < src_rect->bottom; y++)
3207 dst_pixel = dst_start;
3208 src_pixel = src_start;
3209 for(x = src_rect->left; x < src_rect->right; x++)
3211 src_val = *src_pixel++;
3212 dst_val = rgb_to_pixel_colortable(dst,
3213 get_field(src_val, src->red_shift, src->red_len),
3214 get_field(src_val, src->green_shift, src->green_len),
3215 get_field(src_val, src->blue_shift, src->blue_len));
3216 if((x - src_rect->left) & 1)
3218 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3219 dst_pixel++;
3221 else
3222 *dst_pixel = (dst_val << 4) & 0xf0;
3224 if(pad_size)
3226 if((x - src_rect->left) & 1) dst_pixel++;
3227 memset(dst_pixel, 0, pad_size);
3229 dst_start += dst->stride;
3230 src_start += src->stride / 2;
3233 break;
3236 case 8:
3238 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3240 for(y = src_rect->top; y < src_rect->bottom; y++)
3242 dst_pixel = dst_start;
3243 src_pixel = src_start;
3244 for(x = src_rect->left; x < src_rect->right; x++)
3246 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3247 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3248 if((x - src_rect->left) & 1)
3250 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3251 dst_pixel++;
3253 else
3254 *dst_pixel = (dst_val << 4) & 0xf0;
3256 if(pad_size)
3258 if((x - src_rect->left) & 1) dst_pixel++;
3259 memset(dst_pixel, 0, pad_size);
3261 dst_start += dst->stride;
3262 src_start += src->stride;
3264 break;
3267 case 4:
3269 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3271 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
3273 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
3274 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3275 else
3277 for(y = src_rect->top; y < src_rect->bottom; y++)
3279 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3280 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3281 dst_start += dst->stride;
3282 src_start += src->stride;
3286 else
3288 for(y = src_rect->top; y < src_rect->bottom; y++)
3290 dst_pixel = dst_start;
3291 src_pixel = src_start;
3292 for(x = src_rect->left; x < src_rect->right; x++)
3294 RGBQUAD rgb;
3295 if(x & 1)
3296 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3297 else
3298 rgb = colortable_entry( src, *src_pixel >> 4 );
3299 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3300 if((x - src_rect->left) & 1)
3302 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3303 dst_pixel++;
3305 else
3306 *dst_pixel = (dst_val << 4) & 0xf0;
3308 if(pad_size)
3310 if((x - src_rect->left) & 1) dst_pixel++;
3311 memset(dst_pixel, 0, pad_size);
3313 dst_start += dst->stride;
3314 src_start += src->stride;
3317 break;
3320 case 1:
3322 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3323 for(y = src_rect->top; y < src_rect->bottom; y++)
3325 dst_pixel = dst_start;
3326 src_pixel = src_start;
3327 for(x = src_rect->left; x < src_rect->right; x++)
3329 RGBQUAD rgb;
3330 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3331 if((x % 8) == 7) src_pixel++;
3332 rgb = src->color_table[src_val];
3333 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3334 if((x - src_rect->left) & 1)
3336 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3337 dst_pixel++;
3339 else
3340 *dst_pixel = (dst_val << 4) & 0xf0;
3342 if(pad_size)
3344 if((x - src_rect->left) & 1) dst_pixel++;
3345 memset(dst_pixel, 0, pad_size);
3347 dst_start += dst->stride;
3348 src_start += src->stride;
3350 break;
3355 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3357 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3358 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3359 DWORD src_val;
3360 int bit_pos;
3362 /* FIXME: Brushes should be dithered. */
3364 switch(src->bit_count)
3366 case 32:
3368 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3370 if(src->funcs == &funcs_8888)
3372 for(y = src_rect->top; y < src_rect->bottom; y++)
3374 dst_pixel = dst_start;
3375 src_pixel = src_start;
3376 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3378 src_val = *src_pixel++;
3379 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3381 if(bit_pos == 0) *dst_pixel = 0;
3382 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3384 if(++bit_pos == 8)
3386 dst_pixel++;
3387 bit_pos = 0;
3390 if(pad_size)
3392 if(bit_pos != 0) dst_pixel++;
3393 memset(dst_pixel, 0, pad_size);
3395 dst_start += dst->stride;
3396 src_start += src->stride / 4;
3399 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3401 for(y = src_rect->top; y < src_rect->bottom; y++)
3403 dst_pixel = dst_start;
3404 src_pixel = src_start;
3405 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3407 src_val = *src_pixel++;
3408 dst_val = rgb_to_pixel_colortable(dst,
3409 src_val >> src->red_shift,
3410 src_val >> src->green_shift,
3411 src_val >> src->blue_shift) ? 0xff : 0;
3413 if(bit_pos == 0) *dst_pixel = 0;
3414 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3416 if(++bit_pos == 8)
3418 dst_pixel++;
3419 bit_pos = 0;
3422 if(pad_size)
3424 if(bit_pos != 0) dst_pixel++;
3425 memset(dst_pixel, 0, pad_size);
3427 dst_start += dst->stride;
3428 src_start += src->stride / 4;
3431 else
3433 for(y = src_rect->top; y < src_rect->bottom; y++)
3435 dst_pixel = dst_start;
3436 src_pixel = src_start;
3437 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3439 src_val = *src_pixel++;
3440 dst_val = rgb_to_pixel_colortable(dst,
3441 get_field(src_val, src->red_shift, src->red_len),
3442 get_field(src_val, src->green_shift, src->green_len),
3443 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3445 if(bit_pos == 0) *dst_pixel = 0;
3446 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3448 if(++bit_pos == 8)
3450 dst_pixel++;
3451 bit_pos = 0;
3454 if(pad_size)
3456 if(bit_pos != 0) dst_pixel++;
3457 memset(dst_pixel, 0, pad_size);
3459 dst_start += dst->stride;
3460 src_start += src->stride / 4;
3463 break;
3466 case 24:
3468 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3470 for(y = src_rect->top; y < src_rect->bottom; y++)
3472 dst_pixel = dst_start;
3473 src_pixel = src_start;
3474 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3476 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3478 if(bit_pos == 0) *dst_pixel = 0;
3479 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3481 if(++bit_pos == 8)
3483 dst_pixel++;
3484 bit_pos = 0;
3487 if(pad_size)
3489 if(bit_pos != 0) dst_pixel++;
3490 memset(dst_pixel, 0, pad_size);
3492 dst_start += dst->stride;
3493 src_start += src->stride;
3495 break;
3498 case 16:
3500 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3501 if(src->funcs == &funcs_555)
3503 for(y = src_rect->top; y < src_rect->bottom; y++)
3505 dst_pixel = dst_start;
3506 src_pixel = src_start;
3507 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3509 src_val = *src_pixel++;
3510 dst_val = rgb_to_pixel_colortable(dst,
3511 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3512 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3513 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3515 if(bit_pos == 0) *dst_pixel = 0;
3516 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3518 if(++bit_pos == 8)
3520 dst_pixel++;
3521 bit_pos = 0;
3524 if(pad_size)
3526 if(bit_pos != 0) dst_pixel++;
3527 memset(dst_pixel, 0, pad_size);
3529 dst_start += dst->stride;
3530 src_start += src->stride / 2;
3533 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3535 for(y = src_rect->top; y < src_rect->bottom; y++)
3537 dst_pixel = dst_start;
3538 src_pixel = src_start;
3539 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3541 src_val = *src_pixel++;
3542 dst_val = rgb_to_pixel_colortable(dst,
3543 (((src_val >> src->red_shift) << 3) & 0xf8) |
3544 (((src_val >> src->red_shift) >> 2) & 0x07),
3545 (((src_val >> src->green_shift) << 3) & 0xf8) |
3546 (((src_val >> src->green_shift) >> 2) & 0x07),
3547 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3548 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3549 if(bit_pos == 0) *dst_pixel = 0;
3550 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3552 if(++bit_pos == 8)
3554 dst_pixel++;
3555 bit_pos = 0;
3558 if(pad_size)
3560 if(bit_pos != 0) dst_pixel++;
3561 memset(dst_pixel, 0, pad_size);
3563 dst_start += dst->stride;
3564 src_start += src->stride / 2;
3567 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3569 for(y = src_rect->top; y < src_rect->bottom; y++)
3571 dst_pixel = dst_start;
3572 src_pixel = src_start;
3573 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3575 src_val = *src_pixel++;
3576 dst_val = rgb_to_pixel_colortable(dst,
3577 (((src_val >> src->red_shift) << 3) & 0xf8) |
3578 (((src_val >> src->red_shift) >> 2) & 0x07),
3579 (((src_val >> src->green_shift) << 2) & 0xfc) |
3580 (((src_val >> src->green_shift) >> 4) & 0x03),
3581 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3582 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3583 if(bit_pos == 0) *dst_pixel = 0;
3584 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3586 if(++bit_pos == 8)
3588 dst_pixel++;
3589 bit_pos = 0;
3592 if(pad_size)
3594 if(bit_pos != 0) dst_pixel++;
3595 memset(dst_pixel, 0, pad_size);
3597 dst_start += dst->stride;
3598 src_start += src->stride / 2;
3601 else
3603 for(y = src_rect->top; y < src_rect->bottom; y++)
3605 dst_pixel = dst_start;
3606 src_pixel = src_start;
3607 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3609 src_val = *src_pixel++;
3610 dst_val = rgb_to_pixel_colortable(dst,
3611 get_field(src_val, src->red_shift, src->red_len),
3612 get_field(src_val, src->green_shift, src->green_len),
3613 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3614 if(bit_pos == 0) *dst_pixel = 0;
3615 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3617 if(++bit_pos == 8)
3619 dst_pixel++;
3620 bit_pos = 0;
3623 if(pad_size)
3625 if(bit_pos != 0) dst_pixel++;
3626 memset(dst_pixel, 0, pad_size);
3628 dst_start += dst->stride;
3629 src_start += src->stride / 2;
3632 break;
3635 case 8:
3637 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3639 for(y = src_rect->top; y < src_rect->bottom; y++)
3641 dst_pixel = dst_start;
3642 src_pixel = src_start;
3643 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3645 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3646 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3648 if(bit_pos == 0) *dst_pixel = 0;
3649 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3651 if(++bit_pos == 8)
3653 dst_pixel++;
3654 bit_pos = 0;
3657 if(pad_size)
3659 if(bit_pos != 0) dst_pixel++;
3660 memset(dst_pixel, 0, pad_size);
3662 dst_start += dst->stride;
3663 src_start += src->stride;
3665 break;
3668 case 4:
3670 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3672 for(y = src_rect->top; y < src_rect->bottom; y++)
3674 dst_pixel = dst_start;
3675 src_pixel = src_start;
3676 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3678 RGBQUAD rgb;
3679 if(x & 1)
3680 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3681 else
3682 rgb = colortable_entry( src, *src_pixel >> 4 );
3683 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3685 if(bit_pos == 0) *dst_pixel = 0;
3686 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3688 if(++bit_pos == 8)
3690 dst_pixel++;
3691 bit_pos = 0;
3694 if(pad_size)
3696 if(bit_pos != 0) dst_pixel++;
3697 memset(dst_pixel, 0, pad_size);
3699 dst_start += dst->stride;
3700 src_start += src->stride;
3702 break;
3705 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3706 uses text/bkgnd colours instead of the dib's colour table, this
3707 doesn't appear to be the case for a dc backed by a
3708 dibsection. */
3710 case 1:
3712 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3713 for(y = src_rect->top; y < src_rect->bottom; y++)
3715 dst_pixel = dst_start;
3716 src_pixel = src_start;
3717 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3719 RGBQUAD rgb;
3720 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3721 if((x % 8) == 7) src_pixel++;
3722 rgb = src->color_table[src_val];
3723 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3725 if(bit_pos == 0) *dst_pixel = 0;
3726 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3728 if(++bit_pos == 8)
3730 dst_pixel++;
3731 bit_pos = 0;
3734 if(pad_size)
3736 if(bit_pos != 0) dst_pixel++;
3737 memset(dst_pixel, 0, pad_size);
3739 dst_start += dst->stride;
3740 src_start += src->stride;
3742 break;
3747 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3751 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3753 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3756 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3758 return (blend_color( dst, src, alpha ) |
3759 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3760 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3761 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3764 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3766 BYTE b = ((BYTE)src * alpha + 127) / 255;
3767 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3768 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3769 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3770 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3771 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3772 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3773 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3776 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3778 if (blend.AlphaFormat & AC_SRC_ALPHA)
3780 DWORD alpha = blend.SourceConstantAlpha;
3781 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3782 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3783 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3784 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3785 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3786 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3787 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3789 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3790 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3791 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3794 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3795 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3797 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3798 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3799 int x, y;
3801 if (blend.AlphaFormat & AC_SRC_ALPHA)
3802 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3803 for (x = 0; x < rc->right - rc->left; x++)
3804 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3805 else
3806 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3807 for (x = 0; x < rc->right - rc->left; x++)
3808 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3811 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3812 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3814 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3815 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3816 int x, y;
3818 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3820 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3822 for (x = 0; x < rc->right - rc->left; x++)
3824 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3825 dst_ptr[x] >> dst->green_shift,
3826 dst_ptr[x] >> dst->blue_shift,
3827 src_ptr[x], blend );
3828 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3829 (((val >> 8) & 0xff) << dst->green_shift) |
3830 (((val >> 16) & 0xff) << dst->red_shift));
3834 else
3836 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3838 for (x = 0; x < rc->right - rc->left; x++)
3840 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3841 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3842 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3843 src_ptr[x], blend );
3844 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3845 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3846 put_field( val, dst->blue_shift, dst->blue_len ));
3852 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3853 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3855 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3856 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3857 int x, y;
3859 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3861 for (x = 0; x < rc->right - rc->left; x++)
3863 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3864 src_ptr[x], blend );
3865 dst_ptr[x * 3] = val;
3866 dst_ptr[x * 3 + 1] = val >> 8;
3867 dst_ptr[x * 3 + 2] = val >> 16;
3872 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3873 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3875 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3876 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3877 int x, y;
3879 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3881 for (x = 0; x < rc->right - rc->left; x++)
3883 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3884 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3885 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3886 src_ptr[x], blend );
3887 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3892 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3893 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3895 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3896 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3897 int x, y;
3899 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3901 for (x = 0; x < rc->right - rc->left; x++)
3903 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3904 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3905 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3906 src_ptr[x], blend );
3907 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3908 put_field((val >> 8), dst->green_shift, dst->green_len) |
3909 put_field( val, dst->blue_shift, dst->blue_len));
3914 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3915 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3917 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3918 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3919 int x, y;
3921 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3923 for (x = 0; x < rc->right - rc->left; x++)
3925 RGBQUAD rgb = colortable_entry( dst, dst_ptr[x] );
3926 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3927 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3932 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3933 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3935 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3936 BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3937 int x, y;
3939 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3941 for (x = rc->left; x < rc->right; x++)
3943 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3944 RGBQUAD rgb = colortable_entry( dst, val );
3945 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3946 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3947 if (x & 1)
3948 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3949 else
3950 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3955 static void blend_rect_1(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_1( 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 = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3967 RGBQUAD rgb = dst->color_table[val];
3968 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3969 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
3970 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
3975 static void blend_rect_null(const dib_info *dst, const RECT *rc,
3976 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3980 static inline DWORD gradient_rgb_8888( const TRIVERTEX *v, unsigned int pos, unsigned int len )
3982 BYTE r, g, b, a;
3983 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
3984 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
3985 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
3986 a = (v[0].Alpha * (len - pos) + v[1].Alpha * pos) / len / 256;
3987 return a << 24 | r << 16 | g << 8 | b;
3990 static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsigned int len )
3992 BYTE r, g, b;
3993 r = (v[0].Red * (len - pos) + v[1].Red * pos) / len / 256;
3994 g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 256;
3995 b = (v[0].Blue * (len - pos) + v[1].Blue * pos) / len / 256;
3996 return r << 16 | g << 8 | b;
3999 static void gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4001 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4002 int x, y;
4004 switch (mode)
4006 case GRADIENT_FILL_RECT_H:
4007 for (x = 0; x < rc->right - rc->left; x++)
4008 ptr[x] = gradient_rgb_8888( v, x + rc->left - v[0].x, v[1].x - v[0].x );
4010 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4011 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4012 break;
4014 case GRADIENT_FILL_RECT_V:
4015 for (y = rc->top; y < rc->bottom; y++)
4017 DWORD val = gradient_rgb_8888( v, y - v[0].y, v[1].y - v[0].y );
4018 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4019 ptr += dib->stride / 4;
4021 break;
4025 static void gradient_rect_32( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4027 DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
4028 int x, y;
4030 switch (mode)
4032 case GRADIENT_FILL_RECT_H:
4033 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4035 for (x = 0; x < rc->right - rc->left; x++)
4037 DWORD val = gradient_rgb_24( v, x + rc->left - v[0].x, v[1].x - v[0].x );
4038 ptr[x] = ((( val & 0xff) << dib->blue_shift) |
4039 (((val >> 8) & 0xff) << dib->green_shift) |
4040 (((val >> 16) & 0xff) << dib->red_shift));
4043 else
4045 for (x = 0; x < rc->right - rc->left; x++)
4047 DWORD val = gradient_rgb_24( v, x + rc->left - v[0].x, v[1].x - v[0].x );
4048 ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4049 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4050 put_field( val, dib->blue_shift, dib->blue_len ));
4054 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 4)
4055 memcpy( ptr + dib->stride / 4, ptr, (rc->right - rc->left) * 4 );
4056 break;
4058 case GRADIENT_FILL_RECT_V:
4059 for (y = rc->top; y < rc->bottom; y++)
4061 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4062 if (dib->red_len == 8 && dib->green_len == 8 && dib->blue_len == 8)
4063 val = ((( val & 0xff) << dib->blue_shift) |
4064 (((val >> 8) & 0xff) << dib->green_shift) |
4065 (((val >> 16) & 0xff) << dib->red_shift));
4066 else
4067 val = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4068 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4069 put_field( val, dib->blue_shift, dib->blue_len ));
4071 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4072 ptr += dib->stride / 4;
4074 break;
4078 static void gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4080 BYTE *ptr = get_pixel_ptr_24( dib, rc->left, rc->top );
4081 int x, y;
4083 switch (mode)
4085 case GRADIENT_FILL_RECT_H:
4086 for (x = 0; x < rc->right - rc->left; x++)
4088 DWORD val = gradient_rgb_24( v, x + rc->left - v[0].x, v[1].x - v[0].x );
4089 ptr[x * 3] = val;
4090 ptr[x * 3 + 1] = val >> 8;
4091 ptr[x * 3 + 2] = val >> 16;
4094 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4095 memcpy( ptr + dib->stride, ptr, (rc->right - rc->left) * 3 );
4096 break;
4098 case GRADIENT_FILL_RECT_V:
4099 for (y = rc->top; y < rc->bottom; y++)
4101 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4102 for (x = 0; x < rc->right - rc->left; x++)
4104 ptr[x * 3] = val;
4105 ptr[x * 3 + 1] = val >> 8;
4106 ptr[x * 3 + 2] = val >> 16;
4108 ptr += dib->stride;
4110 break;
4114 static void gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4116 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4117 int x, y;
4119 switch (mode)
4121 case GRADIENT_FILL_RECT_H:
4122 for (x = 0; x < rc->right - rc->left; x++)
4124 DWORD val = gradient_rgb_24( v, x + rc->left - v[0].x, v[1].x - v[0].x );
4125 ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4128 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 2)
4129 memcpy( ptr + dib->stride / 2, ptr, (rc->right - rc->left) * 2 );
4130 break;
4132 case GRADIENT_FILL_RECT_V:
4133 for (y = rc->top; y < rc->bottom; y++)
4135 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4136 val = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4137 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4138 ptr += dib->stride / 2;
4140 break;
4144 static void gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4146 WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
4147 int x, y;
4149 switch (mode)
4151 case GRADIENT_FILL_RECT_H:
4152 for (x = 0; x < rc->right - rc->left; x++)
4154 DWORD val = gradient_rgb_24( v, x + rc->left - v[0].x, v[1].x - v[0].x );
4155 ptr[x] = (put_field((val >> 16), dib->red_shift, dib->red_len) |
4156 put_field((val >> 8), dib->green_shift, dib->green_len) |
4157 put_field( val, dib->blue_shift, dib->blue_len));
4160 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 2)
4161 memcpy( ptr + dib->stride / 2, ptr, (rc->right - rc->left) * 2 );
4162 break;
4164 case GRADIENT_FILL_RECT_V:
4165 for (y = rc->top; y < rc->bottom; y++)
4167 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4168 val = (put_field((val >> 16), dib->red_shift, dib->red_len) |
4169 put_field((val >> 8), dib->green_shift, dib->green_len) |
4170 put_field( val, dib->blue_shift, dib->blue_len));
4171 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4172 ptr += dib->stride / 2;
4174 break;
4178 static void gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4180 BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
4181 int x, y;
4183 switch (mode)
4185 case GRADIENT_FILL_RECT_H:
4186 for (x = 0; x < rc->right - rc->left; x++)
4188 DWORD val = gradient_rgb_24( v, x + rc->left - v[0].x, v[1].x - v[0].x );
4189 ptr[x] = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
4192 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4193 memcpy( ptr + dib->stride, ptr, rc->right - rc->left );
4194 break;
4196 case GRADIENT_FILL_RECT_V:
4197 for (y = rc->top; y < rc->bottom; y++)
4199 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4200 val = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
4201 for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
4202 ptr += dib->stride;
4204 break;
4208 static void gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4210 BYTE *ptr = get_pixel_ptr_4( dib, 0, rc->top );
4211 int x, y;
4213 switch (mode)
4215 case GRADIENT_FILL_RECT_H:
4216 for (x = rc->left; x < rc->right; x++)
4218 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4219 val = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
4220 if (x & 1)
4221 ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4222 else
4223 ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
4226 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4228 x = rc->left;
4229 if (x & 1)
4231 ptr[dib->stride + x / 2] = (ptr[x / 2] & 0x0f) | (ptr[dib->stride + x / 2] & 0xf0);
4232 x++;
4234 for (; x < rc->right - 1; x += 2) ptr[dib->stride + x / 2] = ptr[x / 2];
4235 if (x < rc->right)
4236 ptr[dib->stride + x / 2] = (ptr[dib->stride + x / 2] & 0x0f) | (ptr[x / 2] & 0xf0);
4238 break;
4240 case GRADIENT_FILL_RECT_V:
4241 for (y = rc->top; y < rc->bottom; y++)
4243 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4244 val = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
4245 x = rc->left;
4246 if (x & 1)
4248 ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
4249 x++;
4251 for (; x < rc->right - 1; x += 2) ptr[x / 2] = (val << 4) | val;
4252 if (x < rc->right) ptr[x / 2] = (ptr[x / 2] & 0x0f) | (val << 4);
4253 ptr += dib->stride;
4255 break;
4259 static void gradient_rect_1( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4261 BYTE *ptr = get_pixel_ptr_1( dib, 0, rc->top );
4262 int x, y;
4264 switch (mode)
4266 case GRADIENT_FILL_RECT_H:
4267 for (x = rc->left; x < rc->right; x++)
4269 DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
4270 val = rgb_to_pixel_colortable( dib, val >> 16, val >> 8, val ) ? 0xff : 0;
4271 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4274 for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
4275 for (x = rc->left; x < rc->right; x++)
4276 ptr[dib->stride + x / 8] = (ptr[dib->stride + x / 8] & ~pixel_masks_1[x % 8]) |
4277 (ptr[x / 8] & pixel_masks_1[x % 8]);
4278 break;
4280 case GRADIENT_FILL_RECT_V:
4281 for (y = rc->top; y < rc->bottom; y++)
4283 DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
4284 val = rgb_to_pixel_colortable( dib, val >> 16, val >> 8, val ) ? 0xff : 0;
4285 for (x = rc->left; x < rc->right; x++)
4286 ptr[x / 8] = (ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
4287 ptr += dib->stride;
4289 break;
4293 static void gradient_rect_null( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
4297 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
4299 if (dst == text) return dst;
4301 if (dst > text)
4303 DWORD diff = dst - text;
4304 DWORD range = max_comp - text;
4305 dst = text + (diff * range ) / (0xff - text);
4306 return dst;
4308 else
4310 DWORD diff = text - dst;
4311 DWORD range = text - min_comp;
4312 dst = text - (diff * range) / text;
4313 return dst;
4317 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4319 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4320 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4321 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4324 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4325 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4327 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4328 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4329 int x, y;
4331 for (y = rect->top; y < rect->bottom; y++)
4333 for (x = 0; x < rect->right - rect->left; x++)
4335 if (glyph_ptr[x] <= 1) continue;
4336 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4337 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4339 dst_ptr += dib->stride / 4;
4340 glyph_ptr += glyph->stride;
4344 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4345 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4347 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4348 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4349 int x, y;
4350 DWORD text, val;
4352 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4353 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4354 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4356 for (y = rect->top; y < rect->bottom; y++)
4358 for (x = 0; x < rect->right - rect->left; x++)
4360 if (glyph_ptr[x] <= 1) continue;
4361 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4362 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4363 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4364 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4365 text, ranges + glyph_ptr[x] );
4366 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4367 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4368 put_field( val, dib->blue_shift, dib->blue_len ));
4370 dst_ptr += dib->stride / 4;
4371 glyph_ptr += glyph->stride;
4375 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4376 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4378 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4379 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4380 int x, y;
4381 DWORD val;
4383 for (y = rect->top; y < rect->bottom; y++)
4385 for (x = 0; x < rect->right - rect->left; x++)
4387 if (glyph_ptr[x] <= 1) continue;
4388 if (glyph_ptr[x] >= 16)
4389 val = text_pixel;
4390 else
4391 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4392 text_pixel, ranges + glyph_ptr[x] );
4393 dst_ptr[x * 3] = val;
4394 dst_ptr[x * 3 + 1] = val >> 8;
4395 dst_ptr[x * 3 + 2] = val >> 16;
4397 dst_ptr += dib->stride;
4398 glyph_ptr += glyph->stride;
4402 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4403 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4405 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4406 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4407 int x, y;
4408 DWORD text, val;
4410 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4411 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4412 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4414 for (y = rect->top; y < rect->bottom; y++)
4416 for (x = 0; x < rect->right - rect->left; x++)
4418 if (glyph_ptr[x] <= 1) continue;
4419 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4420 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4421 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4422 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4423 text, ranges + glyph_ptr[x] );
4424 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4426 dst_ptr += dib->stride / 2;
4427 glyph_ptr += glyph->stride;
4431 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4432 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4434 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4435 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4436 int x, y;
4437 DWORD text, val;
4439 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4440 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4441 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4443 for (y = rect->top; y < rect->bottom; y++)
4445 for (x = 0; x < rect->right - rect->left; x++)
4447 if (glyph_ptr[x] <= 1) continue;
4448 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4449 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4450 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4451 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4452 text, ranges + glyph_ptr[x] );
4453 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4454 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4455 put_field( val, dib->blue_shift, dib->blue_len ));
4457 dst_ptr += dib->stride / 2;
4458 glyph_ptr += glyph->stride;
4462 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4463 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4465 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4466 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4467 int x, y;
4469 for (y = rect->top; y < rect->bottom; y++)
4471 for (x = 0; x < rect->right - rect->left; x++)
4473 /* no antialiasing, glyph should only contain 0 or 16. */
4474 if (glyph_ptr[x] >= 16)
4475 dst_ptr[x] = text_pixel;
4477 dst_ptr += dib->stride;
4478 glyph_ptr += glyph->stride;
4482 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4483 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4485 BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
4486 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4487 int x, y;
4489 for (y = rect->top; y < rect->bottom; y++)
4491 for (x = rect->left; x < rect->right; x++)
4493 /* no antialiasing, glyph should only contain 0 or 16. */
4494 if (glyph_ptr[x] >= 16)
4496 if (x & 1)
4497 dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
4498 else
4499 dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
4502 dst_ptr += dib->stride;
4503 glyph_ptr += glyph->stride;
4507 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4508 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4510 BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
4511 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4512 int x, y;
4513 BYTE text = (text_pixel & 1) ? 0xff : 0;
4515 for (y = rect->top; y < rect->bottom; y++)
4517 for (x = rect->left; x < rect->right; x++)
4519 /* no antialiasing, glyph should only contain 0 or 16. */
4520 if (glyph_ptr[x] >= 16)
4521 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
4523 dst_ptr += dib->stride;
4524 glyph_ptr += glyph->stride;
4528 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4529 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4531 return;
4534 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)
4536 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4537 DWORD mask_start = 0, mask_offset;
4538 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4539 int x, y;
4541 for(y = 0; y < hatch->height; y++)
4543 hatch_ptr = hatch_start;
4544 mask_offset = mask_start;
4545 for(x = 0; x < hatch->width; x++)
4547 if(*hatch_ptr & pixel_masks_1[x % 8])
4549 and_bits[mask_offset] = fg->and;
4550 xor_bits[mask_offset] = fg->xor;
4552 else
4554 and_bits[mask_offset] = bg->and;
4555 xor_bits[mask_offset] = bg->xor;
4557 if(x % 8 == 7) hatch_ptr++;
4558 mask_offset++;
4560 hatch_start += hatch->stride;
4561 mask_start += dib->stride / 4;
4564 return TRUE;
4567 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)
4569 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4570 DWORD mask_start = 0, mask_offset;
4571 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4572 int x, y;
4574 for(y = 0; y < hatch->height; y++)
4576 hatch_ptr = hatch_start;
4577 mask_offset = mask_start;
4578 for(x = 0; x < hatch->width; x++)
4580 if(*hatch_ptr & pixel_masks_1[x % 8])
4582 and_bits[mask_offset] = fg->and & 0xff;
4583 xor_bits[mask_offset++] = fg->xor & 0xff;
4584 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4585 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4586 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4587 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4589 else
4591 and_bits[mask_offset] = bg->and & 0xff;
4592 xor_bits[mask_offset++] = bg->xor & 0xff;
4593 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4594 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4595 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4596 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4598 if(x % 8 == 7) hatch_ptr++;
4600 hatch_start += hatch->stride;
4601 mask_start += dib->stride;
4604 return TRUE;
4607 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)
4609 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4610 DWORD mask_start = 0, mask_offset;
4611 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4612 int x, y;
4614 for(y = 0; y < hatch->height; y++)
4616 hatch_ptr = hatch_start;
4617 mask_offset = mask_start;
4618 for(x = 0; x < hatch->width; x++)
4620 if(*hatch_ptr & pixel_masks_1[x % 8])
4622 and_bits[mask_offset] = fg->and;
4623 xor_bits[mask_offset] = fg->xor;
4625 else
4627 and_bits[mask_offset] = bg->and;
4628 xor_bits[mask_offset] = bg->xor;
4630 if(x % 8 == 7) hatch_ptr++;
4631 mask_offset++;
4633 hatch_start += hatch->stride;
4634 mask_start += dib->stride / 2;
4637 return TRUE;
4640 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)
4642 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4643 DWORD mask_start = 0, mask_offset;
4644 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4645 int x, y;
4647 for(y = 0; y < hatch->height; y++)
4649 hatch_ptr = hatch_start;
4650 mask_offset = mask_start;
4651 for(x = 0; x < hatch->width; x++)
4653 if(*hatch_ptr & pixel_masks_1[x % 8])
4655 and_bits[mask_offset] = fg->and;
4656 xor_bits[mask_offset] = fg->xor;
4658 else
4660 and_bits[mask_offset] = bg->and;
4661 xor_bits[mask_offset] = bg->xor;
4663 if(x % 8 == 7) hatch_ptr++;
4664 mask_offset++;
4666 hatch_start += hatch->stride;
4667 mask_start += dib->stride;
4670 return TRUE;
4673 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)
4675 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4676 DWORD mask_start = 0, mask_offset;
4677 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4678 const rop_mask *rop_mask;
4679 int x, y;
4681 for(y = 0; y < hatch->height; y++)
4683 hatch_ptr = hatch_start;
4684 mask_offset = mask_start;
4685 for(x = 0; x < hatch->width; x++)
4687 if(*hatch_ptr & pixel_masks_1[x % 8])
4688 rop_mask = fg;
4689 else
4690 rop_mask = bg;
4692 if(x & 1)
4694 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4695 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4696 mask_offset++;
4698 else
4700 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4701 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4704 if(x % 8 == 7) hatch_ptr++;
4706 hatch_start += hatch->stride;
4707 mask_start += dib->stride;
4710 return TRUE;
4713 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)
4715 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4716 DWORD mask_start = 0, mask_offset;
4717 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4718 rop_mask rop_mask;
4719 int x, y, bit_pos;
4721 for(y = 0; y < hatch->height; y++)
4723 hatch_ptr = hatch_start;
4724 mask_offset = mask_start;
4725 for(x = 0, bit_pos = 0; x < hatch->width; x++)
4727 if(*hatch_ptr & pixel_masks_1[x % 8])
4729 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4730 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4732 else
4734 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4735 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4738 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4740 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4741 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4743 if(++bit_pos == 8)
4745 mask_offset++;
4746 hatch_ptr++;
4747 bit_pos = 0;
4750 hatch_start += hatch->stride;
4751 mask_start += dib->stride;
4754 return TRUE;
4757 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)
4759 return FALSE;
4762 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
4764 switch (mode)
4766 default:
4767 case STRETCH_DELETESCANS:
4768 get_rop_codes( R2_COPYPEN, codes );
4769 break;
4770 case STRETCH_ORSCANS:
4771 get_rop_codes( R2_MERGEPEN, codes );
4772 break;
4773 case STRETCH_ANDSCANS:
4774 get_rop_codes( R2_MASKPEN, codes );
4775 break;
4777 return;
4780 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
4781 const dib_info *src_dib, const POINT *src_start,
4782 const struct stretch_params *params, int mode,
4783 BOOL keep_dst)
4785 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4786 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4787 int err = params->err_start;
4788 int width;
4789 struct rop_codes codes;
4791 rop_codes_from_stretch_mode( mode, &codes );
4792 for (width = params->length; width; width--)
4794 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4795 dst_ptr += params->dst_inc;
4796 if (err > 0)
4798 src_ptr += params->src_inc;
4799 err += params->err_add_1;
4801 else err += params->err_add_2;
4805 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
4806 const dib_info *src_dib, const POINT *src_start,
4807 const struct stretch_params *params, int mode,
4808 BOOL keep_dst)
4810 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4811 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4812 int err = params->err_start;
4813 int width;
4814 struct rop_codes codes;
4816 rop_codes_from_stretch_mode( mode, &codes );
4817 for (width = params->length; width; width--)
4819 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4820 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4821 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4822 dst_ptr += 3 * params->dst_inc;
4823 if (err > 0)
4825 src_ptr += 3 * params->src_inc;
4826 err += params->err_add_1;
4828 else err += params->err_add_2;
4832 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
4833 const dib_info *src_dib, const POINT *src_start,
4834 const struct stretch_params *params, int mode,
4835 BOOL keep_dst)
4837 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4838 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4839 int err = params->err_start;
4840 int width;
4841 struct rop_codes codes;
4843 rop_codes_from_stretch_mode( mode, &codes );
4844 for (width = params->length; width; width--)
4846 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4847 dst_ptr += params->dst_inc;
4848 if (err > 0)
4850 src_ptr += params->src_inc;
4851 err += params->err_add_1;
4853 else err += params->err_add_2;
4857 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
4858 const dib_info *src_dib, const POINT *src_start,
4859 const struct stretch_params *params, int mode,
4860 BOOL keep_dst)
4862 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4863 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4864 int err = params->err_start;
4865 int width;
4866 struct rop_codes codes;
4868 rop_codes_from_stretch_mode( mode, &codes );
4869 for (width = params->length; width; width--)
4871 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4872 dst_ptr += params->dst_inc;
4873 if (err > 0)
4875 src_ptr += params->src_inc;
4876 err += params->err_add_1;
4878 else err += params->err_add_2;
4882 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
4883 const dib_info *src_dib, const POINT *src_start,
4884 const struct stretch_params *params, int mode,
4885 BOOL keep_dst)
4887 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
4888 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
4889 int err = params->err_start;
4890 int width, dst_x = dst_start->x, src_x = src_start->x;
4891 struct rop_codes codes;
4892 BYTE src_val;
4894 rop_codes_from_stretch_mode( mode, &codes );
4895 for (width = params->length; width; width--)
4897 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4898 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4900 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
4902 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4903 dst_ptr += params->dst_inc;
4904 dst_x += params->dst_inc;
4906 if (err > 0)
4908 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4909 src_ptr += params->src_inc;
4910 src_x += params->src_inc;
4911 err += params->err_add_1;
4913 else err += params->err_add_2;
4917 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
4918 const dib_info *src_dib, const POINT *src_start,
4919 const struct stretch_params *params, int mode,
4920 BOOL keep_dst)
4922 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4923 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4924 int err = params->err_start;
4925 int width, dst_x = dst_start->x, src_x = src_start->x;
4926 struct rop_codes codes;
4927 BYTE src_val;
4929 rop_codes_from_stretch_mode( mode, &codes );
4930 for (width = params->length; width; width--)
4932 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4933 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4935 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4936 dst_ptr += params->dst_inc;
4937 dst_x += params->dst_inc;
4939 if (err > 0)
4941 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4942 src_ptr += params->src_inc;
4943 src_x += params->src_inc;
4944 err += params->err_add_1;
4946 else err += params->err_add_2;
4950 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
4951 const dib_info *src_dib, const POINT *src_start,
4952 const struct stretch_params *params, int mode,
4953 BOOL keep_dst)
4955 FIXME("bit count %d\n", dst_dib->bit_count);
4956 return;
4959 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
4960 const dib_info *src_dib, const POINT *src_start,
4961 const struct stretch_params *params, int mode,
4962 BOOL keep_dst)
4964 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4965 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4966 int err = params->err_start;
4967 int width;
4968 struct rop_codes codes;
4969 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4970 BOOL new_pix = TRUE;
4972 rop_codes_from_stretch_mode( mode, &codes );
4973 for (width = params->length; width; width--)
4975 if (new_pix && !keep_dst) *dst_ptr = init_val;
4976 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4977 new_pix = FALSE;
4978 src_ptr += params->src_inc;
4979 if (err > 0)
4981 dst_ptr += params->dst_inc;
4982 new_pix = TRUE;
4983 err += params->err_add_1;
4985 else err += params->err_add_2;
4989 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
4990 const dib_info *src_dib, const POINT *src_start,
4991 const struct stretch_params *params, int mode,
4992 BOOL keep_dst)
4994 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4995 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4996 int err = params->err_start;
4997 int width;
4998 struct rop_codes codes;
4999 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5000 BOOL new_pix = TRUE;
5002 rop_codes_from_stretch_mode( mode, &codes );
5003 for (width = params->length; width; width--)
5005 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
5006 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5007 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
5008 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
5009 new_pix = FALSE;
5010 src_ptr += 3 * params->src_inc;
5011 if (err > 0)
5013 dst_ptr += 3 * params->dst_inc;
5014 new_pix = TRUE;
5015 err += params->err_add_1;
5017 else err += params->err_add_2;
5021 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
5022 const dib_info *src_dib, const POINT *src_start,
5023 const struct stretch_params *params, int mode,
5024 BOOL keep_dst)
5026 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
5027 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
5028 int err = params->err_start;
5029 int width;
5030 struct rop_codes codes;
5031 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5032 BOOL new_pix = TRUE;
5034 rop_codes_from_stretch_mode( mode, &codes );
5035 for (width = params->length; width; width--)
5037 if (new_pix && !keep_dst) *dst_ptr = init_val;
5038 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
5039 new_pix = FALSE;
5040 src_ptr += params->src_inc;
5041 if (err > 0)
5043 dst_ptr += params->dst_inc;
5044 new_pix = TRUE;
5045 err += params->err_add_1;
5047 else err += params->err_add_2;
5051 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
5052 const dib_info *src_dib, const POINT *src_start,
5053 const struct stretch_params *params, int mode,
5054 BOOL keep_dst)
5056 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5057 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5058 int err = params->err_start;
5059 int width;
5060 struct rop_codes codes;
5061 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5062 BOOL new_pix = TRUE;
5064 rop_codes_from_stretch_mode( mode, &codes );
5065 for (width = params->length; width; width--)
5067 if (new_pix && !keep_dst) *dst_ptr = init_val;
5068 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
5069 new_pix = FALSE;
5070 src_ptr += params->src_inc;
5071 if (err > 0)
5073 dst_ptr += params->dst_inc;
5074 new_pix = TRUE;
5075 err += params->err_add_1;
5077 else err += params->err_add_2;
5081 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
5082 const dib_info *src_dib, const POINT *src_start,
5083 const struct stretch_params *params, int mode,
5084 BOOL keep_dst)
5086 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
5087 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
5088 int err = params->err_start;
5089 int width, dst_x = dst_start->x, src_x = src_start->x;
5090 struct rop_codes codes;
5091 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5092 BOOL new_pix = TRUE;
5094 rop_codes_from_stretch_mode( mode, &codes );
5095 for (width = params->length; width; width--)
5097 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
5099 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
5100 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
5102 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
5103 new_pix = FALSE;
5105 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
5106 src_ptr += params->src_inc;
5107 src_x += params->src_inc;
5109 if (err > 0)
5111 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
5112 dst_ptr += params->dst_inc;
5113 dst_x += params->dst_inc;
5114 new_pix = TRUE;
5115 err += params->err_add_1;
5117 else err += params->err_add_2;
5121 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
5122 const dib_info *src_dib, const POINT *src_start,
5123 const struct stretch_params *params, int mode,
5124 BOOL keep_dst)
5126 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
5127 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
5128 int err = params->err_start;
5129 int width, dst_x = dst_start->x, src_x = src_start->x;
5130 struct rop_codes codes;
5131 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
5132 BOOL new_pix = TRUE;
5134 rop_codes_from_stretch_mode( mode, &codes );
5135 for (width = params->length; width; width--)
5137 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
5138 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
5139 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
5140 new_pix = FALSE;
5142 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
5143 src_ptr += params->src_inc;
5144 src_x += params->src_inc;
5146 if (err > 0)
5148 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
5149 dst_ptr += params->dst_inc;
5150 dst_x += params->dst_inc;
5151 new_pix = TRUE;
5152 err += params->err_add_1;
5154 else err += params->err_add_2;
5158 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
5159 const dib_info *src_dib, const POINT *src_start,
5160 const struct stretch_params *params, int mode,
5161 BOOL keep_dst)
5163 FIXME("bit count %d\n", dst_dib->bit_count);
5164 return;
5167 const primitive_funcs funcs_8888 =
5169 solid_rects_32,
5170 solid_line_32,
5171 pattern_rects_32,
5172 copy_rect_32,
5173 blend_rect_8888,
5174 gradient_rect_8888,
5175 draw_glyph_8888,
5176 get_pixel_32,
5177 colorref_to_pixel_888,
5178 pixel_to_colorref_888,
5179 convert_to_8888,
5180 create_rop_masks_32,
5181 stretch_row_32,
5182 shrink_row_32
5185 const primitive_funcs funcs_32 =
5187 solid_rects_32,
5188 solid_line_32,
5189 pattern_rects_32,
5190 copy_rect_32,
5191 blend_rect_32,
5192 gradient_rect_32,
5193 draw_glyph_32,
5194 get_pixel_32,
5195 colorref_to_pixel_masks,
5196 pixel_to_colorref_masks,
5197 convert_to_32,
5198 create_rop_masks_32,
5199 stretch_row_32,
5200 shrink_row_32
5203 const primitive_funcs funcs_24 =
5205 solid_rects_24,
5206 solid_line_24,
5207 pattern_rects_24,
5208 copy_rect_24,
5209 blend_rect_24,
5210 gradient_rect_24,
5211 draw_glyph_24,
5212 get_pixel_24,
5213 colorref_to_pixel_888,
5214 pixel_to_colorref_888,
5215 convert_to_24,
5216 create_rop_masks_24,
5217 stretch_row_24,
5218 shrink_row_24
5221 const primitive_funcs funcs_555 =
5223 solid_rects_16,
5224 solid_line_16,
5225 pattern_rects_16,
5226 copy_rect_16,
5227 blend_rect_555,
5228 gradient_rect_555,
5229 draw_glyph_555,
5230 get_pixel_16,
5231 colorref_to_pixel_555,
5232 pixel_to_colorref_555,
5233 convert_to_555,
5234 create_rop_masks_16,
5235 stretch_row_16,
5236 shrink_row_16
5239 const primitive_funcs funcs_16 =
5241 solid_rects_16,
5242 solid_line_16,
5243 pattern_rects_16,
5244 copy_rect_16,
5245 blend_rect_16,
5246 gradient_rect_16,
5247 draw_glyph_16,
5248 get_pixel_16,
5249 colorref_to_pixel_masks,
5250 pixel_to_colorref_masks,
5251 convert_to_16,
5252 create_rop_masks_16,
5253 stretch_row_16,
5254 shrink_row_16
5257 const primitive_funcs funcs_8 =
5259 solid_rects_8,
5260 solid_line_8,
5261 pattern_rects_8,
5262 copy_rect_8,
5263 blend_rect_8,
5264 gradient_rect_8,
5265 draw_glyph_8,
5266 get_pixel_8,
5267 colorref_to_pixel_colortable,
5268 pixel_to_colorref_colortable,
5269 convert_to_8,
5270 create_rop_masks_8,
5271 stretch_row_8,
5272 shrink_row_8
5275 const primitive_funcs funcs_4 =
5277 solid_rects_4,
5278 solid_line_4,
5279 pattern_rects_4,
5280 copy_rect_4,
5281 blend_rect_4,
5282 gradient_rect_4,
5283 draw_glyph_4,
5284 get_pixel_4,
5285 colorref_to_pixel_colortable,
5286 pixel_to_colorref_colortable,
5287 convert_to_4,
5288 create_rop_masks_4,
5289 stretch_row_4,
5290 shrink_row_4
5293 const primitive_funcs funcs_1 =
5295 solid_rects_1,
5296 solid_line_1,
5297 pattern_rects_1,
5298 copy_rect_1,
5299 blend_rect_1,
5300 gradient_rect_1,
5301 draw_glyph_1,
5302 get_pixel_1,
5303 colorref_to_pixel_colortable,
5304 pixel_to_colorref_colortable,
5305 convert_to_1,
5306 create_rop_masks_1,
5307 stretch_row_1,
5308 shrink_row_1
5311 const primitive_funcs funcs_null =
5313 solid_rects_null,
5314 solid_line_null,
5315 pattern_rects_null,
5316 copy_rect_null,
5317 blend_rect_null,
5318 gradient_rect_null,
5319 draw_glyph_null,
5320 get_pixel_null,
5321 colorref_to_pixel_null,
5322 pixel_to_colorref_null,
5323 convert_to_null,
5324 create_rop_masks_null,
5325 stretch_row_null,
5326 shrink_row_null