gdi32: Add solid_line primitives.
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blobfa902b9eca1951e16e776839cb6d80012a7a3779
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 BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
3982 if (dst == text) return dst;
3984 if (dst > text)
3986 DWORD diff = dst - text;
3987 DWORD range = max_comp - text;
3988 dst = text + (diff * range ) / (0xff - text);
3989 return dst;
3991 else
3993 DWORD diff = text - dst;
3994 DWORD range = text - min_comp;
3995 dst = text - (diff * range) / text;
3996 return dst;
4000 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
4002 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
4003 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
4004 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
4007 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4008 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4010 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4011 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4012 int x, y;
4014 for (y = rect->top; y < rect->bottom; y++)
4016 for (x = 0; x < rect->right - rect->left; x++)
4018 if (glyph_ptr[x] <= 1) continue;
4019 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4020 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
4022 dst_ptr += dib->stride / 4;
4023 glyph_ptr += glyph->stride;
4027 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4028 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4030 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
4031 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4032 int x, y;
4033 DWORD text, val;
4035 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4036 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4037 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4039 for (y = rect->top; y < rect->bottom; y++)
4041 for (x = 0; x < rect->right - rect->left; x++)
4043 if (glyph_ptr[x] <= 1) continue;
4044 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4045 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4046 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4047 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4048 text, ranges + glyph_ptr[x] );
4049 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4050 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4051 put_field( val, dib->blue_shift, dib->blue_len ));
4053 dst_ptr += dib->stride / 4;
4054 glyph_ptr += glyph->stride;
4058 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4059 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4061 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
4062 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4063 int x, y;
4064 DWORD val;
4066 for (y = rect->top; y < rect->bottom; y++)
4068 for (x = 0; x < rect->right - rect->left; x++)
4070 if (glyph_ptr[x] <= 1) continue;
4071 if (glyph_ptr[x] >= 16)
4072 val = text_pixel;
4073 else
4074 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
4075 text_pixel, ranges + glyph_ptr[x] );
4076 dst_ptr[x * 3] = val;
4077 dst_ptr[x * 3 + 1] = val >> 8;
4078 dst_ptr[x * 3 + 2] = val >> 16;
4080 dst_ptr += dib->stride;
4081 glyph_ptr += glyph->stride;
4085 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4086 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4088 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4089 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4090 int x, y;
4091 DWORD text, val;
4093 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
4094 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
4095 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
4097 for (y = rect->top; y < rect->bottom; y++)
4099 for (x = 0; x < rect->right - rect->left; x++)
4101 if (glyph_ptr[x] <= 1) continue;
4102 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4103 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
4104 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
4105 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
4106 text, ranges + glyph_ptr[x] );
4107 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
4109 dst_ptr += dib->stride / 2;
4110 glyph_ptr += glyph->stride;
4114 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4115 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4117 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
4118 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4119 int x, y;
4120 DWORD text, val;
4122 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
4123 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
4124 get_field( text_pixel, dib->blue_shift, dib->blue_len );
4126 for (y = rect->top; y < rect->bottom; y++)
4128 for (x = 0; x < rect->right - rect->left; x++)
4130 if (glyph_ptr[x] <= 1) continue;
4131 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
4132 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
4133 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
4134 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
4135 text, ranges + glyph_ptr[x] );
4136 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
4137 put_field( val >> 8, dib->green_shift, dib->green_len ) |
4138 put_field( val, dib->blue_shift, dib->blue_len ));
4140 dst_ptr += dib->stride / 2;
4141 glyph_ptr += glyph->stride;
4145 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4146 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4148 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
4149 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
4150 int x, y;
4152 for (y = rect->top; y < rect->bottom; y++)
4154 for (x = 0; x < rect->right - rect->left; x++)
4156 /* no antialiasing, glyph should only contain 0 or 16. */
4157 if (glyph_ptr[x] >= 16)
4158 dst_ptr[x] = text_pixel;
4160 dst_ptr += dib->stride;
4161 glyph_ptr += glyph->stride;
4165 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4166 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4168 BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
4169 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4170 int x, y;
4172 for (y = rect->top; y < rect->bottom; y++)
4174 for (x = rect->left; x < rect->right; x++)
4176 /* no antialiasing, glyph should only contain 0 or 16. */
4177 if (glyph_ptr[x] >= 16)
4179 if (x & 1)
4180 dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
4181 else
4182 dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
4185 dst_ptr += dib->stride;
4186 glyph_ptr += glyph->stride;
4190 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4191 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4193 BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
4194 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
4195 int x, y;
4196 BYTE text = (text_pixel & 1) ? 0xff : 0;
4198 for (y = rect->top; y < rect->bottom; y++)
4200 for (x = rect->left; x < rect->right; x++)
4202 /* no antialiasing, glyph should only contain 0 or 16. */
4203 if (glyph_ptr[x] >= 16)
4204 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
4206 dst_ptr += dib->stride;
4207 glyph_ptr += glyph->stride;
4211 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
4212 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
4214 return;
4217 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)
4219 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4220 DWORD mask_start = 0, mask_offset;
4221 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4222 int x, y;
4224 for(y = 0; y < hatch->height; y++)
4226 hatch_ptr = hatch_start;
4227 mask_offset = mask_start;
4228 for(x = 0; x < hatch->width; x++)
4230 if(*hatch_ptr & pixel_masks_1[x % 8])
4232 and_bits[mask_offset] = fg->and;
4233 xor_bits[mask_offset] = fg->xor;
4235 else
4237 and_bits[mask_offset] = bg->and;
4238 xor_bits[mask_offset] = bg->xor;
4240 if(x % 8 == 7) hatch_ptr++;
4241 mask_offset++;
4243 hatch_start += hatch->stride;
4244 mask_start += dib->stride / 4;
4247 return TRUE;
4250 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)
4252 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4253 DWORD mask_start = 0, mask_offset;
4254 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4255 int x, y;
4257 for(y = 0; y < hatch->height; y++)
4259 hatch_ptr = hatch_start;
4260 mask_offset = mask_start;
4261 for(x = 0; x < hatch->width; x++)
4263 if(*hatch_ptr & pixel_masks_1[x % 8])
4265 and_bits[mask_offset] = fg->and & 0xff;
4266 xor_bits[mask_offset++] = fg->xor & 0xff;
4267 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4268 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4269 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4270 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4272 else
4274 and_bits[mask_offset] = bg->and & 0xff;
4275 xor_bits[mask_offset++] = bg->xor & 0xff;
4276 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4277 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4278 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4279 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4281 if(x % 8 == 7) hatch_ptr++;
4283 hatch_start += hatch->stride;
4284 mask_start += dib->stride;
4287 return TRUE;
4290 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)
4292 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4293 DWORD mask_start = 0, mask_offset;
4294 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4295 int x, y;
4297 for(y = 0; y < hatch->height; y++)
4299 hatch_ptr = hatch_start;
4300 mask_offset = mask_start;
4301 for(x = 0; x < hatch->width; x++)
4303 if(*hatch_ptr & pixel_masks_1[x % 8])
4305 and_bits[mask_offset] = fg->and;
4306 xor_bits[mask_offset] = fg->xor;
4308 else
4310 and_bits[mask_offset] = bg->and;
4311 xor_bits[mask_offset] = bg->xor;
4313 if(x % 8 == 7) hatch_ptr++;
4314 mask_offset++;
4316 hatch_start += hatch->stride;
4317 mask_start += dib->stride / 2;
4320 return TRUE;
4323 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)
4325 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4326 DWORD mask_start = 0, mask_offset;
4327 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4328 int x, y;
4330 for(y = 0; y < hatch->height; y++)
4332 hatch_ptr = hatch_start;
4333 mask_offset = mask_start;
4334 for(x = 0; x < hatch->width; x++)
4336 if(*hatch_ptr & pixel_masks_1[x % 8])
4338 and_bits[mask_offset] = fg->and;
4339 xor_bits[mask_offset] = fg->xor;
4341 else
4343 and_bits[mask_offset] = bg->and;
4344 xor_bits[mask_offset] = bg->xor;
4346 if(x % 8 == 7) hatch_ptr++;
4347 mask_offset++;
4349 hatch_start += hatch->stride;
4350 mask_start += dib->stride;
4353 return TRUE;
4356 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)
4358 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4359 DWORD mask_start = 0, mask_offset;
4360 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4361 const rop_mask *rop_mask;
4362 int x, y;
4364 for(y = 0; y < hatch->height; y++)
4366 hatch_ptr = hatch_start;
4367 mask_offset = mask_start;
4368 for(x = 0; x < hatch->width; x++)
4370 if(*hatch_ptr & pixel_masks_1[x % 8])
4371 rop_mask = fg;
4372 else
4373 rop_mask = bg;
4375 if(x & 1)
4377 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4378 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4379 mask_offset++;
4381 else
4383 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4384 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4387 if(x % 8 == 7) hatch_ptr++;
4389 hatch_start += hatch->stride;
4390 mask_start += dib->stride;
4393 return TRUE;
4396 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)
4398 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4399 DWORD mask_start = 0, mask_offset;
4400 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4401 rop_mask rop_mask;
4402 int x, y, bit_pos;
4404 for(y = 0; y < hatch->height; y++)
4406 hatch_ptr = hatch_start;
4407 mask_offset = mask_start;
4408 for(x = 0, bit_pos = 0; x < hatch->width; x++)
4410 if(*hatch_ptr & pixel_masks_1[x % 8])
4412 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4413 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4415 else
4417 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4418 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4421 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4423 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4424 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4426 if(++bit_pos == 8)
4428 mask_offset++;
4429 hatch_ptr++;
4430 bit_pos = 0;
4433 hatch_start += hatch->stride;
4434 mask_start += dib->stride;
4437 return TRUE;
4440 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)
4442 return FALSE;
4445 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
4447 switch (mode)
4449 default:
4450 case STRETCH_DELETESCANS:
4451 get_rop_codes( R2_COPYPEN, codes );
4452 break;
4453 case STRETCH_ORSCANS:
4454 get_rop_codes( R2_MERGEPEN, codes );
4455 break;
4456 case STRETCH_ANDSCANS:
4457 get_rop_codes( R2_MASKPEN, codes );
4458 break;
4460 return;
4463 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
4464 const dib_info *src_dib, const POINT *src_start,
4465 const struct stretch_params *params, int mode,
4466 BOOL keep_dst)
4468 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4469 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4470 int err = params->err_start;
4471 int width;
4472 struct rop_codes codes;
4474 rop_codes_from_stretch_mode( mode, &codes );
4475 for (width = params->length; width; width--)
4477 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4478 dst_ptr += params->dst_inc;
4479 if (err > 0)
4481 src_ptr += params->src_inc;
4482 err += params->err_add_1;
4484 else err += params->err_add_2;
4488 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
4489 const dib_info *src_dib, const POINT *src_start,
4490 const struct stretch_params *params, int mode,
4491 BOOL keep_dst)
4493 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4494 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4495 int err = params->err_start;
4496 int width;
4497 struct rop_codes codes;
4499 rop_codes_from_stretch_mode( mode, &codes );
4500 for (width = params->length; width; width--)
4502 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4503 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4504 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4505 dst_ptr += 3 * params->dst_inc;
4506 if (err > 0)
4508 src_ptr += 3 * params->src_inc;
4509 err += params->err_add_1;
4511 else err += params->err_add_2;
4515 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
4516 const dib_info *src_dib, const POINT *src_start,
4517 const struct stretch_params *params, int mode,
4518 BOOL keep_dst)
4520 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4521 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4522 int err = params->err_start;
4523 int width;
4524 struct rop_codes codes;
4526 rop_codes_from_stretch_mode( mode, &codes );
4527 for (width = params->length; width; width--)
4529 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4530 dst_ptr += params->dst_inc;
4531 if (err > 0)
4533 src_ptr += params->src_inc;
4534 err += params->err_add_1;
4536 else err += params->err_add_2;
4540 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
4541 const dib_info *src_dib, const POINT *src_start,
4542 const struct stretch_params *params, int mode,
4543 BOOL keep_dst)
4545 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4546 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4547 int err = params->err_start;
4548 int width;
4549 struct rop_codes codes;
4551 rop_codes_from_stretch_mode( mode, &codes );
4552 for (width = params->length; width; width--)
4554 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4555 dst_ptr += params->dst_inc;
4556 if (err > 0)
4558 src_ptr += params->src_inc;
4559 err += params->err_add_1;
4561 else err += params->err_add_2;
4565 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
4566 const dib_info *src_dib, const POINT *src_start,
4567 const struct stretch_params *params, int mode,
4568 BOOL keep_dst)
4570 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
4571 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
4572 int err = params->err_start;
4573 int width, dst_x = dst_start->x, src_x = src_start->x;
4574 struct rop_codes codes;
4575 BYTE src_val;
4577 rop_codes_from_stretch_mode( mode, &codes );
4578 for (width = params->length; width; width--)
4580 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4581 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4583 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
4585 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4586 dst_ptr += params->dst_inc;
4587 dst_x += params->dst_inc;
4589 if (err > 0)
4591 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4592 src_ptr += params->src_inc;
4593 src_x += params->src_inc;
4594 err += params->err_add_1;
4596 else err += params->err_add_2;
4600 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
4601 const dib_info *src_dib, const POINT *src_start,
4602 const struct stretch_params *params, int mode,
4603 BOOL keep_dst)
4605 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4606 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4607 int err = params->err_start;
4608 int width, dst_x = dst_start->x, src_x = src_start->x;
4609 struct rop_codes codes;
4610 BYTE src_val;
4612 rop_codes_from_stretch_mode( mode, &codes );
4613 for (width = params->length; width; width--)
4615 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4616 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4618 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4619 dst_ptr += params->dst_inc;
4620 dst_x += params->dst_inc;
4622 if (err > 0)
4624 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4625 src_ptr += params->src_inc;
4626 src_x += params->src_inc;
4627 err += params->err_add_1;
4629 else err += params->err_add_2;
4633 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
4634 const dib_info *src_dib, const POINT *src_start,
4635 const struct stretch_params *params, int mode,
4636 BOOL keep_dst)
4638 FIXME("bit count %d\n", dst_dib->bit_count);
4639 return;
4642 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
4643 const dib_info *src_dib, const POINT *src_start,
4644 const struct stretch_params *params, int mode,
4645 BOOL keep_dst)
4647 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4648 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4649 int err = params->err_start;
4650 int width;
4651 struct rop_codes codes;
4652 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4653 BOOL new_pix = TRUE;
4655 rop_codes_from_stretch_mode( mode, &codes );
4656 for (width = params->length; width; width--)
4658 if (new_pix && !keep_dst) *dst_ptr = init_val;
4659 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4660 new_pix = FALSE;
4661 src_ptr += params->src_inc;
4662 if (err > 0)
4664 dst_ptr += params->dst_inc;
4665 new_pix = TRUE;
4666 err += params->err_add_1;
4668 else err += params->err_add_2;
4672 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
4673 const dib_info *src_dib, const POINT *src_start,
4674 const struct stretch_params *params, int mode,
4675 BOOL keep_dst)
4677 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4678 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4679 int err = params->err_start;
4680 int width;
4681 struct rop_codes codes;
4682 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4683 BOOL new_pix = TRUE;
4685 rop_codes_from_stretch_mode( mode, &codes );
4686 for (width = params->length; width; width--)
4688 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
4689 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4690 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4691 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4692 new_pix = FALSE;
4693 src_ptr += 3 * params->src_inc;
4694 if (err > 0)
4696 dst_ptr += 3 * params->dst_inc;
4697 new_pix = TRUE;
4698 err += params->err_add_1;
4700 else err += params->err_add_2;
4704 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
4705 const dib_info *src_dib, const POINT *src_start,
4706 const struct stretch_params *params, int mode,
4707 BOOL keep_dst)
4709 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4710 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4711 int err = params->err_start;
4712 int width;
4713 struct rop_codes codes;
4714 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4715 BOOL new_pix = TRUE;
4717 rop_codes_from_stretch_mode( mode, &codes );
4718 for (width = params->length; width; width--)
4720 if (new_pix && !keep_dst) *dst_ptr = init_val;
4721 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4722 new_pix = FALSE;
4723 src_ptr += params->src_inc;
4724 if (err > 0)
4726 dst_ptr += params->dst_inc;
4727 new_pix = TRUE;
4728 err += params->err_add_1;
4730 else err += params->err_add_2;
4734 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
4735 const dib_info *src_dib, const POINT *src_start,
4736 const struct stretch_params *params, int mode,
4737 BOOL keep_dst)
4739 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4740 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4741 int err = params->err_start;
4742 int width;
4743 struct rop_codes codes;
4744 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4745 BOOL new_pix = TRUE;
4747 rop_codes_from_stretch_mode( mode, &codes );
4748 for (width = params->length; width; width--)
4750 if (new_pix && !keep_dst) *dst_ptr = init_val;
4751 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4752 new_pix = FALSE;
4753 src_ptr += params->src_inc;
4754 if (err > 0)
4756 dst_ptr += params->dst_inc;
4757 new_pix = TRUE;
4758 err += params->err_add_1;
4760 else err += params->err_add_2;
4764 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
4765 const dib_info *src_dib, const POINT *src_start,
4766 const struct stretch_params *params, int mode,
4767 BOOL keep_dst)
4769 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4770 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4771 int err = params->err_start;
4772 int width, dst_x = dst_start->x, src_x = src_start->x;
4773 struct rop_codes codes;
4774 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4775 BOOL new_pix = TRUE;
4777 rop_codes_from_stretch_mode( mode, &codes );
4778 for (width = params->length; width; width--)
4780 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4782 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4783 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4785 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4786 new_pix = FALSE;
4788 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4789 src_ptr += params->src_inc;
4790 src_x += params->src_inc;
4792 if (err > 0)
4794 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4795 dst_ptr += params->dst_inc;
4796 dst_x += params->dst_inc;
4797 new_pix = TRUE;
4798 err += params->err_add_1;
4800 else err += params->err_add_2;
4804 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4805 const dib_info *src_dib, const POINT *src_start,
4806 const struct stretch_params *params, int mode,
4807 BOOL keep_dst)
4809 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4810 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4811 int err = params->err_start;
4812 int width, dst_x = dst_start->x, src_x = src_start->x;
4813 struct rop_codes codes;
4814 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4815 BOOL new_pix = TRUE;
4817 rop_codes_from_stretch_mode( mode, &codes );
4818 for (width = params->length; width; width--)
4820 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4821 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4822 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4823 new_pix = FALSE;
4825 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4826 src_ptr += params->src_inc;
4827 src_x += params->src_inc;
4829 if (err > 0)
4831 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4832 dst_ptr += params->dst_inc;
4833 dst_x += params->dst_inc;
4834 new_pix = TRUE;
4835 err += params->err_add_1;
4837 else err += params->err_add_2;
4841 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4842 const dib_info *src_dib, const POINT *src_start,
4843 const struct stretch_params *params, int mode,
4844 BOOL keep_dst)
4846 FIXME("bit count %d\n", dst_dib->bit_count);
4847 return;
4850 const primitive_funcs funcs_8888 =
4852 solid_rects_32,
4853 solid_line_32,
4854 pattern_rects_32,
4855 copy_rect_32,
4856 blend_rect_8888,
4857 draw_glyph_8888,
4858 get_pixel_32,
4859 colorref_to_pixel_888,
4860 pixel_to_colorref_888,
4861 convert_to_8888,
4862 create_rop_masks_32,
4863 stretch_row_32,
4864 shrink_row_32
4867 const primitive_funcs funcs_32 =
4869 solid_rects_32,
4870 solid_line_32,
4871 pattern_rects_32,
4872 copy_rect_32,
4873 blend_rect_32,
4874 draw_glyph_32,
4875 get_pixel_32,
4876 colorref_to_pixel_masks,
4877 pixel_to_colorref_masks,
4878 convert_to_32,
4879 create_rop_masks_32,
4880 stretch_row_32,
4881 shrink_row_32
4884 const primitive_funcs funcs_24 =
4886 solid_rects_24,
4887 solid_line_24,
4888 pattern_rects_24,
4889 copy_rect_24,
4890 blend_rect_24,
4891 draw_glyph_24,
4892 get_pixel_24,
4893 colorref_to_pixel_888,
4894 pixel_to_colorref_888,
4895 convert_to_24,
4896 create_rop_masks_24,
4897 stretch_row_24,
4898 shrink_row_24
4901 const primitive_funcs funcs_555 =
4903 solid_rects_16,
4904 solid_line_16,
4905 pattern_rects_16,
4906 copy_rect_16,
4907 blend_rect_555,
4908 draw_glyph_555,
4909 get_pixel_16,
4910 colorref_to_pixel_555,
4911 pixel_to_colorref_555,
4912 convert_to_555,
4913 create_rop_masks_16,
4914 stretch_row_16,
4915 shrink_row_16
4918 const primitive_funcs funcs_16 =
4920 solid_rects_16,
4921 solid_line_16,
4922 pattern_rects_16,
4923 copy_rect_16,
4924 blend_rect_16,
4925 draw_glyph_16,
4926 get_pixel_16,
4927 colorref_to_pixel_masks,
4928 pixel_to_colorref_masks,
4929 convert_to_16,
4930 create_rop_masks_16,
4931 stretch_row_16,
4932 shrink_row_16
4935 const primitive_funcs funcs_8 =
4937 solid_rects_8,
4938 solid_line_8,
4939 pattern_rects_8,
4940 copy_rect_8,
4941 blend_rect_8,
4942 draw_glyph_8,
4943 get_pixel_8,
4944 colorref_to_pixel_colortable,
4945 pixel_to_colorref_colortable,
4946 convert_to_8,
4947 create_rop_masks_8,
4948 stretch_row_8,
4949 shrink_row_8
4952 const primitive_funcs funcs_4 =
4954 solid_rects_4,
4955 solid_line_4,
4956 pattern_rects_4,
4957 copy_rect_4,
4958 blend_rect_4,
4959 draw_glyph_4,
4960 get_pixel_4,
4961 colorref_to_pixel_colortable,
4962 pixel_to_colorref_colortable,
4963 convert_to_4,
4964 create_rop_masks_4,
4965 stretch_row_4,
4966 shrink_row_4
4969 const primitive_funcs funcs_1 =
4971 solid_rects_1,
4972 solid_line_1,
4973 pattern_rects_1,
4974 copy_rect_1,
4975 blend_rect_1,
4976 draw_glyph_1,
4977 get_pixel_1,
4978 colorref_to_pixel_colortable,
4979 pixel_to_colorref_colortable,
4980 convert_to_1,
4981 create_rop_masks_1,
4982 stretch_row_1,
4983 shrink_row_1
4986 const primitive_funcs funcs_null =
4988 solid_rects_null,
4989 solid_line_null,
4990 pattern_rects_null,
4991 copy_rect_null,
4992 blend_rect_null,
4993 draw_glyph_null,
4994 get_pixel_null,
4995 colorref_to_pixel_null,
4996 pixel_to_colorref_null,
4997 convert_to_null,
4998 create_rop_masks_null,
4999 stretch_row_null,
5000 shrink_row_null