gdi32: Introduce a unified function to perform COLORREF to pixel color mapping.
[wine.git] / dlls / gdi32 / dibdrv / primitives.c
blob7477a790632b4ba4eb3bcafa566dcafce0eb696c
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_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
67 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
69 *ptr = (*ptr & and) ^ xor;
72 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
74 *ptr = (*ptr & and) ^ xor;
77 static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
79 *ptr = (*ptr & and) ^ xor;
82 static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
84 *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
87 static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
89 do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
92 static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
94 do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
97 static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
99 do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
102 static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
104 do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
107 static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
109 for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
112 static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
114 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
115 do_rop_codes_32( dst, *src, codes );
118 static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
120 for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
123 static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
125 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
126 do_rop_codes_16( dst, *src, codes );
129 static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
131 for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
134 static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
136 for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
137 do_rop_codes_8( dst, *src, codes );
140 static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
141 struct rop_codes *codes, int len)
143 BYTE src_val;
145 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
147 if (dst_x & 1)
149 if (src_x & 1) src_val = *src++;
150 else src_val = *src >> 4;
151 do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
153 else
155 if (src_x & 1) src_val = *src++ << 4;
156 else src_val = *src;
157 do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
162 static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
163 struct rop_codes *codes, int len)
165 BYTE src_val;
167 src_x += len - 1;
168 dst_x += len - 1;
169 for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
171 if (dst_x & 1)
173 if (src_x & 1) src_val = *src;
174 else src_val = *src-- >> 4;
175 do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
177 else
179 if (src_x & 1) src_val = *src << 4;
180 else src_val = *src--;
181 do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
186 static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
187 struct rop_codes *codes, int len)
189 BYTE src_val;
191 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
193 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
194 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
195 if ((src_x & 7) == 7) src++;
196 if ((dst_x & 7) == 7) dst++;
200 static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
201 struct rop_codes *codes, int len)
203 BYTE src_val;
205 src_x += len - 1;
206 dst_x += len - 1;
207 for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
209 src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
210 do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
211 if ((src_x & 7) == 0) src--;
212 if ((dst_x & 7) == 0) dst--;
216 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
218 DWORD *ptr, *start;
219 int x, y, i;
221 for(i = 0; i < num; i++, rc++)
223 start = get_pixel_ptr_32(dib, rc->left, rc->top);
224 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
225 for(x = rc->left, ptr = start; x < rc->right; x++)
226 do_rop_32(ptr++, and, xor);
230 static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
232 DWORD *ptr, *start;
233 BYTE *byte_ptr, *byte_start;
234 int x, y, i;
235 DWORD and_masks[3], xor_masks[3];
237 and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
238 and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
239 and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
240 xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
241 xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
242 xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
244 for(i = 0; i < num; i++, rc++)
246 if(rc->left >= rc->right) continue;
248 if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
250 byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
251 for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
253 for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
255 do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
256 do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
257 do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
261 else
263 start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
264 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
266 ptr = start;
268 switch(rc->left & 3)
270 case 1:
271 do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
272 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
273 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
274 break;
275 case 2:
276 do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
277 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
278 break;
279 case 3:
280 do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
281 break;
284 for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
286 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
287 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
288 do_rop_32(ptr++, and_masks[2], xor_masks[2]);
291 switch(rc->right & 3)
293 case 1:
294 do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
295 break;
296 case 2:
297 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
298 do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
299 break;
300 case 3:
301 do_rop_32(ptr++, and_masks[0], xor_masks[0]);
302 do_rop_32(ptr++, and_masks[1], xor_masks[1]);
303 do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
304 break;
311 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
313 WORD *ptr, *start;
314 int x, y, i;
316 for(i = 0; i < num; i++, rc++)
318 start = get_pixel_ptr_16(dib, rc->left, rc->top);
319 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
320 for(x = rc->left, ptr = start; x < rc->right; x++)
321 do_rop_16(ptr++, and, xor);
325 static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
327 BYTE *ptr, *start;
328 int x, y, i;
330 for(i = 0; i < num; i++, rc++)
332 start = get_pixel_ptr_8(dib, rc->left, rc->top);
333 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
334 for(x = rc->left, ptr = start; x < rc->right; x++)
335 do_rop_8(ptr++, and, xor);
339 static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
341 BYTE *ptr, *start;
342 int x, y, i;
343 BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
344 BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
346 for(i = 0; i < num; i++, rc++)
348 if(rc->left >= rc->right) continue;
349 start = get_pixel_ptr_4(dib, rc->left, rc->top);
350 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
352 ptr = start;
353 if(rc->left & 1) /* upper nibble untouched */
354 do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
356 for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
357 do_rop_8(ptr++, byte_and, byte_xor);
359 if(rc->right & 1) /* lower nibble untouched */
360 do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
365 static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
367 BYTE *ptr, *start;
368 int x, y, i;
369 BYTE byte_and = (and & 1) ? 0xff : 0;
370 BYTE byte_xor = (xor & 1) ? 0xff : 0;
371 BYTE start_and, start_xor, end_and, end_xor, mask;
372 static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
374 for(i = 0; i < num; i++, rc++)
376 if(rc->left >= rc->right) continue;
378 start = get_pixel_ptr_1(dib, rc->left, rc->top);
380 if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
382 mask = masks[rc->left & 7] & ~masks[rc->right & 7];
384 start_and = byte_and | ~mask;
385 start_xor = byte_xor & mask;
386 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
388 do_rop_8(start, start_and, start_xor);
391 else
393 mask = masks[rc->left & 7];
394 start_and = byte_and | ~mask;
395 start_xor = byte_xor & mask;
397 mask = masks[rc->right & 7];
398 /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
399 end_and = byte_and | mask;
400 end_xor = byte_xor & ~mask;
402 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
404 ptr = start;
406 if(rc->left & 7)
407 do_rop_8(ptr++, start_and, start_xor);
409 for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
410 do_rop_8(ptr++, byte_and, byte_xor);
412 if(rc->right & 7)
413 do_rop_8(ptr, end_and, end_xor);
419 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
421 return;
424 static inline INT calc_offset(INT edge, INT size, INT origin)
426 INT offset;
428 if(edge - origin >= 0)
429 offset = (edge - origin) % size;
430 else
432 offset = (origin - edge) % size;
433 if(offset) offset = size - offset;
435 return offset;
438 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
440 POINT offset;
442 offset.x = calc_offset(rc->left, brush->width, origin->x);
443 offset.y = calc_offset(rc->top, brush->height, origin->y);
445 return offset;
448 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
449 const dib_info *brush, void *and_bits, void *xor_bits)
451 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
452 int x, y, i;
453 POINT offset;
455 for(i = 0; i < num; i++, rc++)
457 offset = calc_brush_offset(rc, brush, origin);
459 start = get_pixel_ptr_32(dib, rc->left, rc->top);
460 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
461 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
463 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
465 and_ptr = start_and + offset.x;
466 xor_ptr = start_xor + offset.x;
468 for(x = rc->left, ptr = start; x < rc->right; x++)
470 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
471 if(and_ptr == start_and + brush->width)
473 and_ptr = start_and;
474 xor_ptr = start_xor;
478 offset.y++;
479 if(offset.y == brush->height)
481 start_and = and_bits;
482 start_xor = xor_bits;
483 offset.y = 0;
485 else
487 start_and += brush->stride / 4;
488 start_xor += brush->stride / 4;
494 static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
495 const dib_info *brush, void *and_bits, void *xor_bits)
497 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
498 int x, y, i;
499 POINT offset;
501 for(i = 0; i < num; i++, rc++)
503 offset = calc_brush_offset(rc, brush, origin);
505 start = get_pixel_ptr_24(dib, rc->left, rc->top);
506 start_and = (BYTE*)and_bits + offset.y * brush->stride;
507 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
509 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
511 and_ptr = start_and + offset.x * 3;
512 xor_ptr = start_xor + offset.x * 3;
514 for(x = rc->left, ptr = start; x < rc->right; x++)
516 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
517 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
518 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
519 if(and_ptr == start_and + brush->width * 3)
521 and_ptr = start_and;
522 xor_ptr = start_xor;
526 offset.y++;
527 if(offset.y == brush->height)
529 start_and = and_bits;
530 start_xor = xor_bits;
531 offset.y = 0;
533 else
535 start_and += brush->stride;
536 start_xor += brush->stride;
542 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
543 const dib_info *brush, void *and_bits, void *xor_bits)
545 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
546 int x, y, i;
547 POINT offset;
549 for(i = 0; i < num; i++, rc++)
551 offset = calc_brush_offset(rc, brush, origin);
553 start = get_pixel_ptr_16(dib, rc->left, rc->top);
554 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
555 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
557 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
559 and_ptr = start_and + offset.x;
560 xor_ptr = start_xor + offset.x;
562 for(x = rc->left, ptr = start; x < rc->right; x++)
564 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
565 if(and_ptr == start_and + brush->width)
567 and_ptr = start_and;
568 xor_ptr = start_xor;
572 offset.y++;
573 if(offset.y == brush->height)
575 start_and = and_bits;
576 start_xor = xor_bits;
577 offset.y = 0;
579 else
581 start_and += brush->stride / 2;
582 start_xor += brush->stride / 2;
588 static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
589 const dib_info *brush, void *and_bits, void *xor_bits)
591 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
592 int x, y, i;
593 POINT offset;
595 for(i = 0; i < num; i++, rc++)
597 offset = calc_brush_offset(rc, brush, origin);
599 start = get_pixel_ptr_8(dib, rc->left, rc->top);
600 start_and = (BYTE*)and_bits + offset.y * brush->stride;
601 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
603 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
605 and_ptr = start_and + offset.x;
606 xor_ptr = start_xor + offset.x;
608 for(x = rc->left, ptr = start; x < rc->right; x++)
610 do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
611 if(and_ptr == start_and + brush->width)
613 and_ptr = start_and;
614 xor_ptr = start_xor;
618 offset.y++;
619 if(offset.y == brush->height)
621 start_and = and_bits;
622 start_xor = xor_bits;
623 offset.y = 0;
625 else
627 start_and += brush->stride;
628 start_xor += brush->stride;
634 static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
635 const dib_info *brush, void *and_bits, void *xor_bits)
637 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
638 int x, y, i;
639 POINT offset;
641 for(i = 0; i < num; i++, rc++)
643 offset = calc_brush_offset(rc, brush, origin);
645 start = get_pixel_ptr_4(dib, rc->left, rc->top);
646 start_and = (BYTE*)and_bits + offset.y * brush->stride;
647 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
649 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
651 INT brush_x = offset.x;
652 BYTE byte_and, byte_xor;
654 and_ptr = start_and + brush_x / 2;
655 xor_ptr = start_xor + brush_x / 2;
657 for(x = rc->left, ptr = start; x < rc->right; x++)
659 /* FIXME: Two pixels at a time */
660 if(x & 1) /* lower dst nibble */
662 if(brush_x & 1) /* lower pat nibble */
664 byte_and = *and_ptr++ | 0xf0;
665 byte_xor = *xor_ptr++ & 0x0f;
667 else /* upper pat nibble */
669 byte_and = (*and_ptr >> 4) | 0xf0;
670 byte_xor = (*xor_ptr >> 4) & 0x0f;
673 else /* upper dst nibble */
675 if(brush_x & 1) /* lower pat nibble */
677 byte_and = (*and_ptr++ << 4) | 0x0f;
678 byte_xor = (*xor_ptr++ << 4) & 0xf0;
680 else /* upper pat nibble */
682 byte_and = *and_ptr | 0x0f;
683 byte_xor = *xor_ptr & 0xf0;
686 do_rop_8(ptr, byte_and, byte_xor);
688 if(x & 1) ptr++;
690 if(++brush_x == brush->width)
692 brush_x = 0;
693 and_ptr = start_and;
694 xor_ptr = start_xor;
698 offset.y++;
699 if(offset.y == brush->height)
701 start_and = and_bits;
702 start_xor = xor_bits;
703 offset.y = 0;
705 else
707 start_and += brush->stride;
708 start_xor += brush->stride;
714 static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
715 const dib_info *brush, void *and_bits, void *xor_bits)
717 BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
718 int x, y, i;
719 POINT offset;
721 for(i = 0; i < num; i++, rc++)
723 offset = calc_brush_offset(rc, brush, origin);
725 start = get_pixel_ptr_1(dib, rc->left, rc->top);
726 start_and = (BYTE*)and_bits + offset.y * brush->stride;
727 start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
729 for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
731 INT brush_x = offset.x;
732 BYTE byte_and, byte_xor;
734 and_ptr = start_and + brush_x / 8;
735 xor_ptr = start_xor + brush_x / 8;
737 for(x = rc->left, ptr = start; x < rc->right; x++)
739 byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
740 byte_and |= ~pixel_masks_1[x % 8];
741 byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
742 byte_xor &= pixel_masks_1[x % 8];
744 do_rop_8(ptr, byte_and, byte_xor);
746 if((x & 7) == 7) ptr++;
748 if((brush_x & 7) == 7)
750 and_ptr++;
751 xor_ptr++;
754 if(++brush_x == brush->width)
756 brush_x = 0;
757 and_ptr = start_and;
758 xor_ptr = start_xor;
762 offset.y++;
763 if(offset.y == brush->height)
765 start_and = and_bits;
766 start_xor = xor_bits;
767 offset.y = 0;
769 else
771 start_and += brush->stride;
772 start_xor += brush->stride;
778 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
779 const dib_info *brush, void *and_bits, void *xor_bits)
781 return;
784 static void copy_rect_32(const dib_info *dst, const RECT *rc,
785 const dib_info *src, const POINT *origin, int rop2, int overlap)
787 DWORD *dst_start, *src_start;
788 struct rop_codes codes;
789 int y, dst_stride, src_stride;
791 if (overlap & OVERLAP_BELOW)
793 dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
794 src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
795 dst_stride = -dst->stride / 4;
796 src_stride = -src->stride / 4;
798 else
800 dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
801 src_start = get_pixel_ptr_32(src, origin->x, origin->y);
802 dst_stride = dst->stride / 4;
803 src_stride = src->stride / 4;
806 if (rop2 == R2_COPYPEN)
808 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
809 memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
810 return;
813 get_rop_codes( rop2, &codes );
814 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
816 if (overlap & OVERLAP_RIGHT)
817 do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
818 else
819 do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
823 static void copy_rect_24(const dib_info *dst, const RECT *rc,
824 const dib_info *src, const POINT *origin, int rop2, int overlap)
826 BYTE *dst_start, *src_start;
827 int y, dst_stride, src_stride;
828 struct rop_codes codes;
830 if (overlap & OVERLAP_BELOW)
832 dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
833 src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
834 dst_stride = -dst->stride;
835 src_stride = -src->stride;
837 else
839 dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
840 src_start = get_pixel_ptr_24(src, origin->x, origin->y);
841 dst_stride = dst->stride;
842 src_stride = src->stride;
845 if (rop2 == R2_COPYPEN)
847 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
848 memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
849 return;
852 get_rop_codes( rop2, &codes );
853 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
855 if (overlap & OVERLAP_RIGHT)
856 do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
857 else
858 do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
862 static void copy_rect_16(const dib_info *dst, const RECT *rc,
863 const dib_info *src, const POINT *origin, int rop2, int overlap)
865 WORD *dst_start, *src_start;
866 int y, dst_stride, src_stride;
867 struct rop_codes codes;
869 if (overlap & OVERLAP_BELOW)
871 dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
872 src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
873 dst_stride = -dst->stride / 2;
874 src_stride = -src->stride / 2;
876 else
878 dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
879 src_start = get_pixel_ptr_16(src, origin->x, origin->y);
880 dst_stride = dst->stride / 2;
881 src_stride = src->stride / 2;
884 if (rop2 == R2_COPYPEN)
886 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
887 memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
888 return;
891 get_rop_codes( rop2, &codes );
892 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
894 if (overlap & OVERLAP_RIGHT)
895 do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
896 else
897 do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
901 static void copy_rect_8(const dib_info *dst, const RECT *rc,
902 const dib_info *src, const POINT *origin, int rop2, int overlap)
904 BYTE *dst_start, *src_start;
905 int y, dst_stride, src_stride;
906 struct rop_codes codes;
908 if (overlap & OVERLAP_BELOW)
910 dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
911 src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
912 dst_stride = -dst->stride;
913 src_stride = -src->stride;
915 else
917 dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
918 src_start = get_pixel_ptr_8(src, origin->x, origin->y);
919 dst_stride = dst->stride;
920 src_stride = src->stride;
923 if (rop2 == R2_COPYPEN)
925 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
926 memmove( dst_start, src_start, (rc->right - rc->left) );
927 return;
930 get_rop_codes( rop2, &codes );
931 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
933 if (overlap & OVERLAP_RIGHT)
934 do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
935 else
936 do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
940 static void copy_rect_4(const dib_info *dst, const RECT *rc,
941 const dib_info *src, const POINT *origin, int rop2, int overlap)
943 BYTE *dst_start, *src_start;
944 int y, dst_stride, src_stride;
945 struct rop_codes codes;
947 if (overlap & OVERLAP_BELOW)
949 dst_start = get_pixel_ptr_4(dst, 0, rc->bottom - 1);
950 src_start = get_pixel_ptr_4(src, 0, origin->y + rc->bottom - rc->top - 1);
951 dst_stride = -dst->stride;
952 src_stride = -src->stride;
954 else
956 dst_start = get_pixel_ptr_4(dst, 0, rc->top);
957 src_start = get_pixel_ptr_4(src, 0, origin->y);
958 dst_stride = dst->stride;
959 src_stride = src->stride;
962 if (rop2 == R2_COPYPEN && (rc->left & 1) == 0 && (origin->x & 1) == 0 && (rc->right & 1) == 0)
964 dst_start += rc->left / 2;
965 src_start += origin->x / 2;
966 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
967 memmove( dst_start, src_start, (rc->right - rc->left) / 2 );
968 return;
971 get_rop_codes( rop2, &codes );
972 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
974 if (overlap & OVERLAP_RIGHT)
975 do_rop_codes_line_rev_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
976 else
977 do_rop_codes_line_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
981 static void copy_rect_1(const dib_info *dst, const RECT *rc,
982 const dib_info *src, const POINT *origin, int rop2, int overlap)
984 BYTE *dst_start, *src_start;
985 int y, dst_stride, src_stride;
986 struct rop_codes codes;
988 if (overlap & OVERLAP_BELOW)
990 dst_start = get_pixel_ptr_1(dst, 0, rc->bottom - 1);
991 src_start = get_pixel_ptr_1(src, 0, origin->y + rc->bottom - rc->top - 1);
992 dst_stride = -dst->stride;
993 src_stride = -src->stride;
995 else
997 dst_start = get_pixel_ptr_1(dst, 0, rc->top);
998 src_start = get_pixel_ptr_1(src, 0, origin->y);
999 dst_stride = dst->stride;
1000 src_stride = src->stride;
1003 if (rop2 == R2_COPYPEN && (rc->left & 7) == 0 && (origin->x & 7) == 0 && (rc->right & 7) == 0)
1005 dst_start += rc->left / 8;
1006 src_start += origin->x / 8;
1007 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1008 memmove( dst_start, src_start, (rc->right - rc->left) / 8 );
1009 return;
1012 get_rop_codes( rop2, &codes );
1013 for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
1015 if (overlap & OVERLAP_RIGHT)
1016 do_rop_codes_line_rev_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1017 else
1018 do_rop_codes_line_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
1022 static void copy_rect_null(const dib_info *dst, const RECT *rc,
1023 const dib_info *src, const POINT *origin, int rop2, int overlap)
1025 return;
1028 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1030 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1033 static const DWORD field_masks[33] =
1035 0x00, /* should never happen */
1036 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1037 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1038 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1039 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1042 static inline DWORD get_field(DWORD field, int shift, int len)
1044 shift = shift - (8 - len);
1045 if (shift < 0)
1046 field <<= -shift;
1047 else
1048 field >>= shift;
1049 field &= field_masks[len];
1050 field |= field >> len;
1051 return field;
1054 static inline DWORD put_field(DWORD field, int shift, int len)
1056 shift = shift - (8 - len);
1057 field &= field_masks[len];
1058 if (shift < 0)
1059 field >>= -shift;
1060 else
1061 field <<= shift;
1062 return field;
1065 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1067 DWORD r,g,b;
1069 r = GetRValue(colour);
1070 g = GetGValue(colour);
1071 b = GetBValue(colour);
1073 return put_field(r, dib->red_shift, dib->red_len) |
1074 put_field(g, dib->green_shift, dib->green_len) |
1075 put_field(b, dib->blue_shift, dib->blue_len);
1078 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1080 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1083 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1085 int i, best_index = 0;
1086 DWORD diff, best_diff = 0xffffffff;
1088 /* special case for conversion to 1-bpp without a color table:
1089 * we get a 1-entry table containing the background color
1091 if (dib->bit_count == 1 && dib->color_table_size == 1)
1092 return (r == dib->color_table[0].rgbRed &&
1093 g == dib->color_table[0].rgbGreen &&
1094 b == dib->color_table[0].rgbBlue);
1096 for(i = 0; i < dib->color_table_size; i++)
1098 RGBQUAD *cur = dib->color_table + i;
1099 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1100 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1101 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1103 if(diff == 0)
1105 best_index = i;
1106 break;
1109 if(diff < best_diff)
1111 best_diff = diff;
1112 best_index = i;
1115 return best_index;
1118 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1120 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1123 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1125 return 0;
1128 static inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1130 static const RGBQUAD default_rgb;
1131 if (index < dib->color_table_size) return dib->color_table[index];
1132 return default_rgb;
1135 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1137 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1139 return d1->red_mask == d2->red_mask &&
1140 d1->green_mask == d2->green_mask &&
1141 d1->blue_mask == d2->blue_mask;
1144 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1146 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1147 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1149 switch(src->bit_count)
1151 case 32:
1153 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1154 if(src->funcs == &funcs_8888)
1156 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1157 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1158 else
1160 for(y = src_rect->top; y < src_rect->bottom; y++)
1162 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1163 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1164 dst_start += dst->stride / 4;
1165 src_start += src->stride / 4;
1169 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1171 for(y = src_rect->top; y < src_rect->bottom; y++)
1173 dst_pixel = dst_start;
1174 src_pixel = src_start;
1175 for(x = src_rect->left; x < src_rect->right; x++)
1177 src_val = *src_pixel++;
1178 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1179 (((src_val >> src->green_shift) & 0xff) << 8) |
1180 ((src_val >> src->blue_shift) & 0xff);
1182 if(pad_size) memset(dst_pixel, 0, pad_size);
1183 dst_start += dst->stride / 4;
1184 src_start += src->stride / 4;
1187 else
1189 for(y = src_rect->top; y < src_rect->bottom; y++)
1191 dst_pixel = dst_start;
1192 src_pixel = src_start;
1193 for(x = src_rect->left; x < src_rect->right; x++)
1195 src_val = *src_pixel++;
1196 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1197 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1198 get_field( src_val, src->blue_shift, src->blue_len ));
1200 if(pad_size) memset(dst_pixel, 0, pad_size);
1201 dst_start += dst->stride / 4;
1202 src_start += src->stride / 4;
1205 break;
1208 case 24:
1210 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1212 for(y = src_rect->top; y < src_rect->bottom; y++)
1214 dst_pixel = dst_start;
1215 src_pixel = src_start;
1216 for(x = src_rect->left; x < src_rect->right; x++)
1218 RGBQUAD rgb;
1219 rgb.rgbBlue = *src_pixel++;
1220 rgb.rgbGreen = *src_pixel++;
1221 rgb.rgbRed = *src_pixel++;
1223 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1225 if(pad_size) memset(dst_pixel, 0, pad_size);
1226 dst_start += dst->stride / 4;
1227 src_start += src->stride;
1229 break;
1232 case 16:
1234 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1235 if(src->funcs == &funcs_555)
1237 for(y = src_rect->top; y < src_rect->bottom; y++)
1239 dst_pixel = dst_start;
1240 src_pixel = src_start;
1241 for(x = src_rect->left; x < src_rect->right; x++)
1243 src_val = *src_pixel++;
1244 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1245 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1246 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1248 if(pad_size) memset(dst_pixel, 0, pad_size);
1249 dst_start += dst->stride / 4;
1250 src_start += src->stride / 2;
1253 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1255 for(y = src_rect->top; y < src_rect->bottom; y++)
1257 dst_pixel = dst_start;
1258 src_pixel = src_start;
1259 for(x = src_rect->left; x < src_rect->right; x++)
1261 src_val = *src_pixel++;
1262 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1263 (((src_val >> src->red_shift) << 14) & 0x070000) |
1264 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1265 (((src_val >> src->green_shift) << 6) & 0x000700) |
1266 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1267 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1269 if(pad_size) memset(dst_pixel, 0, pad_size);
1270 dst_start += dst->stride / 4;
1271 src_start += src->stride / 2;
1274 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1276 for(y = src_rect->top; y < src_rect->bottom; y++)
1278 dst_pixel = dst_start;
1279 src_pixel = src_start;
1280 for(x = src_rect->left; x < src_rect->right; x++)
1282 src_val = *src_pixel++;
1283 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1284 (((src_val >> src->red_shift) << 14) & 0x070000) |
1285 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1286 (((src_val >> src->green_shift) << 4) & 0x000300) |
1287 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1288 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1290 if(pad_size) memset(dst_pixel, 0, pad_size);
1291 dst_start += dst->stride / 4;
1292 src_start += src->stride / 2;
1295 else
1297 for(y = src_rect->top; y < src_rect->bottom; y++)
1299 dst_pixel = dst_start;
1300 src_pixel = src_start;
1301 for(x = src_rect->left; x < src_rect->right; x++)
1303 src_val = *src_pixel++;
1304 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1305 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1306 get_field( src_val, src->blue_shift, src->blue_len ));
1308 if(pad_size) memset(dst_pixel, 0, pad_size);
1309 dst_start += dst->stride / 4;
1310 src_start += src->stride / 2;
1313 break;
1316 case 8:
1318 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1319 for(y = src_rect->top; y < src_rect->bottom; y++)
1321 dst_pixel = dst_start;
1322 src_pixel = src_start;
1323 for(x = src_rect->left; x < src_rect->right; x++)
1325 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1326 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1328 if(pad_size) memset(dst_pixel, 0, pad_size);
1329 dst_start += dst->stride / 4;
1330 src_start += src->stride;
1332 break;
1335 case 4:
1337 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1338 for(y = src_rect->top; y < src_rect->bottom; y++)
1340 dst_pixel = dst_start;
1341 src_pixel = src_start;
1342 for(x = src_rect->left; x < src_rect->right; x++)
1344 RGBQUAD rgb;
1345 if(x & 1)
1346 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1347 else
1348 rgb = colortable_entry( src, *src_pixel >> 4 );
1349 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1351 if(pad_size) memset(dst_pixel, 0, pad_size);
1352 dst_start += dst->stride / 4;
1353 src_start += src->stride;
1355 break;
1358 case 1:
1360 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1361 for(y = src_rect->top; y < src_rect->bottom; y++)
1363 dst_pixel = dst_start;
1364 src_pixel = src_start;
1365 for(x = src_rect->left; x < src_rect->right; x++)
1367 RGBQUAD rgb;
1368 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1369 if((x % 8) == 7) src_pixel++;
1370 rgb = src->color_table[src_val];
1371 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1373 if(pad_size) memset(dst_pixel, 0, pad_size);
1374 dst_start += dst->stride / 4;
1375 src_start += src->stride;
1377 break;
1382 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1384 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1385 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1387 switch(src->bit_count)
1389 case 32:
1391 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1393 if(src->funcs == &funcs_8888)
1395 for(y = src_rect->top; y < src_rect->bottom; y++)
1397 dst_pixel = dst_start;
1398 src_pixel = src_start;
1399 for(x = src_rect->left; x < src_rect->right; x++)
1401 src_val = *src_pixel++;
1402 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1403 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1404 put_field(src_val, dst->blue_shift, dst->blue_len);
1406 if(pad_size) memset(dst_pixel, 0, pad_size);
1407 dst_start += dst->stride / 4;
1408 src_start += src->stride / 4;
1411 else if(bit_fields_match(src, dst))
1413 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1414 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1415 else
1417 for(y = src_rect->top; y < src_rect->bottom; y++)
1419 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1420 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1421 dst_start += dst->stride / 4;
1422 src_start += src->stride / 4;
1426 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1427 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1429 for(y = src_rect->top; y < src_rect->bottom; y++)
1431 dst_pixel = dst_start;
1432 src_pixel = src_start;
1433 for(x = src_rect->left; x < src_rect->right; x++)
1435 src_val = *src_pixel++;
1436 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1437 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1438 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1440 if(pad_size) memset(dst_pixel, 0, pad_size);
1441 dst_start += dst->stride / 4;
1442 src_start += src->stride / 4;
1445 else
1447 for(y = src_rect->top; y < src_rect->bottom; y++)
1449 dst_pixel = dst_start;
1450 src_pixel = src_start;
1451 for(x = src_rect->left; x < src_rect->right; x++)
1453 src_val = *src_pixel++;
1454 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1455 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1456 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1458 if(pad_size) memset(dst_pixel, 0, pad_size);
1459 dst_start += dst->stride / 4;
1460 src_start += src->stride / 4;
1463 break;
1466 case 24:
1468 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1470 for(y = src_rect->top; y < src_rect->bottom; y++)
1472 dst_pixel = dst_start;
1473 src_pixel = src_start;
1474 for(x = src_rect->left; x < src_rect->right; x++)
1476 RGBQUAD rgb;
1477 rgb.rgbBlue = *src_pixel++;
1478 rgb.rgbGreen = *src_pixel++;
1479 rgb.rgbRed = *src_pixel++;
1481 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1482 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1483 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1485 if(pad_size) memset(dst_pixel, 0, pad_size);
1486 dst_start += dst->stride / 4;
1487 src_start += src->stride;
1489 break;
1492 case 16:
1494 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1495 if(src->funcs == &funcs_555)
1497 for(y = src_rect->top; y < src_rect->bottom; y++)
1499 dst_pixel = dst_start;
1500 src_pixel = src_start;
1501 for(x = src_rect->left; x < src_rect->right; x++)
1503 src_val = *src_pixel++;
1504 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1505 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1506 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1508 if(pad_size) memset(dst_pixel, 0, pad_size);
1509 dst_start += dst->stride / 4;
1510 src_start += src->stride / 2;
1513 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1515 for(y = src_rect->top; y < src_rect->bottom; y++)
1517 dst_pixel = dst_start;
1518 src_pixel = src_start;
1519 for(x = src_rect->left; x < src_rect->right; x++)
1521 src_val = *src_pixel++;
1522 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1523 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1524 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1525 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1526 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1527 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1529 if(pad_size) memset(dst_pixel, 0, pad_size);
1530 dst_start += dst->stride / 4;
1531 src_start += src->stride / 2;
1534 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1536 for(y = src_rect->top; y < src_rect->bottom; y++)
1538 dst_pixel = dst_start;
1539 src_pixel = src_start;
1540 for(x = src_rect->left; x < src_rect->right; x++)
1542 src_val = *src_pixel++;
1543 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1544 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1545 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1546 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1547 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1548 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1550 if(pad_size) memset(dst_pixel, 0, pad_size);
1551 dst_start += dst->stride / 4;
1552 src_start += src->stride / 2;
1555 else
1557 for(y = src_rect->top; y < src_rect->bottom; y++)
1559 dst_pixel = dst_start;
1560 src_pixel = src_start;
1561 for(x = src_rect->left; x < src_rect->right; x++)
1563 src_val = *src_pixel++;
1564 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1565 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1566 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1568 if(pad_size) memset(dst_pixel, 0, pad_size);
1569 dst_start += dst->stride / 4;
1570 src_start += src->stride / 2;
1573 break;
1576 case 8:
1578 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1579 for(y = src_rect->top; y < src_rect->bottom; y++)
1581 dst_pixel = dst_start;
1582 src_pixel = src_start;
1583 for(x = src_rect->left; x < src_rect->right; x++)
1585 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1586 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1587 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1588 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1590 if(pad_size) memset(dst_pixel, 0, pad_size);
1591 dst_start += dst->stride / 4;
1592 src_start += src->stride;
1594 break;
1597 case 4:
1599 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1600 for(y = src_rect->top; y < src_rect->bottom; y++)
1602 dst_pixel = dst_start;
1603 src_pixel = src_start;
1604 for(x = src_rect->left; x < src_rect->right; x++)
1606 RGBQUAD rgb;
1607 if(x & 1)
1608 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1609 else
1610 rgb = colortable_entry( src, *src_pixel >> 4 );
1611 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1612 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1613 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1615 if(pad_size) memset(dst_pixel, 0, pad_size);
1616 dst_start += dst->stride / 4;
1617 src_start += src->stride;
1619 break;
1622 case 1:
1624 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1625 for(y = src_rect->top; y < src_rect->bottom; y++)
1627 dst_pixel = dst_start;
1628 src_pixel = src_start;
1629 for(x = src_rect->left; x < src_rect->right; x++)
1631 RGBQUAD rgb;
1632 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1633 if((x % 8) == 7) src_pixel++;
1634 rgb = src->color_table[src_val];
1635 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1636 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1637 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1639 if(pad_size) memset(dst_pixel, 0, pad_size);
1640 dst_start += dst->stride / 4;
1641 src_start += src->stride;
1643 break;
1648 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1650 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1651 DWORD src_val;
1652 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1654 switch(src->bit_count)
1656 case 32:
1658 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1659 if(src->funcs == &funcs_8888)
1661 for(y = src_rect->top; y < src_rect->bottom; y++)
1663 dst_pixel = dst_start;
1664 src_pixel = src_start;
1665 for(x = src_rect->left; x < src_rect->right; x++)
1667 src_val = *src_pixel++;
1668 *dst_pixel++ = src_val & 0xff;
1669 *dst_pixel++ = (src_val >> 8) & 0xff;
1670 *dst_pixel++ = (src_val >> 16) & 0xff;
1672 if(pad_size) memset(dst_pixel, 0, pad_size);
1673 dst_start += dst->stride;
1674 src_start += src->stride / 4;
1677 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1679 for(y = src_rect->top; y < src_rect->bottom; y++)
1681 dst_pixel = dst_start;
1682 src_pixel = src_start;
1683 for(x = src_rect->left; x < src_rect->right; x++)
1685 src_val = *src_pixel++;
1686 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
1687 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1688 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
1690 if(pad_size) memset(dst_pixel, 0, pad_size);
1691 dst_start += dst->stride;
1692 src_start += src->stride / 4;
1695 else
1697 for(y = src_rect->top; y < src_rect->bottom; y++)
1699 dst_pixel = dst_start;
1700 src_pixel = src_start;
1701 for(x = src_rect->left; x < src_rect->right; x++)
1703 src_val = *src_pixel++;
1704 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
1705 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
1706 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
1708 if(pad_size) memset(dst_pixel, 0, pad_size);
1709 dst_start += dst->stride;
1710 src_start += src->stride / 4;
1713 break;
1716 case 24:
1718 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1720 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1721 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1722 else
1724 for(y = src_rect->top; y < src_rect->bottom; y++)
1726 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1727 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1728 dst_start += dst->stride;
1729 src_start += src->stride;
1732 break;
1735 case 16:
1737 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1738 if(src->funcs == &funcs_555)
1740 for(y = src_rect->top; y < src_rect->bottom; y++)
1742 dst_pixel = dst_start;
1743 src_pixel = src_start;
1744 for(x = src_rect->left; x < src_rect->right; x++)
1746 src_val = *src_pixel++;
1747 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
1748 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
1749 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1751 if(pad_size) memset(dst_pixel, 0, pad_size);
1752 dst_start += dst->stride;
1753 src_start += src->stride / 2;
1756 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1758 for(y = src_rect->top; y < src_rect->bottom; y++)
1760 dst_pixel = dst_start;
1761 src_pixel = src_start;
1762 for(x = src_rect->left; x < src_rect->right; x++)
1764 src_val = *src_pixel++;
1765 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1766 (((src_val >> src->blue_shift) >> 2) & 0x07);
1767 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1768 (((src_val >> src->green_shift) >> 2) & 0x07);
1769 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1770 (((src_val >> src->red_shift) >> 2) & 0x07);
1772 if(pad_size) memset(dst_pixel, 0, pad_size);
1773 dst_start += dst->stride;
1774 src_start += src->stride / 2;
1777 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1779 for(y = src_rect->top; y < src_rect->bottom; y++)
1781 dst_pixel = dst_start;
1782 src_pixel = src_start;
1783 for(x = src_rect->left; x < src_rect->right; x++)
1785 src_val = *src_pixel++;
1786 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1787 (((src_val >> src->blue_shift) >> 2) & 0x07);
1788 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1789 (((src_val >> src->green_shift) >> 4) & 0x03);
1790 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1791 (((src_val >> src->red_shift) >> 2) & 0x07);
1793 if(pad_size) memset(dst_pixel, 0, pad_size);
1794 dst_start += dst->stride;
1795 src_start += src->stride / 2;
1798 else
1800 for(y = src_rect->top; y < src_rect->bottom; y++)
1802 dst_pixel = dst_start;
1803 src_pixel = src_start;
1804 for(x = src_rect->left; x < src_rect->right; x++)
1806 src_val = *src_pixel++;
1807 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
1808 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
1809 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
1811 if(pad_size) memset(dst_pixel, 0, pad_size);
1812 dst_start += dst->stride;
1813 src_start += src->stride / 2;
1816 break;
1819 case 8:
1821 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1822 for(y = src_rect->top; y < src_rect->bottom; y++)
1824 dst_pixel = dst_start;
1825 src_pixel = src_start;
1826 for(x = src_rect->left; x < src_rect->right; x++)
1828 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1829 *dst_pixel++ = rgb.rgbBlue;
1830 *dst_pixel++ = rgb.rgbGreen;
1831 *dst_pixel++ = rgb.rgbRed;
1833 if(pad_size) memset(dst_pixel, 0, pad_size);
1834 dst_start += dst->stride;
1835 src_start += src->stride;
1837 break;
1840 case 4:
1842 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1843 for(y = src_rect->top; y < src_rect->bottom; y++)
1845 dst_pixel = dst_start;
1846 src_pixel = src_start;
1847 for(x = src_rect->left; x < src_rect->right; x++)
1849 RGBQUAD rgb;
1850 if(x & 1)
1851 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1852 else
1853 rgb = colortable_entry( src, *src_pixel >> 4 );
1854 *dst_pixel++ = rgb.rgbBlue;
1855 *dst_pixel++ = rgb.rgbGreen;
1856 *dst_pixel++ = rgb.rgbRed;
1858 if(pad_size) memset(dst_pixel, 0, pad_size);
1859 dst_start += dst->stride;
1860 src_start += src->stride;
1862 break;
1865 case 1:
1867 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1868 for(y = src_rect->top; y < src_rect->bottom; y++)
1870 dst_pixel = dst_start;
1871 src_pixel = src_start;
1872 for(x = src_rect->left; x < src_rect->right; x++)
1874 RGBQUAD rgb;
1875 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1876 if((x % 8) == 7) src_pixel++;
1877 rgb = src->color_table[src_val];
1878 *dst_pixel++ = rgb.rgbBlue;
1879 *dst_pixel++ = rgb.rgbGreen;
1880 *dst_pixel++ = rgb.rgbRed;
1882 if(pad_size) memset(dst_pixel, 0, pad_size);
1883 dst_start += dst->stride;
1884 src_start += src->stride;
1886 break;
1891 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1893 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
1894 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1895 DWORD src_val;
1897 switch(src->bit_count)
1899 case 32:
1901 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1903 if(src->funcs == &funcs_8888)
1905 for(y = src_rect->top; y < src_rect->bottom; y++)
1907 dst_pixel = dst_start;
1908 src_pixel = src_start;
1909 for(x = src_rect->left; x < src_rect->right; x++)
1911 src_val = *src_pixel++;
1912 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1913 ((src_val >> 6) & 0x03e0) |
1914 ((src_val >> 3) & 0x001f);
1916 if(pad_size) memset(dst_pixel, 0, pad_size);
1917 dst_start += dst->stride / 2;
1918 src_start += src->stride / 4;
1921 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1923 for(y = src_rect->top; y < src_rect->bottom; y++)
1925 dst_pixel = dst_start;
1926 src_pixel = src_start;
1927 for(x = src_rect->left; x < src_rect->right; x++)
1929 src_val = *src_pixel++;
1930 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
1931 (((src_val >> src->green_shift) << 2) & 0x03e0) |
1932 (((src_val >> src->blue_shift) >> 3) & 0x001f);
1934 if(pad_size) memset(dst_pixel, 0, pad_size);
1935 dst_start += dst->stride / 2;
1936 src_start += src->stride / 4;
1939 else
1941 for(y = src_rect->top; y < src_rect->bottom; y++)
1943 dst_pixel = dst_start;
1944 src_pixel = src_start;
1945 for(x = src_rect->left; x < src_rect->right; x++)
1947 src_val = *src_pixel++;
1948 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
1949 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
1950 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
1952 if(pad_size) memset(dst_pixel, 0, pad_size);
1953 dst_start += dst->stride / 2;
1954 src_start += src->stride / 4;
1957 break;
1960 case 24:
1962 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1964 for(y = src_rect->top; y < src_rect->bottom; y++)
1966 dst_pixel = dst_start;
1967 src_pixel = src_start;
1968 for(x = src_rect->left; x < src_rect->right; x++)
1970 RGBQUAD rgb;
1971 rgb.rgbBlue = *src_pixel++;
1972 rgb.rgbGreen = *src_pixel++;
1973 rgb.rgbRed = *src_pixel++;
1975 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
1976 ((rgb.rgbGreen << 2) & 0x03e0) |
1977 ((rgb.rgbBlue >> 3) & 0x001f);
1979 if(pad_size) memset(dst_pixel, 0, pad_size);
1980 dst_start += dst->stride / 2;
1981 src_start += src->stride;
1983 break;
1986 case 16:
1988 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1989 if(src->funcs == &funcs_555)
1991 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1992 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1993 else
1995 for(y = src_rect->top; y < src_rect->bottom; y++)
1997 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
1998 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1999 dst_start += dst->stride / 2;
2000 src_start += src->stride / 2;
2004 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2006 for(y = src_rect->top; y < src_rect->bottom; y++)
2008 dst_pixel = dst_start;
2009 src_pixel = src_start;
2010 for(x = src_rect->left; x < src_rect->right; x++)
2012 src_val = *src_pixel++;
2013 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2014 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2015 ( (src_val >> src->blue_shift) & 0x001f);
2017 if(pad_size) memset(dst_pixel, 0, pad_size);
2018 dst_start += dst->stride / 2;
2019 src_start += src->stride / 2;
2022 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2024 for(y = src_rect->top; y < src_rect->bottom; y++)
2026 dst_pixel = dst_start;
2027 src_pixel = src_start;
2028 for(x = src_rect->left; x < src_rect->right; x++)
2030 src_val = *src_pixel++;
2031 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2032 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2033 ( (src_val >> src->blue_shift) & 0x001f);
2035 if(pad_size) memset(dst_pixel, 0, pad_size);
2036 dst_start += dst->stride / 2;
2037 src_start += src->stride / 2;
2040 else
2042 for(y = src_rect->top; y < src_rect->bottom; y++)
2044 dst_pixel = dst_start;
2045 src_pixel = src_start;
2046 for(x = src_rect->left; x < src_rect->right; x++)
2048 src_val = *src_pixel++;
2049 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2050 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2051 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2053 if(pad_size) memset(dst_pixel, 0, pad_size);
2054 dst_start += dst->stride / 2;
2055 src_start += src->stride / 2;
2058 break;
2061 case 8:
2063 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2064 for(y = src_rect->top; y < src_rect->bottom; y++)
2066 dst_pixel = dst_start;
2067 src_pixel = src_start;
2068 for(x = src_rect->left; x < src_rect->right; x++)
2070 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2071 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2072 ((rgb.rgbGreen << 2) & 0x03e0) |
2073 ((rgb.rgbBlue >> 3) & 0x001f);
2075 if(pad_size) memset(dst_pixel, 0, pad_size);
2076 dst_start += dst->stride / 2;
2077 src_start += src->stride;
2079 break;
2082 case 4:
2084 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2085 for(y = src_rect->top; y < src_rect->bottom; y++)
2087 dst_pixel = dst_start;
2088 src_pixel = src_start;
2089 for(x = src_rect->left; x < src_rect->right; x++)
2091 RGBQUAD rgb;
2092 if(x & 1)
2093 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2094 else
2095 rgb = colortable_entry( src, *src_pixel >> 4 );
2096 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2097 ((rgb.rgbGreen << 2) & 0x03e0) |
2098 ((rgb.rgbBlue >> 3) & 0x001f);
2100 if(pad_size) memset(dst_pixel, 0, pad_size);
2101 dst_start += dst->stride / 2;
2102 src_start += src->stride;
2104 break;
2107 case 1:
2109 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2110 for(y = src_rect->top; y < src_rect->bottom; y++)
2112 dst_pixel = dst_start;
2113 src_pixel = src_start;
2114 for(x = src_rect->left; x < src_rect->right; x++)
2116 RGBQUAD rgb;
2117 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2118 if((x % 8) == 7) src_pixel++;
2119 rgb = src->color_table[src_val];
2120 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2121 ((rgb.rgbGreen << 2) & 0x03e0) |
2122 ((rgb.rgbBlue >> 3) & 0x001f);
2124 if(pad_size) memset(dst_pixel, 0, pad_size);
2125 dst_start += dst->stride / 2;
2126 src_start += src->stride;
2128 break;
2133 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2135 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2136 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2137 DWORD src_val;
2139 switch(src->bit_count)
2141 case 32:
2143 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2145 if(src->funcs == &funcs_8888)
2147 for(y = src_rect->top; y < src_rect->bottom; y++)
2149 dst_pixel = dst_start;
2150 src_pixel = src_start;
2151 for(x = src_rect->left; x < src_rect->right; x++)
2153 src_val = *src_pixel++;
2154 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2155 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2156 put_field(src_val, dst->blue_shift, dst->blue_len);
2158 if(pad_size) memset(dst_pixel, 0, pad_size);
2159 dst_start += dst->stride / 2;
2160 src_start += src->stride / 4;
2163 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
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 src_val = *src_pixel++;
2172 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2173 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2174 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2176 if(pad_size) memset(dst_pixel, 0, pad_size);
2177 dst_start += dst->stride / 2;
2178 src_start += src->stride / 4;
2181 else
2183 for(y = src_rect->top; y < src_rect->bottom; y++)
2185 dst_pixel = dst_start;
2186 src_pixel = src_start;
2187 for(x = src_rect->left; x < src_rect->right; x++)
2189 src_val = *src_pixel++;
2190 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2191 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2192 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2194 if(pad_size) memset(dst_pixel, 0, pad_size);
2195 dst_start += dst->stride / 2;
2196 src_start += src->stride / 4;
2199 break;
2202 case 24:
2204 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2206 for(y = src_rect->top; y < src_rect->bottom; y++)
2208 dst_pixel = dst_start;
2209 src_pixel = src_start;
2210 for(x = src_rect->left; x < src_rect->right; x++)
2212 RGBQUAD rgb;
2213 rgb.rgbBlue = *src_pixel++;
2214 rgb.rgbGreen = *src_pixel++;
2215 rgb.rgbRed = *src_pixel++;
2217 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2218 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2219 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2221 if(pad_size) memset(dst_pixel, 0, pad_size);
2222 dst_start += dst->stride / 2;
2223 src_start += src->stride;
2225 break;
2228 case 16:
2230 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2231 if(src->funcs == &funcs_555)
2233 for(y = src_rect->top; y < src_rect->bottom; y++)
2235 dst_pixel = dst_start;
2236 src_pixel = src_start;
2237 for(x = src_rect->left; x < src_rect->right; x++)
2239 src_val = *src_pixel++;
2240 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2241 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2242 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2244 if(pad_size) memset(dst_pixel, 0, pad_size);
2245 dst_start += dst->stride / 2;
2246 src_start += src->stride / 2;
2249 else if(bit_fields_match(src, dst))
2251 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2252 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2253 else
2255 for(y = src_rect->top; y < src_rect->bottom; y++)
2257 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2258 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2259 dst_start += dst->stride / 2;
2260 src_start += src->stride / 2;
2264 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2266 for(y = src_rect->top; y < src_rect->bottom; y++)
2268 dst_pixel = dst_start;
2269 src_pixel = src_start;
2270 for(x = src_rect->left; x < src_rect->right; x++)
2272 src_val = *src_pixel++;
2273 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2274 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2275 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2276 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2277 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2278 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2280 if(pad_size) memset(dst_pixel, 0, pad_size);
2281 dst_start += dst->stride / 2;
2282 src_start += src->stride / 2;
2285 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2287 for(y = src_rect->top; y < src_rect->bottom; y++)
2289 dst_pixel = dst_start;
2290 src_pixel = src_start;
2291 for(x = src_rect->left; x < src_rect->right; x++)
2293 src_val = *src_pixel++;
2294 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2295 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2296 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2297 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2298 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2299 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2301 if(pad_size) memset(dst_pixel, 0, pad_size);
2302 dst_start += dst->stride / 2;
2303 src_start += src->stride / 2;
2306 else
2308 for(y = src_rect->top; y < src_rect->bottom; y++)
2310 dst_pixel = dst_start;
2311 src_pixel = src_start;
2312 for(x = src_rect->left; x < src_rect->right; x++)
2314 src_val = *src_pixel++;
2315 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2316 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2317 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2319 if(pad_size) memset(dst_pixel, 0, pad_size);
2320 dst_start += dst->stride / 2;
2321 src_start += src->stride / 2;
2324 break;
2327 case 8:
2329 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2330 for(y = src_rect->top; y < src_rect->bottom; y++)
2332 dst_pixel = dst_start;
2333 src_pixel = src_start;
2334 for(x = src_rect->left; x < src_rect->right; x++)
2336 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2337 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2338 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2339 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2341 if(pad_size) memset(dst_pixel, 0, pad_size);
2342 dst_start += dst->stride / 2;
2343 src_start += src->stride;
2345 break;
2348 case 4:
2350 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2351 for(y = src_rect->top; y < src_rect->bottom; y++)
2353 dst_pixel = dst_start;
2354 src_pixel = src_start;
2355 for(x = src_rect->left; x < src_rect->right; x++)
2357 RGBQUAD rgb;
2358 if(x & 1)
2359 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2360 else
2361 rgb = colortable_entry( src, *src_pixel >> 4 );
2362 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2363 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2364 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2366 if(pad_size) memset(dst_pixel, 0, pad_size);
2367 dst_start += dst->stride / 2;
2368 src_start += src->stride;
2370 break;
2373 case 1:
2375 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2376 for(y = src_rect->top; y < src_rect->bottom; y++)
2378 dst_pixel = dst_start;
2379 src_pixel = src_start;
2380 for(x = src_rect->left; x < src_rect->right; x++)
2382 RGBQUAD rgb;
2383 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2384 if((x % 8) == 7) src_pixel++;
2385 rgb = src->color_table[src_val];
2386 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2387 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2388 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2390 if(pad_size) memset(dst_pixel, 0, pad_size);
2391 dst_start += dst->stride / 2;
2392 src_start += src->stride;
2394 break;
2399 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2401 assert(d1->color_table_size && d2->color_table_size);
2403 if(d1->color_table_size != d2->color_table_size) return FALSE;
2404 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2407 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2409 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2410 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2413 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2415 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2416 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2417 DWORD src_val;
2419 switch(src->bit_count)
2421 case 32:
2423 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2425 if(src->funcs == &funcs_8888)
2427 for(y = src_rect->top; y < src_rect->bottom; y++)
2429 dst_pixel = dst_start;
2430 src_pixel = src_start;
2431 for(x = src_rect->left; x < src_rect->right; x++)
2433 src_val = *src_pixel++;
2434 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2436 if(pad_size) memset(dst_pixel, 0, pad_size);
2437 dst_start += dst->stride;
2438 src_start += src->stride / 4;
2441 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2443 for(y = src_rect->top; y < src_rect->bottom; y++)
2445 dst_pixel = dst_start;
2446 src_pixel = src_start;
2447 for(x = src_rect->left; x < src_rect->right; x++)
2449 src_val = *src_pixel++;
2450 *dst_pixel++ = rgb_lookup_colortable(dst,
2451 src_val >> src->red_shift,
2452 src_val >> src->green_shift,
2453 src_val >> src->blue_shift );
2455 if(pad_size) memset(dst_pixel, 0, pad_size);
2456 dst_start += dst->stride;
2457 src_start += src->stride / 4;
2460 else
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++ = rgb_lookup_colortable(dst,
2470 get_field(src_val, src->red_shift, src->red_len),
2471 get_field(src_val, src->green_shift, src->green_len),
2472 get_field(src_val, src->blue_shift, src->blue_len));
2474 if(pad_size) memset(dst_pixel, 0, pad_size);
2475 dst_start += dst->stride;
2476 src_start += src->stride / 4;
2479 break;
2482 case 24:
2484 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2486 for(y = src_rect->top; y < src_rect->bottom; y++)
2488 dst_pixel = dst_start;
2489 src_pixel = src_start;
2490 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2492 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2494 if(pad_size) memset(dst_pixel, 0, pad_size);
2495 dst_start += dst->stride;
2496 src_start += src->stride;
2498 break;
2501 case 16:
2503 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2504 if(src->funcs == &funcs_555)
2506 for(y = src_rect->top; y < src_rect->bottom; y++)
2508 dst_pixel = dst_start;
2509 src_pixel = src_start;
2510 for(x = src_rect->left; x < src_rect->right; x++)
2512 src_val = *src_pixel++;
2513 *dst_pixel++ = rgb_lookup_colortable(dst,
2514 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2515 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2516 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2518 if(pad_size) memset(dst_pixel, 0, pad_size);
2519 dst_start += dst->stride;
2520 src_start += src->stride / 2;
2523 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2525 for(y = src_rect->top; y < src_rect->bottom; y++)
2527 dst_pixel = dst_start;
2528 src_pixel = src_start;
2529 for(x = src_rect->left; x < src_rect->right; x++)
2531 src_val = *src_pixel++;
2532 *dst_pixel++ = rgb_lookup_colortable(dst,
2533 (((src_val >> src->red_shift) << 3) & 0xf8) |
2534 (((src_val >> src->red_shift) >> 2) & 0x07),
2535 (((src_val >> src->green_shift) << 3) & 0xf8) |
2536 (((src_val >> src->green_shift) >> 2) & 0x07),
2537 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2538 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2540 if(pad_size) memset(dst_pixel, 0, pad_size);
2541 dst_start += dst->stride;
2542 src_start += src->stride / 2;
2545 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2547 for(y = src_rect->top; y < src_rect->bottom; y++)
2549 dst_pixel = dst_start;
2550 src_pixel = src_start;
2551 for(x = src_rect->left; x < src_rect->right; x++)
2553 src_val = *src_pixel++;
2554 *dst_pixel++ = rgb_lookup_colortable(dst,
2555 (((src_val >> src->red_shift) << 3) & 0xf8) |
2556 (((src_val >> src->red_shift) >> 2) & 0x07),
2557 (((src_val >> src->green_shift) << 2) & 0xfc) |
2558 (((src_val >> src->green_shift) >> 4) & 0x03),
2559 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2560 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2562 if(pad_size) memset(dst_pixel, 0, pad_size);
2563 dst_start += dst->stride;
2564 src_start += src->stride / 2;
2567 else
2569 for(y = src_rect->top; y < src_rect->bottom; y++)
2571 dst_pixel = dst_start;
2572 src_pixel = src_start;
2573 for(x = src_rect->left; x < src_rect->right; x++)
2575 src_val = *src_pixel++;
2576 *dst_pixel++ = rgb_lookup_colortable(dst,
2577 get_field(src_val, src->red_shift, src->red_len),
2578 get_field(src_val, src->green_shift, src->green_len),
2579 get_field(src_val, src->blue_shift, src->blue_len));
2581 if(pad_size) memset(dst_pixel, 0, pad_size);
2582 dst_start += dst->stride;
2583 src_start += src->stride / 2;
2586 break;
2589 case 8:
2591 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2593 if(color_tables_match(dst, src))
2595 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2596 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2597 else
2599 for(y = src_rect->top; y < src_rect->bottom; y++)
2601 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2602 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2603 dst_start += dst->stride;
2604 src_start += src->stride;
2608 else
2610 for(y = src_rect->top; y < src_rect->bottom; y++)
2612 dst_pixel = dst_start;
2613 src_pixel = src_start;
2614 for(x = src_rect->left; x < src_rect->right; x++)
2616 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2617 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2619 if(pad_size) memset(dst_pixel, 0, pad_size);
2620 dst_start += dst->stride;
2621 src_start += src->stride;
2624 break;
2627 case 4:
2629 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2630 for(y = src_rect->top; y < src_rect->bottom; y++)
2632 dst_pixel = dst_start;
2633 src_pixel = src_start;
2634 for(x = src_rect->left; x < src_rect->right; x++)
2636 RGBQUAD rgb;
2637 if(x & 1)
2638 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2639 else
2640 rgb = colortable_entry( src, *src_pixel >> 4 );
2641 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2643 if(pad_size) memset(dst_pixel, 0, pad_size);
2644 dst_start += dst->stride;
2645 src_start += src->stride;
2647 break;
2650 case 1:
2652 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2653 for(y = src_rect->top; y < src_rect->bottom; y++)
2655 dst_pixel = dst_start;
2656 src_pixel = src_start;
2657 for(x = src_rect->left; x < src_rect->right; x++)
2659 RGBQUAD rgb;
2660 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2661 if((x % 8) == 7) src_pixel++;
2662 rgb = src->color_table[src_val];
2663 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2665 if(pad_size) memset(dst_pixel, 0, pad_size);
2666 dst_start += dst->stride;
2667 src_start += src->stride;
2669 break;
2674 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2676 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2677 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2678 DWORD src_val;
2680 switch(src->bit_count)
2682 case 32:
2684 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2686 if(src->funcs == &funcs_8888)
2688 for(y = src_rect->top; y < src_rect->bottom; y++)
2690 dst_pixel = dst_start;
2691 src_pixel = src_start;
2692 for(x = src_rect->left; x < src_rect->right; x++)
2694 src_val = *src_pixel++;
2695 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
2696 if((x - src_rect->left) & 1)
2698 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2699 dst_pixel++;
2701 else
2702 *dst_pixel = (dst_val << 4) & 0xf0;
2704 if(pad_size)
2706 if((x - src_rect->left) & 1) dst_pixel++;
2707 memset(dst_pixel, 0, pad_size);
2709 dst_start += dst->stride;
2710 src_start += src->stride / 4;
2713 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2715 for(y = src_rect->top; y < src_rect->bottom; y++)
2717 dst_pixel = dst_start;
2718 src_pixel = src_start;
2719 for(x = src_rect->left; x < src_rect->right; x++)
2721 src_val = *src_pixel++;
2722 dst_val = rgb_to_pixel_colortable(dst,
2723 src_val >> src->red_shift,
2724 src_val >> src->green_shift,
2725 src_val >> src->blue_shift);
2726 if((x - src_rect->left) & 1)
2728 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2729 dst_pixel++;
2731 else
2732 *dst_pixel = (dst_val << 4) & 0xf0;
2734 if(pad_size)
2736 if((x - src_rect->left) & 1) dst_pixel++;
2737 memset(dst_pixel, 0, pad_size);
2739 dst_start += dst->stride;
2740 src_start += src->stride / 4;
2743 else
2745 for(y = src_rect->top; y < src_rect->bottom; y++)
2747 dst_pixel = dst_start;
2748 src_pixel = src_start;
2749 for(x = src_rect->left; x < src_rect->right; x++)
2751 src_val = *src_pixel++;
2752 dst_val = rgb_to_pixel_colortable(dst,
2753 get_field(src_val, src->red_shift, src->red_len),
2754 get_field(src_val, src->green_shift, src->green_len),
2755 get_field(src_val, src->blue_shift, src->blue_len));
2756 if((x - src_rect->left) & 1)
2758 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2759 dst_pixel++;
2761 else
2762 *dst_pixel = (dst_val << 4) & 0xf0;
2764 if(pad_size)
2766 if((x - src_rect->left) & 1) dst_pixel++;
2767 memset(dst_pixel, 0, pad_size);
2769 dst_start += dst->stride;
2770 src_start += src->stride / 4;
2773 break;
2776 case 24:
2778 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2780 for(y = src_rect->top; y < src_rect->bottom; y++)
2782 dst_pixel = dst_start;
2783 src_pixel = src_start;
2784 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2786 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2788 if((x - src_rect->left) & 1)
2790 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2791 dst_pixel++;
2793 else
2794 *dst_pixel = (dst_val << 4) & 0xf0;
2796 if(pad_size)
2798 if((x - src_rect->left) & 1) dst_pixel++;
2799 memset(dst_pixel, 0, pad_size);
2801 dst_start += dst->stride;
2802 src_start += src->stride;
2804 break;
2807 case 16:
2809 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2810 if(src->funcs == &funcs_555)
2812 for(y = src_rect->top; y < src_rect->bottom; y++)
2814 dst_pixel = dst_start;
2815 src_pixel = src_start;
2816 for(x = src_rect->left; x < src_rect->right; x++)
2818 src_val = *src_pixel++;
2819 dst_val = rgb_to_pixel_colortable(dst,
2820 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2821 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2822 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2823 if((x - src_rect->left) & 1)
2825 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2826 dst_pixel++;
2828 else
2829 *dst_pixel = (dst_val << 4) & 0xf0;
2831 if(pad_size)
2833 if((x - src_rect->left) & 1) dst_pixel++;
2834 memset(dst_pixel, 0, pad_size);
2836 dst_start += dst->stride;
2837 src_start += src->stride / 2;
2840 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2842 for(y = src_rect->top; y < src_rect->bottom; y++)
2844 dst_pixel = dst_start;
2845 src_pixel = src_start;
2846 for(x = src_rect->left; x < src_rect->right; x++)
2848 src_val = *src_pixel++;
2849 dst_val = rgb_to_pixel_colortable(dst,
2850 (((src_val >> src->red_shift) << 3) & 0xf8) |
2851 (((src_val >> src->red_shift) >> 2) & 0x07),
2852 (((src_val >> src->green_shift) << 3) & 0xf8) |
2853 (((src_val >> src->green_shift) >> 2) & 0x07),
2854 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2855 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2856 if((x - src_rect->left) & 1)
2858 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2859 dst_pixel++;
2861 else
2862 *dst_pixel = (dst_val << 4) & 0xf0;
2864 if(pad_size)
2866 if((x - src_rect->left) & 1) dst_pixel++;
2867 memset(dst_pixel, 0, pad_size);
2869 dst_start += dst->stride;
2870 src_start += src->stride / 2;
2873 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2875 for(y = src_rect->top; y < src_rect->bottom; y++)
2877 dst_pixel = dst_start;
2878 src_pixel = src_start;
2879 for(x = src_rect->left; x < src_rect->right; x++)
2881 src_val = *src_pixel++;
2882 dst_val = rgb_to_pixel_colortable(dst,
2883 (((src_val >> src->red_shift) << 3) & 0xf8) |
2884 (((src_val >> src->red_shift) >> 2) & 0x07),
2885 (((src_val >> src->green_shift) << 2) & 0xfc) |
2886 (((src_val >> src->green_shift) >> 4) & 0x03),
2887 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2888 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2889 if((x - src_rect->left) & 1)
2891 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2892 dst_pixel++;
2894 else
2895 *dst_pixel = (dst_val << 4) & 0xf0;
2897 if(pad_size)
2899 if((x - src_rect->left) & 1) dst_pixel++;
2900 memset(dst_pixel, 0, pad_size);
2902 dst_start += dst->stride;
2903 src_start += src->stride / 2;
2906 else
2908 for(y = src_rect->top; y < src_rect->bottom; y++)
2910 dst_pixel = dst_start;
2911 src_pixel = src_start;
2912 for(x = src_rect->left; x < src_rect->right; x++)
2914 src_val = *src_pixel++;
2915 dst_val = rgb_to_pixel_colortable(dst,
2916 get_field(src_val, src->red_shift, src->red_len),
2917 get_field(src_val, src->green_shift, src->green_len),
2918 get_field(src_val, src->blue_shift, src->blue_len));
2919 if((x - src_rect->left) & 1)
2921 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2922 dst_pixel++;
2924 else
2925 *dst_pixel = (dst_val << 4) & 0xf0;
2927 if(pad_size)
2929 if((x - src_rect->left) & 1) dst_pixel++;
2930 memset(dst_pixel, 0, pad_size);
2932 dst_start += dst->stride;
2933 src_start += src->stride / 2;
2936 break;
2939 case 8:
2941 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2943 for(y = src_rect->top; y < src_rect->bottom; y++)
2945 dst_pixel = dst_start;
2946 src_pixel = src_start;
2947 for(x = src_rect->left; x < src_rect->right; x++)
2949 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2950 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2951 if((x - src_rect->left) & 1)
2953 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2954 dst_pixel++;
2956 else
2957 *dst_pixel = (dst_val << 4) & 0xf0;
2959 if(pad_size)
2961 if((x - src_rect->left) & 1) dst_pixel++;
2962 memset(dst_pixel, 0, pad_size);
2964 dst_start += dst->stride;
2965 src_start += src->stride;
2967 break;
2970 case 4:
2972 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2974 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
2976 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2977 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2978 else
2980 for(y = src_rect->top; y < src_rect->bottom; y++)
2982 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
2983 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
2984 dst_start += dst->stride;
2985 src_start += src->stride;
2989 else
2991 for(y = src_rect->top; y < src_rect->bottom; y++)
2993 dst_pixel = dst_start;
2994 src_pixel = src_start;
2995 for(x = src_rect->left; x < src_rect->right; x++)
2997 RGBQUAD rgb;
2998 if(x & 1)
2999 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3000 else
3001 rgb = colortable_entry( src, *src_pixel >> 4 );
3002 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3003 if((x - src_rect->left) & 1)
3005 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3006 dst_pixel++;
3008 else
3009 *dst_pixel = (dst_val << 4) & 0xf0;
3011 if(pad_size)
3013 if((x - src_rect->left) & 1) dst_pixel++;
3014 memset(dst_pixel, 0, pad_size);
3016 dst_start += dst->stride;
3017 src_start += src->stride;
3020 break;
3023 case 1:
3025 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3026 for(y = src_rect->top; y < src_rect->bottom; y++)
3028 dst_pixel = dst_start;
3029 src_pixel = src_start;
3030 for(x = src_rect->left; x < src_rect->right; x++)
3032 RGBQUAD rgb;
3033 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3034 if((x % 8) == 7) src_pixel++;
3035 rgb = src->color_table[src_val];
3036 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3037 if((x - src_rect->left) & 1)
3039 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3040 dst_pixel++;
3042 else
3043 *dst_pixel = (dst_val << 4) & 0xf0;
3045 if(pad_size)
3047 if((x - src_rect->left) & 1) dst_pixel++;
3048 memset(dst_pixel, 0, pad_size);
3050 dst_start += dst->stride;
3051 src_start += src->stride;
3053 break;
3058 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3060 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3061 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3062 DWORD src_val;
3063 int bit_pos;
3065 /* FIXME: Brushes should be dithered. */
3067 switch(src->bit_count)
3069 case 32:
3071 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3073 if(src->funcs == &funcs_8888)
3075 for(y = src_rect->top; y < src_rect->bottom; y++)
3077 dst_pixel = dst_start;
3078 src_pixel = src_start;
3079 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3081 src_val = *src_pixel++;
3082 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3084 if(bit_pos == 0) *dst_pixel = 0;
3085 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3087 if(++bit_pos == 8)
3089 dst_pixel++;
3090 bit_pos = 0;
3093 if(pad_size)
3095 if(bit_pos != 0) dst_pixel++;
3096 memset(dst_pixel, 0, pad_size);
3098 dst_start += dst->stride;
3099 src_start += src->stride / 4;
3102 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3104 for(y = src_rect->top; y < src_rect->bottom; y++)
3106 dst_pixel = dst_start;
3107 src_pixel = src_start;
3108 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3110 src_val = *src_pixel++;
3111 dst_val = rgb_to_pixel_colortable(dst,
3112 src_val >> src->red_shift,
3113 src_val >> src->green_shift,
3114 src_val >> src->blue_shift) ? 0xff : 0;
3116 if(bit_pos == 0) *dst_pixel = 0;
3117 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3119 if(++bit_pos == 8)
3121 dst_pixel++;
3122 bit_pos = 0;
3125 if(pad_size)
3127 if(bit_pos != 0) dst_pixel++;
3128 memset(dst_pixel, 0, pad_size);
3130 dst_start += dst->stride;
3131 src_start += src->stride / 4;
3134 else
3136 for(y = src_rect->top; y < src_rect->bottom; y++)
3138 dst_pixel = dst_start;
3139 src_pixel = src_start;
3140 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3142 src_val = *src_pixel++;
3143 dst_val = rgb_to_pixel_colortable(dst,
3144 get_field(src_val, src->red_shift, src->red_len),
3145 get_field(src_val, src->green_shift, src->green_len),
3146 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3148 if(bit_pos == 0) *dst_pixel = 0;
3149 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3151 if(++bit_pos == 8)
3153 dst_pixel++;
3154 bit_pos = 0;
3157 if(pad_size)
3159 if(bit_pos != 0) dst_pixel++;
3160 memset(dst_pixel, 0, pad_size);
3162 dst_start += dst->stride;
3163 src_start += src->stride / 4;
3166 break;
3169 case 24:
3171 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3173 for(y = src_rect->top; y < src_rect->bottom; y++)
3175 dst_pixel = dst_start;
3176 src_pixel = src_start;
3177 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3179 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3181 if(bit_pos == 0) *dst_pixel = 0;
3182 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3184 if(++bit_pos == 8)
3186 dst_pixel++;
3187 bit_pos = 0;
3190 if(pad_size)
3192 if(bit_pos != 0) dst_pixel++;
3193 memset(dst_pixel, 0, pad_size);
3195 dst_start += dst->stride;
3196 src_start += src->stride;
3198 break;
3201 case 16:
3203 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3204 if(src->funcs == &funcs_555)
3206 for(y = src_rect->top; y < src_rect->bottom; y++)
3208 dst_pixel = dst_start;
3209 src_pixel = src_start;
3210 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3212 src_val = *src_pixel++;
3213 dst_val = rgb_to_pixel_colortable(dst,
3214 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3215 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3216 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3218 if(bit_pos == 0) *dst_pixel = 0;
3219 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3221 if(++bit_pos == 8)
3223 dst_pixel++;
3224 bit_pos = 0;
3227 if(pad_size)
3229 if(bit_pos != 0) dst_pixel++;
3230 memset(dst_pixel, 0, pad_size);
3232 dst_start += dst->stride;
3233 src_start += src->stride / 2;
3236 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3238 for(y = src_rect->top; y < src_rect->bottom; y++)
3240 dst_pixel = dst_start;
3241 src_pixel = src_start;
3242 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3244 src_val = *src_pixel++;
3245 dst_val = rgb_to_pixel_colortable(dst,
3246 (((src_val >> src->red_shift) << 3) & 0xf8) |
3247 (((src_val >> src->red_shift) >> 2) & 0x07),
3248 (((src_val >> src->green_shift) << 3) & 0xf8) |
3249 (((src_val >> src->green_shift) >> 2) & 0x07),
3250 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3251 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3252 if(bit_pos == 0) *dst_pixel = 0;
3253 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3255 if(++bit_pos == 8)
3257 dst_pixel++;
3258 bit_pos = 0;
3261 if(pad_size)
3263 if(bit_pos != 0) dst_pixel++;
3264 memset(dst_pixel, 0, pad_size);
3266 dst_start += dst->stride;
3267 src_start += src->stride / 2;
3270 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3272 for(y = src_rect->top; y < src_rect->bottom; y++)
3274 dst_pixel = dst_start;
3275 src_pixel = src_start;
3276 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3278 src_val = *src_pixel++;
3279 dst_val = rgb_to_pixel_colortable(dst,
3280 (((src_val >> src->red_shift) << 3) & 0xf8) |
3281 (((src_val >> src->red_shift) >> 2) & 0x07),
3282 (((src_val >> src->green_shift) << 2) & 0xfc) |
3283 (((src_val >> src->green_shift) >> 4) & 0x03),
3284 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3285 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3286 if(bit_pos == 0) *dst_pixel = 0;
3287 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3289 if(++bit_pos == 8)
3291 dst_pixel++;
3292 bit_pos = 0;
3295 if(pad_size)
3297 if(bit_pos != 0) dst_pixel++;
3298 memset(dst_pixel, 0, pad_size);
3300 dst_start += dst->stride;
3301 src_start += src->stride / 2;
3304 else
3306 for(y = src_rect->top; y < src_rect->bottom; y++)
3308 dst_pixel = dst_start;
3309 src_pixel = src_start;
3310 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3312 src_val = *src_pixel++;
3313 dst_val = rgb_to_pixel_colortable(dst,
3314 get_field(src_val, src->red_shift, src->red_len),
3315 get_field(src_val, src->green_shift, src->green_len),
3316 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3317 if(bit_pos == 0) *dst_pixel = 0;
3318 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3320 if(++bit_pos == 8)
3322 dst_pixel++;
3323 bit_pos = 0;
3326 if(pad_size)
3328 if(bit_pos != 0) dst_pixel++;
3329 memset(dst_pixel, 0, pad_size);
3331 dst_start += dst->stride;
3332 src_start += src->stride / 2;
3335 break;
3338 case 8:
3340 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3342 for(y = src_rect->top; y < src_rect->bottom; y++)
3344 dst_pixel = dst_start;
3345 src_pixel = src_start;
3346 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3348 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3349 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3351 if(bit_pos == 0) *dst_pixel = 0;
3352 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3354 if(++bit_pos == 8)
3356 dst_pixel++;
3357 bit_pos = 0;
3360 if(pad_size)
3362 if(bit_pos != 0) dst_pixel++;
3363 memset(dst_pixel, 0, pad_size);
3365 dst_start += dst->stride;
3366 src_start += src->stride;
3368 break;
3371 case 4:
3373 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3375 for(y = src_rect->top; y < src_rect->bottom; y++)
3377 dst_pixel = dst_start;
3378 src_pixel = src_start;
3379 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3381 RGBQUAD rgb;
3382 if(x & 1)
3383 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3384 else
3385 rgb = colortable_entry( src, *src_pixel >> 4 );
3386 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3388 if(bit_pos == 0) *dst_pixel = 0;
3389 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3391 if(++bit_pos == 8)
3393 dst_pixel++;
3394 bit_pos = 0;
3397 if(pad_size)
3399 if(bit_pos != 0) dst_pixel++;
3400 memset(dst_pixel, 0, pad_size);
3402 dst_start += dst->stride;
3403 src_start += src->stride;
3405 break;
3408 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3409 uses text/bkgnd colours instead of the dib's colour table, this
3410 doesn't appear to be the case for a dc backed by a
3411 dibsection. */
3413 case 1:
3415 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3416 for(y = src_rect->top; y < src_rect->bottom; y++)
3418 dst_pixel = dst_start;
3419 src_pixel = src_start;
3420 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3422 RGBQUAD rgb;
3423 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3424 if((x % 8) == 7) src_pixel++;
3425 rgb = src->color_table[src_val];
3426 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3428 if(bit_pos == 0) *dst_pixel = 0;
3429 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3431 if(++bit_pos == 8)
3433 dst_pixel++;
3434 bit_pos = 0;
3437 if(pad_size)
3439 if(bit_pos != 0) dst_pixel++;
3440 memset(dst_pixel, 0, pad_size);
3442 dst_start += dst->stride;
3443 src_start += src->stride;
3445 break;
3450 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3454 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3456 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3459 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3461 return (blend_color( dst, src, alpha ) |
3462 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3463 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3464 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3467 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3469 BYTE b = ((BYTE)src * alpha + 127) / 255;
3470 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3471 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3472 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3473 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3474 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3475 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3476 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3479 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3481 if (blend.AlphaFormat & AC_SRC_ALPHA)
3483 DWORD alpha = blend.SourceConstantAlpha;
3484 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3485 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3486 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3487 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3488 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3489 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3490 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3492 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3493 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3494 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3497 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3498 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3500 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3501 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3502 int x, y;
3504 if (blend.AlphaFormat & AC_SRC_ALPHA)
3505 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3506 for (x = 0; x < rc->right - rc->left; x++)
3507 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3508 else
3509 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3510 for (x = 0; x < rc->right - rc->left; x++)
3511 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3514 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3515 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3517 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3518 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3519 int x, y;
3521 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3523 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3525 for (x = 0; x < rc->right - rc->left; x++)
3527 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3528 dst_ptr[x] >> dst->green_shift,
3529 dst_ptr[x] >> dst->blue_shift,
3530 src_ptr[x], blend );
3531 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3532 (((val >> 8) & 0xff) << dst->green_shift) |
3533 (((val >> 16) & 0xff) << dst->red_shift));
3537 else
3539 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3541 for (x = 0; x < rc->right - rc->left; x++)
3543 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3544 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3545 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3546 src_ptr[x], blend );
3547 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3548 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3549 put_field( val, dst->blue_shift, dst->blue_len ));
3555 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3556 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3558 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3559 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3560 int x, y;
3562 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3564 for (x = 0; x < rc->right - rc->left; x++)
3566 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3567 src_ptr[x], blend );
3568 dst_ptr[x * 3] = val;
3569 dst_ptr[x * 3 + 1] = val >> 8;
3570 dst_ptr[x * 3 + 2] = val >> 16;
3575 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3576 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3578 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3579 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3580 int x, y;
3582 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3584 for (x = 0; x < rc->right - rc->left; x++)
3586 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3587 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3588 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3589 src_ptr[x], blend );
3590 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3595 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3596 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3598 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3599 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3600 int x, y;
3602 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3604 for (x = 0; x < rc->right - rc->left; x++)
3606 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3607 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3608 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3609 src_ptr[x], blend );
3610 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3611 put_field((val >> 8), dst->green_shift, dst->green_len) |
3612 put_field( val, dst->blue_shift, dst->blue_len));
3617 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3618 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3620 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3621 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3622 int x, y;
3624 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3626 for (x = 0; x < rc->right - rc->left; x++)
3628 RGBQUAD rgb = colortable_entry( dst, dst_ptr[x] );
3629 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3630 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3635 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3636 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3638 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3639 BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3640 int x, y;
3642 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3644 for (x = rc->left; x < rc->right; x++)
3646 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3647 RGBQUAD rgb = colortable_entry( dst, val );
3648 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3649 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3650 if (x & 1)
3651 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3652 else
3653 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3658 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3659 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3661 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3662 BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
3663 int x, y;
3665 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3667 for (x = rc->left; x < rc->right; x++)
3669 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3670 RGBQUAD rgb = dst->color_table[val];
3671 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3672 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
3673 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
3678 static void blend_rect_null(const dib_info *dst, const RECT *rc,
3679 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3683 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)
3685 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3686 DWORD mask_start = 0, mask_offset;
3687 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
3688 int x, y;
3690 for(y = 0; y < hatch->height; y++)
3692 hatch_ptr = hatch_start;
3693 mask_offset = mask_start;
3694 for(x = 0; x < hatch->width; x++)
3696 if(*hatch_ptr & pixel_masks_1[x % 8])
3698 and_bits[mask_offset] = fg->and;
3699 xor_bits[mask_offset] = fg->xor;
3701 else
3703 and_bits[mask_offset] = bg->and;
3704 xor_bits[mask_offset] = bg->xor;
3706 if(x % 8 == 7) hatch_ptr++;
3707 mask_offset++;
3709 hatch_start += hatch->stride;
3710 mask_start += dib->stride / 4;
3713 return TRUE;
3716 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)
3718 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3719 DWORD mask_start = 0, mask_offset;
3720 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3721 int x, y;
3723 for(y = 0; y < hatch->height; y++)
3725 hatch_ptr = hatch_start;
3726 mask_offset = mask_start;
3727 for(x = 0; x < hatch->width; x++)
3729 if(*hatch_ptr & pixel_masks_1[x % 8])
3731 and_bits[mask_offset] = fg->and & 0xff;
3732 xor_bits[mask_offset++] = fg->xor & 0xff;
3733 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
3734 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
3735 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
3736 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
3738 else
3740 and_bits[mask_offset] = bg->and & 0xff;
3741 xor_bits[mask_offset++] = bg->xor & 0xff;
3742 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
3743 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
3744 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
3745 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
3747 if(x % 8 == 7) hatch_ptr++;
3749 hatch_start += hatch->stride;
3750 mask_start += dib->stride;
3753 return TRUE;
3756 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)
3758 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3759 DWORD mask_start = 0, mask_offset;
3760 WORD *and_bits = bits->and, *xor_bits = bits->xor;
3761 int x, y;
3763 for(y = 0; y < hatch->height; y++)
3765 hatch_ptr = hatch_start;
3766 mask_offset = mask_start;
3767 for(x = 0; x < hatch->width; x++)
3769 if(*hatch_ptr & pixel_masks_1[x % 8])
3771 and_bits[mask_offset] = fg->and;
3772 xor_bits[mask_offset] = fg->xor;
3774 else
3776 and_bits[mask_offset] = bg->and;
3777 xor_bits[mask_offset] = bg->xor;
3779 if(x % 8 == 7) hatch_ptr++;
3780 mask_offset++;
3782 hatch_start += hatch->stride;
3783 mask_start += dib->stride / 2;
3786 return TRUE;
3789 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)
3791 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3792 DWORD mask_start = 0, mask_offset;
3793 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3794 int x, y;
3796 for(y = 0; y < hatch->height; y++)
3798 hatch_ptr = hatch_start;
3799 mask_offset = mask_start;
3800 for(x = 0; x < hatch->width; x++)
3802 if(*hatch_ptr & pixel_masks_1[x % 8])
3804 and_bits[mask_offset] = fg->and;
3805 xor_bits[mask_offset] = fg->xor;
3807 else
3809 and_bits[mask_offset] = bg->and;
3810 xor_bits[mask_offset] = bg->xor;
3812 if(x % 8 == 7) hatch_ptr++;
3813 mask_offset++;
3815 hatch_start += hatch->stride;
3816 mask_start += dib->stride;
3819 return TRUE;
3822 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)
3824 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3825 DWORD mask_start = 0, mask_offset;
3826 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3827 const rop_mask *rop_mask;
3828 int x, y;
3830 for(y = 0; y < hatch->height; y++)
3832 hatch_ptr = hatch_start;
3833 mask_offset = mask_start;
3834 for(x = 0; x < hatch->width; x++)
3836 if(*hatch_ptr & pixel_masks_1[x % 8])
3837 rop_mask = fg;
3838 else
3839 rop_mask = bg;
3841 if(x & 1)
3843 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3844 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3845 mask_offset++;
3847 else
3849 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3850 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3853 if(x % 8 == 7) hatch_ptr++;
3855 hatch_start += hatch->stride;
3856 mask_start += dib->stride;
3859 return TRUE;
3862 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)
3864 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3865 DWORD mask_start = 0, mask_offset;
3866 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3867 rop_mask rop_mask;
3868 int x, y, bit_pos;
3870 for(y = 0; y < hatch->height; y++)
3872 hatch_ptr = hatch_start;
3873 mask_offset = mask_start;
3874 for(x = 0, bit_pos = 0; x < hatch->width; x++)
3876 if(*hatch_ptr & pixel_masks_1[x % 8])
3878 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3879 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3881 else
3883 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3884 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3887 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3889 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3890 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3892 if(++bit_pos == 8)
3894 mask_offset++;
3895 hatch_ptr++;
3896 bit_pos = 0;
3899 hatch_start += hatch->stride;
3900 mask_start += dib->stride;
3903 return TRUE;
3906 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)
3908 return FALSE;
3911 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
3913 switch (mode)
3915 default:
3916 case STRETCH_DELETESCANS:
3917 get_rop_codes( R2_COPYPEN, codes );
3918 break;
3919 case STRETCH_ORSCANS:
3920 get_rop_codes( R2_MERGEPEN, codes );
3921 break;
3922 case STRETCH_ANDSCANS:
3923 get_rop_codes( R2_MASKPEN, codes );
3924 break;
3926 return;
3929 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
3930 const dib_info *src_dib, const POINT *src_start,
3931 const struct stretch_params *params, int mode,
3932 BOOL keep_dst)
3934 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
3935 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
3936 int err = params->err_start;
3937 int width;
3938 struct rop_codes codes;
3940 rop_codes_from_stretch_mode( mode, &codes );
3941 for (width = params->length; width; width--)
3943 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
3944 dst_ptr += params->dst_inc;
3945 if (err > 0)
3947 src_ptr += params->src_inc;
3948 err += params->err_add_1;
3950 else err += params->err_add_2;
3954 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
3955 const dib_info *src_dib, const POINT *src_start,
3956 const struct stretch_params *params, int mode,
3957 BOOL keep_dst)
3959 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
3960 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
3961 int err = params->err_start;
3962 int width;
3963 struct rop_codes codes;
3965 rop_codes_from_stretch_mode( mode, &codes );
3966 for (width = params->length; width; width--)
3968 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3969 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
3970 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
3971 dst_ptr += 3 * params->dst_inc;
3972 if (err > 0)
3974 src_ptr += 3 * params->src_inc;
3975 err += params->err_add_1;
3977 else err += params->err_add_2;
3981 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
3982 const dib_info *src_dib, const POINT *src_start,
3983 const struct stretch_params *params, int mode,
3984 BOOL keep_dst)
3986 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
3987 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
3988 int err = params->err_start;
3989 int width;
3990 struct rop_codes codes;
3992 rop_codes_from_stretch_mode( mode, &codes );
3993 for (width = params->length; width; width--)
3995 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
3996 dst_ptr += params->dst_inc;
3997 if (err > 0)
3999 src_ptr += params->src_inc;
4000 err += params->err_add_1;
4002 else err += params->err_add_2;
4006 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
4007 const dib_info *src_dib, const POINT *src_start,
4008 const struct stretch_params *params, int mode,
4009 BOOL keep_dst)
4011 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4012 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4013 int err = params->err_start;
4014 int width;
4015 struct rop_codes codes;
4017 rop_codes_from_stretch_mode( mode, &codes );
4018 for (width = params->length; width; width--)
4020 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4021 dst_ptr += params->dst_inc;
4022 if (err > 0)
4024 src_ptr += params->src_inc;
4025 err += params->err_add_1;
4027 else err += params->err_add_2;
4031 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
4032 const dib_info *src_dib, const POINT *src_start,
4033 const struct stretch_params *params, int mode,
4034 BOOL keep_dst)
4036 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
4037 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
4038 int err = params->err_start;
4039 int width, dst_x = dst_start->x, src_x = src_start->x;
4040 struct rop_codes codes;
4041 BYTE src_val;
4043 rop_codes_from_stretch_mode( mode, &codes );
4044 for (width = params->length; width; width--)
4046 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4047 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4049 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
4051 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4052 dst_ptr += params->dst_inc;
4053 dst_x += params->dst_inc;
4055 if (err > 0)
4057 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4058 src_ptr += params->src_inc;
4059 src_x += params->src_inc;
4060 err += params->err_add_1;
4062 else err += params->err_add_2;
4066 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
4067 const dib_info *src_dib, const POINT *src_start,
4068 const struct stretch_params *params, int mode,
4069 BOOL keep_dst)
4071 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4072 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4073 int err = params->err_start;
4074 int width, dst_x = dst_start->x, src_x = src_start->x;
4075 struct rop_codes codes;
4076 BYTE src_val;
4078 rop_codes_from_stretch_mode( mode, &codes );
4079 for (width = params->length; width; width--)
4081 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4082 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4084 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4085 dst_ptr += params->dst_inc;
4086 dst_x += params->dst_inc;
4088 if (err > 0)
4090 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4091 src_ptr += params->src_inc;
4092 src_x += params->src_inc;
4093 err += params->err_add_1;
4095 else err += params->err_add_2;
4099 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
4100 const dib_info *src_dib, const POINT *src_start,
4101 const struct stretch_params *params, int mode,
4102 BOOL keep_dst)
4104 FIXME("bit count %d\n", dst_dib->bit_count);
4105 return;
4108 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
4109 const dib_info *src_dib, const POINT *src_start,
4110 const struct stretch_params *params, int mode,
4111 BOOL keep_dst)
4113 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4114 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4115 int err = params->err_start;
4116 int width;
4117 struct rop_codes codes;
4118 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4119 BOOL new_pix = TRUE;
4121 rop_codes_from_stretch_mode( mode, &codes );
4122 for (width = params->length; width; width--)
4124 if (new_pix && !keep_dst) *dst_ptr = init_val;
4125 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4126 new_pix = FALSE;
4127 src_ptr += params->src_inc;
4128 if (err > 0)
4130 dst_ptr += params->dst_inc;
4131 new_pix = TRUE;
4132 err += params->err_add_1;
4134 else err += params->err_add_2;
4138 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
4139 const dib_info *src_dib, const POINT *src_start,
4140 const struct stretch_params *params, int mode,
4141 BOOL keep_dst)
4143 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4144 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4145 int err = params->err_start;
4146 int width;
4147 struct rop_codes codes;
4148 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4149 BOOL new_pix = TRUE;
4151 rop_codes_from_stretch_mode( mode, &codes );
4152 for (width = params->length; width; width--)
4154 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
4155 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4156 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4157 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4158 new_pix = FALSE;
4159 src_ptr += 3 * params->src_inc;
4160 if (err > 0)
4162 dst_ptr += 3 * params->dst_inc;
4163 new_pix = TRUE;
4164 err += params->err_add_1;
4166 else err += params->err_add_2;
4170 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
4171 const dib_info *src_dib, const POINT *src_start,
4172 const struct stretch_params *params, int mode,
4173 BOOL keep_dst)
4175 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4176 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4177 int err = params->err_start;
4178 int width;
4179 struct rop_codes codes;
4180 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4181 BOOL new_pix = TRUE;
4183 rop_codes_from_stretch_mode( mode, &codes );
4184 for (width = params->length; width; width--)
4186 if (new_pix && !keep_dst) *dst_ptr = init_val;
4187 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4188 new_pix = FALSE;
4189 src_ptr += params->src_inc;
4190 if (err > 0)
4192 dst_ptr += params->dst_inc;
4193 new_pix = TRUE;
4194 err += params->err_add_1;
4196 else err += params->err_add_2;
4200 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
4201 const dib_info *src_dib, const POINT *src_start,
4202 const struct stretch_params *params, int mode,
4203 BOOL keep_dst)
4205 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4206 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4207 int err = params->err_start;
4208 int width;
4209 struct rop_codes codes;
4210 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4211 BOOL new_pix = TRUE;
4213 rop_codes_from_stretch_mode( mode, &codes );
4214 for (width = params->length; width; width--)
4216 if (new_pix && !keep_dst) *dst_ptr = init_val;
4217 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4218 new_pix = FALSE;
4219 src_ptr += params->src_inc;
4220 if (err > 0)
4222 dst_ptr += params->dst_inc;
4223 new_pix = TRUE;
4224 err += params->err_add_1;
4226 else err += params->err_add_2;
4230 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
4231 const dib_info *src_dib, const POINT *src_start,
4232 const struct stretch_params *params, int mode,
4233 BOOL keep_dst)
4235 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4236 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4237 int err = params->err_start;
4238 int width, dst_x = dst_start->x, src_x = src_start->x;
4239 struct rop_codes codes;
4240 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4241 BOOL new_pix = TRUE;
4243 rop_codes_from_stretch_mode( mode, &codes );
4244 for (width = params->length; width; width--)
4246 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4248 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4249 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4251 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4252 new_pix = FALSE;
4254 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4255 src_ptr += params->src_inc;
4256 src_x += params->src_inc;
4258 if (err > 0)
4260 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4261 dst_ptr += params->dst_inc;
4262 dst_x += params->dst_inc;
4263 new_pix = TRUE;
4264 err += params->err_add_1;
4266 else err += params->err_add_2;
4270 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4271 const dib_info *src_dib, const POINT *src_start,
4272 const struct stretch_params *params, int mode,
4273 BOOL keep_dst)
4275 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4276 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4277 int err = params->err_start;
4278 int width, dst_x = dst_start->x, src_x = src_start->x;
4279 struct rop_codes codes;
4280 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4281 BOOL new_pix = TRUE;
4283 rop_codes_from_stretch_mode( mode, &codes );
4284 for (width = params->length; width; width--)
4286 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4287 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4288 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4289 new_pix = FALSE;
4291 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4292 src_ptr += params->src_inc;
4293 src_x += params->src_inc;
4295 if (err > 0)
4297 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4298 dst_ptr += params->dst_inc;
4299 dst_x += params->dst_inc;
4300 new_pix = TRUE;
4301 err += params->err_add_1;
4303 else err += params->err_add_2;
4307 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4308 const dib_info *src_dib, const POINT *src_start,
4309 const struct stretch_params *params, int mode,
4310 BOOL keep_dst)
4312 FIXME("bit count %d\n", dst_dib->bit_count);
4313 return;
4316 const primitive_funcs funcs_8888 =
4318 solid_rects_32,
4319 pattern_rects_32,
4320 copy_rect_32,
4321 blend_rect_8888,
4322 colorref_to_pixel_888,
4323 convert_to_8888,
4324 create_rop_masks_32,
4325 stretch_row_32,
4326 shrink_row_32
4329 const primitive_funcs funcs_32 =
4331 solid_rects_32,
4332 pattern_rects_32,
4333 copy_rect_32,
4334 blend_rect_32,
4335 colorref_to_pixel_masks,
4336 convert_to_32,
4337 create_rop_masks_32,
4338 stretch_row_32,
4339 shrink_row_32
4342 const primitive_funcs funcs_24 =
4344 solid_rects_24,
4345 pattern_rects_24,
4346 copy_rect_24,
4347 blend_rect_24,
4348 colorref_to_pixel_888,
4349 convert_to_24,
4350 create_rop_masks_24,
4351 stretch_row_24,
4352 shrink_row_24
4355 const primitive_funcs funcs_555 =
4357 solid_rects_16,
4358 pattern_rects_16,
4359 copy_rect_16,
4360 blend_rect_555,
4361 colorref_to_pixel_555,
4362 convert_to_555,
4363 create_rop_masks_16,
4364 stretch_row_16,
4365 shrink_row_16
4368 const primitive_funcs funcs_16 =
4370 solid_rects_16,
4371 pattern_rects_16,
4372 copy_rect_16,
4373 blend_rect_16,
4374 colorref_to_pixel_masks,
4375 convert_to_16,
4376 create_rop_masks_16,
4377 stretch_row_16,
4378 shrink_row_16
4381 const primitive_funcs funcs_8 =
4383 solid_rects_8,
4384 pattern_rects_8,
4385 copy_rect_8,
4386 blend_rect_8,
4387 colorref_to_pixel_colortable,
4388 convert_to_8,
4389 create_rop_masks_8,
4390 stretch_row_8,
4391 shrink_row_8
4394 const primitive_funcs funcs_4 =
4396 solid_rects_4,
4397 pattern_rects_4,
4398 copy_rect_4,
4399 blend_rect_4,
4400 colorref_to_pixel_colortable,
4401 convert_to_4,
4402 create_rop_masks_4,
4403 stretch_row_4,
4404 shrink_row_4
4407 const primitive_funcs funcs_1 =
4409 solid_rects_1,
4410 pattern_rects_1,
4411 copy_rect_1,
4412 blend_rect_1,
4413 colorref_to_pixel_colortable,
4414 convert_to_1,
4415 create_rop_masks_1,
4416 stretch_row_1,
4417 shrink_row_1
4420 const primitive_funcs funcs_null =
4422 solid_rects_null,
4423 pattern_rects_null,
4424 copy_rect_null,
4425 blend_rect_null,
4426 colorref_to_pixel_null,
4427 convert_to_null,
4428 create_rop_masks_null,
4429 stretch_row_null,
4430 shrink_row_null