2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * TODO: Still contains some references to X11DRV.
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
)
31 case 1: words
= (width
+ 31) / 32; break;
32 case 4: words
= (width
+ 7) / 8; break;
33 case 8: words
= (width
+ 3) / 4; break;
35 case 16: words
= (width
+ 1) / 2; break;
36 case 24: words
= (width
* 3 + 3)/4; break;
39 WARN(bitmap
, "(%d): Unsupported depth\n", depth
);
48 /***********************************************************************
51 * Return the size of the bitmap info structure including color table.
53 int DIB_BitmapInfoSize( BITMAPINFO
* info
, WORD coloruse
)
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 /***********************************************************************
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
;
92 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
94 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)header
;
95 *width
= core
->bcWidth
;
96 *height
= core
->bcHeight
;
97 *bpp
= core
->bcBitCount
;
101 WARN(bitmap
, "(%ld): wrong size for header\n", header
->biSize
);
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
,
136 else { /* use StretchBlt32 */
137 HBITMAP32 hBitmap
, hOldBitmap
;
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
);
156 /***********************************************************************
157 * SetDIBits16 (GDI.440)
159 INT16 WINAPI
SetDIBits16( HDC16 hdc
, HBITMAP16 hbitmap
, UINT16 startscan
,
160 UINT16 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
163 return SetDIBits32( hdc
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
167 /******************************************************************************
168 * SetDIBits32 [GDI32.312] Sets pixels in a bitmap using colors from DIB
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
180 * Success: Number of scan lines copied
183 INT32 WINAPI
SetDIBits32( HDC32 hdc
, HBITMAP32 hbitmap
, UINT32 startscan
,
184 UINT32 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
187 DIB_SETIMAGEBITS_DESCR descr
;
189 int height
, tmpheight
;
192 /* Check parameters */
194 descr
.dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
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
);
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
);
213 if (height
< 0) height
= -height
;
214 if (!lines
|| (startscan
>= height
))
216 GDI_HEAP_UNLOCK( hbitmap
);
217 GDI_HEAP_UNLOCK( hdc
);
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
);
229 GDI_HEAP_UNLOCK( hbitmap
);
230 GDI_HEAP_UNLOCK( hdc
);
238 X11DRV_CreateBitmap(hbitmap
);
240 X11DRV_PHYSBITMAP
*pbitmap
= bmp
->DDBitmap
->physBitmap
;
245 descr
.lines
= tmpheight
>= 0 ? lines
: -lines
;
246 descr
.depth
= bmp
->bitmap
.bmBitsPixel
;
247 descr
.drawable
= pbitmap
->pixmap
;
248 descr
.gc
= BITMAP_GC(bmp
);
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
);
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
,
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
,
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
,
299 FIXME(bitmap
, "unimplemented on hdc %08x\n", hdc
);
303 GDI_HEAP_UNLOCK( hdc
);
307 /***********************************************************************
308 * SetDIBColorTable16 (GDI.602)
310 UINT16 WINAPI
SetDIBColorTable16( HDC16 hdc
, UINT16 startpos
, UINT16 entries
,
313 return SetDIBColorTable32( hdc
, startpos
, entries
, colors
);
316 /***********************************************************************
317 * SetDIBColorTable32 (GDI32.311)
319 UINT32 WINAPI
SetDIBColorTable32( HDC32 hdc
, UINT32 startpos
, UINT32 entries
,
323 PALETTEENTRY
* palEntry
;
324 PALETTEOBJ
* palette
;
327 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
330 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
334 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
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
;
355 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
359 /***********************************************************************
360 * GetDIBColorTable16 (GDI.603)
362 UINT16 WINAPI
GetDIBColorTable16( HDC16 hdc
, UINT16 startpos
, UINT16 entries
,
365 return GetDIBColorTable32( hdc
, startpos
, entries
, colors
);
368 /***********************************************************************
369 * GetDIBColorTable32 (GDI32.169)
371 UINT32 WINAPI
GetDIBColorTable32( HDC32 hdc
, UINT32 startpos
, UINT32 entries
,
375 PALETTEENTRY
* palEntry
;
376 PALETTEOBJ
* palette
;
379 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
382 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
386 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
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;
408 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
412 /***********************************************************************
413 * GetDIBits16 (GDI.441)
415 INT16 WINAPI
GetDIBits16( HDC16 hdc
, HBITMAP16 hbitmap
, UINT16 startscan
,
416 UINT16 lines
, LPSTR bits
, BITMAPINFO
* info
,
419 return GetDIBits32( hdc
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
423 /******************************************************************************
424 * GetDIBits32 [GDI32.170] Retrieves bits of bitmap and copies to buffer
427 * Success: Number of scan lines copied from bitmap
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 */
443 PALETTEENTRY
* palEntry
;
444 PALETTEOBJ
* palette
;
448 if (!lines
) return 0;
449 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
452 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
455 if (!(bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
457 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
459 GDI_HEAP_UNLOCK( hbitmap
);
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
;
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
);
503 if( yend
> bmp
->bitmap
.bmHeight
) yend
= bmp
->bitmap
.bmHeight
;
505 /* adjust scanline width */
507 pad
= info
->bmiHeader
.biWidth
- bmp
->bitmap
.bmWidth
;
510 /* bitmap is wider than DIB, copy only a part */
513 xend
= info
->bmiHeader
.biWidth
;
518 X11DRV_CreateBitmap(hbitmap
);
520 EnterCriticalSection( &X11DRV_CritSection
);
521 bmpImage
= (XImage
*)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage
, bmp
);
523 switch( info
->bmiHeader
.biBitCount
)
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
);
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
++;
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
++;
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;
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;
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;
597 WARN(bitmap
,"Unsupported depth %d\n",
598 info
->bmiHeader
.biBitCount
);
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
);
627 /***********************************************************************
628 * CreateDIBitmap16 (GDI.442)
630 HBITMAP16 WINAPI
CreateDIBitmap16( HDC16 hdc
, const BITMAPINFOHEADER
* header
,
631 DWORD init
, LPCVOID bits
, const BITMAPINFO
* data
,
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
,
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
;
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)))
672 col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
673 fColor
= ((col
!= RGB(0,0,0)) && (col
!= RGB(0xff,0xff,0xff)));
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)))
684 col
= RGB( rgb
->rgbtRed
, rgb
->rgbtGreen
, rgb
->rgbtBlue
);
685 fColor
= ((col
!= RGB(0,0,0)) && (col
!= RGB(0xff,0xff,0xff)));
691 WARN(bitmap
, "(%ld): wrong size for data\n",
692 data
->bmiHeader
.biSize
);
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
);
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
;
721 VirtualProtect(dib
->dsBm
.bmBits
, totalSize
, new_prot
, &old_prot
);
722 TRACE(bitmap
, "Changed protection from %ld to %ld\n",
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)
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
;
746 descr
.drawable
= ((X11DRV_PHYSBITMAP
*)bmp
->DDBitmap
->physBitmap
)->pixmap
;
747 descr
.gc
= BITMAP_GC(bmp
);
752 descr
.width
= bmp
->bitmap
.bmWidth
;
753 descr
.height
= bmp
->bitmap
.bmHeight
;
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
);
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 /***********************************************************************
774 static BOOL32
DIB_FaultHandler( LPVOID res
, LPVOID addr
)
776 BOOL32 handled
= FALSE
;
779 bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( (HBITMAP32
)res
, BITMAP_MAGIC
);
780 if (!bmp
) return FALSE
;
783 switch (bmp
->dib
->status
)
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
;
795 TRACE( bitmap
, "called in status DIB_InSync\n" );
796 DIB_DoProtectDIBSection( bmp
, PAGE_READWRITE
);
797 bmp
->dib
->status
= DIB_AppMod
;
802 FIXME( bitmap
, "called in status DIB_AppMod: "
803 "this can't happen!\n" );
807 FIXME( bitmap
, "called in status DIB_NoHandler: "
808 "this can't happen!\n" );
812 GDI_HEAP_UNLOCK( (HBITMAP32
)res
);
816 /***********************************************************************
817 * DIB_UpdateDIBSection
819 void DIB_UpdateDIBSection( DC
*dc
, BOOL32 toDIB
)
823 /* Ensure this is a Compatible DC that has a DIB section selected */
826 if (!(dc
->w
.flags
& DC_MEMORY
)) return;
828 bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( dc
->w
.hBitmap
, BITMAP_MAGIC
);
833 GDI_HEAP_UNLOCK(dc
->w
.hBitmap
);
840 /* Prepare for access to the DIB by GDI functions */
842 switch (bmp
->dib
->status
)
846 DIB_DoUpdateDIBSection( bmp
, FALSE
);
850 TRACE( bitmap
, "fromDIB called in status DIB_GdiMod\n" );
855 TRACE( bitmap
, "fromDIB called in status DIB_InSync\n" );
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
;
869 /* Acknowledge write access to the DIB by GDI functions */
871 switch (bmp
->dib
->status
)
875 DIB_DoUpdateDIBSection( bmp
, TRUE
);
879 TRACE( bitmap
, " toDIB called in status DIB_GdiMod\n" );
884 TRACE( bitmap
, " toDIB called in status DIB_InSync\n" );
885 DIB_DoProtectDIBSection( bmp
, PAGE_NOACCESS
);
886 bmp
->dib
->status
= DIB_GdiMod
;
890 FIXME( bitmap
, " toDIB called in status DIB_AppMod: "
891 "this can't happen!\n" );
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
,
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
,
918 BITMAPOBJ
*bmp
= NULL
;
919 DIBSECTIONOBJ
*dib
= NULL
;
920 int *colorMap
= NULL
;
923 /* Fill BITMAP32 structure with DIB data */
924 BITMAPINFOHEADER
*bi
= &bmi
->bmiHeader
;
925 INT32 effHeight
, totalSize
;
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");
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
;
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
;
945 bm
.bmBits
= MapViewOfFile(section
, FILE_MAP_ALL_ACCESS
,
946 0L, offset
, totalSize
);
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
);
958 colorMap
= X11DRV_DIB_BuildColorMap( dc
, usage
, bm
.bmBitsPixel
,
960 GDI_HEAP_UNLOCK(hdc
);
963 /* Allocate Memory for DIB and fill structure */
965 dib
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DIBSECTIONOBJ
));
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 */
983 res
= CreateDIBitmap32(hdc
, bi
, 0, NULL
, bmi
, usage
);
986 bmp
= (BITMAPOBJ
*) GDI_GetObjPtr(res
, BITMAP_MAGIC
);
992 X11DRV_CreateBitmap(res
);
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
);
1009 UnmapViewOfFile(bm
.bmBits
), bm
.bmBits
= NULL
;
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 */
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
;
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
);
1050 VirtualFree(dib
->dibSection
.dsBm
.bmBits
, MEM_RELEASE
, 0L);
1054 XDestroyImage( dib
->image
);
1057 HeapFree(GetProcessHeap(), 0, dib
->colorMap
);
1059 HeapFree(GetProcessHeap(), 0, dib
);
1064 /***********************************************************************
1065 * DIB_FixColorsToLoadflags
1067 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1070 void DIB_FixColorsToLoadflags(BITMAPINFO
* bmi
, UINT32 loadflags
, BYTE pix
)
1073 COLORREF c_W
, c_S
, c_F
, c_L
, c_C
;
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;
1081 WARN(bitmap
, "Wrong bitmap header size!\n");
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;
1097 WARN(bitmap
, "(%d): Unsupported depth\n", bmi
->bmiHeader
.biBitCount
);
1100 if (pix
>= colors
) {
1101 WARN(bitmap
, "pixel has color index greater than biClrUsed!\n");
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
);