Getting strings with VerQueryValue32W was broken. Complete
[wine/multimedia.git] / objects / dib.c
blob6d12b28fd802f82f82d3811079639f5f75f40cdf
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * TODO: Still contains some references to X11DRV.
7 */
9 #include <stdlib.h>
10 #include "dc.h"
11 #include "bitmap.h"
12 #include "callback.h"
13 #include "palette.h"
14 #include "global.h"
15 #include "debug.h"
16 #include "x11drv.h"
19 /***********************************************************************
20 * DIB_GetDIBWidthBytes
22 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
23 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
25 int DIB_GetDIBWidthBytes( int width, int depth )
27 int words;
29 switch(depth)
31 case 1: words = (width + 31) / 32; break;
32 case 4: words = (width + 7) / 8; break;
33 case 8: words = (width + 3) / 4; break;
34 case 15:
35 case 16: words = (width + 1) / 2; break;
36 case 24: words = (width * 3 + 3)/4; break;
38 default:
39 WARN(bitmap, "(%d): Unsupported depth\n", depth );
40 /* fall through */
41 case 32:
42 words = width;
44 return 4 * words;
48 /***********************************************************************
49 * DIB_BitmapInfoSize
51 * Return the size of the bitmap info structure including color table.
53 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
55 int colors;
57 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
59 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
60 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
61 return sizeof(BITMAPCOREHEADER) + colors *
62 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
64 else /* assume BITMAPINFOHEADER */
66 colors = info->bmiHeader.biClrUsed;
67 if (!colors && (info->bmiHeader.biBitCount <= 8))
68 colors = 1 << info->bmiHeader.biBitCount;
69 return sizeof(BITMAPINFOHEADER) + colors *
70 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
75 /***********************************************************************
76 * DIB_GetBitmapInfo
78 * Get the info from a bitmap header.
79 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
81 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
82 int *height, WORD *bpp, WORD *compr )
84 if (header->biSize == sizeof(BITMAPINFOHEADER))
86 *width = header->biWidth;
87 *height = header->biHeight;
88 *bpp = header->biBitCount;
89 *compr = header->biCompression;
90 return 1;
92 if (header->biSize == sizeof(BITMAPCOREHEADER))
94 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
95 *width = core->bcWidth;
96 *height = core->bcHeight;
97 *bpp = core->bcBitCount;
98 *compr = 0;
99 return 0;
101 WARN(bitmap, "(%ld): wrong size for header\n", header->biSize );
102 return -1;
106 /***********************************************************************
107 * StretchDIBits16 (GDI.439)
109 INT16 WINAPI StretchDIBits16(HDC16 hdc, INT16 xDst, INT16 yDst, INT16 widthDst,
110 INT16 heightDst, INT16 xSrc, INT16 ySrc, INT16 widthSrc,
111 INT16 heightSrc, const VOID *bits,
112 const BITMAPINFO *info, UINT16 wUsage, DWORD dwRop )
114 return (INT16)StretchDIBits32( hdc, xDst, yDst, widthDst, heightDst,
115 xSrc, ySrc, widthSrc, heightSrc, bits,
116 info, wUsage, dwRop );
120 /***********************************************************************
121 * StretchDIBits32 (GDI32.351)
123 INT32 WINAPI StretchDIBits32(HDC32 hdc, INT32 xDst, INT32 yDst, INT32 widthDst,
124 INT32 heightDst, INT32 xSrc, INT32 ySrc, INT32 widthSrc,
125 INT32 heightSrc, const void *bits,
126 const BITMAPINFO *info, UINT32 wUsage, DWORD dwRop )
128 DC *dc = DC_GetDCPtr( hdc );
129 if(!dc) return FALSE;
131 if(dc->funcs->pStretchDIBits)
132 return dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst,
133 heightDst, xSrc, ySrc, widthSrc,
134 heightSrc, bits, info, wUsage,
135 dwRop);
136 else { /* use StretchBlt32 */
137 HBITMAP32 hBitmap, hOldBitmap;
138 HDC32 hdcMem;
140 hBitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
141 bits, info, wUsage );
142 hdcMem = CreateCompatibleDC32( hdc );
143 hOldBitmap = SelectObject32( hdcMem, hBitmap );
144 /* Origin for DIBitmap is bottom left ! */
145 StretchBlt32( hdc, xDst, yDst, widthDst, heightDst,
146 hdcMem, xSrc, info->bmiHeader.biHeight - heightSrc - ySrc,
147 widthSrc, heightSrc, dwRop );
148 SelectObject32( hdcMem, hOldBitmap );
149 DeleteDC32( hdcMem );
150 DeleteObject32( hBitmap );
151 return heightSrc;
156 /***********************************************************************
157 * SetDIBits16 (GDI.440)
159 INT16 WINAPI SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
160 UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
161 UINT16 coloruse )
163 return SetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
167 /******************************************************************************
168 * SetDIBits32 [GDI32.312] Sets pixels in a bitmap using colors from DIB
170 * PARAMS
171 * hdc [I] Handle to device context
172 * hbitmap [I] Handle to bitmap
173 * startscan [I] Starting scan line
174 * lines [I] Number of scan lines
175 * bits [I] Array of bitmap bits
176 * info [I] Address of structure with data
177 * coloruse [I] Type of color indexes to use
179 * RETURNS
180 * Success: Number of scan lines copied
181 * Failure: 0
183 INT32 WINAPI SetDIBits32( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan,
184 UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
185 UINT32 coloruse )
187 DIB_SETIMAGEBITS_DESCR descr;
188 BITMAPOBJ * bmp;
189 int height, tmpheight;
190 INT32 result;
192 /* Check parameters */
194 descr.dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
195 if (!descr.dc)
197 descr.dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
198 if (!descr.dc) return 0;
200 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
202 GDI_HEAP_UNLOCK( hdc );
203 return 0;
205 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
206 &descr.infoBpp, &descr.compression ) == -1)
208 GDI_HEAP_UNLOCK( hbitmap );
209 GDI_HEAP_UNLOCK( hdc );
210 return 0;
212 tmpheight = height;
213 if (height < 0) height = -height;
214 if (!lines || (startscan >= height))
216 GDI_HEAP_UNLOCK( hbitmap );
217 GDI_HEAP_UNLOCK( hdc );
218 return 0;
220 if (startscan + lines > height) lines = height - startscan;
222 if (descr.infoBpp <= 8)
224 descr.colorMap = X11DRV_DIB_BuildColorMap( descr.dc, coloruse,
225 bmp->bitmap.bmBitsPixel,
226 info, &descr.nColorMap );
227 if (!descr.colorMap)
229 GDI_HEAP_UNLOCK( hbitmap );
230 GDI_HEAP_UNLOCK( hdc );
231 return 0;
233 } else
234 descr.colorMap = 0;
236 /* HACK for now */
237 if(!bmp->DDBitmap)
238 X11DRV_CreateBitmap(hbitmap);
240 X11DRV_PHYSBITMAP *pbitmap = bmp->DDBitmap->physBitmap;
243 descr.bits = bits;
244 descr.image = NULL;
245 descr.lines = tmpheight >= 0 ? lines : -lines;
246 descr.depth = bmp->bitmap.bmBitsPixel;
247 descr.drawable = pbitmap->pixmap;
248 descr.gc = BITMAP_GC(bmp);
249 descr.xSrc = 0;
250 descr.ySrc = 0;
251 descr.xDest = 0;
252 descr.yDest = height - startscan - lines;
253 descr.width = bmp->bitmap.bmWidth;
254 descr.height = lines;
256 EnterCriticalSection( &X11DRV_CritSection );
257 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
258 LeaveCriticalSection( &X11DRV_CritSection );
260 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
262 GDI_HEAP_UNLOCK( hdc );
263 GDI_HEAP_UNLOCK( hbitmap );
264 return result;
268 /***********************************************************************
269 * SetDIBitsToDevice16 (GDI.443)
271 INT16 WINAPI SetDIBitsToDevice16(HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
272 INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
273 UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
274 UINT16 coloruse )
276 return SetDIBitsToDevice32( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
277 startscan, lines, bits, info, coloruse );
281 /***********************************************************************
282 * SetDIBitsToDevice32 (GDI32.313)
284 INT32 WINAPI SetDIBitsToDevice32(HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
285 DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
286 UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
287 UINT32 coloruse )
289 INT32 ret;
290 DC *dc;
292 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
294 if(dc->funcs->pSetDIBitsToDevice)
295 ret = dc->funcs->pSetDIBitsToDevice( dc, xDest, yDest, cx, cy, xSrc,
296 ySrc, startscan, lines, bits,
297 info, coloruse );
298 else {
299 FIXME(bitmap, "unimplemented on hdc %08x\n", hdc);
300 ret = 0;
303 GDI_HEAP_UNLOCK( hdc );
304 return ret;
307 /***********************************************************************
308 * SetDIBColorTable16 (GDI.602)
310 UINT16 WINAPI SetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
311 RGBQUAD *colors )
313 return SetDIBColorTable32( hdc, startpos, entries, colors );
316 /***********************************************************************
317 * SetDIBColorTable32 (GDI32.311)
319 UINT32 WINAPI SetDIBColorTable32( HDC32 hdc, UINT32 startpos, UINT32 entries,
320 RGBQUAD *colors )
322 DC * dc;
323 PALETTEENTRY * palEntry;
324 PALETTEOBJ * palette;
325 RGBQUAD *end;
327 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
328 if (!dc)
330 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
331 if (!dc) return 0;
334 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
336 return 0;
339 /* Transfer color info */
341 if (dc->w.bitsPerPixel <= 8) {
342 palEntry = palette->logpalette.palPalEntry + startpos;
343 if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
344 entries = (1 << dc->w.bitsPerPixel) - startpos;
346 for (end = colors + entries; colors < end; palEntry++, colors++)
348 palEntry->peRed = colors->rgbRed;
349 palEntry->peGreen = colors->rgbGreen;
350 palEntry->peBlue = colors->rgbBlue;
352 } else {
353 entries = 0;
355 GDI_HEAP_UNLOCK( dc->w.hPalette );
356 return entries;
359 /***********************************************************************
360 * GetDIBColorTable16 (GDI.603)
362 UINT16 WINAPI GetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
363 RGBQUAD *colors )
365 return GetDIBColorTable32( hdc, startpos, entries, colors );
368 /***********************************************************************
369 * GetDIBColorTable32 (GDI32.169)
371 UINT32 WINAPI GetDIBColorTable32( HDC32 hdc, UINT32 startpos, UINT32 entries,
372 RGBQUAD *colors )
374 DC * dc;
375 PALETTEENTRY * palEntry;
376 PALETTEOBJ * palette;
377 RGBQUAD *end;
379 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
380 if (!dc)
382 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
383 if (!dc) return 0;
386 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
388 return 0;
391 /* Transfer color info */
393 if (dc->w.bitsPerPixel <= 8) {
394 palEntry = palette->logpalette.palPalEntry + startpos;
395 if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
396 entries = (1 << dc->w.bitsPerPixel) - startpos;
398 for (end = colors + entries; colors < end; palEntry++, colors++)
400 colors->rgbRed = palEntry->peRed;
401 colors->rgbGreen = palEntry->peGreen;
402 colors->rgbBlue = palEntry->peBlue;
403 colors->rgbReserved = 0;
405 } else {
406 entries = 0;
408 GDI_HEAP_UNLOCK( dc->w.hPalette );
409 return entries;
412 /***********************************************************************
413 * GetDIBits16 (GDI.441)
415 INT16 WINAPI GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
416 UINT16 lines, LPSTR bits, BITMAPINFO * info,
417 UINT16 coloruse )
419 return GetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
423 /******************************************************************************
424 * GetDIBits32 [GDI32.170] Retrieves bits of bitmap and copies to buffer
426 * RETURNS
427 * Success: Number of scan lines copied from bitmap
428 * Failure: 0
430 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
432 INT32 WINAPI GetDIBits32(
433 HDC32 hdc, /* [in] Handle to device context */
434 HBITMAP32 hbitmap, /* [in] Handle to bitmap */
435 UINT32 startscan, /* [in] First scan line to set in dest bitmap */
436 UINT32 lines, /* [in] Number of scan lines to copy */
437 LPSTR bits, /* [out] Address of array for bitmap bits */
438 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
439 UINT32 coloruse) /* [in] RGB or palette index */
441 DC * dc;
442 BITMAPOBJ * bmp;
443 PALETTEENTRY * palEntry;
444 PALETTEOBJ * palette;
445 XImage * bmpImage;
446 int i, x, y;
448 if (!lines) return 0;
449 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
450 if (!dc)
452 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
453 if (!dc) return 0;
455 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
456 return 0;
457 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
459 GDI_HEAP_UNLOCK( hbitmap );
460 return 0;
463 /* Transfer color info (FIXME) */
465 if (info && (info->bmiHeader.biBitCount <= 8) &&
466 (bmp->bitmap.bmBitsPixel <= 8))
468 int colors = 1 << info->bmiHeader.biBitCount;
469 info->bmiHeader.biClrUsed = 0;
470 palEntry = palette->logpalette.palPalEntry;
471 for (i = 0; i < colors; i++, palEntry++)
473 if (coloruse == DIB_RGB_COLORS)
475 info->bmiColors[i].rgbRed = palEntry->peRed;
476 info->bmiColors[i].rgbGreen = palEntry->peGreen;
477 info->bmiColors[i].rgbBlue = palEntry->peBlue;
478 info->bmiColors[i].rgbReserved = 0;
480 else ((WORD *)info->bmiColors)[i] = (WORD)i;
484 if (bits)
486 BYTE* bbits = bits;
487 int pad, yend, xend = bmp->bitmap.bmWidth;
489 TRACE(bitmap, "%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
490 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
491 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight, startscan );
493 /* adjust number of scanlines to copy */
495 if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
496 yend = startscan + lines;
497 if( startscan >= bmp->bitmap.bmHeight )
499 GDI_HEAP_UNLOCK( hbitmap );
500 GDI_HEAP_UNLOCK( dc->w.hPalette );
501 return FALSE;
503 if( yend > bmp->bitmap.bmHeight ) yend = bmp->bitmap.bmHeight;
505 /* adjust scanline width */
507 pad = info->bmiHeader.biWidth - bmp->bitmap.bmWidth;
508 if( pad < 0 )
510 /* bitmap is wider than DIB, copy only a part */
512 pad = 0;
513 xend = info->bmiHeader.biWidth;
516 /* HACK for now */
517 if(!bmp->DDBitmap)
518 X11DRV_CreateBitmap(hbitmap);
520 EnterCriticalSection( &X11DRV_CritSection );
521 bmpImage = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
523 switch( info->bmiHeader.biBitCount )
525 case 8:
526 /* pad up to 32 bit */
527 pad += (4 - (info->bmiHeader.biWidth & 3)) & 3;
528 for( y = yend - 1; (int)y >= (int)startscan; y-- )
530 for( x = 0; x < xend; x++ )
531 *bbits++ = XGetPixel( bmpImage, x, y );
532 bbits += pad;
534 break;
535 case 1:
536 pad += ((32 - (info->bmiHeader.biWidth & 31)) / 8) & 3;
537 for( y = yend - 1; (int)y >= (int)startscan; y-- )
539 for( x = 0; x < xend; x++ ) {
540 if (!(x&7)) *bbits = 0;
541 *bbits |= XGetPixel( bmpImage, x, y)<<(7-(x&7));
542 if ((x&7)==7) bbits++;
544 bbits += pad;
546 break;
547 case 4:
548 pad += ((8 - (info->bmiHeader.biWidth & 7)) / 2) & 3;
549 for( y = yend - 1; (int)y >= (int)startscan; y-- )
551 for( x = 0; x < xend; x++ ) {
552 if (!(x&1)) *bbits = 0;
553 *bbits |= XGetPixel( bmpImage, x, y)<<(4*(1-(x&1)));
554 if ((x&1)==1) bbits++;
556 bbits += pad;
558 break;
559 case 15:
560 case 16:
561 pad += (4 - ((info->bmiHeader.biWidth*2) & 3)) & 3;
562 for( y = yend - 1; (int)y >= (int)startscan; y-- )
564 for( x = 0; x < xend; x++ ) {
565 unsigned long pixel=XGetPixel( bmpImage, x, y);
566 *bbits++ = pixel & 0xff;
567 *bbits++ = (pixel >> 8) & 0xff;
569 bbits += pad;
571 break;
572 case 24:
573 pad += (4 - ((info->bmiHeader.biWidth*3) & 3)) & 3;
574 for( y = yend - 1; (int)y >= (int)startscan; y-- )
576 for( x = 0; x < xend; x++ ) {
577 unsigned long pixel=XGetPixel( bmpImage, x, y);
578 *bbits++ = (pixel >>16) & 0xff;
579 *bbits++ = (pixel >> 8) & 0xff;
580 *bbits++ = pixel & 0xff;
582 bbits += pad;
584 break;
585 case 32:
586 for( y = yend - 1; (int)y >= (int)startscan; y-- )
588 for( x = 0; x < xend; x++ ) {
589 unsigned long pixel=XGetPixel( bmpImage, x, y);
590 *bbits++ = (pixel >>16) & 0xff;
591 *bbits++ = (pixel >> 8) & 0xff;
592 *bbits++ = pixel & 0xff;
595 break;
596 default:
597 WARN(bitmap,"Unsupported depth %d\n",
598 info->bmiHeader.biBitCount);
599 break;
602 XDestroyImage( bmpImage );
603 LeaveCriticalSection( &X11DRV_CritSection );
605 info->bmiHeader.biCompression = 0;
607 else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
609 /* fill in struct members */
611 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
612 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
613 info->bmiHeader.biPlanes = 1;
614 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
615 info->bmiHeader.biSizeImage = bmp->bitmap.bmHeight *
616 DIB_GetDIBWidthBytes( bmp->bitmap.bmWidth,
617 bmp->bitmap.bmBitsPixel );
618 info->bmiHeader.biCompression = 0;
621 GDI_HEAP_UNLOCK( hbitmap );
622 GDI_HEAP_UNLOCK( dc->w.hPalette );
623 return lines;
627 /***********************************************************************
628 * CreateDIBitmap16 (GDI.442)
630 HBITMAP16 WINAPI CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
631 DWORD init, LPCVOID bits, const BITMAPINFO * data,
632 UINT16 coloruse )
634 return CreateDIBitmap32( hdc, header, init, bits, data, coloruse );
638 /***********************************************************************
639 * CreateDIBitmap32 (GDI32.37)
641 HBITMAP32 WINAPI CreateDIBitmap32( HDC32 hdc, const BITMAPINFOHEADER *header,
642 DWORD init, LPCVOID bits, const BITMAPINFO *data,
643 UINT32 coloruse )
645 HBITMAP32 handle;
646 BOOL32 fColor;
647 DWORD width;
648 int height;
649 WORD bpp;
650 WORD compr;
652 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
653 if (height < 0) height = -height;
655 /* Check if we should create a monochrome or color bitmap. */
656 /* We create a monochrome bitmap only if it has exactly 2 */
657 /* colors, which are either black or white, nothing else. */
658 /* In all other cases, we create a color bitmap. */
660 if (bpp != 1) fColor = TRUE;
661 else if ((coloruse != DIB_RGB_COLORS) ||
662 (init != CBM_INIT) || !data) fColor = FALSE;
663 else
665 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
667 RGBQUAD *rgb = data->bmiColors;
668 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
669 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
671 rgb++;
672 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
673 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
675 else fColor = TRUE;
677 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
679 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
680 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
681 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
683 rgb++;
684 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
685 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
687 else fColor = TRUE;
689 else
691 WARN(bitmap, "(%ld): wrong size for data\n",
692 data->bmiHeader.biSize );
693 return 0;
697 /* Now create the bitmap */
699 handle = fColor ? CreateBitmap32( width, height, 1, screenDepth, NULL ) :
700 CreateBitmap32( width, height, 1, 1, NULL );
701 if (!handle) return 0;
703 if (init == CBM_INIT)
704 SetDIBits32( hdc, handle, 0, height, bits, data, coloruse );
705 return handle;
709 /***********************************************************************
710 * DIB_DoProtectDIBSection
712 static void DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
714 DIBSECTION *dib = &bmp->dib->dibSection;
715 INT32 effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
716 : -dib->dsBm.bmHeight;
717 INT32 totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
718 : dib->dsBm.bmWidthBytes * effHeight;
719 DWORD old_prot;
721 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
722 TRACE(bitmap, "Changed protection from %ld to %ld\n",
723 old_prot, new_prot);
726 /***********************************************************************
727 * DIB_DoUpdateDIBSection
729 static void DIB_DoUpdateDIBSection( BITMAPOBJ *bmp, BOOL32 toDIB )
731 DIBSECTIONOBJ *dib = bmp->dib;
732 DIB_SETIMAGEBITS_DESCR descr;
734 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
735 &descr.infoBpp, &descr.compression ) == -1)
736 return;
738 descr.dc = NULL;
739 descr.image = dib->image;
740 descr.colorMap = dib->colorMap;
741 descr.nColorMap = dib->nColorMap;
742 descr.bits = dib->dibSection.dsBm.bmBits;
743 descr.depth = bmp->bitmap.bmBitsPixel;
745 /* Hack for now */
746 descr.drawable = ((X11DRV_PHYSBITMAP *)bmp->DDBitmap->physBitmap)->pixmap;
747 descr.gc = BITMAP_GC(bmp);
748 descr.xSrc = 0;
749 descr.ySrc = 0;
750 descr.xDest = 0;
751 descr.yDest = 0;
752 descr.width = bmp->bitmap.bmWidth;
753 descr.height = bmp->bitmap.bmHeight;
755 if (toDIB)
757 TRACE(bitmap, "Copying from Pixmap to DIB bits\n");
758 EnterCriticalSection( &X11DRV_CritSection );
759 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
760 LeaveCriticalSection( &X11DRV_CritSection );
762 else
764 TRACE(bitmap, "Copying from DIB bits to Pixmap\n");
765 EnterCriticalSection( &X11DRV_CritSection );
766 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
767 LeaveCriticalSection( &X11DRV_CritSection );
771 /***********************************************************************
772 * DIB_FaultHandler
774 static BOOL32 DIB_FaultHandler( LPVOID res, LPVOID addr )
776 BOOL32 handled = FALSE;
777 BITMAPOBJ *bmp;
779 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP32)res, BITMAP_MAGIC );
780 if (!bmp) return FALSE;
782 if (bmp->dib)
783 switch (bmp->dib->status)
785 case DIB_GdiMod:
786 TRACE( bitmap, "called in status DIB_GdiMod\n" );
787 DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
788 DIB_DoUpdateDIBSection( bmp, TRUE );
789 DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
790 bmp->dib->status = DIB_InSync;
791 handled = TRUE;
792 break;
794 case DIB_InSync:
795 TRACE( bitmap, "called in status DIB_InSync\n" );
796 DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
797 bmp->dib->status = DIB_AppMod;
798 handled = TRUE;
799 break;
801 case DIB_AppMod:
802 FIXME( bitmap, "called in status DIB_AppMod: "
803 "this can't happen!\n" );
804 break;
806 case DIB_NoHandler:
807 FIXME( bitmap, "called in status DIB_NoHandler: "
808 "this can't happen!\n" );
809 break;
812 GDI_HEAP_UNLOCK( (HBITMAP32)res );
813 return handled;
816 /***********************************************************************
817 * DIB_UpdateDIBSection
819 void DIB_UpdateDIBSection( DC *dc, BOOL32 toDIB )
821 BITMAPOBJ *bmp;
823 /* Ensure this is a Compatible DC that has a DIB section selected */
825 if (!dc) return;
826 if (!(dc->w.flags & DC_MEMORY)) return;
828 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
829 if (!bmp) return;
831 if (!bmp->dib)
833 GDI_HEAP_UNLOCK(dc->w.hBitmap);
834 return;
838 if (!toDIB)
840 /* Prepare for access to the DIB by GDI functions */
842 switch (bmp->dib->status)
844 default:
845 case DIB_NoHandler:
846 DIB_DoUpdateDIBSection( bmp, FALSE );
847 break;
849 case DIB_GdiMod:
850 TRACE( bitmap, "fromDIB called in status DIB_GdiMod\n" );
851 /* nothing to do */
852 break;
854 case DIB_InSync:
855 TRACE( bitmap, "fromDIB called in status DIB_InSync\n" );
856 /* nothing to do */
857 break;
859 case DIB_AppMod:
860 TRACE( bitmap, "fromDIB called in status DIB_AppMod\n" );
861 DIB_DoUpdateDIBSection( bmp, FALSE );
862 DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
863 bmp->dib->status = DIB_InSync;
864 break;
867 else
869 /* Acknowledge write access to the DIB by GDI functions */
871 switch (bmp->dib->status)
873 default:
874 case DIB_NoHandler:
875 DIB_DoUpdateDIBSection( bmp, TRUE );
876 break;
878 case DIB_GdiMod:
879 TRACE( bitmap, " toDIB called in status DIB_GdiMod\n" );
880 /* nothing to do */
881 break;
883 case DIB_InSync:
884 TRACE( bitmap, " toDIB called in status DIB_InSync\n" );
885 DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
886 bmp->dib->status = DIB_GdiMod;
887 break;
889 case DIB_AppMod:
890 FIXME( bitmap, " toDIB called in status DIB_AppMod: "
891 "this can't happen!\n" );
892 break;
897 GDI_HEAP_UNLOCK(dc->w.hBitmap);
900 /***********************************************************************
901 * CreateDIBSection16 (GDI.489)
903 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
904 LPVOID **bits, HANDLE32 section,
905 DWORD offset)
907 return CreateDIBSection32(hdc, bmi, usage, bits, section, offset);
910 /***********************************************************************
911 * CreateDIBSection32 (GDI32.36)
913 HBITMAP32 WINAPI CreateDIBSection32 (HDC32 hdc, BITMAPINFO *bmi, UINT32 usage,
914 LPVOID **bits,HANDLE32 section,
915 DWORD offset)
917 HBITMAP32 res = 0;
918 BITMAPOBJ *bmp = NULL;
919 DIBSECTIONOBJ *dib = NULL;
920 int *colorMap = NULL;
921 int nColorMap;
923 /* Fill BITMAP32 structure with DIB data */
924 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
925 INT32 effHeight, totalSize;
926 BITMAP32 bm;
928 TRACE(bitmap, "format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
929 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
930 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
932 bm.bmType = 0;
933 bm.bmWidth = bi->biWidth;
934 bm.bmHeight = bi->biHeight;
935 bm.bmWidthBytes = DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
936 bm.bmPlanes = bi->biPlanes;
937 bm.bmBitsPixel = bi->biBitCount;
938 bm.bmBits = NULL;
940 /* Get storage location for DIB bits */
941 effHeight = bm.bmHeight >= 0 ? bm.bmHeight : -bm.bmHeight;
942 totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
944 if (section)
945 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
946 0L, offset, totalSize);
947 else
948 bm.bmBits = VirtualAlloc(NULL, totalSize,
949 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
951 /* Create Color Map */
952 if (bm.bmBits && bm.bmBitsPixel <= 8)
954 DC *dc = hdc? (DC *)GDI_GetObjPtr(hdc, DC_MAGIC) : NULL;
955 if (hdc && !dc) dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
957 if (!hdc || dc)
958 colorMap = X11DRV_DIB_BuildColorMap( dc, usage, bm.bmBitsPixel,
959 bmi, &nColorMap );
960 GDI_HEAP_UNLOCK(hdc);
963 /* Allocate Memory for DIB and fill structure */
964 if (bm.bmBits)
965 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DIBSECTIONOBJ));
966 if (dib)
968 dib->dibSection.dsBm = bm;
969 dib->dibSection.dsBmih = *bi;
970 /* FIXME: dib->dibSection.dsBitfields ??? */
971 dib->dibSection.dshSection = section;
972 dib->dibSection.dsOffset = offset;
974 dib->status = DIB_NoHandler;
976 dib->nColorMap = nColorMap;
977 dib->colorMap = colorMap;
980 /* Create Device Dependent Bitmap and add DIB pointer */
981 if (dib)
983 res = CreateDIBitmap32(hdc, bi, 0, NULL, bmi, usage);
984 if (res)
986 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
987 if (bmp)
989 bmp->dib = dib;
990 /* HACK for now */
991 if(!bmp->DDBitmap)
992 X11DRV_CreateBitmap(res);
997 /* Create XImage */
998 if (dib && bmp)
999 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
1001 /* Clean up in case of errors */
1002 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
1004 TRACE(bitmap, "got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
1005 res, bmp, dib, bm.bmBits);
1006 if (bm.bmBits)
1008 if (section)
1009 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
1010 else
1011 VirtualFree(bm.bmBits, MEM_RELEASE, 0L), bm.bmBits = NULL;
1014 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
1015 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
1016 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
1017 if (res) { DeleteObject32(res); res = 0; }
1020 /* Install fault handler, if possible */
1021 if (bm.bmBits)
1023 if (VIRTUAL_SetFaultHandler(bm.bmBits, DIB_FaultHandler, (LPVOID)res))
1025 DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
1026 if (dib) dib->status = DIB_InSync;
1030 /* Return BITMAP handle and storage location */
1031 if (res) GDI_HEAP_UNLOCK(res);
1032 if (bm.bmBits && bits) *bits = bm.bmBits;
1033 return res;
1036 /***********************************************************************
1037 * DIB_DeleteDIBSection
1039 void DIB_DeleteDIBSection( BITMAPOBJ *bmp )
1041 if (bmp && bmp->dib)
1043 DIBSECTIONOBJ *dib = bmp->dib;
1045 if (dib->dibSection.dsBm.bmBits)
1047 if (dib->dibSection.dshSection)
1048 UnmapViewOfFile(dib->dibSection.dsBm.bmBits);
1049 else
1050 VirtualFree(dib->dibSection.dsBm.bmBits, MEM_RELEASE, 0L);
1053 if (dib->image)
1054 XDestroyImage( dib->image );
1056 if (dib->colorMap)
1057 HeapFree(GetProcessHeap(), 0, dib->colorMap);
1059 HeapFree(GetProcessHeap(), 0, dib);
1060 bmp->dib = NULL;
1064 /***********************************************************************
1065 * DIB_FixColorsToLoadflags
1067 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1068 * are in loadflags
1070 void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT32 loadflags, BYTE pix)
1072 int colors;
1073 COLORREF c_W, c_S, c_F, c_L, c_C;
1074 int incr,i;
1075 RGBQUAD *ptr;
1077 if (bmi->bmiHeader.biBitCount > 8) return;
1078 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
1079 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
1080 else {
1081 WARN(bitmap, "Wrong bitmap header size!\n");
1082 return;
1084 colors = bmi->bmiHeader.biClrUsed;
1085 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
1086 colors = 1 << bmi->bmiHeader.biBitCount;
1087 c_W = GetSysColor32(COLOR_WINDOW);
1088 c_S = GetSysColor32(COLOR_3DSHADOW);
1089 c_F = GetSysColor32(COLOR_3DFACE);
1090 c_L = GetSysColor32(COLOR_3DLIGHT);
1091 if (loadflags & LR_LOADTRANSPARENT) {
1092 switch (bmi->bmiHeader.biBitCount) {
1093 case 1: pix = pix >> 7; break;
1094 case 4: pix = pix >> 4; break;
1095 case 8: break;
1096 default:
1097 WARN(bitmap, "(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
1098 return;
1100 if (pix >= colors) {
1101 WARN(bitmap, "pixel has color index greater than biClrUsed!\n");
1102 return;
1104 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
1105 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
1106 ptr->rgbBlue = GetBValue(c_W);
1107 ptr->rgbGreen = GetGValue(c_W);
1108 ptr->rgbRed = GetRValue(c_W);
1110 if (loadflags & LR_LOADMAP3DCOLORS)
1111 for (i=0; i<colors; i++) {
1112 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
1113 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
1114 if (c_C == RGB(128, 128, 128)) {
1115 ptr->rgbRed = GetRValue(c_S);
1116 ptr->rgbGreen = GetGValue(c_S);
1117 ptr->rgbBlue = GetBValue(c_S);
1118 } else if (c_C == RGB(192, 192, 192)) {
1119 ptr->rgbRed = GetRValue(c_F);
1120 ptr->rgbGreen = GetGValue(c_F);
1121 ptr->rgbBlue = GetBValue(c_F);
1122 } else if (c_C == RGB(223, 223, 223)) {
1123 ptr->rgbRed = GetRValue(c_L);
1124 ptr->rgbGreen = GetGValue(c_L);
1125 ptr->rgbBlue = GetBValue(c_L);