gdi32: Add support for 16 bpp dibs.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / primitives.c
blobc1d159712a8b376f906e2ec10aa2fb6eaf105e8b
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 "gdi_private.h"
22 #include "dibdrv.h"
24 static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
26 return (DWORD *)((BYTE*)dib->bits + y * dib->stride + x * 4);
29 static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
31 return (WORD *)((BYTE*)dib->bits + y * dib->stride + x * 2);
34 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
36 *ptr = (*ptr & and) ^ xor;
39 static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
41 *ptr = (*ptr & and) ^ xor;
44 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
46 DWORD *ptr, *start;
47 int x, y, i;
49 for(i = 0; i < num; i++, rc++)
51 start = get_pixel_ptr_32(dib, rc->left, rc->top);
52 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
53 for(x = rc->left, ptr = start; x < rc->right; x++)
54 do_rop_32(ptr++, and, xor);
58 static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
60 WORD *ptr, *start;
61 int x, y, i;
63 for(i = 0; i < num; i++, rc++)
65 start = get_pixel_ptr_16(dib, rc->left, rc->top);
66 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
67 for(x = rc->left, ptr = start; x < rc->right; x++)
68 do_rop_16(ptr++, and, xor);
72 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
74 return;
77 static inline INT calc_offset(INT edge, INT size, INT origin)
79 INT offset;
81 if(edge - origin >= 0)
82 offset = (edge - origin) % size;
83 else
85 offset = (origin - edge) % size;
86 if(offset) offset = size - offset;
88 return offset;
91 static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
93 POINT offset;
95 offset.x = calc_offset(rc->left, brush->width, origin->x);
96 offset.y = calc_offset(rc->top, brush->height, origin->y);
98 return offset;
101 static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
102 const dib_info *brush, void *and_bits, void *xor_bits)
104 DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
105 int x, y, i;
106 POINT offset;
108 for(i = 0; i < num; i++, rc++)
110 offset = calc_brush_offset(rc, brush, origin);
112 start = get_pixel_ptr_32(dib, rc->left, rc->top);
113 start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
114 start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
116 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
118 and_ptr = start_and + offset.x;
119 xor_ptr = start_xor + offset.x;
121 for(x = rc->left, ptr = start; x < rc->right; x++)
123 do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
124 if(and_ptr == start_and + brush->width)
126 and_ptr = start_and;
127 xor_ptr = start_xor;
131 offset.y++;
132 if(offset.y == brush->height)
134 start_and = and_bits;
135 start_xor = xor_bits;
136 offset.y = 0;
138 else
140 start_and += brush->stride / 4;
141 start_xor += brush->stride / 4;
147 static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
148 const dib_info *brush, void *and_bits, void *xor_bits)
150 WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
151 int x, y, i;
152 POINT offset;
154 for(i = 0; i < num; i++, rc++)
156 offset = calc_brush_offset(rc, brush, origin);
158 start = get_pixel_ptr_16(dib, rc->left, rc->top);
159 start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
160 start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
162 for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
164 and_ptr = start_and + offset.x;
165 xor_ptr = start_xor + offset.x;
167 for(x = rc->left, ptr = start; x < rc->right; x++)
169 do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
170 if(and_ptr == start_and + brush->width)
172 and_ptr = start_and;
173 xor_ptr = start_xor;
177 offset.y++;
178 if(offset.y == brush->height)
180 start_and = and_bits;
181 start_xor = xor_bits;
182 offset.y = 0;
184 else
186 start_and += brush->stride / 2;
187 start_xor += brush->stride / 2;
193 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
194 const dib_info *brush, void *and_bits, void *xor_bits)
196 return;
199 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
201 return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
204 static inline DWORD put_field(DWORD field, int shift, int len)
206 shift = shift - (8 - len);
207 if (len <= 8)
208 field &= (((1 << len) - 1) << (8 - len));
209 if (shift < 0)
210 field >>= -shift;
211 else
212 field <<= shift;
213 return field;
216 static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
218 DWORD r,g,b;
220 r = GetRValue(colour);
221 g = GetGValue(colour);
222 b = GetBValue(colour);
224 return put_field(r, dib->red_shift, dib->red_len) |
225 put_field(g, dib->green_shift, dib->green_len) |
226 put_field(b, dib->blue_shift, dib->blue_len);
229 static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
231 return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
235 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
237 return 0;
240 const primitive_funcs funcs_8888 =
242 solid_rects_32,
243 pattern_rects_32,
244 colorref_to_pixel_888
247 const primitive_funcs funcs_32 =
249 solid_rects_32,
250 pattern_rects_32,
251 colorref_to_pixel_masks
254 const primitive_funcs funcs_555 =
256 solid_rects_16,
257 pattern_rects_16,
258 colorref_to_pixel_555
261 const primitive_funcs funcs_16 =
263 solid_rects_16,
264 pattern_rects_16,
265 colorref_to_pixel_masks
268 const primitive_funcs funcs_null =
270 solid_rects_null,
271 pattern_rects_null,
272 colorref_to_pixel_null