2 * DIBDRV device-independent bitmaps
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
22 #include "wine/port.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
28 /* Default 1 BPP palette */
35 /* Default 4 BPP palette */
38 0x000000,0x800000,0x008000,0x808000,
39 0x000080,0x800080,0x008080,0x808080,
40 0xc0c0c0,0xff0000,0x00ff00,0xffff00,
41 0x0000ff,0xff00ff,0x00ffff,0xffffff
44 /* Default 8 BPP palette */
47 0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0xc0c0c0,0xc0dcc0,0xa6caf0,0x000000,0x000033,0x000066,0x000099,0x0000cc,0x0000ff,
48 0x003300,0x003333,0x003366,0x003399,0x0033cc,0x0033ff,0x006600,0x006633,0x006666,0x006699,0x0066cc,0x0066ff,0x009900,0x009933,0x009966,0x009999,
49 0x0099cc,0x0099ff,0x00cc00,0x00cc33,0x00cc66,0x00cc99,0x00cccc,0x00ccff,0x00ff00,0x00ff33,0x00ff66,0x00ff99,0x00ffcc,0x00ffff,0x330000,0x330033,
50 0x330066,0x330099,0x3300cc,0x3300ff,0x333300,0x333333,0x333366,0x333399,0x3333cc,0x3333ff,0x336600,0x336633,0x336666,0x336699,0x3366cc,0x3366ff,
51 0x339900,0x339933,0x339966,0x339999,0x3399cc,0x3399ff,0x33cc00,0x33cc33,0x33cc66,0x33cc99,0x33cccc,0x33ccff,0x33ff00,0x33ff33,0x33ff66,0x33ff99,
52 0x33ffcc,0x33ffff,0x660000,0x660033,0x660066,0x660099,0x6600cc,0x6600ff,0x663300,0x663333,0x663366,0x663399,0x6633cc,0x6633ff,0x666600,0x666633,
53 0x666666,0x666699,0x6666cc,0x6666ff,0x669900,0x669933,0x669966,0x669999,0x6699cc,0x6699ff,0x66cc00,0x66cc33,0x66cc66,0x66cc99,0x66cccc,0x66ccff,
54 0x66ff00,0x66ff33,0x66ff66,0x66ff99,0x66ffcc,0x66ffff,0x990000,0x990033,0x990066,0x990099,0x9900cc,0x9900ff,0x993300,0x993333,0x993366,0x993399,
55 0x9933cc,0x9933ff,0x996600,0x996633,0x996666,0x996699,0x9966cc,0x9966ff,0x999900,0x999933,0x999966,0x999999,0x9999cc,0x9999ff,0x99cc00,0x99cc33,
56 0x99cc66,0x99cc99,0x99cccc,0x99ccff,0x99ff00,0x99ff33,0x99ff66,0x99ff99,0x99ffcc,0x99ffff,0xcc0000,0xcc0033,0xcc0066,0xcc0099,0xcc00cc,0xcc00ff,
57 0xcc3300,0xcc3333,0xcc3366,0xcc3399,0xcc33cc,0xcc33ff,0xcc6600,0xcc6633,0xcc6666,0xcc6699,0xcc66cc,0xcc66ff,0xcc9900,0xcc9933,0xcc9966,0xcc9999,
58 0xcc99cc,0xcc99ff,0xcccc00,0xcccc33,0xcccc66,0xcccc99,0xcccccc,0xccccff,0xccff00,0xccff33,0xccff66,0xccff99,0xccffcc,0xccffff,0xff0000,0xff0033,
59 0xff0066,0xff0099,0xff00cc,0xff00ff,0xff3300,0xff3333,0xff3366,0xff3399,0xff33cc,0xff33ff,0xff6600,0xff6633,0xff6666,0xff6699,0xff66cc,0xff66ff,
60 0xff9900,0xff9933,0xff9966,0xff9999,0xff99cc,0xff99ff,0xffcc00,0xffcc33,0xffcc66,0xffcc99,0xffcccc,0xffccff,0xffff00,0xffff33,0xffff66,0xffff99,
61 0xffffcc,0xffffff,0x050500,0x050501,0x050502,0x050503,0x050504,0x050505,0xe8e8e8,0xe9e9e9,0xeaeaea,0xebebeb,0xececec,0xededed,0xeeeeee,0xefefef,
62 0xf0f0f0,0xf1f1f1,0xf2f2f2,0xf3f3f3,0xf4f4f4,0xf5f5f5,0xfffbf0,0xa0a0a4,0x808080,0xf00000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff
65 /***********************************************************************
66 * DIBDRV_CreateDIBSection
68 HBITMAP
DIBDRV_CreateDIBSection( DIBDRVPHYSDEV
*physDev
, HBITMAP hbitmap
,
69 const BITMAPINFO
*bmi
, UINT usage
)
73 MAYBE(TRACE("physDev:%p, hbitmap:%p, bmi:%p, usage:%d\n", physDev
, hbitmap
, bmi
, usage
));
75 /* createDIBSection is only DIB-related, so we just use the engine */
76 ONCE(FIXME("STUB\n"));
82 /***********************************************************************
85 INT
DIBDRV_GetDIBits( DIBDRVPHYSDEV
*physDev
, HBITMAP hbitmap
, UINT startscan
,
86 UINT lines
, LPVOID bits
, BITMAPINFO
*info
, UINT coloruse
)
90 DIBDRVBITMAP sBmp
, dBmp
;
94 BOOL justInfo
, justInfoHeader
;
98 BITMAPINFO
*sourceInfo
;
100 MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
101 physDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
));
102 if(GetObjectW(hbitmap
, sizeof(DIBSECTION
), &ds
) == sizeof(DIBSECTION
))
104 /* GetDIBits reads bits from a DIB, so we should use the engine driver */
106 /* for the moment, we don't support startscan != 0 */
109 FIXME("startscan != 0 still not supported\n");
114 size
= info
->bmiHeader
.biSize
;
115 if(size
!= sizeof(BITMAPINFOHEADER
) && size
!= sizeof(BITMAPCOREHEADER
))
117 ERR("Unknown header size %d\n", size
);
121 /* get requested BPP */
122 requestedBpp
= info
->bmiHeader
.biBitCount
;
124 /* check wetrher we wants just the BITMAPINFO data */
125 justInfo
= (bits
== NULL
);
127 /* check wether we wants just to get BITMAPINFOHEADER data */
128 justInfoHeader
= (requestedBpp
== 0);
130 if(!justInfo
&& justInfoHeader
)
132 ERR("Bad requested BPP\n");
136 /* copy / set missing DIB info */
139 info
->bmiHeader
.biWidth
= ds
.dsBmih
.biWidth
;
140 info
->bmiHeader
.biHeight
= ds
.dsBmih
.biHeight
;
142 info
->bmiHeader
.biPlanes
= 1;
144 info
->bmiHeader
.biBitCount
= ds
.dsBmih
.biBitCount
;
145 if(size
== sizeof(BITMAPINFOHEADER
))
149 info
->bmiHeader
.biCompression
= ds
.dsBmih
.biCompression
;
150 info
->bmiHeader
.biXPelsPerMeter
= ds
.dsBmih
.biXPelsPerMeter
;
151 info
->bmiHeader
.biYPelsPerMeter
= ds
.dsBmih
.biYPelsPerMeter
;
152 info
->bmiHeader
.biClrUsed
= ds
.dsBmih
.biClrUsed
;
153 info
->bmiHeader
.biClrImportant
= ds
.dsBmih
.biClrImportant
;
155 info
->bmiHeader
.biSizeImage
= ds
.dsBmih
.biSizeImage
;
158 /* width and height *must* match source's ones */
159 if(info
->bmiHeader
.biWidth
!= ds
.dsBmih
.biWidth
||
160 abs(info
->bmiHeader
.biHeight
) != abs(ds
.dsBmih
.biHeight
))
162 ERR("Size of requested bitmap data don't match source's ones\n");
166 /* if we just wants the BITMAPINFOHEADER data, we're done */
167 if(justInfoHeader
|| (justInfo
&& ds
.dsBmih
.biBitCount
> 8))
168 return abs(info
->bmiHeader
.biHeight
);
170 /* we now have to get source data -- we need it for palette, for example */
172 if(ds
.dsBmih
.biBitCount
<= 8)
173 colorTableSize
= (1 << ds
.dsBmih
.biBitCount
);
174 else if(ds
.dsBmih
.biCompression
== BI_BITFIELDS
)
176 sourceInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER
) + colorTableSize
* sizeof(RGBQUAD
));
179 ERR("HeapAlloc failed\n");
182 memcpy(sourceInfo
, &ds
.dsBmih
, sizeof(BITMAPINFOHEADER
));
183 if(ds
.dsBmih
.biBitCount
<= 8)
185 /* grab palette - well, we should. No way to do it by now....
186 we should add a list HBITMAP <--> DIBDRVBITMAP and fiddle to many
187 , many parts of the engine. Not worth the effort by now.
188 So, we just synthesize the table */
192 memcpy((BYTE
*)sourceInfo
+ sizeof(BITMAPINFOHEADER
), pal1
, 2*sizeof(DWORD
));
196 memcpy((BYTE
*)sourceInfo
+ sizeof(BITMAPINFOHEADER
), pal4
, 16*sizeof(DWORD
));
200 memcpy((BYTE
*)sourceInfo
+ sizeof(BITMAPINFOHEADER
), pal8
, 256*sizeof(DWORD
));
204 ERR("Unknown requested bith depth %d\n", requestedBpp
);
205 _DIBDRVBITMAP_Free(&sBmp
);
209 else if(ds
.dsBmih
.biCompression
== BI_BITFIELDS
)
210 memcpy((BYTE
*)sourceInfo
+ sizeof(BITMAPINFOHEADER
), ds
.dsBitfields
, 3 * sizeof(RGBQUAD
));
211 _DIBDRVBITMAP_Clear(&sBmp
);
212 if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp
, sourceInfo
))
214 ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
215 HeapFree(GetProcessHeap(), 0, sourceInfo
);
218 _DIBDRVBITMAP_Set_Bits(&sBmp
, ds
.dsBm
.bmBits
, FALSE
);
219 HeapFree(GetProcessHeap(), 0, sourceInfo
);
221 /* now grab / synthesize the color table if needed */
222 if(requestedBpp
<= 8)
224 colorTable
= (RGBQUAD
*)((BYTE
*)info
+ size
);
225 if(requestedBpp
== ds
.dsBmih
.biBitCount
)
227 /* same source and dest format - copy color tables */
228 memcpy(colorTable
, sBmp
.colorTable
, colorTableSize
);
232 /* different formats -- synthesize color table */
236 memcpy(colorTable
, pal1
, 2*sizeof(DWORD
));
240 memcpy(colorTable
, pal4
, 16*sizeof(DWORD
));
244 memcpy(colorTable
, pal8
, 256*sizeof(DWORD
));
248 ERR("Unknown requested bith depth %d\n", requestedBpp
);
249 _DIBDRVBITMAP_Free(&sBmp
);
255 /* if we just wanted DIB info, job is done */
258 _DIBDRVBITMAP_Free(&sBmp
);
259 return abs(info
->bmiHeader
.biHeight
);
262 /* Creates a DIBDRVBITMAP from dest dib */
263 _DIBDRVBITMAP_Clear(&dBmp
);
264 if(!_DIBDRVBITMAP_InitFromBitmapinfo(&dBmp
, info
))
266 ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
267 _DIBDRVBITMAP_Free(&sBmp
);
270 _DIBDRVBITMAP_Set_Bits(&dBmp
, bits
, FALSE
);
272 /* now we can do the bit conversion */
273 buf
= HeapAlloc(GetProcessHeap(), 0, ds
.dsBmih
.biWidth
* sizeof(RGBQUAD
));
274 for(iLine
= 0; iLine
< lines
; iLine
++)
276 sBmp
.funcs
->GetLine(&sBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
277 dBmp
.funcs
->PutLine(&dBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
279 _DIBDRVBITMAP_Free(&sBmp
);
280 _DIBDRVBITMAP_Free(&dBmp
);
284 /* GetDIBits reads bits from a DDB, use X11 driver */
285 res
= _DIBDRV_GetDisplayDriver()->pGetDIBits(physDev
->X11PhysDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
290 /***********************************************************************
291 * DIBDRV_SetDIBColorTable
293 UINT
DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV
*physDev
, UINT start
, UINT count
,
294 const RGBQUAD
*colors
)
296 DIBDRVBITMAP
*dib
= &physDev
->physBitmap
;
301 MAYBE(TRACE("physDev:%p, start:%d, count:%d, colors:%p\n", physDev
, start
, count
, colors
));
303 /* SetDIBColorTable operates on a DIB, so we use the engine */
305 /* if bpp > 8, some error occurred... */
306 if(dib
->bitCount
> 8)
308 ERR("Called for BPP > 8\n");
312 /* if dib hasn't a color table, or has a small one, we must before
316 dib
->colorTableSize
= (1 << dib
->bitCount
);
317 dib
->colorTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(RGBQUAD
) * dib
->colorTableSize
);
319 else if(dib
->colorTableSize
< (1 << dib
->bitCount
))
321 int newSize
= (1 << dib
->bitCount
);
322 RGBQUAD
*newTable
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RGBQUAD
) * newSize
);
323 memcpy(newTable
, dib
->colorTable
, sizeof(RGBQUAD
) * dib
->colorTableSize
);
324 HeapFree(GetProcessHeap(), 0, dib
->colorTable
);
325 dib
->colorTable
= newTable
;
326 dib
->colorTableSize
= newSize
;
330 if(start
+ count
> dib
->colorTableSize
)
332 ERR("Out of range setting color table, size is %d, requested is %d\n", dib
->colorTableSize
, start
+count
);
335 memcpy(dib
->colorTable
+ start
, colors
, sizeof(RGBQUAD
) * count
);
336 dib
->colorTableGrabbed
= TRUE
;
338 /* hack to make GDI32 sense the DIB color table change
339 (fixes a couple of todos in bitmap test suite */
341 thisDIB
= SelectObject(physDev
->hdc
, GetStockObject(OBJ_BITMAP
));
342 SelectObject(physDev
->hdc
, thisDIB
);
348 /***********************************************************************
351 INT
DIBDRV_SetDIBits( DIBDRVPHYSDEV
*physDev
, HBITMAP hbitmap
, UINT startscan
,
352 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
, UINT coloruse
)
356 DIBDRVBITMAP sBmp
, dBmp
;
360 MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n",
361 physDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
));
364 if(GetObjectW(hbitmap
, sizeof(DIBSECTION
), &ds
) == sizeof(DIBSECTION
))
366 /* SetDIBits writes bits to a DIB, so we should use the engine driver */
368 /* for the moment, we don't support startscan != 0 */
371 FIXME("startscan != 0 still not supported\n");
375 /* Creates a DIBDRVBITMAP from source dib */
376 _DIBDRVBITMAP_Clear(&sBmp
);
377 if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp
, info
))
379 ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
382 _DIBDRVBITMAP_Set_Bits(&sBmp
, (LPVOID
)bits
, FALSE
);
384 /* same for destination dib */
385 if(!_DIBDRVBITMAP_InitFromHBITMAP(&dBmp
, hbitmap
, FALSE
))
387 ERR("_DIBDRVBITMAP_InitFromHBITMAP failed\n");
388 _DIBDRVBITMAP_Free(&sBmp
);
392 /* now we can do the bit conversion */
393 buf
= HeapAlloc(GetProcessHeap(), 0, ds
.dsBmih
.biWidth
* sizeof(RGBQUAD
));
394 for(iLine
= 0; iLine
< lines
; iLine
++)
396 sBmp
.funcs
->GetLine(&sBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
397 dBmp
.funcs
->PutLine(&dBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
399 _DIBDRVBITMAP_Free(&sBmp
);
400 _DIBDRVBITMAP_Free(&dBmp
);
405 /* SetDIBits writes bits to a DDB, so we should use the X11 driver */
406 res
= _DIBDRV_GetDisplayDriver()->pSetDIBits(physDev
->X11PhysDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
411 /*************************************************************************
412 * DIBDRV_SetDIBitsToDevice
414 INT
DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV
*physDev
, INT xDest
, INT yDest
, DWORD cx
,
415 DWORD cy
, INT xSrc
, INT ySrc
,
416 UINT startscan
, UINT lines
, LPCVOID bits
,
417 const BITMAPINFO
*info
, UINT coloruse
)
419 BITMAPINFO
*bitmapInfo
;
421 int dibHeight
, dibWidth
;
423 int sLine
, dLine
, iLine
;
426 MAYBE(TRACE("physDev:%p, xDest:%d, yDest:%d, cx:%x, cy:%x, xSrc:%d, ySrc:%d, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
427 physDev
, xDest
, yDest
, cx
, cy
, xSrc
, ySrc
, startscan
, lines
, bits
, info
, coloruse
));
431 /* DIB section selected in, use DIB Engine */
433 /* inverts y on source -- FIXME: check if right with some tests, it seems so */
434 ySrc
= abs(info
->bmiHeader
.biHeight
) - ySrc
- cy
;
436 dibHeight
= info
->bmiHeader
.biHeight
;
437 dibWidth
= info
->bmiHeader
.biWidth
;
439 /* sanity check and source clipping on physical sizes */
440 if(startscan
>= abs(dibHeight
))
442 if(startscan
+ lines
> abs(dibHeight
))
443 lines
= abs(dibHeight
) - startscan
;
445 /* adjust height because of startscan */
446 dibHeight
+= (dibHeight
> 0 ? -startscan
: startscan
);
450 if(xSrc
+ cx
> dibWidth
)
451 cx
= dibWidth
- xSrc
;
452 if(ySrc
> abs(dibHeight
))
454 if(ySrc
+ cy
> abs(dibHeight
))
455 cy
= abs(dibHeight
) - ySrc
;
470 /* grab a copy of BITMAPINFO */
471 bmInfoSize
= sizeof(BITMAPINFOHEADER
);
472 if(info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
473 bmInfoSize
+= 3 * sizeof(RGBQUAD
);
474 else if (info
->bmiHeader
.biBitCount
<= 8)
476 if(info
->bmiHeader
.biClrUsed
)
477 bmInfoSize
+= info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
479 bmInfoSize
+= (1 << info
->bmiHeader
.biBitCount
) * sizeof(RGBQUAD
);
481 if(!(bitmapInfo
= HeapAlloc(GetProcessHeap(), 0, bmInfoSize
)))
483 ERR("HeapAlloc failed\n");
486 memcpy(bitmapInfo
, info
, bmInfoSize
);
487 bitmapInfo
->bmiHeader
.biHeight
= dibHeight
;
489 /* create a DIBDRVBITMAP from BITMAPINFO data */
490 _DIBDRVBITMAP_Clear(&sBmp
);
491 if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp
, bitmapInfo
))
493 ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
494 HeapFree(GetProcessHeap
, 0, bitmapInfo
);
497 HeapFree(GetProcessHeap(), 0, bitmapInfo
);
498 _DIBDRVBITMAP_Set_Bits(&sBmp
, (LPVOID
)bits
, FALSE
);
500 /* transfer lines to dest bitmap */
501 if(!(buf
= HeapAlloc(GetProcessHeap(), 0, cx
* sizeof(RGBQUAD
))))
503 ERR("HeapAlloc failed\n");
506 for(sLine
= ySrc
, dLine
= yDest
, iLine
= 0; iLine
< cy
; sLine
++, dLine
++, iLine
++)
508 sBmp
.funcs
->GetLine(&sBmp
, sLine
, xSrc
, cx
, buf
);
509 physDev
->physBitmap
.funcs
->PutLine(&physDev
->physBitmap
, dLine
, xDest
, cx
, buf
);
511 HeapFree(GetProcessHeap(), 0, buf
);
517 return _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev
->X11PhysDev
, xDest
, yDest
, cx
, cy
, xSrc
, ySrc
,
518 startscan
, lines
, bits
, info
, coloruse
);