configure: Changes from running autconf after previous patch.
[wine/hacks.git] / dlls / winedib.drv / dib.c
blobae6a5cf30053e34de90db57e8f3eb9469847acc4
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include "dibdrv.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
28 /* Default 1 BPP palette */
29 static DWORD pal1[] =
31 0x000000,
32 0xffffff
35 /* Default 4 BPP palette */
36 static DWORD pal4[] =
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 */
45 static DWORD pal8[] =
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 )
71 DIBDRVBITMAP *bmp;
72 DIBSECTION ds;
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");
82 return NULL;
85 /* creates the physical bitmap */
86 if(!(bmp = _DIBDRVBITMAP_CreateFromBitmapinfo(bmi, ds.dsBm.bmBits)))
88 ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
89 return NULL;
92 /* TEMPORARY -- if usage is DIB_PAL_COLOR, sets the palette
93 as ungrabbed, so next call to RealizeDefaultPalette will
94 do it */
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);
106 return NULL;
108 return hbitmap;
111 /***********************************************************************
112 * DIBDRV_GetDIBits
114 INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
115 UINT lines, LPVOID bits, BITMAPINFO *info, UINT coloruse )
117 INT res;
118 DIBSECTION ds;
119 DIBDRVBITMAP *sBmp, *dBmp;
120 DWORD *buf;
121 int iLine;
122 int size;
123 int requestedBpp;
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 */
133 if(startscan != 0)
135 FIXME("startscan != 0 still not supported\n");
136 return 0;
139 /* sanity check */
140 size = info->bmiHeader.biSize;
141 if(size != sizeof(BITMAPINFOHEADER) && size != sizeof(BITMAPCOREHEADER))
143 ERR("Unknown header size %d\n", size);
144 return 0;
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");
158 return 0;
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);
168 return 0;
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");
175 return 0;
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 */
185 else
187 switch(requestedBpp)
189 case 1:
190 memcpy(colorTable, pal1, 2*sizeof(DWORD));
191 break;
193 case 4:
194 memcpy(colorTable, pal4, 16*sizeof(DWORD));
195 break;
197 case 8:
198 memcpy(colorTable, pal8, 256*sizeof(DWORD));
199 break;
201 default:
202 ERR("Unknown requested bith depth %d\n", requestedBpp);
203 return 0;
208 /* If we wanted just BITMAPINFO data, we're done */
209 if(!bits)
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");
218 return 0;
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);
230 return lines;
232 else
233 /* GetDIBits reads bits from a DDB, use X11 driver */
234 res = _DIBDRV_GetDisplayDriver()->pGetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, info, coloruse);
236 return res;
239 /***********************************************************************
240 * DIBDRV_SetDIBColorTable
242 UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count,
243 const RGBQUAD *colors )
245 DIBDRVBITMAP *dib = physDev->physBitmap;
246 HBRUSH thisBrush;
247 HPEN thisPen;
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");
256 return 0;
259 /* if dib hasn't a color table, or has a small one, we must before
260 create/extend it */
261 if(!dib->colorTable)
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;
276 /* sanity check */
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);
280 return 0;
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);
295 return TRUE;
298 /***********************************************************************
299 * DIBDRV_SetDIBits
301 INT DIBDRV_SetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
302 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
304 INT res;
305 DIBSECTION ds;
306 DIBDRVBITMAP *sBmp, *dBmp;
307 DWORD *buf;
308 int iLine;
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 */
319 if(startscan != 0)
321 FIXME("startscan != 0 still not supported\n");
322 return 0;
325 /* Creates a DIBDRVBITMAP from source dib */
326 if(!(sBmp = _DIBDRVBITMAP_CreateFromBitmapinfo(info, (LPVOID)bits)))
328 ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
329 return 0;
332 /* get destination physical bitmap */
333 if(!(dBmp = _BITMAPLIST_Get(hbitmap)))
335 ERR("Couldn't retrieve dest physical bitmap\n");
336 _DIBDRVBITMAP_Free(sBmp);
337 return 0;
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);
349 return lines;
351 else
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);
356 return res;
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;
369 int iLine;
370 void *buf;
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));
375 if(physDev->hasDIB)
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");
389 return 0;
391 if(startscan + lines > abs(dibHeight))
392 lines = abs(dibHeight) - startscan;
394 /* adjust height because of startscan */
395 dibHeight += (dibHeight > 0 ? -startscan : startscan);
397 if(xSrc >= dibWidth)
399 ERR("xSrc out of range\n");
400 return 0;
402 if(xSrc + cx > dibWidth)
403 cx = dibWidth - xSrc;
404 if(ySrc > abs(dibHeight))
406 ERR("ySrc out of range\n");
407 return 0;
409 if(ySrc + cy > abs(dibHeight))
410 cy = abs(dibHeight) - ySrc;
412 ySrc -= startscan;
413 cy -= startscan;
414 if(cy <= 0)
416 ERR("Null or negative vertical size\n");
417 return 0;
419 if(ySrc < 0)
421 yDst += ySrc;
422 cy += ySrc;
423 ySrc = 0;
425 if(cy <= 0)
427 ERR("Null or negative vertical size\n");
428 return 0;
431 /* Creates a DIBDRVBITMAP from source dib */
432 if(!(sBmp = _DIBDRVBITMAP_CreateFromBitmapinfo(info, (LPVOID)bits)))
434 ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
435 return 0;
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);
450 return cy;
452 else
454 return _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev->X11PhysDev, xDst, yDst, cx, cy, xSrc, ySrc,
455 startscan, lines, bits, info, coloruse);