gdi32: Add a helper for RGB to color index mapping to avoid redundant shifts.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blobda009a2c4b199365b53c3d3ecf42f61b734779e4
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 void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2409 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2410 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2411 DWORD src_val;
2413 switch(src->bit_count)
2415 case 32:
2417 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2419 if(src->funcs == &funcs_8888)
2421 for(y = src_rect->top; y < src_rect->bottom; y++)
2423 dst_pixel = dst_start;
2424 src_pixel = src_start;
2425 for(x = src_rect->left; x < src_rect->right; x++)
2427 src_val = *src_pixel++;
2428 *dst_pixel++ = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2430 if(pad_size) memset(dst_pixel, 0, pad_size);
2431 dst_start += dst->stride;
2432 src_start += src->stride / 4;
2435 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2437 for(y = src_rect->top; y < src_rect->bottom; y++)
2439 dst_pixel = dst_start;
2440 src_pixel = src_start;
2441 for(x = src_rect->left; x < src_rect->right; x++)
2443 src_val = *src_pixel++;
2444 *dst_pixel++ = rgb_to_pixel_colortable(dst,
2445 src_val >> src->red_shift,
2446 src_val >> src->green_shift,
2447 src_val >> src->blue_shift );
2449 if(pad_size) memset(dst_pixel, 0, pad_size);
2450 dst_start += dst->stride;
2451 src_start += src->stride / 4;
2454 else
2456 for(y = src_rect->top; y < src_rect->bottom; y++)
2458 dst_pixel = dst_start;
2459 src_pixel = src_start;
2460 for(x = src_rect->left; x < src_rect->right; x++)
2462 src_val = *src_pixel++;
2463 *dst_pixel++ = rgb_to_pixel_colortable(dst,
2464 get_field(src_val, src->red_shift, src->red_len),
2465 get_field(src_val, src->green_shift, src->green_len),
2466 get_field(src_val, src->blue_shift, src->blue_len));
2468 if(pad_size) memset(dst_pixel, 0, pad_size);
2469 dst_start += dst->stride;
2470 src_start += src->stride / 4;
2473 break;
2476 case 24:
2478 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2480 for(y = src_rect->top; y < src_rect->bottom; y++)
2482 dst_pixel = dst_start;
2483 src_pixel = src_start;
2484 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2486 *dst_pixel++ = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2488 if(pad_size) memset(dst_pixel, 0, pad_size);
2489 dst_start += dst->stride;
2490 src_start += src->stride;
2492 break;
2495 case 16:
2497 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2498 if(src->funcs == &funcs_555)
2500 for(y = src_rect->top; y < src_rect->bottom; y++)
2502 dst_pixel = dst_start;
2503 src_pixel = src_start;
2504 for(x = src_rect->left; x < src_rect->right; x++)
2506 src_val = *src_pixel++;
2507 *dst_pixel++ = rgb_to_pixel_colortable(dst,
2508 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2509 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2510 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2512 if(pad_size) memset(dst_pixel, 0, pad_size);
2513 dst_start += dst->stride;
2514 src_start += src->stride / 2;
2517 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2519 for(y = src_rect->top; y < src_rect->bottom; y++)
2521 dst_pixel = dst_start;
2522 src_pixel = src_start;
2523 for(x = src_rect->left; x < src_rect->right; x++)
2525 src_val = *src_pixel++;
2526 *dst_pixel++ = rgb_to_pixel_colortable(dst,
2527 (((src_val >> src->red_shift) << 3) & 0xf8) |
2528 (((src_val >> src->red_shift) >> 2) & 0x07),
2529 (((src_val >> src->green_shift) << 3) & 0xf8) |
2530 (((src_val >> src->green_shift) >> 2) & 0x07),
2531 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2532 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2534 if(pad_size) memset(dst_pixel, 0, pad_size);
2535 dst_start += dst->stride;
2536 src_start += src->stride / 2;
2539 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2541 for(y = src_rect->top; y < src_rect->bottom; y++)
2543 dst_pixel = dst_start;
2544 src_pixel = src_start;
2545 for(x = src_rect->left; x < src_rect->right; x++)
2547 src_val = *src_pixel++;
2548 *dst_pixel++ = rgb_to_pixel_colortable(dst,
2549 (((src_val >> src->red_shift) << 3) & 0xf8) |
2550 (((src_val >> src->red_shift) >> 2) & 0x07),
2551 (((src_val >> src->green_shift) << 2) & 0xfc) |
2552 (((src_val >> src->green_shift) >> 4) & 0x03),
2553 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2554 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2556 if(pad_size) memset(dst_pixel, 0, pad_size);
2557 dst_start += dst->stride;
2558 src_start += src->stride / 2;
2561 else
2563 for(y = src_rect->top; y < src_rect->bottom; y++)
2565 dst_pixel = dst_start;
2566 src_pixel = src_start;
2567 for(x = src_rect->left; x < src_rect->right; x++)
2569 src_val = *src_pixel++;
2570 *dst_pixel++ = rgb_to_pixel_colortable(dst,
2571 get_field(src_val, src->red_shift, src->red_len),
2572 get_field(src_val, src->green_shift, src->green_len),
2573 get_field(src_val, src->blue_shift, src->blue_len));
2575 if(pad_size) memset(dst_pixel, 0, pad_size);
2576 dst_start += dst->stride;
2577 src_start += src->stride / 2;
2580 break;
2583 case 8:
2585 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2587 if(color_tables_match(dst, src))
2589 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2590 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2591 else
2593 for(y = src_rect->top; y < src_rect->bottom; y++)
2595 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2596 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2597 dst_start += dst->stride;
2598 src_start += src->stride;
2602 else
2604 for(y = src_rect->top; y < src_rect->bottom; y++)
2606 dst_pixel = dst_start;
2607 src_pixel = src_start;
2608 for(x = src_rect->left; x < src_rect->right; x++)
2610 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2611 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2613 if(pad_size) memset(dst_pixel, 0, pad_size);
2614 dst_start += dst->stride;
2615 src_start += src->stride;
2618 break;
2621 case 4:
2623 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2624 for(y = src_rect->top; y < src_rect->bottom; y++)
2626 dst_pixel = dst_start;
2627 src_pixel = src_start;
2628 for(x = src_rect->left; x < src_rect->right; x++)
2630 RGBQUAD rgb;
2631 if(x & 1)
2632 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2633 else
2634 rgb = colortable_entry( src, *src_pixel >> 4 );
2635 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2637 if(pad_size) memset(dst_pixel, 0, pad_size);
2638 dst_start += dst->stride;
2639 src_start += src->stride;
2641 break;
2644 case 1:
2646 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2647 for(y = src_rect->top; y < src_rect->bottom; y++)
2649 dst_pixel = dst_start;
2650 src_pixel = src_start;
2651 for(x = src_rect->left; x < src_rect->right; x++)
2653 RGBQUAD rgb;
2654 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2655 if((x % 8) == 7) src_pixel++;
2656 rgb = src->color_table[src_val];
2657 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2659 if(pad_size) memset(dst_pixel, 0, pad_size);
2660 dst_start += dst->stride;
2661 src_start += src->stride;
2663 break;
2668 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2670 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2671 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2672 DWORD src_val;
2674 switch(src->bit_count)
2676 case 32:
2678 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2680 if(src->funcs == &funcs_8888)
2682 for(y = src_rect->top; y < src_rect->bottom; y++)
2684 dst_pixel = dst_start;
2685 src_pixel = src_start;
2686 for(x = src_rect->left; x < src_rect->right; x++)
2688 src_val = *src_pixel++;
2689 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
2690 if((x - src_rect->left) & 1)
2692 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2693 dst_pixel++;
2695 else
2696 *dst_pixel = (dst_val << 4) & 0xf0;
2698 if(pad_size)
2700 if((x - src_rect->left) & 1) dst_pixel++;
2701 memset(dst_pixel, 0, pad_size);
2703 dst_start += dst->stride;
2704 src_start += src->stride / 4;
2707 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2709 for(y = src_rect->top; y < src_rect->bottom; y++)
2711 dst_pixel = dst_start;
2712 src_pixel = src_start;
2713 for(x = src_rect->left; x < src_rect->right; x++)
2715 src_val = *src_pixel++;
2716 dst_val = rgb_to_pixel_colortable(dst,
2717 src_val >> src->red_shift,
2718 src_val >> src->green_shift,
2719 src_val >> src->blue_shift);
2720 if((x - src_rect->left) & 1)
2722 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2723 dst_pixel++;
2725 else
2726 *dst_pixel = (dst_val << 4) & 0xf0;
2728 if(pad_size)
2730 if((x - src_rect->left) & 1) dst_pixel++;
2731 memset(dst_pixel, 0, pad_size);
2733 dst_start += dst->stride;
2734 src_start += src->stride / 4;
2737 else
2739 for(y = src_rect->top; y < src_rect->bottom; y++)
2741 dst_pixel = dst_start;
2742 src_pixel = src_start;
2743 for(x = src_rect->left; x < src_rect->right; x++)
2745 src_val = *src_pixel++;
2746 dst_val = rgb_to_pixel_colortable(dst,
2747 get_field(src_val, src->red_shift, src->red_len),
2748 get_field(src_val, src->green_shift, src->green_len),
2749 get_field(src_val, src->blue_shift, src->blue_len));
2750 if((x - src_rect->left) & 1)
2752 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2753 dst_pixel++;
2755 else
2756 *dst_pixel = (dst_val << 4) & 0xf0;
2758 if(pad_size)
2760 if((x - src_rect->left) & 1) dst_pixel++;
2761 memset(dst_pixel, 0, pad_size);
2763 dst_start += dst->stride;
2764 src_start += src->stride / 4;
2767 break;
2770 case 24:
2772 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2774 for(y = src_rect->top; y < src_rect->bottom; y++)
2776 dst_pixel = dst_start;
2777 src_pixel = src_start;
2778 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2780 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2782 if((x - src_rect->left) & 1)
2784 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2785 dst_pixel++;
2787 else
2788 *dst_pixel = (dst_val << 4) & 0xf0;
2790 if(pad_size)
2792 if((x - src_rect->left) & 1) dst_pixel++;
2793 memset(dst_pixel, 0, pad_size);
2795 dst_start += dst->stride;
2796 src_start += src->stride;
2798 break;
2801 case 16:
2803 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2804 if(src->funcs == &funcs_555)
2806 for(y = src_rect->top; y < src_rect->bottom; y++)
2808 dst_pixel = dst_start;
2809 src_pixel = src_start;
2810 for(x = src_rect->left; x < src_rect->right; x++)
2812 src_val = *src_pixel++;
2813 dst_val = rgb_to_pixel_colortable(dst,
2814 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2815 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2816 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2817 if((x - src_rect->left) & 1)
2819 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2820 dst_pixel++;
2822 else
2823 *dst_pixel = (dst_val << 4) & 0xf0;
2825 if(pad_size)
2827 if((x - src_rect->left) & 1) dst_pixel++;
2828 memset(dst_pixel, 0, pad_size);
2830 dst_start += dst->stride;
2831 src_start += src->stride / 2;
2834 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2836 for(y = src_rect->top; y < src_rect->bottom; y++)
2838 dst_pixel = dst_start;
2839 src_pixel = src_start;
2840 for(x = src_rect->left; x < src_rect->right; x++)
2842 src_val = *src_pixel++;
2843 dst_val = rgb_to_pixel_colortable(dst,
2844 (((src_val >> src->red_shift) << 3) & 0xf8) |
2845 (((src_val >> src->red_shift) >> 2) & 0x07),
2846 (((src_val >> src->green_shift) << 3) & 0xf8) |
2847 (((src_val >> src->green_shift) >> 2) & 0x07),
2848 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2849 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2850 if((x - src_rect->left) & 1)
2852 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2853 dst_pixel++;
2855 else
2856 *dst_pixel = (dst_val << 4) & 0xf0;
2858 if(pad_size)
2860 if((x - src_rect->left) & 1) dst_pixel++;
2861 memset(dst_pixel, 0, pad_size);
2863 dst_start += dst->stride;
2864 src_start += src->stride / 2;
2867 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2869 for(y = src_rect->top; y < src_rect->bottom; y++)
2871 dst_pixel = dst_start;
2872 src_pixel = src_start;
2873 for(x = src_rect->left; x < src_rect->right; x++)
2875 src_val = *src_pixel++;
2876 dst_val = rgb_to_pixel_colortable(dst,
2877 (((src_val >> src->red_shift) << 3) & 0xf8) |
2878 (((src_val >> src->red_shift) >> 2) & 0x07),
2879 (((src_val >> src->green_shift) << 2) & 0xfc) |
2880 (((src_val >> src->green_shift) >> 4) & 0x03),
2881 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2882 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2883 if((x - src_rect->left) & 1)
2885 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2886 dst_pixel++;
2888 else
2889 *dst_pixel = (dst_val << 4) & 0xf0;
2891 if(pad_size)
2893 if((x - src_rect->left) & 1) dst_pixel++;
2894 memset(dst_pixel, 0, pad_size);
2896 dst_start += dst->stride;
2897 src_start += src->stride / 2;
2900 else
2902 for(y = src_rect->top; y < src_rect->bottom; y++)
2904 dst_pixel = dst_start;
2905 src_pixel = src_start;
2906 for(x = src_rect->left; x < src_rect->right; x++)
2908 src_val = *src_pixel++;
2909 dst_val = rgb_to_pixel_colortable(dst,
2910 get_field(src_val, src->red_shift, src->red_len),
2911 get_field(src_val, src->green_shift, src->green_len),
2912 get_field(src_val, src->blue_shift, src->blue_len));
2913 if((x - src_rect->left) & 1)
2915 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2916 dst_pixel++;
2918 else
2919 *dst_pixel = (dst_val << 4) & 0xf0;
2921 if(pad_size)
2923 if((x - src_rect->left) & 1) dst_pixel++;
2924 memset(dst_pixel, 0, pad_size);
2926 dst_start += dst->stride;
2927 src_start += src->stride / 2;
2930 break;
2933 case 8:
2935 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2937 for(y = src_rect->top; y < src_rect->bottom; y++)
2939 dst_pixel = dst_start;
2940 src_pixel = src_start;
2941 for(x = src_rect->left; x < src_rect->right; x++)
2943 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2944 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2945 if((x - src_rect->left) & 1)
2947 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2948 dst_pixel++;
2950 else
2951 *dst_pixel = (dst_val << 4) & 0xf0;
2953 if(pad_size)
2955 if((x - src_rect->left) & 1) dst_pixel++;
2956 memset(dst_pixel, 0, pad_size);
2958 dst_start += dst->stride;
2959 src_start += src->stride;
2961 break;
2964 case 4:
2966 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2968 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
2970 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2971 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2972 else
2974 for(y = src_rect->top; y < src_rect->bottom; y++)
2976 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
2977 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
2978 dst_start += dst->stride;
2979 src_start += src->stride;
2983 else
2985 for(y = src_rect->top; y < src_rect->bottom; y++)
2987 dst_pixel = dst_start;
2988 src_pixel = src_start;
2989 for(x = src_rect->left; x < src_rect->right; x++)
2991 RGBQUAD rgb;
2992 if(x & 1)
2993 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2994 else
2995 rgb = colortable_entry( src, *src_pixel >> 4 );
2996 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2997 if((x - src_rect->left) & 1)
2999 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3000 dst_pixel++;
3002 else
3003 *dst_pixel = (dst_val << 4) & 0xf0;
3005 if(pad_size)
3007 if((x - src_rect->left) & 1) dst_pixel++;
3008 memset(dst_pixel, 0, pad_size);
3010 dst_start += dst->stride;
3011 src_start += src->stride;
3014 break;
3017 case 1:
3019 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3020 for(y = src_rect->top; y < src_rect->bottom; y++)
3022 dst_pixel = dst_start;
3023 src_pixel = src_start;
3024 for(x = src_rect->left; x < src_rect->right; x++)
3026 RGBQUAD rgb;
3027 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3028 if((x % 8) == 7) src_pixel++;
3029 rgb = src->color_table[src_val];
3030 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3031 if((x - src_rect->left) & 1)
3033 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3034 dst_pixel++;
3036 else
3037 *dst_pixel = (dst_val << 4) & 0xf0;
3039 if(pad_size)
3041 if((x - src_rect->left) & 1) dst_pixel++;
3042 memset(dst_pixel, 0, pad_size);
3044 dst_start += dst->stride;
3045 src_start += src->stride;
3047 break;
3052 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3054 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3055 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3056 DWORD src_val;
3057 int bit_pos;
3059 /* FIXME: Brushes should be dithered. */
3061 switch(src->bit_count)
3063 case 32:
3065 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3067 if(src->funcs == &funcs_8888)
3069 for(y = src_rect->top; y < src_rect->bottom; y++)
3071 dst_pixel = dst_start;
3072 src_pixel = src_start;
3073 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3075 src_val = *src_pixel++;
3076 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3078 if(bit_pos == 0) *dst_pixel = 0;
3079 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3081 if(++bit_pos == 8)
3083 dst_pixel++;
3084 bit_pos = 0;
3087 if(pad_size)
3089 if(bit_pos != 0) dst_pixel++;
3090 memset(dst_pixel, 0, pad_size);
3092 dst_start += dst->stride;
3093 src_start += src->stride / 4;
3096 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3098 for(y = src_rect->top; y < src_rect->bottom; y++)
3100 dst_pixel = dst_start;
3101 src_pixel = src_start;
3102 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3104 src_val = *src_pixel++;
3105 dst_val = rgb_to_pixel_colortable(dst,
3106 src_val >> src->red_shift,
3107 src_val >> src->green_shift,
3108 src_val >> src->blue_shift) ? 0xff : 0;
3110 if(bit_pos == 0) *dst_pixel = 0;
3111 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3113 if(++bit_pos == 8)
3115 dst_pixel++;
3116 bit_pos = 0;
3119 if(pad_size)
3121 if(bit_pos != 0) dst_pixel++;
3122 memset(dst_pixel, 0, pad_size);
3124 dst_start += dst->stride;
3125 src_start += src->stride / 4;
3128 else
3130 for(y = src_rect->top; y < src_rect->bottom; y++)
3132 dst_pixel = dst_start;
3133 src_pixel = src_start;
3134 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3136 src_val = *src_pixel++;
3137 dst_val = rgb_to_pixel_colortable(dst,
3138 get_field(src_val, src->red_shift, src->red_len),
3139 get_field(src_val, src->green_shift, src->green_len),
3140 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3142 if(bit_pos == 0) *dst_pixel = 0;
3143 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3145 if(++bit_pos == 8)
3147 dst_pixel++;
3148 bit_pos = 0;
3151 if(pad_size)
3153 if(bit_pos != 0) dst_pixel++;
3154 memset(dst_pixel, 0, pad_size);
3156 dst_start += dst->stride;
3157 src_start += src->stride / 4;
3160 break;
3163 case 24:
3165 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3167 for(y = src_rect->top; y < src_rect->bottom; y++)
3169 dst_pixel = dst_start;
3170 src_pixel = src_start;
3171 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3173 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3175 if(bit_pos == 0) *dst_pixel = 0;
3176 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3178 if(++bit_pos == 8)
3180 dst_pixel++;
3181 bit_pos = 0;
3184 if(pad_size)
3186 if(bit_pos != 0) dst_pixel++;
3187 memset(dst_pixel, 0, pad_size);
3189 dst_start += dst->stride;
3190 src_start += src->stride;
3192 break;
3195 case 16:
3197 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3198 if(src->funcs == &funcs_555)
3200 for(y = src_rect->top; y < src_rect->bottom; y++)
3202 dst_pixel = dst_start;
3203 src_pixel = src_start;
3204 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3206 src_val = *src_pixel++;
3207 dst_val = rgb_to_pixel_colortable(dst,
3208 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3209 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3210 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3212 if(bit_pos == 0) *dst_pixel = 0;
3213 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3215 if(++bit_pos == 8)
3217 dst_pixel++;
3218 bit_pos = 0;
3221 if(pad_size)
3223 if(bit_pos != 0) dst_pixel++;
3224 memset(dst_pixel, 0, pad_size);
3226 dst_start += dst->stride;
3227 src_start += src->stride / 2;
3230 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3232 for(y = src_rect->top; y < src_rect->bottom; y++)
3234 dst_pixel = dst_start;
3235 src_pixel = src_start;
3236 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3238 src_val = *src_pixel++;
3239 dst_val = rgb_to_pixel_colortable(dst,
3240 (((src_val >> src->red_shift) << 3) & 0xf8) |
3241 (((src_val >> src->red_shift) >> 2) & 0x07),
3242 (((src_val >> src->green_shift) << 3) & 0xf8) |
3243 (((src_val >> src->green_shift) >> 2) & 0x07),
3244 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3245 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3246 if(bit_pos == 0) *dst_pixel = 0;
3247 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3249 if(++bit_pos == 8)
3251 dst_pixel++;
3252 bit_pos = 0;
3255 if(pad_size)
3257 if(bit_pos != 0) dst_pixel++;
3258 memset(dst_pixel, 0, pad_size);
3260 dst_start += dst->stride;
3261 src_start += src->stride / 2;
3264 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3266 for(y = src_rect->top; y < src_rect->bottom; y++)
3268 dst_pixel = dst_start;
3269 src_pixel = src_start;
3270 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3272 src_val = *src_pixel++;
3273 dst_val = rgb_to_pixel_colortable(dst,
3274 (((src_val >> src->red_shift) << 3) & 0xf8) |
3275 (((src_val >> src->red_shift) >> 2) & 0x07),
3276 (((src_val >> src->green_shift) << 2) & 0xfc) |
3277 (((src_val >> src->green_shift) >> 4) & 0x03),
3278 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3279 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3280 if(bit_pos == 0) *dst_pixel = 0;
3281 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3283 if(++bit_pos == 8)
3285 dst_pixel++;
3286 bit_pos = 0;
3289 if(pad_size)
3291 if(bit_pos != 0) dst_pixel++;
3292 memset(dst_pixel, 0, pad_size);
3294 dst_start += dst->stride;
3295 src_start += src->stride / 2;
3298 else
3300 for(y = src_rect->top; y < src_rect->bottom; y++)
3302 dst_pixel = dst_start;
3303 src_pixel = src_start;
3304 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3306 src_val = *src_pixel++;
3307 dst_val = rgb_to_pixel_colortable(dst,
3308 get_field(src_val, src->red_shift, src->red_len),
3309 get_field(src_val, src->green_shift, src->green_len),
3310 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3311 if(bit_pos == 0) *dst_pixel = 0;
3312 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3314 if(++bit_pos == 8)
3316 dst_pixel++;
3317 bit_pos = 0;
3320 if(pad_size)
3322 if(bit_pos != 0) dst_pixel++;
3323 memset(dst_pixel, 0, pad_size);
3325 dst_start += dst->stride;
3326 src_start += src->stride / 2;
3329 break;
3332 case 8:
3334 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3336 for(y = src_rect->top; y < src_rect->bottom; y++)
3338 dst_pixel = dst_start;
3339 src_pixel = src_start;
3340 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3342 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3343 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3345 if(bit_pos == 0) *dst_pixel = 0;
3346 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3348 if(++bit_pos == 8)
3350 dst_pixel++;
3351 bit_pos = 0;
3354 if(pad_size)
3356 if(bit_pos != 0) dst_pixel++;
3357 memset(dst_pixel, 0, pad_size);
3359 dst_start += dst->stride;
3360 src_start += src->stride;
3362 break;
3365 case 4:
3367 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3369 for(y = src_rect->top; y < src_rect->bottom; y++)
3371 dst_pixel = dst_start;
3372 src_pixel = src_start;
3373 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3375 RGBQUAD rgb;
3376 if(x & 1)
3377 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3378 else
3379 rgb = colortable_entry( src, *src_pixel >> 4 );
3380 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3382 if(bit_pos == 0) *dst_pixel = 0;
3383 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3385 if(++bit_pos == 8)
3387 dst_pixel++;
3388 bit_pos = 0;
3391 if(pad_size)
3393 if(bit_pos != 0) dst_pixel++;
3394 memset(dst_pixel, 0, pad_size);
3396 dst_start += dst->stride;
3397 src_start += src->stride;
3399 break;
3402 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3403 uses text/bkgnd colours instead of the dib's colour table, this
3404 doesn't appear to be the case for a dc backed by a
3405 dibsection. */
3407 case 1:
3409 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3410 for(y = src_rect->top; y < src_rect->bottom; y++)
3412 dst_pixel = dst_start;
3413 src_pixel = src_start;
3414 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3416 RGBQUAD rgb;
3417 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3418 if((x % 8) == 7) src_pixel++;
3419 rgb = src->color_table[src_val];
3420 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3422 if(bit_pos == 0) *dst_pixel = 0;
3423 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3425 if(++bit_pos == 8)
3427 dst_pixel++;
3428 bit_pos = 0;
3431 if(pad_size)
3433 if(bit_pos != 0) dst_pixel++;
3434 memset(dst_pixel, 0, pad_size);
3436 dst_start += dst->stride;
3437 src_start += src->stride;
3439 break;
3444 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3448 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)
3450 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3451 DWORD mask_start = 0, mask_offset;
3452 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
3453 int x, y;
3455 for(y = 0; y < hatch->height; y++)
3457 hatch_ptr = hatch_start;
3458 mask_offset = mask_start;
3459 for(x = 0; x < hatch->width; x++)
3461 if(*hatch_ptr & pixel_masks_1[x % 8])
3463 and_bits[mask_offset] = fg->and;
3464 xor_bits[mask_offset] = fg->xor;
3466 else
3468 and_bits[mask_offset] = bg->and;
3469 xor_bits[mask_offset] = bg->xor;
3471 if(x % 8 == 7) hatch_ptr++;
3472 mask_offset++;
3474 hatch_start += hatch->stride;
3475 mask_start += dib->stride / 4;
3478 return TRUE;
3481 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)
3483 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3484 DWORD mask_start = 0, mask_offset;
3485 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3486 int x, y;
3488 for(y = 0; y < hatch->height; y++)
3490 hatch_ptr = hatch_start;
3491 mask_offset = mask_start;
3492 for(x = 0; x < hatch->width; x++)
3494 if(*hatch_ptr & pixel_masks_1[x % 8])
3496 and_bits[mask_offset] = fg->and & 0xff;
3497 xor_bits[mask_offset++] = fg->xor & 0xff;
3498 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
3499 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
3500 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
3501 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
3503 else
3505 and_bits[mask_offset] = bg->and & 0xff;
3506 xor_bits[mask_offset++] = bg->xor & 0xff;
3507 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
3508 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
3509 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
3510 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
3512 if(x % 8 == 7) hatch_ptr++;
3514 hatch_start += hatch->stride;
3515 mask_start += dib->stride;
3518 return TRUE;
3521 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)
3523 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3524 DWORD mask_start = 0, mask_offset;
3525 WORD *and_bits = bits->and, *xor_bits = bits->xor;
3526 int x, y;
3528 for(y = 0; y < hatch->height; y++)
3530 hatch_ptr = hatch_start;
3531 mask_offset = mask_start;
3532 for(x = 0; x < hatch->width; x++)
3534 if(*hatch_ptr & pixel_masks_1[x % 8])
3536 and_bits[mask_offset] = fg->and;
3537 xor_bits[mask_offset] = fg->xor;
3539 else
3541 and_bits[mask_offset] = bg->and;
3542 xor_bits[mask_offset] = bg->xor;
3544 if(x % 8 == 7) hatch_ptr++;
3545 mask_offset++;
3547 hatch_start += hatch->stride;
3548 mask_start += dib->stride / 2;
3551 return TRUE;
3554 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)
3556 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3557 DWORD mask_start = 0, mask_offset;
3558 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3559 int x, y;
3561 for(y = 0; y < hatch->height; y++)
3563 hatch_ptr = hatch_start;
3564 mask_offset = mask_start;
3565 for(x = 0; x < hatch->width; x++)
3567 if(*hatch_ptr & pixel_masks_1[x % 8])
3569 and_bits[mask_offset] = fg->and;
3570 xor_bits[mask_offset] = fg->xor;
3572 else
3574 and_bits[mask_offset] = bg->and;
3575 xor_bits[mask_offset] = bg->xor;
3577 if(x % 8 == 7) hatch_ptr++;
3578 mask_offset++;
3580 hatch_start += hatch->stride;
3581 mask_start += dib->stride;
3584 return TRUE;
3587 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)
3589 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3590 DWORD mask_start = 0, mask_offset;
3591 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3592 const rop_mask *rop_mask;
3593 int x, y;
3595 for(y = 0; y < hatch->height; y++)
3597 hatch_ptr = hatch_start;
3598 mask_offset = mask_start;
3599 for(x = 0; x < hatch->width; x++)
3601 if(*hatch_ptr & pixel_masks_1[x % 8])
3602 rop_mask = fg;
3603 else
3604 rop_mask = bg;
3606 if(x & 1)
3608 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
3609 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
3610 mask_offset++;
3612 else
3614 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
3615 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
3618 if(x % 8 == 7) hatch_ptr++;
3620 hatch_start += hatch->stride;
3621 mask_start += dib->stride;
3624 return TRUE;
3627 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)
3629 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3630 DWORD mask_start = 0, mask_offset;
3631 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
3632 rop_mask rop_mask;
3633 int x, y, bit_pos;
3635 for(y = 0; y < hatch->height; y++)
3637 hatch_ptr = hatch_start;
3638 mask_offset = mask_start;
3639 for(x = 0, bit_pos = 0; x < hatch->width; x++)
3641 if(*hatch_ptr & pixel_masks_1[x % 8])
3643 rop_mask.and = (fg->and & 1) ? 0xff : 0;
3644 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
3646 else
3648 rop_mask.and = (bg->and & 1) ? 0xff : 0;
3649 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
3652 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
3654 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3655 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
3657 if(++bit_pos == 8)
3659 mask_offset++;
3660 hatch_ptr++;
3661 bit_pos = 0;
3664 hatch_start += hatch->stride;
3665 mask_start += dib->stride;
3668 return TRUE;
3671 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)
3673 return FALSE;
3676 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
3678 switch (mode)
3680 default:
3681 case STRETCH_DELETESCANS:
3682 get_rop_codes( R2_COPYPEN, codes );
3683 break;
3684 case STRETCH_ORSCANS:
3685 get_rop_codes( R2_MERGEPEN, codes );
3686 break;
3687 case STRETCH_ANDSCANS:
3688 get_rop_codes( R2_MASKPEN, codes );
3689 break;
3691 return;
3694 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
3695 const dib_info *src_dib, const POINT *src_start,
3696 const struct stretch_params *params, int mode,
3697 BOOL keep_dst)
3699 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
3700 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
3701 int err = params->err_start;
3702 int width;
3703 struct rop_codes codes;
3705 rop_codes_from_stretch_mode( mode, &codes );
3706 for (width = params->length; width; width--)
3708 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
3709 dst_ptr += params->dst_inc;
3710 if (err > 0)
3712 src_ptr += params->src_inc;
3713 err += params->err_add_1;
3715 else err += params->err_add_2;
3719 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
3720 const dib_info *src_dib, const POINT *src_start,
3721 const struct stretch_params *params, int mode,
3722 BOOL keep_dst)
3724 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
3725 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
3726 int err = params->err_start;
3727 int width;
3728 struct rop_codes codes;
3730 rop_codes_from_stretch_mode( mode, &codes );
3731 for (width = params->length; width; width--)
3733 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3734 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
3735 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
3736 dst_ptr += 3 * params->dst_inc;
3737 if (err > 0)
3739 src_ptr += 3 * params->src_inc;
3740 err += params->err_add_1;
3742 else err += params->err_add_2;
3746 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
3747 const dib_info *src_dib, const POINT *src_start,
3748 const struct stretch_params *params, int mode,
3749 BOOL keep_dst)
3751 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
3752 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
3753 int err = params->err_start;
3754 int width;
3755 struct rop_codes codes;
3757 rop_codes_from_stretch_mode( mode, &codes );
3758 for (width = params->length; width; width--)
3760 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
3761 dst_ptr += params->dst_inc;
3762 if (err > 0)
3764 src_ptr += params->src_inc;
3765 err += params->err_add_1;
3767 else err += params->err_add_2;
3771 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
3772 const dib_info *src_dib, const POINT *src_start,
3773 const struct stretch_params *params, int mode,
3774 BOOL keep_dst)
3776 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
3777 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
3778 int err = params->err_start;
3779 int width;
3780 struct rop_codes codes;
3782 rop_codes_from_stretch_mode( mode, &codes );
3783 for (width = params->length; width; width--)
3785 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3786 dst_ptr += params->dst_inc;
3787 if (err > 0)
3789 src_ptr += params->src_inc;
3790 err += params->err_add_1;
3792 else err += params->err_add_2;
3796 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
3797 const dib_info *src_dib, const POINT *src_start,
3798 const struct stretch_params *params, int mode,
3799 BOOL keep_dst)
3801 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
3802 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
3803 int err = params->err_start;
3804 int width, dst_x = dst_start->x, src_x = src_start->x;
3805 struct rop_codes codes;
3806 BYTE src_val;
3808 rop_codes_from_stretch_mode( mode, &codes );
3809 for (width = params->length; width; width--)
3811 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
3812 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
3814 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
3816 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
3817 dst_ptr += params->dst_inc;
3818 dst_x += params->dst_inc;
3820 if (err > 0)
3822 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
3823 src_ptr += params->src_inc;
3824 src_x += params->src_inc;
3825 err += params->err_add_1;
3827 else err += params->err_add_2;
3831 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
3832 const dib_info *src_dib, const POINT *src_start,
3833 const struct stretch_params *params, int mode,
3834 BOOL keep_dst)
3836 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
3837 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
3838 int err = params->err_start;
3839 int width, dst_x = dst_start->x, src_x = src_start->x;
3840 struct rop_codes codes;
3841 BYTE src_val;
3843 rop_codes_from_stretch_mode( mode, &codes );
3844 for (width = params->length; width; width--)
3846 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
3847 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
3849 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
3850 dst_ptr += params->dst_inc;
3851 dst_x += params->dst_inc;
3853 if (err > 0)
3855 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
3856 src_ptr += params->src_inc;
3857 src_x += params->src_inc;
3858 err += params->err_add_1;
3860 else err += params->err_add_2;
3864 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
3865 const dib_info *src_dib, const POINT *src_start,
3866 const struct stretch_params *params, int mode,
3867 BOOL keep_dst)
3869 FIXME("bit count %d\n", dst_dib->bit_count);
3870 return;
3873 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
3874 const dib_info *src_dib, const POINT *src_start,
3875 const struct stretch_params *params, int mode,
3876 BOOL keep_dst)
3878 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
3879 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
3880 int err = params->err_start;
3881 int width;
3882 struct rop_codes codes;
3883 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3884 BOOL new_pix = TRUE;
3886 rop_codes_from_stretch_mode( mode, &codes );
3887 for (width = params->length; width; width--)
3889 if (new_pix && !keep_dst) *dst_ptr = init_val;
3890 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
3891 new_pix = FALSE;
3892 src_ptr += params->src_inc;
3893 if (err > 0)
3895 dst_ptr += params->dst_inc;
3896 new_pix = TRUE;
3897 err += params->err_add_1;
3899 else err += params->err_add_2;
3903 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
3904 const dib_info *src_dib, const POINT *src_start,
3905 const struct stretch_params *params, int mode,
3906 BOOL keep_dst)
3908 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
3909 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
3910 int err = params->err_start;
3911 int width;
3912 struct rop_codes codes;
3913 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3914 BOOL new_pix = TRUE;
3916 rop_codes_from_stretch_mode( mode, &codes );
3917 for (width = params->length; width; width--)
3919 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
3920 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3921 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
3922 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
3923 new_pix = FALSE;
3924 src_ptr += 3 * params->src_inc;
3925 if (err > 0)
3927 dst_ptr += 3 * params->dst_inc;
3928 new_pix = TRUE;
3929 err += params->err_add_1;
3931 else err += params->err_add_2;
3935 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
3936 const dib_info *src_dib, const POINT *src_start,
3937 const struct stretch_params *params, int mode,
3938 BOOL keep_dst)
3940 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
3941 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
3942 int err = params->err_start;
3943 int width;
3944 struct rop_codes codes;
3945 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3946 BOOL new_pix = TRUE;
3948 rop_codes_from_stretch_mode( mode, &codes );
3949 for (width = params->length; width; width--)
3951 if (new_pix && !keep_dst) *dst_ptr = init_val;
3952 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
3953 new_pix = FALSE;
3954 src_ptr += params->src_inc;
3955 if (err > 0)
3957 dst_ptr += params->dst_inc;
3958 new_pix = TRUE;
3959 err += params->err_add_1;
3961 else err += params->err_add_2;
3965 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
3966 const dib_info *src_dib, const POINT *src_start,
3967 const struct stretch_params *params, int mode,
3968 BOOL keep_dst)
3970 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
3971 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
3972 int err = params->err_start;
3973 int width;
3974 struct rop_codes codes;
3975 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
3976 BOOL new_pix = TRUE;
3978 rop_codes_from_stretch_mode( mode, &codes );
3979 for (width = params->length; width; width--)
3981 if (new_pix && !keep_dst) *dst_ptr = init_val;
3982 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
3983 new_pix = FALSE;
3984 src_ptr += params->src_inc;
3985 if (err > 0)
3987 dst_ptr += params->dst_inc;
3988 new_pix = TRUE;
3989 err += params->err_add_1;
3991 else err += params->err_add_2;
3995 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
3996 const dib_info *src_dib, const POINT *src_start,
3997 const struct stretch_params *params, int mode,
3998 BOOL keep_dst)
4000 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4001 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4002 int err = params->err_start;
4003 int width, dst_x = dst_start->x, src_x = src_start->x;
4004 struct rop_codes codes;
4005 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4006 BOOL new_pix = TRUE;
4008 rop_codes_from_stretch_mode( mode, &codes );
4009 for (width = params->length; width; width--)
4011 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4013 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4014 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4016 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4017 new_pix = FALSE;
4019 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4020 src_ptr += params->src_inc;
4021 src_x += params->src_inc;
4023 if (err > 0)
4025 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4026 dst_ptr += params->dst_inc;
4027 dst_x += params->dst_inc;
4028 new_pix = TRUE;
4029 err += params->err_add_1;
4031 else err += params->err_add_2;
4035 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4036 const dib_info *src_dib, const POINT *src_start,
4037 const struct stretch_params *params, int mode,
4038 BOOL keep_dst)
4040 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4041 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4042 int err = params->err_start;
4043 int width, dst_x = dst_start->x, src_x = src_start->x;
4044 struct rop_codes codes;
4045 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4046 BOOL new_pix = TRUE;
4048 rop_codes_from_stretch_mode( mode, &codes );
4049 for (width = params->length; width; width--)
4051 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4052 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4053 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4054 new_pix = FALSE;
4056 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4057 src_ptr += params->src_inc;
4058 src_x += params->src_inc;
4060 if (err > 0)
4062 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4063 dst_ptr += params->dst_inc;
4064 dst_x += params->dst_inc;
4065 new_pix = TRUE;
4066 err += params->err_add_1;
4068 else err += params->err_add_2;
4072 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4073 const dib_info *src_dib, const POINT *src_start,
4074 const struct stretch_params *params, int mode,
4075 BOOL keep_dst)
4077 FIXME("bit count %d\n", dst_dib->bit_count);
4078 return;
4081 const primitive_funcs funcs_8888 =
4083 solid_rects_32,
4084 pattern_rects_32,
4085 copy_rect_32,
4086 colorref_to_pixel_888,
4087 convert_to_8888,
4088 create_rop_masks_32,
4089 stretch_row_32,
4090 shrink_row_32
4093 const primitive_funcs funcs_32 =
4095 solid_rects_32,
4096 pattern_rects_32,
4097 copy_rect_32,
4098 colorref_to_pixel_masks,
4099 convert_to_32,
4100 create_rop_masks_32,
4101 stretch_row_32,
4102 shrink_row_32
4105 const primitive_funcs funcs_24 =
4107 solid_rects_24,
4108 pattern_rects_24,
4109 copy_rect_24,
4110 colorref_to_pixel_888,
4111 convert_to_24,
4112 create_rop_masks_24,
4113 stretch_row_24,
4114 shrink_row_24
4117 const primitive_funcs funcs_555 =
4119 solid_rects_16,
4120 pattern_rects_16,
4121 copy_rect_16,
4122 colorref_to_pixel_555,
4123 convert_to_555,
4124 create_rop_masks_16,
4125 stretch_row_16,
4126 shrink_row_16
4129 const primitive_funcs funcs_16 =
4131 solid_rects_16,
4132 pattern_rects_16,
4133 copy_rect_16,
4134 colorref_to_pixel_masks,
4135 convert_to_16,
4136 create_rop_masks_16,
4137 stretch_row_16,
4138 shrink_row_16
4141 const primitive_funcs funcs_8 =
4143 solid_rects_8,
4144 pattern_rects_8,
4145 copy_rect_8,
4146 colorref_to_pixel_colortable,
4147 convert_to_8,
4148 create_rop_masks_8,
4149 stretch_row_8,
4150 shrink_row_8
4153 const primitive_funcs funcs_4 =
4155 solid_rects_4,
4156 pattern_rects_4,
4157 copy_rect_4,
4158 colorref_to_pixel_colortable,
4159 convert_to_4,
4160 create_rop_masks_4,
4161 stretch_row_4,
4162 shrink_row_4
4165 const primitive_funcs funcs_1 =
4167 solid_rects_1,
4168 pattern_rects_1,
4169 copy_rect_1,
4170 colorref_to_pixel_colortable,
4171 convert_to_1,
4172 create_rop_masks_1,
4173 stretch_row_1,
4174 shrink_row_1
4177 const primitive_funcs funcs_null =
4179 solid_rects_null,
4180 pattern_rects_null,
4181 copy_rect_null,
4182 colorref_to_pixel_null,
4183 convert_to_null,
4184 create_rop_masks_null,
4185 stretch_row_null,
4186 shrink_row_null