DIB Engine: introduction of bitmaplist structure
[wine/hacks.git] / dlls / winedib.drv / primitives_convert.c
blob7c4da14d08e17619ee0f0735cd83b1acf14fccea
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 static inline DWORD PlaceField32(BYTE c, int shift, int len)
36 DWORD res = c;
37 if(len < 8)
38 res >>= (8 - len);
39 else
40 res <<= (len - 8);
41 return res << shift;
44 static inline WORD PlaceField16(BYTE c, int shift, int len)
46 WORD res = c;
47 if(len < 8)
48 res >>= (8 - len);
49 else
50 res <<= (len - 8);
51 return res << shift;
54 static inline BYTE GetField32(DWORD dwColor, int shift, int len)
56 dwColor = dwColor & (((1 << (len)) - 1) << shift);
57 dwColor = dwColor << (32 - (shift + len)) >> 24;
58 return dwColor;
61 /* ----------------------------------------------------------------*/
62 /* CONVERT PRIMITIVES */
63 /* converts (part of) line of any DIB format from/to DIB32_RGB one */
64 BOOL _DIBDRV_GetLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
66 DWORD *dwBuf = (DWORD *)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 dwBuf -= 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--)
87 *dwBuf++ = *src++;
88 return TRUE;
91 BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
93 DWORD *dwBuf = (DWORD *)buf;
94 DWORD *src;
96 #ifdef DIBDRV_CHECK_RANGES
97 /* range check */
98 if(line < 0 || line >= bmp->height)
99 return FALSE;
100 if(startx < 0)
102 width += startx;
103 bBuf -= 4 * startx;
104 startx = 0;
106 if(startx + width > bmp->width)
107 width = bmp->width - startx;
108 if(width <= 0)
109 return FALSE;
110 #endif
112 src = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
113 for(; width ; width--)
115 *dwBuf++ =
116 GetField32(*src, bmp->redShift , bmp->redLen ) << 16 |
117 GetField32(*src, bmp->greenShift, bmp->greenLen) << 8 |
118 GetField32(*src, bmp->blueShift , bmp->blueLen );
119 src++;
121 return TRUE;
124 BOOL _DIBDRV_GetLine24(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
126 BYTE *bBuf = (BYTE *)buf;
127 BYTE *src;
129 #ifdef DIBDRV_CHECK_RANGES
130 /* range check */
131 if(line < 0 || line >= bmp->height)
132 return FALSE;
133 if(startx < 0)
135 width += startx;
136 bBuf -= 4 * startx;
137 startx = 0;
139 if(startx + width > bmp->width)
140 width = bmp->width - startx;
141 if(width <= 0)
142 return FALSE;
143 #endif
145 src = ((BYTE *)bmp->bits + line * bmp->stride + 3 * startx);
146 for(; width ; width--)
148 *bBuf++ = *src++;
149 *bBuf++ = *src++;
150 *bBuf++ = *src++;
151 *bBuf++ = 0x0;
153 return TRUE;
156 BOOL _DIBDRV_GetLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
158 DWORD *dwBuf = (DWORD *)buf;
159 WORD *src;
160 DWORD b;
162 #ifdef DIBDRV_CHECK_RANGES
163 /* range check */
164 if(line < 0 || line >= bmp->height)
165 return FALSE;
166 if(startx < 0)
168 width += startx;
169 dwBuf -= startx;
170 startx = 0;
172 if(startx + width > bmp->width)
173 width = bmp->width - startx;
174 if(width <= 0)
175 return FALSE;
176 #endif
178 src = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
179 for(; width ; width--)
181 b = *src++;
182 /* 0RRR|RRGG|GGGB|BBBB */
183 *dwBuf++ = ((b & 0x1f) << 3) | ((b & 0x3e0) << 6) | ((b & 0x7c00) << 9);
185 return TRUE;
188 BOOL _DIBDRV_GetLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
190 DWORD *dwBuf = (DWORD *)buf;
191 WORD *src;
192 DWORD b;
194 #ifdef DIBDRV_CHECK_RANGES
195 /* range check */
196 if(line < 0 || line >= bmp->height)
197 return FALSE;
198 if(startx < 0)
200 width += startx;
201 dwBuf -= startx;
202 startx = 0;
204 if(startx + width > bmp->width)
205 width = bmp->width - startx;
206 if(width <= 0)
207 return FALSE;
208 #endif
210 src = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
211 for(; width ; width--)
213 b = *src++;
215 *dwBuf++ =((( b & bmp->blueMask) >> bmp->blueShift ) << ( 8 - bmp->blueLen )) |
216 (((b & bmp->greenMask) >> bmp->greenShift) << (16 - bmp->greenLen)) |
217 (((b & bmp->redMask ) >> bmp->redShift ) << (24 - bmp->redLen ));
219 return TRUE;
222 BOOL _DIBDRV_GetLine8(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
224 DWORD *dwBuf = (DWORD *)buf;
225 BYTE *src;
227 #ifdef DIBDRV_CHECK_RANGES
228 /* range check */
229 if(line < 0 || line >= bmp->height)
230 return FALSE;
231 if(startx < 0)
233 width += startx;
234 dwBuf -= startx;
235 startx = 0;
237 if(startx + width > bmp->width)
238 width = bmp->width - startx;
239 if(width <= 0)
240 return FALSE;
241 #endif
243 src = ((BYTE *)bmp->bits + line * bmp->stride + startx);
244 for(; width ; width--)
245 *dwBuf++ = *((DWORD *)bmp->colorTable + *src++);
246 return TRUE;
249 BOOL _DIBDRV_GetLine4(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
251 DWORD *dwBuf = (DWORD *)buf;
252 BYTE *src;
254 #ifdef DIBDRV_CHECK_RANGES
255 /* range check */
256 if(line < 0 || line >= bmp->height)
257 return FALSE;
258 if(startx < 0)
260 width += startx;
261 dwBuf -= startx;
262 startx = 0;
264 if(startx + width > bmp->width)
265 width = bmp->width - startx;
266 if(width <= 0)
267 return FALSE;
268 if(!bmp->colorTable)
270 ERR("Called with uninitialized color table\n");
271 return FALSE;
273 #endif
275 src = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 1));
276 /* if startx is odd, get first nibble */
277 if(startx & 0x01)
279 *dwBuf++ = *((DWORD *)bmp->colorTable + (*src++ & 0x0f));
280 width--;
283 /* then gets all full image bytes */
284 for( ; width > 1 ; width -= 2)
286 *dwBuf++ = *((DWORD *)bmp->colorTable + ((*src >> 4) & 0x0f));
287 *dwBuf++ = *((DWORD *)bmp->colorTable + (*src++ & 0x0f));
290 /* last nibble, if any */
291 if(width)
292 *dwBuf++ = *((DWORD *)bmp->colorTable + ((*src >> 4) & 0x0f));
293 return TRUE;
296 BOOL _DIBDRV_GetLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
298 DWORD *dwBuf = (DWORD *)buf;
299 BYTE *src;
300 BYTE b;
301 char i;
302 DWORD pixOn = *((DWORD *)bmp->colorTable + 1);
303 DWORD pixOff = *(DWORD *)bmp->colorTable;
305 #ifdef DIBDRV_CHECK_RANGES
306 /* range check */
307 if(line < 0 || line >= bmp->height)
308 return FALSE;
309 if(startx < 0)
311 width += startx;
312 dwBuf -= startx;
313 startx = 0;
315 if(startx + width > bmp->width)
316 width = bmp->width - startx;
317 if(width <= 0)
318 return FALSE;
319 #endif
321 src = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 3));
322 /* get first partial byte, if any */
323 startx = (8 - (startx & 0x07)) & 0x07;
324 width -= startx;
325 if(startx)
327 b = *src++ << (8 - startx);
328 while(startx--)
330 if(b & 0x80)
331 *dwBuf++ = pixOn;
332 else
333 *dwBuf++ = pixOff;
334 b <<= 1;
338 /* then gets full next bytes */
339 for( ; width > 7 ; width -= 8)
341 b = *src++;
342 for(i = 0 ; i < 8 ; i++)
344 if(b & 0x80)
345 *dwBuf++ = pixOn;
346 else
347 *dwBuf++ = pixOff;
348 b <<= 1;
352 /* last partial byte, if any */
353 if(width > 0)
355 b = *src;
356 while(width--)
358 if(b & 0x80)
359 *dwBuf++ = pixOn;
360 else
361 *dwBuf++ = pixOff;
362 b <<= 1;
365 return TRUE;
368 BOOL _DIBDRV_PutLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
370 DWORD *dwBuf = (DWORD *)buf;
371 DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
372 for(; width; width--)
373 *dst++ = *dwBuf++;
374 return TRUE;
377 BOOL _DIBDRV_PutLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
379 DWORD *dwBuf = (DWORD *)buf;
380 DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
381 RGBQUAD *c;
382 for(; width; width--)
384 c = (RGBQUAD *)dwBuf++;
385 *dst++ =
386 PlaceField32(c->rgbRed , bmp->redShift , bmp->redLen ) |
387 PlaceField32(c->rgbGreen, bmp->greenShift, bmp->greenLen) |
388 PlaceField32(c->rgbBlue , bmp->blueShift , bmp->blueLen );
390 return TRUE;
393 BOOL _DIBDRV_PutLine24(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
395 DWORD *dwBuf = (DWORD *)buf;
396 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + 3 * startx);
397 DWORD c;
398 for(; width; width--)
400 c = *dwBuf++;
401 *dst++ = c & 0x000000ff;
402 *dst++ = (c & 0x0000ff00) >> 8;
403 *dst++ = (c & 0x00ff0000) >> 16;
405 return TRUE;
408 BOOL _DIBDRV_PutLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
410 DWORD *dwBuf = (DWORD *)buf;
411 WORD *dst = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
412 DWORD c;
413 for(; width; width--)
415 c = *dwBuf++;
416 *dst++ =
417 /* 0RRR|RRGG|GGGB|BBBB */
418 ((c & 0x000000f8) >> 3) |
419 ((c & 0x0000f800) >> 6) |
420 ((c & 0x00f80000) >> 9);
422 return TRUE;
425 BOOL _DIBDRV_PutLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
427 DWORD *dwBuf = (DWORD *)buf;
428 WORD *dst = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
429 DWORD c;
431 BYTE bShift = 8 - bmp->blueLen;
432 BYTE gShift = 16 - bmp->greenLen;
433 BYTE rShift = 24 - bmp->redLen;
434 for(; width; width--)
436 c = *dwBuf++;
437 *dst++ =
438 ((((c & 0x000000ff) >> bShift) << bmp->blueShift) & bmp->blueMask) |
439 ((((c & 0x0000ff00) >> gShift) << bmp->greenShift) & bmp->greenMask) |
440 ((((c & 0x00ff0000) >> rShift) << bmp->redShift) & bmp->redMask);
442 return TRUE;
445 BOOL _DIBDRV_PutLine8(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
447 DWORD *dwBuf = (DWORD *)buf;
448 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + startx);
449 DWORD c;
450 DWORD last_color = 0xffffffff;
451 int last_index = -1;
453 for(; width; width--)
455 c = *dwBuf++;
457 /* slight optimization, as images often have many
458 consecutive pixels with same color */
459 if(last_index == -1 || c != last_color)
461 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
462 last_color = c;
464 *dst++ = last_index;
466 return TRUE;
469 BOOL _DIBDRV_PutLine4(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
471 DWORD *dwBuf = (DWORD *)buf;
472 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 1));
473 DWORD c;
474 DWORD last_color = 0xffffffff;
475 int last_index = -1;
477 /* if startx is odd, put first nibble */
478 if(startx & 0x01)
480 c = *dwBuf++;
482 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
483 last_color = c;
484 *dst = (*dst & 0xf0) | last_index;
485 dst++;
486 width--;
489 /* then gets all full image bytes */
490 for( ; width > 1 ; width -= 2)
492 c = *dwBuf++;
494 /* slight optimization, as images often have many
495 consecutive pixels with same color */
496 if(last_index == -1 || c != last_color)
498 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
499 last_color = c;
501 *dst = last_index << 4;
503 c = *dwBuf++;
505 /* slight optimization, as images often have many
506 consecutive pixels with same color */
507 if(last_index == -1 || c != last_color)
509 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
510 last_color = c;
512 *dst++ |= last_index;
515 /* last nibble, if any */
516 if(width > 0)
518 c = *dwBuf;
520 /* slight optimization, as images often have many
521 consecutive pixels with same color */
522 if(last_index == -1 || c != last_color)
523 last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
524 *dst = (*dst & 0x0f) | (last_index << 4);
526 return TRUE;
529 BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
531 DWORD *dwBuf = (DWORD *)buf;
532 BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 3));
533 BYTE b, mask;
534 char i;
535 DWORD c;
537 /* get foreground color */
538 DWORD back = *(DWORD *)bmp->colorTable & 0x00ffffff;
539 DWORD fore = *((DWORD *)bmp->colorTable + 1) & 0x00ffffff;
541 /* get 'light' color */
542 int lightColor = bmp->lightColor;
544 /* put first partial byte, if any */
545 startx &= 0x07;
546 mask = 0x80 >> startx;
547 startx = (8 - startx) & 0x07;
548 if(startx)
550 width -= startx;
551 b = *dst;
552 while(startx--)
554 c = *dwBuf++ & 0x00ffffff;
555 if(c == fore)
556 b |= mask;
557 else if(c == back)
558 b &= !mask;
559 else if((c == 0x00ffffff && lightColor) || (c == 0 && !lightColor))
560 b |= mask;
561 else
562 b &= !mask;
563 mask >>= 1;
565 *dst++ = b;
568 /* then puts full next bytes */
569 for( ; width > 7 ; width -= 8)
571 b = 0;
572 mask = 0x80;
573 for(i = 0 ; i < 8 ; i++)
575 c = *dwBuf++ & 0x00ffffff;
576 if(c == fore || (c == 0x00ffffff && c != back && lightColor) || (c == 0 && !lightColor))
577 b |= mask;
578 mask >>= 1;
580 *dst++ = b;
583 /* last partial byte, if any */
584 if(width > 0)
586 b = *dst;
587 mask = 0x80;
588 while(width--)
590 c = *dwBuf++ & 0x00ffffff;
591 if(c == fore)
592 b |= mask;
593 else if(c == back)
594 b &= !mask;
595 else if((c == 0x00ffffff && lightColor) || (c == 0 && !lightColor))
596 b |= mask;
597 else
598 b &= !mask;
599 mask >>= 1;
601 *dst = b;
603 return TRUE;