gdi32: Add draw_glyph primitives.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blob3c4efece3f8b5dadf4c1047fd39b359b23b33779
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 get_pixel_32(const dib_info *dib, const POINT *pt)
1030 DWORD *ptr = get_pixel_ptr_32( dib, pt->x, pt->y );
1031 return *ptr;
1034 static DWORD get_pixel_24(const dib_info *dib, const POINT *pt)
1036 BYTE *ptr = get_pixel_ptr_24( dib, pt->x, pt->y );
1037 return ptr[0] | ((DWORD)ptr[1] << 8) | ((DWORD)ptr[2] << 16);
1040 static DWORD get_pixel_16(const dib_info *dib, const POINT *pt)
1042 WORD *ptr = get_pixel_ptr_16( dib, pt->x, pt->y );
1043 return *ptr;
1046 static DWORD get_pixel_8(const dib_info *dib, const POINT *pt)
1048 BYTE *ptr = get_pixel_ptr_8( dib, pt->x, pt->y );
1049 return *ptr;
1052 static DWORD get_pixel_4(const dib_info *dib, const POINT *pt)
1054 BYTE *ptr = get_pixel_ptr_4( dib, pt->x, pt->y );
1056 if (pt->x & 1)
1057 return *ptr & 0x0f;
1058 else
1059 return (*ptr >> 4) & 0x0f;
1062 static DWORD get_pixel_1(const dib_info *dib, const POINT *pt)
1064 BYTE *ptr = get_pixel_ptr_1( dib, pt->x, pt->y );
1065 return (*ptr & pixel_masks_1[pt->x & 0x7]) ? 1 : 0;
1068 static DWORD get_pixel_null(const dib_info *dib, const POINT *pt)
1070 return 0;
1073 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
1075 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
1078 static const DWORD field_masks[33] =
1080 0x00, /* should never happen */
1081 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
1082 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1083 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1084 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1087 static inline DWORD get_field(DWORD field, int shift, int len)
1089 shift = shift - (8 - len);
1090 if (shift < 0)
1091 field <<= -shift;
1092 else
1093 field >>= shift;
1094 field &= field_masks[len];
1095 field |= field >> len;
1096 return field;
1099 static inline DWORD put_field(DWORD field, int shift, int len)
1101 shift = shift - (8 - len);
1102 field &= field_masks[len];
1103 if (shift < 0)
1104 field >>= -shift;
1105 else
1106 field <<= shift;
1107 return field;
1110 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
1112 DWORD r,g,b;
1114 r = GetRValue(colour);
1115 g = GetGValue(colour);
1116 b = GetBValue(colour);
1118 return put_field(r, dib->red_shift, dib->red_len) |
1119 put_field(g, dib->green_shift, dib->green_len) |
1120 put_field(b, dib->blue_shift, dib->blue_len);
1123 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
1125 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
1128 static DWORD rgb_to_pixel_colortable(const dib_info *dib, BYTE r, BYTE g, BYTE b)
1130 int i, best_index = 0;
1131 DWORD diff, best_diff = 0xffffffff;
1133 /* special case for conversion to 1-bpp without a color table:
1134 * we get a 1-entry table containing the background color
1136 if (dib->bit_count == 1 && dib->color_table_size == 1)
1137 return (r == dib->color_table[0].rgbRed &&
1138 g == dib->color_table[0].rgbGreen &&
1139 b == dib->color_table[0].rgbBlue);
1141 for(i = 0; i < dib->color_table_size; i++)
1143 RGBQUAD *cur = dib->color_table + i;
1144 diff = (r - cur->rgbRed) * (r - cur->rgbRed)
1145 + (g - cur->rgbGreen) * (g - cur->rgbGreen)
1146 + (b - cur->rgbBlue) * (b - cur->rgbBlue);
1148 if(diff == 0)
1150 best_index = i;
1151 break;
1154 if(diff < best_diff)
1156 best_diff = diff;
1157 best_index = i;
1160 return best_index;
1163 static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
1165 return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) );
1168 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
1170 return 0;
1173 static inline RGBQUAD colortable_entry(const dib_info *dib, DWORD index)
1175 static const RGBQUAD default_rgb;
1176 if (index < dib->color_table_size) return dib->color_table[index];
1177 return default_rgb;
1180 static COLORREF pixel_to_colorref_888(const dib_info *dib, DWORD pixel)
1182 return ( ((pixel >> 16) & 0xff) | (pixel & 0xff00) | ((pixel << 16) & 0xff0000) );
1185 static COLORREF pixel_to_colorref_masks(const dib_info *dib, DWORD pixel)
1187 return RGB( get_field( pixel, dib->red_shift, dib->red_len ),
1188 get_field( pixel, dib->green_shift, dib->green_len ),
1189 get_field( pixel, dib->blue_shift, dib->blue_len ) );
1192 static COLORREF pixel_to_colorref_555(const dib_info *dib, DWORD pixel)
1194 return RGB( ((pixel >> 7) & 0xf8) | ((pixel >> 12) & 0x07),
1195 ((pixel >> 2) & 0xf8) | ((pixel >> 7) & 0x07),
1196 ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x07) );
1199 static COLORREF pixel_to_colorref_colortable(const dib_info *dib, DWORD pixel)
1201 RGBQUAD quad = colortable_entry( dib, pixel );
1203 return RGB( quad.rgbRed, quad.rgbGreen, quad.rgbBlue );
1206 static COLORREF pixel_to_colorref_null(const dib_info *dib, DWORD pixel)
1208 return 0;
1211 static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
1213 assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
1215 return d1->red_mask == d2->red_mask &&
1216 d1->green_mask == d2->green_mask &&
1217 d1->blue_mask == d2->blue_mask;
1220 static void convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
1222 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1223 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1225 switch(src->bit_count)
1227 case 32:
1229 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1230 if(src->funcs == &funcs_8888)
1232 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1233 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1234 else
1236 for(y = src_rect->top; y < src_rect->bottom; y++)
1238 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1239 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1240 dst_start += dst->stride / 4;
1241 src_start += src->stride / 4;
1245 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1247 for(y = src_rect->top; y < src_rect->bottom; y++)
1249 dst_pixel = dst_start;
1250 src_pixel = src_start;
1251 for(x = src_rect->left; x < src_rect->right; x++)
1253 src_val = *src_pixel++;
1254 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
1255 (((src_val >> src->green_shift) & 0xff) << 8) |
1256 ((src_val >> src->blue_shift) & 0xff);
1258 if(pad_size) memset(dst_pixel, 0, pad_size);
1259 dst_start += dst->stride / 4;
1260 src_start += src->stride / 4;
1263 else
1265 for(y = src_rect->top; y < src_rect->bottom; y++)
1267 dst_pixel = dst_start;
1268 src_pixel = src_start;
1269 for(x = src_rect->left; x < src_rect->right; x++)
1271 src_val = *src_pixel++;
1272 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1273 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1274 get_field( src_val, src->blue_shift, src->blue_len ));
1276 if(pad_size) memset(dst_pixel, 0, pad_size);
1277 dst_start += dst->stride / 4;
1278 src_start += src->stride / 4;
1281 break;
1284 case 24:
1286 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1288 for(y = src_rect->top; y < src_rect->bottom; y++)
1290 dst_pixel = dst_start;
1291 src_pixel = src_start;
1292 for(x = src_rect->left; x < src_rect->right; x++)
1294 RGBQUAD rgb;
1295 rgb.rgbBlue = *src_pixel++;
1296 rgb.rgbGreen = *src_pixel++;
1297 rgb.rgbRed = *src_pixel++;
1299 *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
1301 if(pad_size) memset(dst_pixel, 0, pad_size);
1302 dst_start += dst->stride / 4;
1303 src_start += src->stride;
1305 break;
1308 case 16:
1310 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1311 if(src->funcs == &funcs_555)
1313 for(y = src_rect->top; y < src_rect->bottom; y++)
1315 dst_pixel = dst_start;
1316 src_pixel = src_start;
1317 for(x = src_rect->left; x < src_rect->right; x++)
1319 src_val = *src_pixel++;
1320 *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
1321 ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
1322 ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
1324 if(pad_size) memset(dst_pixel, 0, pad_size);
1325 dst_start += dst->stride / 4;
1326 src_start += src->stride / 2;
1329 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1331 for(y = src_rect->top; y < src_rect->bottom; y++)
1333 dst_pixel = dst_start;
1334 src_pixel = src_start;
1335 for(x = src_rect->left; x < src_rect->right; x++)
1337 src_val = *src_pixel++;
1338 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1339 (((src_val >> src->red_shift) << 14) & 0x070000) |
1340 (((src_val >> src->green_shift) << 11) & 0x00f800) |
1341 (((src_val >> src->green_shift) << 6) & 0x000700) |
1342 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1343 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1345 if(pad_size) memset(dst_pixel, 0, pad_size);
1346 dst_start += dst->stride / 4;
1347 src_start += src->stride / 2;
1350 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1352 for(y = src_rect->top; y < src_rect->bottom; y++)
1354 dst_pixel = dst_start;
1355 src_pixel = src_start;
1356 for(x = src_rect->left; x < src_rect->right; x++)
1358 src_val = *src_pixel++;
1359 *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
1360 (((src_val >> src->red_shift) << 14) & 0x070000) |
1361 (((src_val >> src->green_shift) << 10) & 0x00fc00) |
1362 (((src_val >> src->green_shift) << 4) & 0x000300) |
1363 (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
1364 (((src_val >> src->blue_shift) >> 2) & 0x000007);
1366 if(pad_size) memset(dst_pixel, 0, pad_size);
1367 dst_start += dst->stride / 4;
1368 src_start += src->stride / 2;
1371 else
1373 for(y = src_rect->top; y < src_rect->bottom; y++)
1375 dst_pixel = dst_start;
1376 src_pixel = src_start;
1377 for(x = src_rect->left; x < src_rect->right; x++)
1379 src_val = *src_pixel++;
1380 *dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
1381 get_field( src_val, src->green_shift, src->green_len ) << 8 |
1382 get_field( src_val, src->blue_shift, src->blue_len ));
1384 if(pad_size) memset(dst_pixel, 0, pad_size);
1385 dst_start += dst->stride / 4;
1386 src_start += src->stride / 2;
1389 break;
1392 case 8:
1394 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
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 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1402 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1404 if(pad_size) memset(dst_pixel, 0, pad_size);
1405 dst_start += dst->stride / 4;
1406 src_start += src->stride;
1408 break;
1411 case 4:
1413 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1414 for(y = src_rect->top; y < src_rect->bottom; y++)
1416 dst_pixel = dst_start;
1417 src_pixel = src_start;
1418 for(x = src_rect->left; x < src_rect->right; x++)
1420 RGBQUAD rgb;
1421 if(x & 1)
1422 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1423 else
1424 rgb = colortable_entry( src, *src_pixel >> 4 );
1425 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1427 if(pad_size) memset(dst_pixel, 0, pad_size);
1428 dst_start += dst->stride / 4;
1429 src_start += src->stride;
1431 break;
1434 case 1:
1436 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1437 for(y = src_rect->top; y < src_rect->bottom; y++)
1439 dst_pixel = dst_start;
1440 src_pixel = src_start;
1441 for(x = src_rect->left; x < src_rect->right; x++)
1443 RGBQUAD rgb;
1444 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1445 if((x % 8) == 7) src_pixel++;
1446 rgb = src->color_table[src_val];
1447 *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
1449 if(pad_size) memset(dst_pixel, 0, pad_size);
1450 dst_start += dst->stride / 4;
1451 src_start += src->stride;
1453 break;
1458 static void convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
1460 DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
1461 int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
1463 switch(src->bit_count)
1465 case 32:
1467 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1469 if(src->funcs == &funcs_8888)
1471 for(y = src_rect->top; y < src_rect->bottom; y++)
1473 dst_pixel = dst_start;
1474 src_pixel = src_start;
1475 for(x = src_rect->left; x < src_rect->right; x++)
1477 src_val = *src_pixel++;
1478 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
1479 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
1480 put_field(src_val, dst->blue_shift, dst->blue_len);
1482 if(pad_size) memset(dst_pixel, 0, pad_size);
1483 dst_start += dst->stride / 4;
1484 src_start += src->stride / 4;
1487 else if(bit_fields_match(src, dst))
1489 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1490 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1491 else
1493 for(y = src_rect->top; y < src_rect->bottom; y++)
1495 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
1496 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
1497 dst_start += dst->stride / 4;
1498 src_start += src->stride / 4;
1502 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
1503 dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
1505 for(y = src_rect->top; y < src_rect->bottom; y++)
1507 dst_pixel = dst_start;
1508 src_pixel = src_start;
1509 for(x = src_rect->left; x < src_rect->right; x++)
1511 src_val = *src_pixel++;
1512 *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
1513 (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
1514 (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
1516 if(pad_size) memset(dst_pixel, 0, pad_size);
1517 dst_start += dst->stride / 4;
1518 src_start += src->stride / 4;
1521 else
1523 for(y = src_rect->top; y < src_rect->bottom; y++)
1525 dst_pixel = dst_start;
1526 src_pixel = src_start;
1527 for(x = src_rect->left; x < src_rect->right; x++)
1529 src_val = *src_pixel++;
1530 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1531 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1532 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1534 if(pad_size) memset(dst_pixel, 0, pad_size);
1535 dst_start += dst->stride / 4;
1536 src_start += src->stride / 4;
1539 break;
1542 case 24:
1544 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
1546 for(y = src_rect->top; y < src_rect->bottom; y++)
1548 dst_pixel = dst_start;
1549 src_pixel = src_start;
1550 for(x = src_rect->left; x < src_rect->right; x++)
1552 RGBQUAD rgb;
1553 rgb.rgbBlue = *src_pixel++;
1554 rgb.rgbGreen = *src_pixel++;
1555 rgb.rgbRed = *src_pixel++;
1557 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1558 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1559 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1561 if(pad_size) memset(dst_pixel, 0, pad_size);
1562 dst_start += dst->stride / 4;
1563 src_start += src->stride;
1565 break;
1568 case 16:
1570 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1571 if(src->funcs == &funcs_555)
1573 for(y = src_rect->top; y < src_rect->bottom; y++)
1575 dst_pixel = dst_start;
1576 src_pixel = src_start;
1577 for(x = src_rect->left; x < src_rect->right; x++)
1579 src_val = *src_pixel++;
1580 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
1581 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
1582 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1584 if(pad_size) memset(dst_pixel, 0, pad_size);
1585 dst_start += dst->stride / 4;
1586 src_start += src->stride / 2;
1589 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1591 for(y = src_rect->top; y < src_rect->bottom; y++)
1593 dst_pixel = dst_start;
1594 src_pixel = src_start;
1595 for(x = src_rect->left; x < src_rect->right; x++)
1597 src_val = *src_pixel++;
1598 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1599 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1600 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
1601 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
1602 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1603 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1605 if(pad_size) memset(dst_pixel, 0, pad_size);
1606 dst_start += dst->stride / 4;
1607 src_start += src->stride / 2;
1610 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1612 for(y = src_rect->top; y < src_rect->bottom; y++)
1614 dst_pixel = dst_start;
1615 src_pixel = src_start;
1616 for(x = src_rect->left; x < src_rect->right; x++)
1618 src_val = *src_pixel++;
1619 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
1620 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
1621 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
1622 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
1623 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
1624 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
1626 if(pad_size) memset(dst_pixel, 0, pad_size);
1627 dst_start += dst->stride / 4;
1628 src_start += src->stride / 2;
1631 else
1633 for(y = src_rect->top; y < src_rect->bottom; y++)
1635 dst_pixel = dst_start;
1636 src_pixel = src_start;
1637 for(x = src_rect->left; x < src_rect->right; x++)
1639 src_val = *src_pixel++;
1640 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
1641 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
1642 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
1644 if(pad_size) memset(dst_pixel, 0, pad_size);
1645 dst_start += dst->stride / 4;
1646 src_start += src->stride / 2;
1649 break;
1652 case 8:
1654 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1655 for(y = src_rect->top; y < src_rect->bottom; y++)
1657 dst_pixel = dst_start;
1658 src_pixel = src_start;
1659 for(x = src_rect->left; x < src_rect->right; x++)
1661 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1662 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1663 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1664 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1666 if(pad_size) memset(dst_pixel, 0, pad_size);
1667 dst_start += dst->stride / 4;
1668 src_start += src->stride;
1670 break;
1673 case 4:
1675 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1676 for(y = src_rect->top; y < src_rect->bottom; y++)
1678 dst_pixel = dst_start;
1679 src_pixel = src_start;
1680 for(x = src_rect->left; x < src_rect->right; x++)
1682 RGBQUAD rgb;
1683 if(x & 1)
1684 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1685 else
1686 rgb = colortable_entry( src, *src_pixel >> 4 );
1687 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1688 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1689 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1691 if(pad_size) memset(dst_pixel, 0, pad_size);
1692 dst_start += dst->stride / 4;
1693 src_start += src->stride;
1695 break;
1698 case 1:
1700 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1701 for(y = src_rect->top; y < src_rect->bottom; y++)
1703 dst_pixel = dst_start;
1704 src_pixel = src_start;
1705 for(x = src_rect->left; x < src_rect->right; x++)
1707 RGBQUAD rgb;
1708 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1709 if((x % 8) == 7) src_pixel++;
1710 rgb = src->color_table[src_val];
1711 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
1712 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
1713 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
1715 if(pad_size) memset(dst_pixel, 0, pad_size);
1716 dst_start += dst->stride / 4;
1717 src_start += src->stride;
1719 break;
1724 static void convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_rect)
1726 BYTE *dst_start = get_pixel_ptr_24(dst, 0, 0), *dst_pixel;
1727 DWORD src_val;
1728 int x, y, pad_size = ((dst->width * 3 + 3) & ~3) - (src_rect->right - src_rect->left) * 3;
1730 switch(src->bit_count)
1732 case 32:
1734 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1735 if(src->funcs == &funcs_8888)
1737 for(y = src_rect->top; y < src_rect->bottom; y++)
1739 dst_pixel = dst_start;
1740 src_pixel = src_start;
1741 for(x = src_rect->left; x < src_rect->right; x++)
1743 src_val = *src_pixel++;
1744 *dst_pixel++ = src_val & 0xff;
1745 *dst_pixel++ = (src_val >> 8) & 0xff;
1746 *dst_pixel++ = (src_val >> 16) & 0xff;
1748 if(pad_size) memset(dst_pixel, 0, pad_size);
1749 dst_start += dst->stride;
1750 src_start += src->stride / 4;
1753 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1755 for(y = src_rect->top; y < src_rect->bottom; y++)
1757 dst_pixel = dst_start;
1758 src_pixel = src_start;
1759 for(x = src_rect->left; x < src_rect->right; x++)
1761 src_val = *src_pixel++;
1762 *dst_pixel++ = (src_val >> src->blue_shift) & 0xff;
1763 *dst_pixel++ = (src_val >> src->green_shift) & 0xff;
1764 *dst_pixel++ = (src_val >> src->red_shift) & 0xff;
1766 if(pad_size) memset(dst_pixel, 0, pad_size);
1767 dst_start += dst->stride;
1768 src_start += src->stride / 4;
1771 else
1773 for(y = src_rect->top; y < src_rect->bottom; y++)
1775 dst_pixel = dst_start;
1776 src_pixel = src_start;
1777 for(x = src_rect->left; x < src_rect->right; x++)
1779 src_val = *src_pixel++;
1780 *dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
1781 *dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
1782 *dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
1784 if(pad_size) memset(dst_pixel, 0, pad_size);
1785 dst_start += dst->stride;
1786 src_start += src->stride / 4;
1789 break;
1792 case 24:
1794 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top);
1796 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
1797 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
1798 else
1800 for(y = src_rect->top; y < src_rect->bottom; y++)
1802 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 3);
1803 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left) * 3, 0, pad_size);
1804 dst_start += dst->stride;
1805 src_start += src->stride;
1808 break;
1811 case 16:
1813 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
1814 if(src->funcs == &funcs_555)
1816 for(y = src_rect->top; y < src_rect->bottom; y++)
1818 dst_pixel = dst_start;
1819 src_pixel = src_start;
1820 for(x = src_rect->left; x < src_rect->right; x++)
1822 src_val = *src_pixel++;
1823 *dst_pixel++ = ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07);
1824 *dst_pixel++ = ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07);
1825 *dst_pixel++ = ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07);
1827 if(pad_size) memset(dst_pixel, 0, pad_size);
1828 dst_start += dst->stride;
1829 src_start += src->stride / 2;
1832 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
1834 for(y = src_rect->top; y < src_rect->bottom; y++)
1836 dst_pixel = dst_start;
1837 src_pixel = src_start;
1838 for(x = src_rect->left; x < src_rect->right; x++)
1840 src_val = *src_pixel++;
1841 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1842 (((src_val >> src->blue_shift) >> 2) & 0x07);
1843 *dst_pixel++ = (((src_val >> src->green_shift) << 3) & 0xf8) |
1844 (((src_val >> src->green_shift) >> 2) & 0x07);
1845 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1846 (((src_val >> src->red_shift) >> 2) & 0x07);
1848 if(pad_size) memset(dst_pixel, 0, pad_size);
1849 dst_start += dst->stride;
1850 src_start += src->stride / 2;
1853 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
1855 for(y = src_rect->top; y < src_rect->bottom; y++)
1857 dst_pixel = dst_start;
1858 src_pixel = src_start;
1859 for(x = src_rect->left; x < src_rect->right; x++)
1861 src_val = *src_pixel++;
1862 *dst_pixel++ = (((src_val >> src->blue_shift) << 3) & 0xf8) |
1863 (((src_val >> src->blue_shift) >> 2) & 0x07);
1864 *dst_pixel++ = (((src_val >> src->green_shift) << 2) & 0xfc) |
1865 (((src_val >> src->green_shift) >> 4) & 0x03);
1866 *dst_pixel++ = (((src_val >> src->red_shift) << 3) & 0xf8) |
1867 (((src_val >> src->red_shift) >> 2) & 0x07);
1869 if(pad_size) memset(dst_pixel, 0, pad_size);
1870 dst_start += dst->stride;
1871 src_start += src->stride / 2;
1874 else
1876 for(y = src_rect->top; y < src_rect->bottom; y++)
1878 dst_pixel = dst_start;
1879 src_pixel = src_start;
1880 for(x = src_rect->left; x < src_rect->right; x++)
1882 src_val = *src_pixel++;
1883 *dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
1884 *dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
1885 *dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
1887 if(pad_size) memset(dst_pixel, 0, pad_size);
1888 dst_start += dst->stride;
1889 src_start += src->stride / 2;
1892 break;
1895 case 8:
1897 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
1898 for(y = src_rect->top; y < src_rect->bottom; y++)
1900 dst_pixel = dst_start;
1901 src_pixel = src_start;
1902 for(x = src_rect->left; x < src_rect->right; x++)
1904 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
1905 *dst_pixel++ = rgb.rgbBlue;
1906 *dst_pixel++ = rgb.rgbGreen;
1907 *dst_pixel++ = rgb.rgbRed;
1909 if(pad_size) memset(dst_pixel, 0, pad_size);
1910 dst_start += dst->stride;
1911 src_start += src->stride;
1913 break;
1916 case 4:
1918 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
1919 for(y = src_rect->top; y < src_rect->bottom; y++)
1921 dst_pixel = dst_start;
1922 src_pixel = src_start;
1923 for(x = src_rect->left; x < src_rect->right; x++)
1925 RGBQUAD rgb;
1926 if(x & 1)
1927 rgb = colortable_entry( src, *src_pixel++ & 0xf );
1928 else
1929 rgb = colortable_entry( src, *src_pixel >> 4 );
1930 *dst_pixel++ = rgb.rgbBlue;
1931 *dst_pixel++ = rgb.rgbGreen;
1932 *dst_pixel++ = rgb.rgbRed;
1934 if(pad_size) memset(dst_pixel, 0, pad_size);
1935 dst_start += dst->stride;
1936 src_start += src->stride;
1938 break;
1941 case 1:
1943 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
1944 for(y = src_rect->top; y < src_rect->bottom; y++)
1946 dst_pixel = dst_start;
1947 src_pixel = src_start;
1948 for(x = src_rect->left; x < src_rect->right; x++)
1950 RGBQUAD rgb;
1951 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
1952 if((x % 8) == 7) src_pixel++;
1953 rgb = src->color_table[src_val];
1954 *dst_pixel++ = rgb.rgbBlue;
1955 *dst_pixel++ = rgb.rgbGreen;
1956 *dst_pixel++ = rgb.rgbRed;
1958 if(pad_size) memset(dst_pixel, 0, pad_size);
1959 dst_start += dst->stride;
1960 src_start += src->stride;
1962 break;
1967 static void convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
1969 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
1970 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
1971 DWORD src_val;
1973 switch(src->bit_count)
1975 case 32:
1977 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
1979 if(src->funcs == &funcs_8888)
1981 for(y = src_rect->top; y < src_rect->bottom; y++)
1983 dst_pixel = dst_start;
1984 src_pixel = src_start;
1985 for(x = src_rect->left; x < src_rect->right; x++)
1987 src_val = *src_pixel++;
1988 *dst_pixel++ = ((src_val >> 9) & 0x7c00) |
1989 ((src_val >> 6) & 0x03e0) |
1990 ((src_val >> 3) & 0x001f);
1992 if(pad_size) memset(dst_pixel, 0, pad_size);
1993 dst_start += dst->stride / 2;
1994 src_start += src->stride / 4;
1997 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
1999 for(y = src_rect->top; y < src_rect->bottom; y++)
2001 dst_pixel = dst_start;
2002 src_pixel = src_start;
2003 for(x = src_rect->left; x < src_rect->right; x++)
2005 src_val = *src_pixel++;
2006 *dst_pixel++ = (((src_val >> src->red_shift) << 7) & 0x7c00) |
2007 (((src_val >> src->green_shift) << 2) & 0x03e0) |
2008 (((src_val >> src->blue_shift) >> 3) & 0x001f);
2010 if(pad_size) memset(dst_pixel, 0, pad_size);
2011 dst_start += dst->stride / 2;
2012 src_start += src->stride / 4;
2015 else
2017 for(y = src_rect->top; y < src_rect->bottom; y++)
2019 dst_pixel = dst_start;
2020 src_pixel = src_start;
2021 for(x = src_rect->left; x < src_rect->right; x++)
2023 src_val = *src_pixel++;
2024 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
2025 ((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
2026 ( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
2028 if(pad_size) memset(dst_pixel, 0, pad_size);
2029 dst_start += dst->stride / 2;
2030 src_start += src->stride / 4;
2033 break;
2036 case 24:
2038 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2040 for(y = src_rect->top; y < src_rect->bottom; y++)
2042 dst_pixel = dst_start;
2043 src_pixel = src_start;
2044 for(x = src_rect->left; x < src_rect->right; x++)
2046 RGBQUAD rgb;
2047 rgb.rgbBlue = *src_pixel++;
2048 rgb.rgbGreen = *src_pixel++;
2049 rgb.rgbRed = *src_pixel++;
2051 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2052 ((rgb.rgbGreen << 2) & 0x03e0) |
2053 ((rgb.rgbBlue >> 3) & 0x001f);
2055 if(pad_size) memset(dst_pixel, 0, pad_size);
2056 dst_start += dst->stride / 2;
2057 src_start += src->stride;
2059 break;
2062 case 16:
2064 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2065 if(src->funcs == &funcs_555)
2067 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2068 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2069 else
2071 for(y = src_rect->top; y < src_rect->bottom; y++)
2073 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2074 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2075 dst_start += dst->stride / 2;
2076 src_start += src->stride / 2;
2080 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2082 for(y = src_rect->top; y < src_rect->bottom; y++)
2084 dst_pixel = dst_start;
2085 src_pixel = src_start;
2086 for(x = src_rect->left; x < src_rect->right; x++)
2088 src_val = *src_pixel++;
2089 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2090 (((src_val >> src->green_shift) << 5) & 0x03e0) |
2091 ( (src_val >> src->blue_shift) & 0x001f);
2093 if(pad_size) memset(dst_pixel, 0, pad_size);
2094 dst_start += dst->stride / 2;
2095 src_start += src->stride / 2;
2098 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2100 for(y = src_rect->top; y < src_rect->bottom; y++)
2102 dst_pixel = dst_start;
2103 src_pixel = src_start;
2104 for(x = src_rect->left; x < src_rect->right; x++)
2106 src_val = *src_pixel++;
2107 *dst_pixel++ = (((src_val >> src->red_shift) << 10) & 0x7c00) |
2108 (((src_val >> src->green_shift) << 4) & 0x03e0) |
2109 ( (src_val >> src->blue_shift) & 0x001f);
2111 if(pad_size) memset(dst_pixel, 0, pad_size);
2112 dst_start += dst->stride / 2;
2113 src_start += src->stride / 2;
2116 else
2118 for(y = src_rect->top; y < src_rect->bottom; y++)
2120 dst_pixel = dst_start;
2121 src_pixel = src_start;
2122 for(x = src_rect->left; x < src_rect->right; x++)
2124 src_val = *src_pixel++;
2125 *dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
2126 ((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
2127 ( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
2129 if(pad_size) memset(dst_pixel, 0, pad_size);
2130 dst_start += dst->stride / 2;
2131 src_start += src->stride / 2;
2134 break;
2137 case 8:
2139 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2140 for(y = src_rect->top; y < src_rect->bottom; y++)
2142 dst_pixel = dst_start;
2143 src_pixel = src_start;
2144 for(x = src_rect->left; x < src_rect->right; x++)
2146 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2147 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2148 ((rgb.rgbGreen << 2) & 0x03e0) |
2149 ((rgb.rgbBlue >> 3) & 0x001f);
2151 if(pad_size) memset(dst_pixel, 0, pad_size);
2152 dst_start += dst->stride / 2;
2153 src_start += src->stride;
2155 break;
2158 case 4:
2160 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2161 for(y = src_rect->top; y < src_rect->bottom; y++)
2163 dst_pixel = dst_start;
2164 src_pixel = src_start;
2165 for(x = src_rect->left; x < src_rect->right; x++)
2167 RGBQUAD rgb;
2168 if(x & 1)
2169 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2170 else
2171 rgb = colortable_entry( src, *src_pixel >> 4 );
2172 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2173 ((rgb.rgbGreen << 2) & 0x03e0) |
2174 ((rgb.rgbBlue >> 3) & 0x001f);
2176 if(pad_size) memset(dst_pixel, 0, pad_size);
2177 dst_start += dst->stride / 2;
2178 src_start += src->stride;
2180 break;
2183 case 1:
2185 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2186 for(y = src_rect->top; y < src_rect->bottom; y++)
2188 dst_pixel = dst_start;
2189 src_pixel = src_start;
2190 for(x = src_rect->left; x < src_rect->right; x++)
2192 RGBQUAD rgb;
2193 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2194 if((x % 8) == 7) src_pixel++;
2195 rgb = src->color_table[src_val];
2196 *dst_pixel++ = ((rgb.rgbRed << 7) & 0x7c00) |
2197 ((rgb.rgbGreen << 2) & 0x03e0) |
2198 ((rgb.rgbBlue >> 3) & 0x001f);
2200 if(pad_size) memset(dst_pixel, 0, pad_size);
2201 dst_start += dst->stride / 2;
2202 src_start += src->stride;
2204 break;
2209 static void convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
2211 WORD *dst_start = get_pixel_ptr_16(dst, 0, 0), *dst_pixel;
2212 INT x, y, pad_size = ((dst->width + 1) & ~1) * 2 - (src_rect->right - src_rect->left) * 2;
2213 DWORD src_val;
2215 switch(src->bit_count)
2217 case 32:
2219 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2221 if(src->funcs == &funcs_8888)
2223 for(y = src_rect->top; y < src_rect->bottom; y++)
2225 dst_pixel = dst_start;
2226 src_pixel = src_start;
2227 for(x = src_rect->left; x < src_rect->right; x++)
2229 src_val = *src_pixel++;
2230 *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
2231 put_field(src_val >> 8, dst->green_shift, dst->green_len) |
2232 put_field(src_val, dst->blue_shift, dst->blue_len);
2234 if(pad_size) memset(dst_pixel, 0, pad_size);
2235 dst_start += dst->stride / 2;
2236 src_start += src->stride / 4;
2239 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2241 for(y = src_rect->top; y < src_rect->bottom; y++)
2243 dst_pixel = dst_start;
2244 src_pixel = src_start;
2245 for(x = src_rect->left; x < src_rect->right; x++)
2247 src_val = *src_pixel++;
2248 *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
2249 put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
2250 put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
2252 if(pad_size) memset(dst_pixel, 0, pad_size);
2253 dst_start += dst->stride / 2;
2254 src_start += src->stride / 4;
2257 else
2259 for(y = src_rect->top; y < src_rect->bottom; y++)
2261 dst_pixel = dst_start;
2262 src_pixel = src_start;
2263 for(x = src_rect->left; x < src_rect->right; x++)
2265 src_val = *src_pixel++;
2266 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2267 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2268 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2270 if(pad_size) memset(dst_pixel, 0, pad_size);
2271 dst_start += dst->stride / 2;
2272 src_start += src->stride / 4;
2275 break;
2278 case 24:
2280 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2282 for(y = src_rect->top; y < src_rect->bottom; y++)
2284 dst_pixel = dst_start;
2285 src_pixel = src_start;
2286 for(x = src_rect->left; x < src_rect->right; x++)
2288 RGBQUAD rgb;
2289 rgb.rgbBlue = *src_pixel++;
2290 rgb.rgbGreen = *src_pixel++;
2291 rgb.rgbRed = *src_pixel++;
2293 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2294 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2295 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2297 if(pad_size) memset(dst_pixel, 0, pad_size);
2298 dst_start += dst->stride / 2;
2299 src_start += src->stride;
2301 break;
2304 case 16:
2306 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2307 if(src->funcs == &funcs_555)
2309 for(y = src_rect->top; y < src_rect->bottom; y++)
2311 dst_pixel = dst_start;
2312 src_pixel = src_start;
2313 for(x = src_rect->left; x < src_rect->right; x++)
2315 src_val = *src_pixel++;
2316 *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
2317 put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
2318 put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2320 if(pad_size) memset(dst_pixel, 0, pad_size);
2321 dst_start += dst->stride / 2;
2322 src_start += src->stride / 2;
2325 else if(bit_fields_match(src, dst))
2327 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2328 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2329 else
2331 for(y = src_rect->top; y < src_rect->bottom; y++)
2333 memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
2334 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2335 dst_start += dst->stride / 2;
2336 src_start += src->stride / 2;
2340 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2342 for(y = src_rect->top; y < src_rect->bottom; y++)
2344 dst_pixel = dst_start;
2345 src_pixel = src_start;
2346 for(x = src_rect->left; x < src_rect->right; x++)
2348 src_val = *src_pixel++;
2349 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2350 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2351 put_field( (((src_val >> src->green_shift) << 3) & 0xf8) |
2352 (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) |
2353 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2354 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2356 if(pad_size) memset(dst_pixel, 0, pad_size);
2357 dst_start += dst->stride / 2;
2358 src_start += src->stride / 2;
2361 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2363 for(y = src_rect->top; y < src_rect->bottom; y++)
2365 dst_pixel = dst_start;
2366 src_pixel = src_start;
2367 for(x = src_rect->left; x < src_rect->right; x++)
2369 src_val = *src_pixel++;
2370 *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) |
2371 (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) |
2372 put_field( (((src_val >> src->green_shift) << 2) & 0xfc) |
2373 (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) |
2374 put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) |
2375 (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len);
2377 if(pad_size) memset(dst_pixel, 0, pad_size);
2378 dst_start += dst->stride / 2;
2379 src_start += src->stride / 2;
2382 else
2384 for(y = src_rect->top; y < src_rect->bottom; y++)
2386 dst_pixel = dst_start;
2387 src_pixel = src_start;
2388 for(x = src_rect->left; x < src_rect->right; x++)
2390 src_val = *src_pixel++;
2391 *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
2392 put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
2393 put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
2395 if(pad_size) memset(dst_pixel, 0, pad_size);
2396 dst_start += dst->stride / 2;
2397 src_start += src->stride / 2;
2400 break;
2403 case 8:
2405 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2406 for(y = src_rect->top; y < src_rect->bottom; y++)
2408 dst_pixel = dst_start;
2409 src_pixel = src_start;
2410 for(x = src_rect->left; x < src_rect->right; x++)
2412 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2413 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2414 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2415 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2417 if(pad_size) memset(dst_pixel, 0, pad_size);
2418 dst_start += dst->stride / 2;
2419 src_start += src->stride;
2421 break;
2424 case 4:
2426 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2427 for(y = src_rect->top; y < src_rect->bottom; y++)
2429 dst_pixel = dst_start;
2430 src_pixel = src_start;
2431 for(x = src_rect->left; x < src_rect->right; x++)
2433 RGBQUAD rgb;
2434 if(x & 1)
2435 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2436 else
2437 rgb = colortable_entry( src, *src_pixel >> 4 );
2438 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2439 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2440 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2442 if(pad_size) memset(dst_pixel, 0, pad_size);
2443 dst_start += dst->stride / 2;
2444 src_start += src->stride;
2446 break;
2449 case 1:
2451 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2452 for(y = src_rect->top; y < src_rect->bottom; y++)
2454 dst_pixel = dst_start;
2455 src_pixel = src_start;
2456 for(x = src_rect->left; x < src_rect->right; x++)
2458 RGBQUAD rgb;
2459 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2460 if((x % 8) == 7) src_pixel++;
2461 rgb = src->color_table[src_val];
2462 *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) |
2463 put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) |
2464 put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len);
2466 if(pad_size) memset(dst_pixel, 0, pad_size);
2467 dst_start += dst->stride / 2;
2468 src_start += src->stride;
2470 break;
2475 static inline BOOL color_tables_match(const dib_info *d1, const dib_info *d2)
2477 assert(d1->color_table_size && d2->color_table_size);
2479 if(d1->color_table_size != d2->color_table_size) return FALSE;
2480 return !memcmp(d1->color_table, d2->color_table, d1->color_table_size * sizeof(d1->color_table[0]));
2483 static inline DWORD rgb_lookup_colortable(const dib_info *dst, BYTE r, BYTE g, BYTE b)
2485 /* Windows reduces precision to 5 bits, probably in order to build some sort of lookup cache */
2486 return rgb_to_pixel_colortable( dst, (r & ~7) + 4, (g & ~7) + 4, (b & ~7) + 4 );
2489 static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
2491 BYTE *dst_start = get_pixel_ptr_8(dst, 0, 0), *dst_pixel;
2492 INT x, y, pad_size = ((dst->width + 3) & ~3) - (src_rect->right - src_rect->left);
2493 DWORD src_val;
2495 switch(src->bit_count)
2497 case 32:
2499 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2501 if(src->funcs == &funcs_8888)
2503 for(y = src_rect->top; y < src_rect->bottom; y++)
2505 dst_pixel = dst_start;
2506 src_pixel = src_start;
2507 for(x = src_rect->left; x < src_rect->right; x++)
2509 src_val = *src_pixel++;
2510 *dst_pixel++ = rgb_lookup_colortable(dst, src_val >> 16, src_val >> 8, src_val );
2512 if(pad_size) memset(dst_pixel, 0, pad_size);
2513 dst_start += dst->stride;
2514 src_start += src->stride / 4;
2517 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
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_lookup_colortable(dst,
2527 src_val >> src->red_shift,
2528 src_val >> src->green_shift,
2529 src_val >> src->blue_shift );
2531 if(pad_size) memset(dst_pixel, 0, pad_size);
2532 dst_start += dst->stride;
2533 src_start += src->stride / 4;
2536 else
2538 for(y = src_rect->top; y < src_rect->bottom; y++)
2540 dst_pixel = dst_start;
2541 src_pixel = src_start;
2542 for(x = src_rect->left; x < src_rect->right; x++)
2544 src_val = *src_pixel++;
2545 *dst_pixel++ = rgb_lookup_colortable(dst,
2546 get_field(src_val, src->red_shift, src->red_len),
2547 get_field(src_val, src->green_shift, src->green_len),
2548 get_field(src_val, src->blue_shift, src->blue_len));
2550 if(pad_size) memset(dst_pixel, 0, pad_size);
2551 dst_start += dst->stride;
2552 src_start += src->stride / 4;
2555 break;
2558 case 24:
2560 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2562 for(y = src_rect->top; y < src_rect->bottom; y++)
2564 dst_pixel = dst_start;
2565 src_pixel = src_start;
2566 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2568 *dst_pixel++ = rgb_lookup_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0] );
2570 if(pad_size) memset(dst_pixel, 0, pad_size);
2571 dst_start += dst->stride;
2572 src_start += src->stride;
2574 break;
2577 case 16:
2579 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2580 if(src->funcs == &funcs_555)
2582 for(y = src_rect->top; y < src_rect->bottom; y++)
2584 dst_pixel = dst_start;
2585 src_pixel = src_start;
2586 for(x = src_rect->left; x < src_rect->right; x++)
2588 src_val = *src_pixel++;
2589 *dst_pixel++ = rgb_lookup_colortable(dst,
2590 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2591 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2592 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2594 if(pad_size) memset(dst_pixel, 0, pad_size);
2595 dst_start += dst->stride;
2596 src_start += src->stride / 2;
2599 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2601 for(y = src_rect->top; y < src_rect->bottom; y++)
2603 dst_pixel = dst_start;
2604 src_pixel = src_start;
2605 for(x = src_rect->left; x < src_rect->right; x++)
2607 src_val = *src_pixel++;
2608 *dst_pixel++ = rgb_lookup_colortable(dst,
2609 (((src_val >> src->red_shift) << 3) & 0xf8) |
2610 (((src_val >> src->red_shift) >> 2) & 0x07),
2611 (((src_val >> src->green_shift) << 3) & 0xf8) |
2612 (((src_val >> src->green_shift) >> 2) & 0x07),
2613 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2614 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2616 if(pad_size) memset(dst_pixel, 0, pad_size);
2617 dst_start += dst->stride;
2618 src_start += src->stride / 2;
2621 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2623 for(y = src_rect->top; y < src_rect->bottom; y++)
2625 dst_pixel = dst_start;
2626 src_pixel = src_start;
2627 for(x = src_rect->left; x < src_rect->right; x++)
2629 src_val = *src_pixel++;
2630 *dst_pixel++ = rgb_lookup_colortable(dst,
2631 (((src_val >> src->red_shift) << 3) & 0xf8) |
2632 (((src_val >> src->red_shift) >> 2) & 0x07),
2633 (((src_val >> src->green_shift) << 2) & 0xfc) |
2634 (((src_val >> src->green_shift) >> 4) & 0x03),
2635 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2636 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2638 if(pad_size) memset(dst_pixel, 0, pad_size);
2639 dst_start += dst->stride;
2640 src_start += src->stride / 2;
2643 else
2645 for(y = src_rect->top; y < src_rect->bottom; y++)
2647 dst_pixel = dst_start;
2648 src_pixel = src_start;
2649 for(x = src_rect->left; x < src_rect->right; x++)
2651 src_val = *src_pixel++;
2652 *dst_pixel++ = rgb_lookup_colortable(dst,
2653 get_field(src_val, src->red_shift, src->red_len),
2654 get_field(src_val, src->green_shift, src->green_len),
2655 get_field(src_val, src->blue_shift, src->blue_len));
2657 if(pad_size) memset(dst_pixel, 0, pad_size);
2658 dst_start += dst->stride;
2659 src_start += src->stride / 2;
2662 break;
2665 case 8:
2667 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
2669 if(color_tables_match(dst, src))
2671 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
2672 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
2673 else
2675 for(y = src_rect->top; y < src_rect->bottom; y++)
2677 memcpy(dst_start, src_start, src_rect->right - src_rect->left);
2678 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
2679 dst_start += dst->stride;
2680 src_start += src->stride;
2684 else
2686 for(y = src_rect->top; y < src_rect->bottom; y++)
2688 dst_pixel = dst_start;
2689 src_pixel = src_start;
2690 for(x = src_rect->left; x < src_rect->right; x++)
2692 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
2693 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2695 if(pad_size) memset(dst_pixel, 0, pad_size);
2696 dst_start += dst->stride;
2697 src_start += src->stride;
2700 break;
2703 case 4:
2705 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
2706 for(y = src_rect->top; y < src_rect->bottom; y++)
2708 dst_pixel = dst_start;
2709 src_pixel = src_start;
2710 for(x = src_rect->left; x < src_rect->right; x++)
2712 RGBQUAD rgb;
2713 if(x & 1)
2714 rgb = colortable_entry( src, *src_pixel++ & 0xf );
2715 else
2716 rgb = colortable_entry( src, *src_pixel >> 4 );
2717 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2719 if(pad_size) memset(dst_pixel, 0, pad_size);
2720 dst_start += dst->stride;
2721 src_start += src->stride;
2723 break;
2726 case 1:
2728 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
2729 for(y = src_rect->top; y < src_rect->bottom; y++)
2731 dst_pixel = dst_start;
2732 src_pixel = src_start;
2733 for(x = src_rect->left; x < src_rect->right; x++)
2735 RGBQUAD rgb;
2736 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
2737 if((x % 8) == 7) src_pixel++;
2738 rgb = src->color_table[src_val];
2739 *dst_pixel++ = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
2741 if(pad_size) memset(dst_pixel, 0, pad_size);
2742 dst_start += dst->stride;
2743 src_start += src->stride;
2745 break;
2750 static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rect)
2752 BYTE *dst_start = get_pixel_ptr_4(dst, 0, 0), *dst_pixel, dst_val;
2753 INT x, y, pad_size = ((dst->width + 7) & ~7) / 2 - (src_rect->right - src_rect->left + 1) / 2;
2754 DWORD src_val;
2756 switch(src->bit_count)
2758 case 32:
2760 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
2762 if(src->funcs == &funcs_8888)
2764 for(y = src_rect->top; y < src_rect->bottom; y++)
2766 dst_pixel = dst_start;
2767 src_pixel = src_start;
2768 for(x = src_rect->left; x < src_rect->right; x++)
2770 src_val = *src_pixel++;
2771 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val);
2772 if((x - src_rect->left) & 1)
2774 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2775 dst_pixel++;
2777 else
2778 *dst_pixel = (dst_val << 4) & 0xf0;
2780 if(pad_size)
2782 if((x - src_rect->left) & 1) dst_pixel++;
2783 memset(dst_pixel, 0, pad_size);
2785 dst_start += dst->stride;
2786 src_start += src->stride / 4;
2789 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
2791 for(y = src_rect->top; y < src_rect->bottom; y++)
2793 dst_pixel = dst_start;
2794 src_pixel = src_start;
2795 for(x = src_rect->left; x < src_rect->right; x++)
2797 src_val = *src_pixel++;
2798 dst_val = rgb_to_pixel_colortable(dst,
2799 src_val >> src->red_shift,
2800 src_val >> src->green_shift,
2801 src_val >> src->blue_shift);
2802 if((x - src_rect->left) & 1)
2804 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2805 dst_pixel++;
2807 else
2808 *dst_pixel = (dst_val << 4) & 0xf0;
2810 if(pad_size)
2812 if((x - src_rect->left) & 1) dst_pixel++;
2813 memset(dst_pixel, 0, pad_size);
2815 dst_start += dst->stride;
2816 src_start += src->stride / 4;
2819 else
2821 for(y = src_rect->top; y < src_rect->bottom; y++)
2823 dst_pixel = dst_start;
2824 src_pixel = src_start;
2825 for(x = src_rect->left; x < src_rect->right; x++)
2827 src_val = *src_pixel++;
2828 dst_val = rgb_to_pixel_colortable(dst,
2829 get_field(src_val, src->red_shift, src->red_len),
2830 get_field(src_val, src->green_shift, src->green_len),
2831 get_field(src_val, src->blue_shift, src->blue_len));
2832 if((x - src_rect->left) & 1)
2834 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2835 dst_pixel++;
2837 else
2838 *dst_pixel = (dst_val << 4) & 0xf0;
2840 if(pad_size)
2842 if((x - src_rect->left) & 1) dst_pixel++;
2843 memset(dst_pixel, 0, pad_size);
2845 dst_start += dst->stride;
2846 src_start += src->stride / 4;
2849 break;
2852 case 24:
2854 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
2856 for(y = src_rect->top; y < src_rect->bottom; y++)
2858 dst_pixel = dst_start;
2859 src_pixel = src_start;
2860 for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3)
2862 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]);
2864 if((x - src_rect->left) & 1)
2866 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2867 dst_pixel++;
2869 else
2870 *dst_pixel = (dst_val << 4) & 0xf0;
2872 if(pad_size)
2874 if((x - src_rect->left) & 1) dst_pixel++;
2875 memset(dst_pixel, 0, pad_size);
2877 dst_start += dst->stride;
2878 src_start += src->stride;
2880 break;
2883 case 16:
2885 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
2886 if(src->funcs == &funcs_555)
2888 for(y = src_rect->top; y < src_rect->bottom; y++)
2890 dst_pixel = dst_start;
2891 src_pixel = src_start;
2892 for(x = src_rect->left; x < src_rect->right; x++)
2894 src_val = *src_pixel++;
2895 dst_val = rgb_to_pixel_colortable(dst,
2896 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
2897 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
2898 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) );
2899 if((x - src_rect->left) & 1)
2901 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2902 dst_pixel++;
2904 else
2905 *dst_pixel = (dst_val << 4) & 0xf0;
2907 if(pad_size)
2909 if((x - src_rect->left) & 1) dst_pixel++;
2910 memset(dst_pixel, 0, pad_size);
2912 dst_start += dst->stride;
2913 src_start += src->stride / 2;
2916 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
2918 for(y = src_rect->top; y < src_rect->bottom; y++)
2920 dst_pixel = dst_start;
2921 src_pixel = src_start;
2922 for(x = src_rect->left; x < src_rect->right; x++)
2924 src_val = *src_pixel++;
2925 dst_val = rgb_to_pixel_colortable(dst,
2926 (((src_val >> src->red_shift) << 3) & 0xf8) |
2927 (((src_val >> src->red_shift) >> 2) & 0x07),
2928 (((src_val >> src->green_shift) << 3) & 0xf8) |
2929 (((src_val >> src->green_shift) >> 2) & 0x07),
2930 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2931 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2932 if((x - src_rect->left) & 1)
2934 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2935 dst_pixel++;
2937 else
2938 *dst_pixel = (dst_val << 4) & 0xf0;
2940 if(pad_size)
2942 if((x - src_rect->left) & 1) dst_pixel++;
2943 memset(dst_pixel, 0, pad_size);
2945 dst_start += dst->stride;
2946 src_start += src->stride / 2;
2949 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
2951 for(y = src_rect->top; y < src_rect->bottom; y++)
2953 dst_pixel = dst_start;
2954 src_pixel = src_start;
2955 for(x = src_rect->left; x < src_rect->right; x++)
2957 src_val = *src_pixel++;
2958 dst_val = rgb_to_pixel_colortable(dst,
2959 (((src_val >> src->red_shift) << 3) & 0xf8) |
2960 (((src_val >> src->red_shift) >> 2) & 0x07),
2961 (((src_val >> src->green_shift) << 2) & 0xfc) |
2962 (((src_val >> src->green_shift) >> 4) & 0x03),
2963 (((src_val >> src->blue_shift) << 3) & 0xf8) |
2964 (((src_val >> src->blue_shift) >> 2) & 0x07) );
2965 if((x - src_rect->left) & 1)
2967 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2968 dst_pixel++;
2970 else
2971 *dst_pixel = (dst_val << 4) & 0xf0;
2973 if(pad_size)
2975 if((x - src_rect->left) & 1) dst_pixel++;
2976 memset(dst_pixel, 0, pad_size);
2978 dst_start += dst->stride;
2979 src_start += src->stride / 2;
2982 else
2984 for(y = src_rect->top; y < src_rect->bottom; y++)
2986 dst_pixel = dst_start;
2987 src_pixel = src_start;
2988 for(x = src_rect->left; x < src_rect->right; x++)
2990 src_val = *src_pixel++;
2991 dst_val = rgb_to_pixel_colortable(dst,
2992 get_field(src_val, src->red_shift, src->red_len),
2993 get_field(src_val, src->green_shift, src->green_len),
2994 get_field(src_val, src->blue_shift, src->blue_len));
2995 if((x - src_rect->left) & 1)
2997 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
2998 dst_pixel++;
3000 else
3001 *dst_pixel = (dst_val << 4) & 0xf0;
3003 if(pad_size)
3005 if((x - src_rect->left) & 1) dst_pixel++;
3006 memset(dst_pixel, 0, pad_size);
3008 dst_start += dst->stride;
3009 src_start += src->stride / 2;
3012 break;
3015 case 8:
3017 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3019 for(y = src_rect->top; y < src_rect->bottom; y++)
3021 dst_pixel = dst_start;
3022 src_pixel = src_start;
3023 for(x = src_rect->left; x < src_rect->right; x++)
3025 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3026 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3027 if((x - src_rect->left) & 1)
3029 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3030 dst_pixel++;
3032 else
3033 *dst_pixel = (dst_val << 4) & 0xf0;
3035 if(pad_size)
3037 if((x - src_rect->left) & 1) dst_pixel++;
3038 memset(dst_pixel, 0, pad_size);
3040 dst_start += dst->stride;
3041 src_start += src->stride;
3043 break;
3046 case 4:
3048 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3050 if(color_tables_match(dst, src) && (src_rect->left & 1) == 0)
3052 if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
3053 memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
3054 else
3056 for(y = src_rect->top; y < src_rect->bottom; y++)
3058 memcpy(dst_start, src_start, (src_rect->right - src_rect->left + 1) / 2);
3059 if(pad_size) memset(dst_start + (src_rect->right - src_rect->left + 1) / 2, 0, pad_size);
3060 dst_start += dst->stride;
3061 src_start += src->stride;
3065 else
3067 for(y = src_rect->top; y < src_rect->bottom; y++)
3069 dst_pixel = dst_start;
3070 src_pixel = src_start;
3071 for(x = src_rect->left; x < src_rect->right; x++)
3073 RGBQUAD rgb;
3074 if(x & 1)
3075 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3076 else
3077 rgb = colortable_entry( src, *src_pixel >> 4 );
3078 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3079 if((x - src_rect->left) & 1)
3081 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3082 dst_pixel++;
3084 else
3085 *dst_pixel = (dst_val << 4) & 0xf0;
3087 if(pad_size)
3089 if((x - src_rect->left) & 1) dst_pixel++;
3090 memset(dst_pixel, 0, pad_size);
3092 dst_start += dst->stride;
3093 src_start += src->stride;
3096 break;
3099 case 1:
3101 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3102 for(y = src_rect->top; y < src_rect->bottom; y++)
3104 dst_pixel = dst_start;
3105 src_pixel = src_start;
3106 for(x = src_rect->left; x < src_rect->right; x++)
3108 RGBQUAD rgb;
3109 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3110 if((x % 8) == 7) src_pixel++;
3111 rgb = src->color_table[src_val];
3112 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
3113 if((x - src_rect->left) & 1)
3115 *dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
3116 dst_pixel++;
3118 else
3119 *dst_pixel = (dst_val << 4) & 0xf0;
3121 if(pad_size)
3123 if((x - src_rect->left) & 1) dst_pixel++;
3124 memset(dst_pixel, 0, pad_size);
3126 dst_start += dst->stride;
3127 src_start += src->stride;
3129 break;
3134 static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rect)
3136 BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val;
3137 INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8;
3138 DWORD src_val;
3139 int bit_pos;
3141 /* FIXME: Brushes should be dithered. */
3143 switch(src->bit_count)
3145 case 32:
3147 DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
3149 if(src->funcs == &funcs_8888)
3151 for(y = src_rect->top; y < src_rect->bottom; y++)
3153 dst_pixel = dst_start;
3154 src_pixel = src_start;
3155 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3157 src_val = *src_pixel++;
3158 dst_val = rgb_to_pixel_colortable(dst, src_val >> 16, src_val >> 8, src_val) ? 0xff : 0;
3160 if(bit_pos == 0) *dst_pixel = 0;
3161 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3163 if(++bit_pos == 8)
3165 dst_pixel++;
3166 bit_pos = 0;
3169 if(pad_size)
3171 if(bit_pos != 0) dst_pixel++;
3172 memset(dst_pixel, 0, pad_size);
3174 dst_start += dst->stride;
3175 src_start += src->stride / 4;
3178 else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
3180 for(y = src_rect->top; y < src_rect->bottom; y++)
3182 dst_pixel = dst_start;
3183 src_pixel = src_start;
3184 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3186 src_val = *src_pixel++;
3187 dst_val = rgb_to_pixel_colortable(dst,
3188 src_val >> src->red_shift,
3189 src_val >> src->green_shift,
3190 src_val >> src->blue_shift) ? 0xff : 0;
3192 if(bit_pos == 0) *dst_pixel = 0;
3193 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3195 if(++bit_pos == 8)
3197 dst_pixel++;
3198 bit_pos = 0;
3201 if(pad_size)
3203 if(bit_pos != 0) dst_pixel++;
3204 memset(dst_pixel, 0, pad_size);
3206 dst_start += dst->stride;
3207 src_start += src->stride / 4;
3210 else
3212 for(y = src_rect->top; y < src_rect->bottom; y++)
3214 dst_pixel = dst_start;
3215 src_pixel = src_start;
3216 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3218 src_val = *src_pixel++;
3219 dst_val = rgb_to_pixel_colortable(dst,
3220 get_field(src_val, src->red_shift, src->red_len),
3221 get_field(src_val, src->green_shift, src->green_len),
3222 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3224 if(bit_pos == 0) *dst_pixel = 0;
3225 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3227 if(++bit_pos == 8)
3229 dst_pixel++;
3230 bit_pos = 0;
3233 if(pad_size)
3235 if(bit_pos != 0) dst_pixel++;
3236 memset(dst_pixel, 0, pad_size);
3238 dst_start += dst->stride;
3239 src_start += src->stride / 4;
3242 break;
3245 case 24:
3247 BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
3249 for(y = src_rect->top; y < src_rect->bottom; y++)
3251 dst_pixel = dst_start;
3252 src_pixel = src_start;
3253 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3)
3255 dst_val = rgb_to_pixel_colortable(dst, src_pixel[2], src_pixel[1], src_pixel[0]) ? 0xff : 0;
3257 if(bit_pos == 0) *dst_pixel = 0;
3258 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3260 if(++bit_pos == 8)
3262 dst_pixel++;
3263 bit_pos = 0;
3266 if(pad_size)
3268 if(bit_pos != 0) dst_pixel++;
3269 memset(dst_pixel, 0, pad_size);
3271 dst_start += dst->stride;
3272 src_start += src->stride;
3274 break;
3277 case 16:
3279 WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
3280 if(src->funcs == &funcs_555)
3282 for(y = src_rect->top; y < src_rect->bottom; y++)
3284 dst_pixel = dst_start;
3285 src_pixel = src_start;
3286 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3288 src_val = *src_pixel++;
3289 dst_val = rgb_to_pixel_colortable(dst,
3290 ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07),
3291 ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07),
3292 ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07) ) ? 0xff : 0;
3294 if(bit_pos == 0) *dst_pixel = 0;
3295 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3297 if(++bit_pos == 8)
3299 dst_pixel++;
3300 bit_pos = 0;
3303 if(pad_size)
3305 if(bit_pos != 0) dst_pixel++;
3306 memset(dst_pixel, 0, pad_size);
3308 dst_start += dst->stride;
3309 src_start += src->stride / 2;
3312 else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
3314 for(y = src_rect->top; y < src_rect->bottom; y++)
3316 dst_pixel = dst_start;
3317 src_pixel = src_start;
3318 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3320 src_val = *src_pixel++;
3321 dst_val = rgb_to_pixel_colortable(dst,
3322 (((src_val >> src->red_shift) << 3) & 0xf8) |
3323 (((src_val >> src->red_shift) >> 2) & 0x07),
3324 (((src_val >> src->green_shift) << 3) & 0xf8) |
3325 (((src_val >> src->green_shift) >> 2) & 0x07),
3326 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3327 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3328 if(bit_pos == 0) *dst_pixel = 0;
3329 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3331 if(++bit_pos == 8)
3333 dst_pixel++;
3334 bit_pos = 0;
3337 if(pad_size)
3339 if(bit_pos != 0) dst_pixel++;
3340 memset(dst_pixel, 0, pad_size);
3342 dst_start += dst->stride;
3343 src_start += src->stride / 2;
3346 else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
3348 for(y = src_rect->top; y < src_rect->bottom; y++)
3350 dst_pixel = dst_start;
3351 src_pixel = src_start;
3352 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3354 src_val = *src_pixel++;
3355 dst_val = rgb_to_pixel_colortable(dst,
3356 (((src_val >> src->red_shift) << 3) & 0xf8) |
3357 (((src_val >> src->red_shift) >> 2) & 0x07),
3358 (((src_val >> src->green_shift) << 2) & 0xfc) |
3359 (((src_val >> src->green_shift) >> 4) & 0x03),
3360 (((src_val >> src->blue_shift) << 3) & 0xf8) |
3361 (((src_val >> src->blue_shift) >> 2) & 0x07) ) ? 0xff : 0;
3362 if(bit_pos == 0) *dst_pixel = 0;
3363 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3365 if(++bit_pos == 8)
3367 dst_pixel++;
3368 bit_pos = 0;
3371 if(pad_size)
3373 if(bit_pos != 0) dst_pixel++;
3374 memset(dst_pixel, 0, pad_size);
3376 dst_start += dst->stride;
3377 src_start += src->stride / 2;
3380 else
3382 for(y = src_rect->top; y < src_rect->bottom; y++)
3384 dst_pixel = dst_start;
3385 src_pixel = src_start;
3386 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3388 src_val = *src_pixel++;
3389 dst_val = rgb_to_pixel_colortable(dst,
3390 get_field(src_val, src->red_shift, src->red_len),
3391 get_field(src_val, src->green_shift, src->green_len),
3392 get_field(src_val, src->blue_shift, src->blue_len)) ? 0xff : 0;
3393 if(bit_pos == 0) *dst_pixel = 0;
3394 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3396 if(++bit_pos == 8)
3398 dst_pixel++;
3399 bit_pos = 0;
3402 if(pad_size)
3404 if(bit_pos != 0) dst_pixel++;
3405 memset(dst_pixel, 0, pad_size);
3407 dst_start += dst->stride;
3408 src_start += src->stride / 2;
3411 break;
3414 case 8:
3416 BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
3418 for(y = src_rect->top; y < src_rect->bottom; y++)
3420 dst_pixel = dst_start;
3421 src_pixel = src_start;
3422 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3424 RGBQUAD rgb = colortable_entry( src, *src_pixel++ );
3425 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3427 if(bit_pos == 0) *dst_pixel = 0;
3428 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3430 if(++bit_pos == 8)
3432 dst_pixel++;
3433 bit_pos = 0;
3436 if(pad_size)
3438 if(bit_pos != 0) dst_pixel++;
3439 memset(dst_pixel, 0, pad_size);
3441 dst_start += dst->stride;
3442 src_start += src->stride;
3444 break;
3447 case 4:
3449 BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
3451 for(y = src_rect->top; y < src_rect->bottom; y++)
3453 dst_pixel = dst_start;
3454 src_pixel = src_start;
3455 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3457 RGBQUAD rgb;
3458 if(x & 1)
3459 rgb = colortable_entry( src, *src_pixel++ & 0xf );
3460 else
3461 rgb = colortable_entry( src, *src_pixel >> 4 );
3462 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3464 if(bit_pos == 0) *dst_pixel = 0;
3465 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3467 if(++bit_pos == 8)
3469 dst_pixel++;
3470 bit_pos = 0;
3473 if(pad_size)
3475 if(bit_pos != 0) dst_pixel++;
3476 memset(dst_pixel, 0, pad_size);
3478 dst_start += dst->stride;
3479 src_start += src->stride;
3481 break;
3484 /* Note that while MSDN states that a 1 bpp dib brush -> mono dc
3485 uses text/bkgnd colours instead of the dib's colour table, this
3486 doesn't appear to be the case for a dc backed by a
3487 dibsection. */
3489 case 1:
3491 BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
3492 for(y = src_rect->top; y < src_rect->bottom; y++)
3494 dst_pixel = dst_start;
3495 src_pixel = src_start;
3496 for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
3498 RGBQUAD rgb;
3499 src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
3500 if((x % 8) == 7) src_pixel++;
3501 rgb = src->color_table[src_val];
3502 dst_val = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue) ? 0xff : 0;
3504 if(bit_pos == 0) *dst_pixel = 0;
3505 *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
3507 if(++bit_pos == 8)
3509 dst_pixel++;
3510 bit_pos = 0;
3513 if(pad_size)
3515 if(bit_pos != 0) dst_pixel++;
3516 memset(dst_pixel, 0, pad_size);
3518 dst_start += dst->stride;
3519 src_start += src->stride;
3521 break;
3526 static void convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
3530 static inline BYTE blend_color(BYTE dst, BYTE src, DWORD alpha)
3532 return (src * alpha + dst * (255 - alpha) + 127) / 255;
3535 static inline DWORD blend_argb( DWORD dst, DWORD src, DWORD alpha )
3537 return (blend_color( dst, src, alpha ) |
3538 blend_color( dst >> 8, src >> 8, alpha ) << 8 |
3539 blend_color( dst >> 16, src >> 16, alpha ) << 16 |
3540 blend_color( dst >> 24, src >> 24, alpha ) << 24);
3543 static inline DWORD blend_argb_alpha( DWORD dst, DWORD src, DWORD alpha )
3545 BYTE b = ((BYTE)src * alpha + 127) / 255;
3546 BYTE g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3547 BYTE r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3548 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3549 return ((b + ((BYTE)dst * (255 - alpha) + 127) / 255) |
3550 (g + ((BYTE)(dst >> 8) * (255 - alpha) + 127) / 255) << 8 |
3551 (r + ((BYTE)(dst >> 16) * (255 - alpha) + 127) / 255) << 16 |
3552 (alpha + ((BYTE)(dst >> 24) * (255 - alpha) + 127) / 255) << 24);
3555 static inline DWORD blend_rgb( BYTE dst_r, BYTE dst_g, BYTE dst_b, DWORD src, BLENDFUNCTION blend )
3557 if (blend.AlphaFormat & AC_SRC_ALPHA)
3559 DWORD alpha = blend.SourceConstantAlpha;
3560 BYTE src_b = ((BYTE)src * alpha + 127) / 255;
3561 BYTE src_g = ((BYTE)(src >> 8) * alpha + 127) / 255;
3562 BYTE src_r = ((BYTE)(src >> 16) * alpha + 127) / 255;
3563 alpha = ((BYTE)(src >> 24) * alpha + 127) / 255;
3564 return ((src_b + (dst_b * (255 - alpha) + 127) / 255) |
3565 (src_g + (dst_g * (255 - alpha) + 127) / 255) << 8 |
3566 (src_r + (dst_r * (255 - alpha) + 127) / 255) << 16);
3568 return (blend_color( dst_b, src, blend.SourceConstantAlpha ) |
3569 blend_color( dst_g, src >> 8, blend.SourceConstantAlpha ) << 8 |
3570 blend_color( dst_r, src >> 16, blend.SourceConstantAlpha ) << 16);
3573 static void blend_rect_8888(const dib_info *dst, const RECT *rc,
3574 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3576 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3577 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3578 int x, y;
3580 if (blend.AlphaFormat & AC_SRC_ALPHA)
3581 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3582 for (x = 0; x < rc->right - rc->left; x++)
3583 dst_ptr[x] = blend_argb_alpha( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3584 else
3585 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3586 for (x = 0; x < rc->right - rc->left; x++)
3587 dst_ptr[x] = blend_argb( dst_ptr[x], src_ptr[x], blend.SourceConstantAlpha );
3590 static void blend_rect_32(const dib_info *dst, const RECT *rc,
3591 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3593 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3594 DWORD *dst_ptr = get_pixel_ptr_32( dst, rc->left, rc->top );
3595 int x, y;
3597 if (dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
3599 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3601 for (x = 0; x < rc->right - rc->left; x++)
3603 DWORD val = blend_rgb( dst_ptr[x] >> dst->red_shift,
3604 dst_ptr[x] >> dst->green_shift,
3605 dst_ptr[x] >> dst->blue_shift,
3606 src_ptr[x], blend );
3607 dst_ptr[x] = ((( val & 0xff) << dst->blue_shift) |
3608 (((val >> 8) & 0xff) << dst->green_shift) |
3609 (((val >> 16) & 0xff) << dst->red_shift));
3613 else
3615 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 4, src_ptr += src->stride / 4)
3617 for (x = 0; x < rc->right - rc->left; x++)
3619 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3620 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3621 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3622 src_ptr[x], blend );
3623 dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) |
3624 put_field( val >> 8, dst->green_shift, dst->green_len ) |
3625 put_field( val, dst->blue_shift, dst->blue_len ));
3631 static void blend_rect_24(const dib_info *dst, const RECT *rc,
3632 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3634 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3635 BYTE *dst_ptr = get_pixel_ptr_24( dst, rc->left, rc->top );
3636 int x, y;
3638 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3640 for (x = 0; x < rc->right - rc->left; x++)
3642 DWORD val = blend_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3643 src_ptr[x], blend );
3644 dst_ptr[x * 3] = val;
3645 dst_ptr[x * 3 + 1] = val >> 8;
3646 dst_ptr[x * 3 + 2] = val >> 16;
3651 static void blend_rect_555(const dib_info *dst, const RECT *rc,
3652 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3654 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3655 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3656 int x, y;
3658 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3660 for (x = 0; x < rc->right - rc->left; x++)
3662 DWORD val = blend_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3663 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3664 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3665 src_ptr[x], blend );
3666 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3671 static void blend_rect_16(const dib_info *dst, const RECT *rc,
3672 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3674 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3675 WORD *dst_ptr = get_pixel_ptr_16( dst, rc->left, rc->top );
3676 int x, y;
3678 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride / 2, src_ptr += src->stride / 4)
3680 for (x = 0; x < rc->right - rc->left; x++)
3682 DWORD val = blend_rgb( get_field( dst_ptr[x], dst->red_shift, dst->red_len ),
3683 get_field( dst_ptr[x], dst->green_shift, dst->green_len ),
3684 get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ),
3685 src_ptr[x], blend );
3686 dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) |
3687 put_field((val >> 8), dst->green_shift, dst->green_len) |
3688 put_field( val, dst->blue_shift, dst->blue_len));
3693 static void blend_rect_8(const dib_info *dst, const RECT *rc,
3694 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3696 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x, origin->y );
3697 BYTE *dst_ptr = get_pixel_ptr_8( dst, rc->left, rc->top );
3698 int x, y;
3700 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3702 for (x = 0; x < rc->right - rc->left; x++)
3704 RGBQUAD rgb = colortable_entry( dst, dst_ptr[x] );
3705 DWORD val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3706 dst_ptr[x] = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3711 static void blend_rect_4(const dib_info *dst, const RECT *rc,
3712 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3714 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3715 BYTE *dst_ptr = get_pixel_ptr_4( dst, 0, rc->top );
3716 int x, y;
3718 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3720 for (x = rc->left; x < rc->right; x++)
3722 DWORD val = ((x & 1) ? dst_ptr[x / 2] : (dst_ptr[x / 2] >> 4)) & 0x0f;
3723 RGBQUAD rgb = colortable_entry( dst, val );
3724 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3725 val = rgb_lookup_colortable( dst, val >> 16, val >> 8, val );
3726 if (x & 1)
3727 dst_ptr[x / 2] = val | (dst_ptr[x / 2] & 0xf0);
3728 else
3729 dst_ptr[x / 2] = (val << 4) | (dst_ptr[x / 2] & 0x0f);
3734 static void blend_rect_1(const dib_info *dst, const RECT *rc,
3735 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3737 DWORD *src_ptr = get_pixel_ptr_32( src, origin->x - rc->left, origin->y );
3738 BYTE *dst_ptr = get_pixel_ptr_1( dst, 0, rc->top );
3739 int x, y;
3741 for (y = rc->top; y < rc->bottom; y++, dst_ptr += dst->stride, src_ptr += src->stride / 4)
3743 for (x = rc->left; x < rc->right; x++)
3745 DWORD val = (dst_ptr[x / 8] & pixel_masks_1[x % 8]) ? 1 : 0;
3746 RGBQUAD rgb = dst->color_table[val];
3747 val = blend_rgb( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, src_ptr[x], blend );
3748 val = rgb_to_pixel_colortable(dst, val >> 16, val >> 8, val) ? 0xff : 0;
3749 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (val & pixel_masks_1[x % 8]);
3754 static void blend_rect_null(const dib_info *dst, const RECT *rc,
3755 const dib_info *src, const POINT *origin, BLENDFUNCTION blend)
3759 static inline BYTE aa_color( BYTE dst, BYTE text, BYTE min_comp, BYTE max_comp )
3761 if (dst == text) return dst;
3763 if (dst > text)
3765 DWORD diff = dst - text;
3766 DWORD range = max_comp - text;
3767 dst = text + (diff * range ) / (0xff - text);
3768 return dst;
3770 else
3772 DWORD diff = text - dst;
3773 DWORD range = text - min_comp;
3774 dst = text - (diff * range) / text;
3775 return dst;
3779 static inline DWORD aa_rgb( BYTE r_dst, BYTE g_dst, BYTE b_dst, DWORD text, const struct intensity_range *range )
3781 return (aa_color( b_dst, text, range->b_min, range->b_max ) |
3782 aa_color( g_dst, text >> 8, range->g_min, range->g_max ) << 8 |
3783 aa_color( r_dst, text >> 16, range->r_min, range->r_max ) << 16);
3786 static void draw_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3787 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3789 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
3790 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
3791 int x, y;
3793 for (y = rect->top; y < rect->bottom; y++)
3795 for (x = 0; x < rect->right - rect->left; x++)
3797 if (glyph_ptr[x] <= 1) continue;
3798 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
3799 dst_ptr[x] = aa_rgb( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, ranges + glyph_ptr[x] );
3801 dst_ptr += dib->stride / 4;
3802 glyph_ptr += glyph->stride;
3806 static void draw_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3807 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3809 DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top );
3810 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
3811 int x, y;
3812 DWORD text, val;
3814 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
3815 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
3816 get_field( text_pixel, dib->blue_shift, dib->blue_len );
3818 for (y = rect->top; y < rect->bottom; y++)
3820 for (x = 0; x < rect->right - rect->left; x++)
3822 if (glyph_ptr[x] <= 1) continue;
3823 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
3824 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
3825 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
3826 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
3827 text, ranges + glyph_ptr[x] );
3828 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
3829 put_field( val >> 8, dib->green_shift, dib->green_len ) |
3830 put_field( val, dib->blue_shift, dib->blue_len ));
3832 dst_ptr += dib->stride / 4;
3833 glyph_ptr += glyph->stride;
3837 static void draw_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3838 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3840 BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top );
3841 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
3842 int x, y;
3843 DWORD val;
3845 for (y = rect->top; y < rect->bottom; y++)
3847 for (x = 0; x < rect->right - rect->left; x++)
3849 if (glyph_ptr[x] <= 1) continue;
3850 if (glyph_ptr[x] >= 16)
3851 val = text_pixel;
3852 else
3853 val = aa_rgb( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3],
3854 text_pixel, ranges + glyph_ptr[x] );
3855 dst_ptr[x * 3] = val;
3856 dst_ptr[x * 3 + 1] = val >> 8;
3857 dst_ptr[x * 3 + 2] = val >> 16;
3859 dst_ptr += dib->stride;
3860 glyph_ptr += glyph->stride;
3864 static void draw_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3865 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3867 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
3868 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
3869 int x, y;
3870 DWORD text, val;
3872 text = ((text_pixel << 9) & 0xf80000) | ((text_pixel << 4) & 0x070000) |
3873 ((text_pixel << 6) & 0x00f800) | ((text_pixel << 1) & 0x000700) |
3874 ((text_pixel << 3) & 0x0000f8) | ((text_pixel >> 2) & 0x000007);
3876 for (y = rect->top; y < rect->bottom; y++)
3878 for (x = 0; x < rect->right - rect->left; x++)
3880 if (glyph_ptr[x] <= 1) continue;
3881 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
3882 val = aa_rgb( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07),
3883 ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07),
3884 ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07),
3885 text, ranges + glyph_ptr[x] );
3886 dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
3888 dst_ptr += dib->stride / 2;
3889 glyph_ptr += glyph->stride;
3893 static void draw_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3894 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3896 WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top );
3897 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
3898 int x, y;
3899 DWORD text, val;
3901 text = get_field( text_pixel, dib->red_shift, dib->red_len ) << 16 |
3902 get_field( text_pixel, dib->green_shift, dib->green_len ) << 8 |
3903 get_field( text_pixel, dib->blue_shift, dib->blue_len );
3905 for (y = rect->top; y < rect->bottom; y++)
3907 for (x = 0; x < rect->right - rect->left; x++)
3909 if (glyph_ptr[x] <= 1) continue;
3910 if (glyph_ptr[x] >= 16) { dst_ptr[x] = text_pixel; continue; }
3911 val = aa_rgb( get_field(dst_ptr[x], dib->red_shift, dib->red_len),
3912 get_field(dst_ptr[x], dib->green_shift, dib->green_len),
3913 get_field(dst_ptr[x], dib->blue_shift, dib->blue_len),
3914 text, ranges + glyph_ptr[x] );
3915 dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) |
3916 put_field( val >> 8, dib->green_shift, dib->green_len ) |
3917 put_field( val, dib->blue_shift, dib->blue_len ));
3919 dst_ptr += dib->stride / 2;
3920 glyph_ptr += glyph->stride;
3924 static void draw_glyph_8( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3925 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3927 BYTE *dst_ptr = get_pixel_ptr_8( dib, rect->left, rect->top );
3928 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x, origin->y );
3929 int x, y;
3931 for (y = rect->top; y < rect->bottom; y++)
3933 for (x = 0; x < rect->right - rect->left; x++)
3935 /* no antialiasing, glyph should only contain 0 or 16. */
3936 if (glyph_ptr[x] >= 16)
3937 dst_ptr[x] = text_pixel;
3939 dst_ptr += dib->stride;
3940 glyph_ptr += glyph->stride;
3944 static void draw_glyph_4( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3945 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3947 BYTE *dst_ptr = get_pixel_ptr_4( dib, 0, rect->top );
3948 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
3949 int x, y;
3951 for (y = rect->top; y < rect->bottom; y++)
3953 for (x = rect->left; x < rect->right; x++)
3955 /* no antialiasing, glyph should only contain 0 or 16. */
3956 if (glyph_ptr[x] >= 16)
3958 if (x & 1)
3959 dst_ptr[x / 2] = text_pixel | (dst_ptr[x / 2] & 0xf0);
3960 else
3961 dst_ptr[x / 2] = (text_pixel << 4) | (dst_ptr[x / 2] & 0x0f);
3964 dst_ptr += dib->stride;
3965 glyph_ptr += glyph->stride;
3969 static void draw_glyph_1( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3970 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3972 BYTE *dst_ptr = get_pixel_ptr_1( dib, 0, rect->top );
3973 const BYTE *glyph_ptr = get_pixel_ptr_8( glyph, origin->x - rect->left, origin->y );
3974 int x, y;
3975 BYTE text = (text_pixel & 1) ? 0xff : 0;
3977 for (y = rect->top; y < rect->bottom; y++)
3979 for (x = rect->left; x < rect->right; x++)
3981 /* no antialiasing, glyph should only contain 0 or 16. */
3982 if (glyph_ptr[x] >= 16)
3983 dst_ptr[x / 8] = (dst_ptr[x / 8] & ~pixel_masks_1[x % 8]) | (text & pixel_masks_1[x % 8]);
3985 dst_ptr += dib->stride;
3986 glyph_ptr += glyph->stride;
3990 static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph,
3991 const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges )
3993 return;
3996 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)
3998 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
3999 DWORD mask_start = 0, mask_offset;
4000 DWORD *and_bits = bits->and, *xor_bits = bits->xor;
4001 int x, y;
4003 for(y = 0; y < hatch->height; y++)
4005 hatch_ptr = hatch_start;
4006 mask_offset = mask_start;
4007 for(x = 0; x < hatch->width; x++)
4009 if(*hatch_ptr & pixel_masks_1[x % 8])
4011 and_bits[mask_offset] = fg->and;
4012 xor_bits[mask_offset] = fg->xor;
4014 else
4016 and_bits[mask_offset] = bg->and;
4017 xor_bits[mask_offset] = bg->xor;
4019 if(x % 8 == 7) hatch_ptr++;
4020 mask_offset++;
4022 hatch_start += hatch->stride;
4023 mask_start += dib->stride / 4;
4026 return TRUE;
4029 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)
4031 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4032 DWORD mask_start = 0, mask_offset;
4033 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4034 int x, y;
4036 for(y = 0; y < hatch->height; y++)
4038 hatch_ptr = hatch_start;
4039 mask_offset = mask_start;
4040 for(x = 0; x < hatch->width; x++)
4042 if(*hatch_ptr & pixel_masks_1[x % 8])
4044 and_bits[mask_offset] = fg->and & 0xff;
4045 xor_bits[mask_offset++] = fg->xor & 0xff;
4046 and_bits[mask_offset] = (fg->and >> 8) & 0xff;
4047 xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff;
4048 and_bits[mask_offset] = (fg->and >> 16) & 0xff;
4049 xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff;
4051 else
4053 and_bits[mask_offset] = bg->and & 0xff;
4054 xor_bits[mask_offset++] = bg->xor & 0xff;
4055 and_bits[mask_offset] = (bg->and >> 8) & 0xff;
4056 xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff;
4057 and_bits[mask_offset] = (bg->and >> 16) & 0xff;
4058 xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff;
4060 if(x % 8 == 7) hatch_ptr++;
4062 hatch_start += hatch->stride;
4063 mask_start += dib->stride;
4066 return TRUE;
4069 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)
4071 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4072 DWORD mask_start = 0, mask_offset;
4073 WORD *and_bits = bits->and, *xor_bits = bits->xor;
4074 int x, y;
4076 for(y = 0; y < hatch->height; y++)
4078 hatch_ptr = hatch_start;
4079 mask_offset = mask_start;
4080 for(x = 0; x < hatch->width; x++)
4082 if(*hatch_ptr & pixel_masks_1[x % 8])
4084 and_bits[mask_offset] = fg->and;
4085 xor_bits[mask_offset] = fg->xor;
4087 else
4089 and_bits[mask_offset] = bg->and;
4090 xor_bits[mask_offset] = bg->xor;
4092 if(x % 8 == 7) hatch_ptr++;
4093 mask_offset++;
4095 hatch_start += hatch->stride;
4096 mask_start += dib->stride / 2;
4099 return TRUE;
4102 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)
4104 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4105 DWORD mask_start = 0, mask_offset;
4106 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4107 int x, y;
4109 for(y = 0; y < hatch->height; y++)
4111 hatch_ptr = hatch_start;
4112 mask_offset = mask_start;
4113 for(x = 0; x < hatch->width; x++)
4115 if(*hatch_ptr & pixel_masks_1[x % 8])
4117 and_bits[mask_offset] = fg->and;
4118 xor_bits[mask_offset] = fg->xor;
4120 else
4122 and_bits[mask_offset] = bg->and;
4123 xor_bits[mask_offset] = bg->xor;
4125 if(x % 8 == 7) hatch_ptr++;
4126 mask_offset++;
4128 hatch_start += hatch->stride;
4129 mask_start += dib->stride;
4132 return TRUE;
4135 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)
4137 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4138 DWORD mask_start = 0, mask_offset;
4139 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4140 const rop_mask *rop_mask;
4141 int x, y;
4143 for(y = 0; y < hatch->height; y++)
4145 hatch_ptr = hatch_start;
4146 mask_offset = mask_start;
4147 for(x = 0; x < hatch->width; x++)
4149 if(*hatch_ptr & pixel_masks_1[x % 8])
4150 rop_mask = fg;
4151 else
4152 rop_mask = bg;
4154 if(x & 1)
4156 and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0);
4157 xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0);
4158 mask_offset++;
4160 else
4162 and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0;
4163 xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0;
4166 if(x % 8 == 7) hatch_ptr++;
4168 hatch_start += hatch->stride;
4169 mask_start += dib->stride;
4172 return TRUE;
4175 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)
4177 BYTE *hatch_start = get_pixel_ptr_1(hatch, 0, 0), *hatch_ptr;
4178 DWORD mask_start = 0, mask_offset;
4179 BYTE *and_bits = bits->and, *xor_bits = bits->xor;
4180 rop_mask rop_mask;
4181 int x, y, bit_pos;
4183 for(y = 0; y < hatch->height; y++)
4185 hatch_ptr = hatch_start;
4186 mask_offset = mask_start;
4187 for(x = 0, bit_pos = 0; x < hatch->width; x++)
4189 if(*hatch_ptr & pixel_masks_1[x % 8])
4191 rop_mask.and = (fg->and & 1) ? 0xff : 0;
4192 rop_mask.xor = (fg->xor & 1) ? 0xff : 0;
4194 else
4196 rop_mask.and = (bg->and & 1) ? 0xff : 0;
4197 rop_mask.xor = (bg->xor & 1) ? 0xff : 0;
4200 if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0;
4202 and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4203 xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]);
4205 if(++bit_pos == 8)
4207 mask_offset++;
4208 hatch_ptr++;
4209 bit_pos = 0;
4212 hatch_start += hatch->stride;
4213 mask_start += dib->stride;
4216 return TRUE;
4219 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)
4221 return FALSE;
4224 static inline void rop_codes_from_stretch_mode( int mode, struct rop_codes *codes )
4226 switch (mode)
4228 default:
4229 case STRETCH_DELETESCANS:
4230 get_rop_codes( R2_COPYPEN, codes );
4231 break;
4232 case STRETCH_ORSCANS:
4233 get_rop_codes( R2_MERGEPEN, codes );
4234 break;
4235 case STRETCH_ANDSCANS:
4236 get_rop_codes( R2_MASKPEN, codes );
4237 break;
4239 return;
4242 static void stretch_row_32(const dib_info *dst_dib, const POINT *dst_start,
4243 const dib_info *src_dib, const POINT *src_start,
4244 const struct stretch_params *params, int mode,
4245 BOOL keep_dst)
4247 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4248 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4249 int err = params->err_start;
4250 int width;
4251 struct rop_codes codes;
4253 rop_codes_from_stretch_mode( mode, &codes );
4254 for (width = params->length; width; width--)
4256 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4257 dst_ptr += params->dst_inc;
4258 if (err > 0)
4260 src_ptr += params->src_inc;
4261 err += params->err_add_1;
4263 else err += params->err_add_2;
4267 static void stretch_row_24(const dib_info *dst_dib, const POINT *dst_start,
4268 const dib_info *src_dib, const POINT *src_start,
4269 const struct stretch_params *params, int mode,
4270 BOOL keep_dst)
4272 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4273 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4274 int err = params->err_start;
4275 int width;
4276 struct rop_codes codes;
4278 rop_codes_from_stretch_mode( mode, &codes );
4279 for (width = params->length; width; width--)
4281 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4282 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4283 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4284 dst_ptr += 3 * params->dst_inc;
4285 if (err > 0)
4287 src_ptr += 3 * params->src_inc;
4288 err += params->err_add_1;
4290 else err += params->err_add_2;
4294 static void stretch_row_16(const dib_info *dst_dib, const POINT *dst_start,
4295 const dib_info *src_dib, const POINT *src_start,
4296 const struct stretch_params *params, int mode,
4297 BOOL keep_dst)
4299 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4300 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4301 int err = params->err_start;
4302 int width;
4303 struct rop_codes codes;
4305 rop_codes_from_stretch_mode( mode, &codes );
4306 for (width = params->length; width; width--)
4308 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4309 dst_ptr += params->dst_inc;
4310 if (err > 0)
4312 src_ptr += params->src_inc;
4313 err += params->err_add_1;
4315 else err += params->err_add_2;
4319 static void stretch_row_8(const dib_info *dst_dib, const POINT *dst_start,
4320 const dib_info *src_dib, const POINT *src_start,
4321 const struct stretch_params *params, int mode,
4322 BOOL keep_dst)
4324 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4325 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4326 int err = params->err_start;
4327 int width;
4328 struct rop_codes codes;
4330 rop_codes_from_stretch_mode( mode, &codes );
4331 for (width = params->length; width; width--)
4333 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4334 dst_ptr += params->dst_inc;
4335 if (err > 0)
4337 src_ptr += params->src_inc;
4338 err += params->err_add_1;
4340 else err += params->err_add_2;
4344 static void stretch_row_4(const dib_info *dst_dib, const POINT *dst_start,
4345 const dib_info *src_dib, const POINT *src_start,
4346 const struct stretch_params *params, int mode,
4347 BOOL keep_dst)
4349 BYTE *dst_ptr = get_pixel_ptr_4( dst_dib, dst_start->x, dst_start->y );
4350 BYTE *src_ptr = get_pixel_ptr_4( src_dib, src_start->x, src_start->y );
4351 int err = params->err_start;
4352 int width, dst_x = dst_start->x, src_x = src_start->x;
4353 struct rop_codes codes;
4354 BYTE src_val;
4356 rop_codes_from_stretch_mode( mode, &codes );
4357 for (width = params->length; width; width--)
4359 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4360 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4362 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0x0f : 0xf0 );
4364 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4365 dst_ptr += params->dst_inc;
4366 dst_x += params->dst_inc;
4368 if (err > 0)
4370 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4371 src_ptr += params->src_inc;
4372 src_x += params->src_inc;
4373 err += params->err_add_1;
4375 else err += params->err_add_2;
4379 static void stretch_row_1(const dib_info *dst_dib, const POINT *dst_start,
4380 const dib_info *src_dib, const POINT *src_start,
4381 const struct stretch_params *params, int mode,
4382 BOOL keep_dst)
4384 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4385 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4386 int err = params->err_start;
4387 int width, dst_x = dst_start->x, src_x = src_start->x;
4388 struct rop_codes codes;
4389 BYTE src_val;
4391 rop_codes_from_stretch_mode( mode, &codes );
4392 for (width = params->length; width; width--)
4394 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4395 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4397 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4398 dst_ptr += params->dst_inc;
4399 dst_x += params->dst_inc;
4401 if (err > 0)
4403 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4404 src_ptr += params->src_inc;
4405 src_x += params->src_inc;
4406 err += params->err_add_1;
4408 else err += params->err_add_2;
4412 static void stretch_row_null(const dib_info *dst_dib, const POINT *dst_start,
4413 const dib_info *src_dib, const POINT *src_start,
4414 const struct stretch_params *params, int mode,
4415 BOOL keep_dst)
4417 FIXME("bit count %d\n", dst_dib->bit_count);
4418 return;
4421 static void shrink_row_32(const dib_info *dst_dib, const POINT *dst_start,
4422 const dib_info *src_dib, const POINT *src_start,
4423 const struct stretch_params *params, int mode,
4424 BOOL keep_dst)
4426 DWORD *dst_ptr = get_pixel_ptr_32( dst_dib, dst_start->x, dst_start->y );
4427 DWORD *src_ptr = get_pixel_ptr_32( src_dib, src_start->x, src_start->y );
4428 int err = params->err_start;
4429 int width;
4430 struct rop_codes codes;
4431 DWORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4432 BOOL new_pix = TRUE;
4434 rop_codes_from_stretch_mode( mode, &codes );
4435 for (width = params->length; width; width--)
4437 if (new_pix && !keep_dst) *dst_ptr = init_val;
4438 do_rop_codes_32( dst_ptr, *src_ptr, &codes );
4439 new_pix = FALSE;
4440 src_ptr += params->src_inc;
4441 if (err > 0)
4443 dst_ptr += params->dst_inc;
4444 new_pix = TRUE;
4445 err += params->err_add_1;
4447 else err += params->err_add_2;
4451 static void shrink_row_24(const dib_info *dst_dib, const POINT *dst_start,
4452 const dib_info *src_dib, const POINT *src_start,
4453 const struct stretch_params *params, int mode,
4454 BOOL keep_dst)
4456 BYTE *dst_ptr = get_pixel_ptr_24( dst_dib, dst_start->x, dst_start->y );
4457 BYTE *src_ptr = get_pixel_ptr_24( src_dib, src_start->x, src_start->y );
4458 int err = params->err_start;
4459 int width;
4460 struct rop_codes codes;
4461 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4462 BOOL new_pix = TRUE;
4464 rop_codes_from_stretch_mode( mode, &codes );
4465 for (width = params->length; width; width--)
4467 if (new_pix && !keep_dst) memset( dst_ptr, init_val, 3 );
4468 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4469 do_rop_codes_8( dst_ptr + 1, *(src_ptr + 1), &codes );
4470 do_rop_codes_8( dst_ptr + 2, *(src_ptr + 2), &codes );
4471 new_pix = FALSE;
4472 src_ptr += 3 * params->src_inc;
4473 if (err > 0)
4475 dst_ptr += 3 * params->dst_inc;
4476 new_pix = TRUE;
4477 err += params->err_add_1;
4479 else err += params->err_add_2;
4483 static void shrink_row_16(const dib_info *dst_dib, const POINT *dst_start,
4484 const dib_info *src_dib, const POINT *src_start,
4485 const struct stretch_params *params, int mode,
4486 BOOL keep_dst)
4488 WORD *dst_ptr = get_pixel_ptr_16( dst_dib, dst_start->x, dst_start->y );
4489 WORD *src_ptr = get_pixel_ptr_16( src_dib, src_start->x, src_start->y );
4490 int err = params->err_start;
4491 int width;
4492 struct rop_codes codes;
4493 WORD init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4494 BOOL new_pix = TRUE;
4496 rop_codes_from_stretch_mode( mode, &codes );
4497 for (width = params->length; width; width--)
4499 if (new_pix && !keep_dst) *dst_ptr = init_val;
4500 do_rop_codes_16( dst_ptr, *src_ptr, &codes );
4501 new_pix = FALSE;
4502 src_ptr += params->src_inc;
4503 if (err > 0)
4505 dst_ptr += params->dst_inc;
4506 new_pix = TRUE;
4507 err += params->err_add_1;
4509 else err += params->err_add_2;
4513 static void shrink_row_8(const dib_info *dst_dib, const POINT *dst_start,
4514 const dib_info *src_dib, const POINT *src_start,
4515 const struct stretch_params *params, int mode,
4516 BOOL keep_dst)
4518 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4519 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4520 int err = params->err_start;
4521 int width;
4522 struct rop_codes codes;
4523 BYTE init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4524 BOOL new_pix = TRUE;
4526 rop_codes_from_stretch_mode( mode, &codes );
4527 for (width = params->length; width; width--)
4529 if (new_pix && !keep_dst) *dst_ptr = init_val;
4530 do_rop_codes_8( dst_ptr, *src_ptr, &codes );
4531 new_pix = FALSE;
4532 src_ptr += params->src_inc;
4533 if (err > 0)
4535 dst_ptr += params->dst_inc;
4536 new_pix = TRUE;
4537 err += params->err_add_1;
4539 else err += params->err_add_2;
4543 static void shrink_row_4(const dib_info *dst_dib, const POINT *dst_start,
4544 const dib_info *src_dib, const POINT *src_start,
4545 const struct stretch_params *params, int mode,
4546 BOOL keep_dst)
4548 BYTE *dst_ptr = get_pixel_ptr_8( dst_dib, dst_start->x, dst_start->y );
4549 BYTE *src_ptr = get_pixel_ptr_8( src_dib, src_start->x, src_start->y );
4550 int err = params->err_start;
4551 int width, dst_x = dst_start->x, src_x = src_start->x;
4552 struct rop_codes codes;
4553 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4554 BOOL new_pix = TRUE;
4556 rop_codes_from_stretch_mode( mode, &codes );
4557 for (width = params->length; width; width--)
4559 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, (dst_x & 1) ? 0xf0 : 0x0f );
4561 if (src_x & 1) src_val = (*src_ptr & 0x0f) | (*src_ptr << 4);
4562 else src_val = (*src_ptr & 0xf0) | (*src_ptr >> 4);
4564 do_rop_codes_mask_8( dst_ptr, src_val, &codes, (dst_x & 1) ? 0xf0 : 0x0f );
4565 new_pix = FALSE;
4567 if ((src_x & ~1) != ((src_x + params->src_inc) & ~1))
4568 src_ptr += params->src_inc;
4569 src_x += params->src_inc;
4571 if (err > 0)
4573 if ((dst_x & ~1) != ((dst_x + params->dst_inc) & ~1))
4574 dst_ptr += params->dst_inc;
4575 dst_x += params->dst_inc;
4576 new_pix = TRUE;
4577 err += params->err_add_1;
4579 else err += params->err_add_2;
4583 static void shrink_row_1(const dib_info *dst_dib, const POINT *dst_start,
4584 const dib_info *src_dib, const POINT *src_start,
4585 const struct stretch_params *params, int mode,
4586 BOOL keep_dst)
4588 BYTE *dst_ptr = get_pixel_ptr_1( dst_dib, dst_start->x, dst_start->y );
4589 BYTE *src_ptr = get_pixel_ptr_1( src_dib, src_start->x, src_start->y );
4590 int err = params->err_start;
4591 int width, dst_x = dst_start->x, src_x = src_start->x;
4592 struct rop_codes codes;
4593 BYTE src_val, init_val = (mode == STRETCH_ANDSCANS) ? ~0u : 0u;
4594 BOOL new_pix = TRUE;
4596 rop_codes_from_stretch_mode( mode, &codes );
4597 for (width = params->length; width; width--)
4599 if (new_pix && !keep_dst) do_rop_mask_8( dst_ptr, 0, init_val, pixel_masks_1[dst_x % 8] );
4600 src_val = *src_ptr & pixel_masks_1[src_x % 8] ? 0xff : 0;
4601 do_rop_codes_mask_8( dst_ptr, src_val, &codes, pixel_masks_1[dst_x % 8] );
4602 new_pix = FALSE;
4604 if ((src_x & ~7) != ((src_x + params->src_inc) & ~7))
4605 src_ptr += params->src_inc;
4606 src_x += params->src_inc;
4608 if (err > 0)
4610 if ((dst_x & ~7) != ((dst_x + params->dst_inc) & ~7))
4611 dst_ptr += params->dst_inc;
4612 dst_x += params->dst_inc;
4613 new_pix = TRUE;
4614 err += params->err_add_1;
4616 else err += params->err_add_2;
4620 static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
4621 const dib_info *src_dib, const POINT *src_start,
4622 const struct stretch_params *params, int mode,
4623 BOOL keep_dst)
4625 FIXME("bit count %d\n", dst_dib->bit_count);
4626 return;
4629 const primitive_funcs funcs_8888 =
4631 solid_rects_32,
4632 pattern_rects_32,
4633 copy_rect_32,
4634 blend_rect_8888,
4635 draw_glyph_8888,
4636 get_pixel_32,
4637 colorref_to_pixel_888,
4638 pixel_to_colorref_888,
4639 convert_to_8888,
4640 create_rop_masks_32,
4641 stretch_row_32,
4642 shrink_row_32
4645 const primitive_funcs funcs_32 =
4647 solid_rects_32,
4648 pattern_rects_32,
4649 copy_rect_32,
4650 blend_rect_32,
4651 draw_glyph_32,
4652 get_pixel_32,
4653 colorref_to_pixel_masks,
4654 pixel_to_colorref_masks,
4655 convert_to_32,
4656 create_rop_masks_32,
4657 stretch_row_32,
4658 shrink_row_32
4661 const primitive_funcs funcs_24 =
4663 solid_rects_24,
4664 pattern_rects_24,
4665 copy_rect_24,
4666 blend_rect_24,
4667 draw_glyph_24,
4668 get_pixel_24,
4669 colorref_to_pixel_888,
4670 pixel_to_colorref_888,
4671 convert_to_24,
4672 create_rop_masks_24,
4673 stretch_row_24,
4674 shrink_row_24
4677 const primitive_funcs funcs_555 =
4679 solid_rects_16,
4680 pattern_rects_16,
4681 copy_rect_16,
4682 blend_rect_555,
4683 draw_glyph_555,
4684 get_pixel_16,
4685 colorref_to_pixel_555,
4686 pixel_to_colorref_555,
4687 convert_to_555,
4688 create_rop_masks_16,
4689 stretch_row_16,
4690 shrink_row_16
4693 const primitive_funcs funcs_16 =
4695 solid_rects_16,
4696 pattern_rects_16,
4697 copy_rect_16,
4698 blend_rect_16,
4699 draw_glyph_16,
4700 get_pixel_16,
4701 colorref_to_pixel_masks,
4702 pixel_to_colorref_masks,
4703 convert_to_16,
4704 create_rop_masks_16,
4705 stretch_row_16,
4706 shrink_row_16
4709 const primitive_funcs funcs_8 =
4711 solid_rects_8,
4712 pattern_rects_8,
4713 copy_rect_8,
4714 blend_rect_8,
4715 draw_glyph_8,
4716 get_pixel_8,
4717 colorref_to_pixel_colortable,
4718 pixel_to_colorref_colortable,
4719 convert_to_8,
4720 create_rop_masks_8,
4721 stretch_row_8,
4722 shrink_row_8
4725 const primitive_funcs funcs_4 =
4727 solid_rects_4,
4728 pattern_rects_4,
4729 copy_rect_4,
4730 blend_rect_4,
4731 draw_glyph_4,
4732 get_pixel_4,
4733 colorref_to_pixel_colortable,
4734 pixel_to_colorref_colortable,
4735 convert_to_4,
4736 create_rop_masks_4,
4737 stretch_row_4,
4738 shrink_row_4
4741 const primitive_funcs funcs_1 =
4743 solid_rects_1,
4744 pattern_rects_1,
4745 copy_rect_1,
4746 blend_rect_1,
4747 draw_glyph_1,
4748 get_pixel_1,
4749 colorref_to_pixel_colortable,
4750 pixel_to_colorref_colortable,
4751 convert_to_1,
4752 create_rop_masks_1,
4753 stretch_row_1,
4754 shrink_row_1
4757 const primitive_funcs funcs_null =
4759 solid_rects_null,
4760 pattern_rects_null,
4761 copy_rect_null,
4762 blend_rect_null,
4763 draw_glyph_null,
4764 get_pixel_null,
4765 colorref_to_pixel_null,
4766 pixel_to_colorref_null,
4767 convert_to_null,
4768 create_rop_masks_null,
4769 stretch_row_null,
4770 shrink_row_null