f8f87ce9220f4b2014e5d4a2beeab470d0897087
[wine/hacks.git] / dlls / winedib.drv / primitives_convert.c
blobf8f87ce9220f4b2014e5d4a2beeab470d0897087
1 /*
2 * DIB Engine conversions Primitives
4 * Copyright 2009 Massimo Del Fedele
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 "config.h"
22 #include "wine/port.h"
24 #include "dibdrv.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
28 static inline COLORREF SwapColors(DWORD c)
30 return ((c & 0x0000ff) << 16) | (c & 0x00ff00) | ((c & 0xff0000) >> 16);
34 /* ----------------------------------------------------------------*/
35 /* CONVERT PRIMITIVES */
36 /* converts (part of) line of any DIB format from/to DIB32_RGB one */
37 BOOL _DIBDRV_GetLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
39 DWORD *dwBuf = (DWORD *)buf;
40 DWORD *src;
42 #ifdef DIBDRV_CHECK_RANGES
43 /* range check */
44 if(line < 0 || line >= bmp->height)
45 return FALSE;
46 if(startx < 0)
48 width += startx;
49 dwBuf -= startx;
50 startx = 0;
52 if(startx + width > bmp->width)
53 width = bmp->width - startx;
54 if(width <= 0)
55 return FALSE;
56 #endif
58 src = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
59 for(; width; width--)
60 *dwBuf++ = *src++;
61 return TRUE;
64 BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
66 BYTE *bBuf = (BYTE *)buf;
67 DWORD *src;
69 #ifdef DIBDRV_CHECK_RANGES
70 /* range check */
71 if(line < 0 || line >= bmp->height)
72 return FALSE;
73 if(startx < 0)
75 width += startx;
76 bBuf -= 4 * startx;
77 startx = 0;
79 if(startx + width > bmp->width)
80 width = bmp->width - startx;
81 if(width <= 0)
82 return FALSE;
83 #endif
85 src = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
86 for(; width ; width--)
88 *bBuf++ = (*src & bmp->blueMask ) >> bmp->blueShift;
89 *bBuf++ = (*src & bmp->greenMask) >> bmp->greenShift;
90 *bBuf++ = (*src & bmp->redMask ) >> bmp->redShift;
91 *bBuf++ = 0x0;
92 src++;
94 return TRUE;
97 BOOL _DIBDRV_GetLine24(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
99 BYTE *bBuf = (BYTE *)buf;
100 BYTE *src;
102 #ifdef DIBDRV_CHECK_RANGES
103 /* range check */
104 if(line < 0 || line >= bmp->height)
105 return FALSE;
106 if(startx < 0)
108 width += startx;
109 bBuf -= 4 * startx;
110 startx = 0;
112 if(startx + width > bmp->width)
113 width = bmp->width - startx;
114 if(width <= 0)
115 return FALSE;
116 #endif
118 src = ((BYTE *)bmp->bits + line * bmp->stride + 3 * startx);
119 for(; width ; width--)
121 *bBuf++ = *src++;
122 *bBuf++ = *src++;
123 *bBuf++ = *src++;
124 *bBuf++ = 0x0;
126 return TRUE;
129 BOOL _DIBDRV_GetLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
131 DWORD *dwBuf = (DWORD *)buf;
132 WORD *src;
133 DWORD b;
135 #ifdef DIBDRV_CHECK_RANGES
136 /* range check */
137 if(line < 0 || line >= bmp->height)
138 return FALSE;
139 if(startx < 0)
141 width += startx;
142 dwBuf -= startx;
143 startx = 0;
145 if(startx + width > bmp->width)
146 width = bmp->width - startx;
147 if(width <= 0)
148 return FALSE;
149 #endif
151 src = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
152 for(; width ; width--)
154 b = *src++;
155 /* 0RRR|RRGG|GGGB|BBBB */
156 *dwBuf++ = ((b & 0x1f) << 3) | ((b & 0x3e0) << 6) | ((b & 0x7c00) << 9);
158 return TRUE;
161 BOOL _DIBDRV_GetLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
163 DWORD *dwBuf = (DWORD *)buf;
164 WORD *src;
165 DWORD b;
167 #ifdef DIBDRV_CHECK_RANGES
168 /* range check */
169 if(line < 0 || line >= bmp->height)
170 return FALSE;
171 if(startx < 0)
173 width += startx;
174 dwBuf -= startx;
175 startx = 0;
177 if(startx + width > bmp->width)
178 width = bmp->width - startx;
179 if(width <= 0)
180 return FALSE;
181 #endif
183 src = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
184 for(; width ; width--)
186 b = *src++;
187 *dwBuf++ =((( b & bmp->blueMask) >> bmp->blueShift ) << ( 8 - bmp->blueLen )) |
188 (((b & bmp->greenMask) >> bmp->greenShift) << (16 - bmp->greenLen)) |
189 (((b & bmp->redMask ) >> bmp->redShift ) << (24 - bmp->redLen ));
191 return TRUE;
194 BOOL _DIBDRV_GetLine8(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
196 DWORD *dwBuf = (DWORD *)buf;
197 BYTE *src;
199 #ifdef DIBDRV_CHECK_RANGES
200 /* range check */
201 if(line < 0 || line >= bmp->height)
202 return FALSE;
203 if(startx < 0)
205 width += startx;
206 dwBuf -= startx;
207 startx = 0;
209 if(startx + width > bmp->width)
210 width = bmp->width - startx;
211 if(width <= 0)
212 return FALSE;
213 #endif
215 src = ((BYTE *)bmp->bits + line * bmp->stride + startx);
216 for(; width ; width--)
217 *dwBuf++ = *((DWORD *)bmp->colorTable + *src++);
218 return TRUE;
221 BOOL _DIBDRV_GetLine4(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
223 DWORD *dwBuf = (DWORD *)buf;
224 BYTE *src;
226 #ifdef DIBDRV_CHECK_RANGES
227 /* range check */
228 if(line < 0 || line >= bmp->height)
229 return FALSE;
230 if(startx < 0)
232 width += startx;
233 dwBuf -= startx;
234 startx = 0;
236 if(startx + width > bmp->width)
237 width = bmp->width - startx;
238 if(width <= 0)
239 return FALSE;
240 if(!bmp->colorTable)
242 ERR("Called with uninitialized color table\n");
243 return FALSE;
245 #endif
247 src = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 1));
248 /* if startx is odd, get first nibble */
249 if(startx & 0x01)
251 *dwBuf++ = *((DWORD *)bmp->colorTable + (*src++ & 0x0f));
252 width--;
255 /* then gets all full image bytes */
256 for( ; width > 1 ; width -= 2)
258 *dwBuf++ = *((DWORD *)bmp->colorTable + ((*src >> 4) & 0x0f));
259 *dwBuf++ = *((DWORD *)bmp->colorTable + (*src++ & 0x0f));
262 /* last nibble, if any */
263 if(width)
264 *dwBuf++ = *((DWORD *)bmp->colorTable + ((*src >> 4) & 0x0f));
265 return TRUE;
268 BOOL _DIBDRV_GetLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
270 DWORD *dwBuf = (DWORD *)buf;
271 BYTE *src;
272 BYTE b;
273 char i;
274 DWORD pixOn = *((DWORD *)bmp->colorTable + 1);
275 DWORD pixOff = *(DWORD *)bmp->colorTable;
277 #ifdef DIBDRV_CHECK_RANGES
278 /* range check */
279 if(line < 0 || line >= bmp->height)
280 return FALSE;
281 if(startx < 0)
283 width += startx;
284 dwBuf -= startx;
285 startx = 0;
287 if(startx + width > bmp->width)
288 width = bmp->width - startx;
289 if(width <= 0)
290 return FALSE;
291 #endif
293 src = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 3));
294 /* get first partial byte, if any */
295 startx = (8 - (startx & 0x07)) & 0x07;
296 width -= startx;
297 if(startx)
299 b = *src++ << (8 - startx);
300 while(startx--)
302 if(b & 0x80)
303 *dwBuf++ = pixOn;
304 else
305 *dwBuf++ = pixOff;
306 b <<= 1;
310 /* then gets full next bytes */
311 for( ; width > 7 ; width -= 8)
313 b = *src++;
314 for(i = 0 ; i < 8 ; i++)
316 if(b & 0x80)
317 *dwBuf++ = pixOn;
318 else
319 *dwBuf++ = pixOff;
320 b <<= 1;
324 /* last partial byte, if any */
325 if(width > 0)
327 b = *src;
328 while(width--)
330 if(b & 0x80)
331 *dwBuf++ = pixOn;
332 else
333 *dwBuf++ = pixOff;
334 b <<= 1;
337 return TRUE;
340 BOOL _DIBDRV_PutLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
342 DWORD *dwBuf = (DWORD *)buf;
343 DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
344 for(; width; width--)
345 *dst++ = *dwBuf++;
346 return TRUE;
349 BOOL _DIBDRV_PutLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
351 DWORD *dwBuf = (DWORD *)buf;
352 DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
353 DWORD c;
354 for(; width; width--)
356 c = *dwBuf++;
357 *dst++ =
358 ((( c & 0x000000ff) << bmp->blueShift) & bmp->blueMask) |
359 ((((c & 0x0000ff00) >> 8) << bmp->greenShift) & bmp->greenMask) |
360 ((((c & 0x00ff0000) >> 16) << bmp->redShift) & bmp->redMask);
362 return TRUE;
365 BOOL _DIBDRV_PutLine24(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
367 DWORD *dwBuf = (DWORD *)buf;
368 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + 3 * startx);
369 DWORD c;
370 for(; width; width--)
372 c = *dwBuf++;
373 *dst++ = c & 0x000000ff;
374 *dst++ = (c & 0x0000ff00) >> 8;
375 *dst++ = (c & 0x00ff0000) >> 16;
377 return TRUE;
380 BOOL _DIBDRV_PutLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
382 DWORD *dwBuf = (DWORD *)buf;
383 WORD *dst = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
384 DWORD c;
385 for(; width; width--)
387 c = *dwBuf++;
388 *dst++ =
389 ((c & 0x000000f8) >> 3) |
390 ((c & 0x0000f800) >> 6) |
391 ((c & 0x00f80000) >> 9);
393 return TRUE;
396 BOOL _DIBDRV_PutLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
398 DWORD *dwBuf = (DWORD *)buf;
399 WORD *dst = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
400 DWORD c;
402 BYTE bShift = 8 - bmp->blueLen;
403 BYTE gShift = 16 - bmp->greenLen;
404 BYTE rShift = 24 - bmp->redLen;
405 for(; width; width--)
407 c = *dwBuf++;
408 *dst++ =
409 ((((c & 0x000000ff) >> bShift) << bmp->blueShift) & bmp->blueMask) |
410 ((((c & 0x0000ff00) >> gShift) << bmp->greenShift) & bmp->greenMask) |
411 ((((c & 0x00ff0000) >> rShift) << bmp->redShift) & bmp->redMask);
413 return TRUE;
416 BOOL _DIBDRV_PutLine8(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
418 DWORD *dwBuf = (DWORD *)buf;
419 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + startx);
420 DWORD c;
421 DWORD last_color = 0xffffffff;
422 int last_index = -1;
424 for(; width; width--)
426 c = *dwBuf++;
428 /* slight optimization, as images often have many
429 consecutive pixels with same color */
430 if(last_index == -1 || c != last_color)
432 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
433 last_color = c;
435 *dst++ = last_index;
437 return TRUE;
440 BOOL _DIBDRV_PutLine4(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
442 DWORD *dwBuf = (DWORD *)buf;
443 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 1));
444 DWORD c;
445 DWORD last_color = 0xffffffff;
446 int last_index = -1;
448 /* if startx is odd, put first nibble */
449 if(startx & 0x01)
451 c = *dwBuf++;
453 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
454 last_color = c;
455 *dst = (*dst & 0xf0) | last_index;
456 dst++;
457 width--;
460 /* then gets all full image bytes */
461 for( ; width > 1 ; width -= 2)
463 c = *dwBuf++;
465 /* slight optimization, as images often have many
466 consecutive pixels with same color */
467 if(last_index == -1 || c != last_color)
469 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
470 last_color = c;
472 *dst = last_index << 4;
474 c = *dwBuf++;
476 /* slight optimization, as images often have many
477 consecutive pixels with same color */
478 if(last_index == -1 || c != last_color)
480 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
481 last_color = c;
483 *dst++ |= last_index;
486 /* last nibble, if any */
487 if(width > 0)
489 c = *dwBuf;
491 /* slight optimization, as images often have many
492 consecutive pixels with same color */
493 if(last_index == -1 || c != last_color)
494 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
495 *dst = (*dst & 0x0f) | (last_index << 4);
497 return TRUE;
500 BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
502 DWORD *dwBuf = (DWORD *)buf;
503 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 3));
504 BYTE b, mask;
505 char i;
506 DWORD c;
508 /* get foreground color */
509 DWORD fore = *((DWORD *)bmp->colorTable + 1) & 0x00ffffff;
511 /* put first partial byte, if any */
512 startx &= 0x07;
513 mask = 0x80 >> startx;
514 startx = (8 - startx) & 0x07;
515 if(startx)
517 width -= startx;
518 b = *dst;
519 while(startx--)
521 c = *dwBuf++ & 0x00ffffff;
522 if(c == 0x00ffffff || c == fore)
523 b |= mask;
524 else
525 b &= !mask;
526 mask >>= 1;
528 *dst++ = b;
531 /* then puts full next bytes */
532 for( ; width > 7 ; width -= 8)
534 b = 0;
535 mask = 0x80;
536 for(i = 0 ; i < 8 ; i++)
538 c = *dwBuf++ & 0x00ffffff;
539 if(c == 0x00ffffff || c == fore)
540 b |= mask;
541 mask >>= 1;
543 *dst++ = b;
546 /* last partial byte, if any */
547 if(width > 0)
549 b = *dst;
550 mask = 0x80;
551 while(width--)
553 c = *dwBuf++ & 0x00ffffff;
554 if(c == 0x00ffffff || c == fore)
555 b |= mask;
556 else
557 b &= !mask;
558 mask >>= 1;
560 *dst = b;
562 return TRUE;