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
)
74 MAYBE(TRACE("physDev:%p, hbitmap:%p, bmi:%p, usage:%d\n", physDev
, hbitmap
, bmi
, usage
));
76 /* createDIBSection is only DIB-related, so we just use the engine */
78 /* we need bitmap bits */
79 if(GetObjectW(hbitmap
, sizeof(DIBSECTION
), &ds
) != sizeof(DIBSECTION
))
81 ERR("Bitmap is not a DIB Section\n");
85 /* creates the physical bitmap */
86 if(!(bmp
= _DIBDRVBITMAP_CreateFromBitmapinfo(bmi
, ds
.dsBm
.bmBits
)))
88 ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
92 /* TEMPORARY -- if usage is DIB_PAL_COLOR, sets the palette
93 as ungrabbed, so next call to RealizeDefaultPalette will
95 if(usage
== DIB_PAL_COLORS
)
97 FIXME("Do color table grabbing here instead of RealizeDefaultPalette\n");
98 bmp
->colorTableGrabbed
= FALSE
;
101 /* adds it to the internal list */
102 if(!_BITMAPLIST_Add(hbitmap
, bmp
))
104 ERR("Couldn't add physical bitmap to list\n");
105 _DIBDRVBITMAP_Free(bmp
);
111 /***********************************************************************
114 INT
DIBDRV_GetDIBits( DIBDRVPHYSDEV
*physDev
, HBITMAP hbitmap
, UINT startscan
,
115 UINT lines
, LPVOID bits
, BITMAPINFO
*info
, UINT coloruse
)
119 DIBDRVBITMAP
*sBmp
, *dBmp
;
124 RGBQUAD
*colorTable
= NULL
;
126 MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
127 physDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
));
128 if(GetObjectW(hbitmap
, sizeof(DIBSECTION
), &ds
) == sizeof(DIBSECTION
))
130 /* GetDIBits reads bits from a DIB, so we should use the engine driver */
132 /* for the moment, we don't support startscan != 0 */
135 FIXME("startscan != 0 still not supported\n");
140 size
= info
->bmiHeader
.biSize
;
141 if(size
!= sizeof(BITMAPINFOHEADER
) && size
!= sizeof(BITMAPCOREHEADER
))
143 ERR("Unknown header size %d\n", size
);
147 /* if we wants just the BITMAPINFOHEADER data, do it */
148 if(bits
== NULL
&& info
->bmiHeader
.biBitCount
== 0)
150 memcpy(&info
->bmiHeader
, &ds
.dsBmih
, size
);
151 return abs(ds
.dsBmih
.biHeight
);
154 /* source and dest sizes must match */
155 if(info
->bmiHeader
.biWidth
!= ds
.dsBmih
.biWidth
|| abs(info
->bmiHeader
.biHeight
) != abs(ds
.dsBmih
.biHeight
))
157 WARN("Source and dest DIBs sizes don't match\n");
161 /* get requested BPP and check it */
162 requestedBpp
= info
->bmiHeader
.biBitCount
;
163 if(requestedBpp
!= 1 && requestedBpp
!= 4 &&
164 requestedBpp
!= 8 && requestedBpp
!= 16 &&
165 requestedBpp
!= 24 && requestedBpp
!= 32)
167 ERR("Unknown BitCount %d\n", requestedBpp
);
171 /* now we must get (if needed) the color table */
172 if(!(sBmp
= _BITMAPLIST_Get(hbitmap
)))
174 ERR("Couldn't retrieve source DIB data\n");
177 if(requestedBpp
<= 8)
179 colorTable
= (RGBQUAD
*)((BYTE
*)info
+ size
);
181 /* if same color format, just grab the color table */
182 if(requestedBpp
== sBmp
->bitCount
)
183 memcpy(colorTable
, sBmp
->colorTable
, sBmp
->colorTableSize
);
184 /* otherwise synthesize a new color table */
190 memcpy(colorTable
, pal1
, 2*sizeof(DWORD
));
194 memcpy(colorTable
, pal4
, 16*sizeof(DWORD
));
198 memcpy(colorTable
, pal8
, 256*sizeof(DWORD
));
202 ERR("Unknown requested bith depth %d\n", requestedBpp
);
208 /* If we wanted just BITMAPINFO data, we're done */
210 return abs(ds
.dsBmih
.biHeight
);
212 /* now it's time to transfer image bits; for this we should create
213 a DIBDRVBITMAP from dest BITMAPINFO data */
214 /* FIXME -- HERE is the place to add support for 'startscan' stuffs */
215 if(!(dBmp
= _DIBDRVBITMAP_CreateFromBMIH((BITMAPINFOHEADER
*)info
, ds
.dsBitfields
, colorTable
, bits
)))
217 ERR("Couldn't create dest DIB\n");
221 /* now we can do the bit conversion */
222 buf
= HeapAlloc(GetProcessHeap(), 0, ds
.dsBmih
.biWidth
* sizeof(RGBQUAD
));
223 for(iLine
= 0; iLine
< lines
; iLine
++)
225 sBmp
->funcs
->GetLine(sBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
226 dBmp
->funcs
->PutLine(dBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
228 HeapFree(GetProcessHeap(), 0, buf
);
229 _DIBDRVBITMAP_Free(dBmp
);
233 /* GetDIBits reads bits from a DDB, use X11 driver */
234 res
= _DIBDRV_GetDisplayDriver()->pGetDIBits(physDev
->X11PhysDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
239 /***********************************************************************
240 * DIBDRV_SetDIBColorTable
242 UINT
DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV
*physDev
, UINT start
, UINT count
,
243 const RGBQUAD
*colors
)
245 DIBDRVBITMAP
*dib
= physDev
->physBitmap
;
249 MAYBE(TRACE("physDev:%p, start:%d, count:%d, colors:%p\n", physDev
, start
, count
, colors
));
250 /* SetDIBColorTable operates on a DIB, so we use the engine */
252 /* if bpp > 8, some error occurred... */
253 if(dib
->bitCount
> 8)
255 ERR("Called for BPP > 8\n");
259 /* if dib hasn't a color table, or has a small one, we must before
263 dib
->colorTableSize
= (1 << dib
->bitCount
);
264 dib
->colorTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(RGBQUAD
) * dib
->colorTableSize
);
266 else if(dib
->colorTableSize
< (1 << dib
->bitCount
))
268 int newSize
= (1 << dib
->bitCount
);
269 RGBQUAD
*newTable
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RGBQUAD
) * newSize
);
270 memcpy(newTable
, dib
->colorTable
, sizeof(RGBQUAD
) * dib
->colorTableSize
);
271 HeapFree(GetProcessHeap(), 0, dib
->colorTable
);
272 dib
->colorTable
= newTable
;
273 dib
->colorTableSize
= newSize
;
277 if(start
+ count
> dib
->colorTableSize
)
279 ERR("Out of range setting color table, size is %d, requested is %d\n", dib
->colorTableSize
, start
+count
);
282 memcpy(dib
->colorTable
+ start
, colors
, sizeof(RGBQUAD
) * count
);
283 dib
->colorTableGrabbed
= TRUE
;
285 /* for monochrome bitmaps, we need the 'lightest' color */
286 _DIBDRVBITMAP_GetLightestColorIndex(dib
);
288 /* we should re-select both current pen and brush
289 in order to update colormap-dependent colors */
290 thisBrush
= SelectObject(physDev
->hdc
, GetStockObject(NULL_BRUSH
));
291 thisPen
= SelectObject(physDev
->hdc
, GetStockObject(NULL_PEN
));
292 SelectObject(physDev
->hdc
, thisBrush
);
293 SelectObject(physDev
->hdc
, thisPen
);
298 /***********************************************************************
301 INT
DIBDRV_SetDIBits( DIBDRVPHYSDEV
*physDev
, HBITMAP hbitmap
, UINT startscan
,
302 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
, UINT coloruse
)
306 DIBDRVBITMAP
*sBmp
, *dBmp
;
310 MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n",
311 physDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
));
314 if(GetObjectW(hbitmap
, sizeof(DIBSECTION
), &ds
) == sizeof(DIBSECTION
))
316 /* SetDIBits writes bits to a DIB, so we should use the engine driver */
318 /* for the moment, we don't support startscan != 0 */
321 FIXME("startscan != 0 still not supported\n");
325 /* Creates a DIBDRVBITMAP from source dib */
326 if(!(sBmp
= _DIBDRVBITMAP_CreateFromBitmapinfo(info
, (LPVOID
)bits
)))
328 ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
332 /* get destination physical bitmap */
333 if(!(dBmp
= _BITMAPLIST_Get(hbitmap
)))
335 ERR("Couldn't retrieve dest physical bitmap\n");
336 _DIBDRVBITMAP_Free(sBmp
);
340 /* now we can do the bit conversion */
341 buf
= HeapAlloc(GetProcessHeap(), 0, ds
.dsBmih
.biWidth
* sizeof(RGBQUAD
));
342 for(iLine
= 0; iLine
< lines
; iLine
++)
344 sBmp
->funcs
->GetLine(sBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
345 dBmp
->funcs
->PutLine(dBmp
, iLine
, 0, ds
.dsBmih
.biWidth
, buf
);
347 HeapFree(GetProcessHeap(), 0, buf
);
348 _DIBDRVBITMAP_Free(sBmp
);
353 /* SetDIBits writes bits to a DDB, so we should use the X11 driver */
354 res
= _DIBDRV_GetDisplayDriver()->pSetDIBits(physDev
->X11PhysDev
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
359 /*************************************************************************
360 * DIBDRV_SetDIBitsToDevice
362 INT
DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV
*physDev
, INT xDst
, INT yDst
, DWORD cx
,
363 DWORD cy
, INT xSrc
, INT ySrc
,
364 UINT startscan
, UINT lines
, LPCVOID bits
,
365 const BITMAPINFO
*info
, UINT coloruse
)
367 int dibHeight
, dibWidth
;
368 DIBDRVBITMAP
*sBmp
, *dBmp
;
372 MAYBE(TRACE("physDev:%p, xDst:%d, yDst:%d, cx:%x, cy:%x, xSrc:%d, ySrc:%d, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
373 physDev
, xDst
, yDst
, cx
, cy
, xSrc
, ySrc
, startscan
, lines
, bits
, info
, coloruse
));
377 /* DIB section selected in, use DIB Engine */
379 /* inverts y on source -- FIXME: check if right with some tests, it seems so */
380 // ySrc = abs(info->bmiHeader.biHeight) - ySrc - cy;
382 dibHeight
= info
->bmiHeader
.biHeight
;
383 dibWidth
= info
->bmiHeader
.biWidth
;
385 /* sanity check and source clipping on physical sizes */
386 if(startscan
>= abs(dibHeight
))
388 ERR("startscan out of range\n");
391 if(startscan
+ lines
> abs(dibHeight
))
392 lines
= abs(dibHeight
) - startscan
;
394 /* adjust height because of startscan */
395 dibHeight
+= (dibHeight
> 0 ? -startscan
: startscan
);
399 ERR("xSrc out of range\n");
402 if(xSrc
+ cx
> dibWidth
)
403 cx
= dibWidth
- xSrc
;
404 if(ySrc
> abs(dibHeight
))
406 ERR("ySrc out of range\n");
409 if(ySrc
+ cy
> abs(dibHeight
))
410 cy
= abs(dibHeight
) - ySrc
;
416 ERR("Null or negative vertical size\n");
427 ERR("Null or negative vertical size\n");
431 /* Creates a DIBDRVBITMAP from source dib */
432 if(!(sBmp
= _DIBDRVBITMAP_CreateFromBitmapinfo(info
, (LPVOID
)bits
)))
434 ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
438 /* get destination physical bitmap */
439 dBmp
= physDev
->physBitmap
;
441 /* now we can do the bit conversion */
442 buf
= HeapAlloc(GetProcessHeap(), 0, cx
* sizeof(RGBQUAD
));
443 for(iLine
= 0; iLine
< cy
; iLine
++)
445 sBmp
->funcs
->GetLine(sBmp
, ySrc
++, xSrc
, cx
, buf
);
446 dBmp
->funcs
->PutLine(dBmp
, yDst
++, xDst
, cx
, buf
);
448 HeapFree(GetProcessHeap(), 0, buf
);
449 _DIBDRVBITMAP_Free(sBmp
);
454 return _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev
->X11PhysDev
, xDst
, yDst
, cx
, cy
, xSrc
, ySrc
,
455 startscan
, lines
, bits
, info
, coloruse
);