2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * TODO: Still contains some references to X11DRV.
20 /***********************************************************************
21 * DIB_GetDIBWidthBytes
23 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
24 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
26 int DIB_GetDIBWidthBytes( int width
, int depth
)
32 case 1: words
= (width
+ 31) / 32; break;
33 case 4: words
= (width
+ 7) / 8; break;
34 case 8: words
= (width
+ 3) / 4; break;
36 case 16: words
= (width
+ 1) / 2; break;
37 case 24: words
= (width
* 3 + 3)/4; break;
40 WARN(bitmap
, "(%d): Unsupported depth\n", depth
);
49 /***********************************************************************
52 * Return the size of the bitmap info structure including color table.
54 int DIB_BitmapInfoSize( BITMAPINFO
* info
, WORD coloruse
)
58 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
60 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)info
;
61 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
62 return sizeof(BITMAPCOREHEADER
) + colors
*
63 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
65 else /* assume BITMAPINFOHEADER */
67 colors
= info
->bmiHeader
.biClrUsed
;
68 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
69 colors
= 1 << info
->bmiHeader
.biBitCount
;
70 return sizeof(BITMAPINFOHEADER
) + colors
*
71 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
76 /***********************************************************************
79 * Get the info from a bitmap header.
80 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
82 int DIB_GetBitmapInfo( const BITMAPINFOHEADER
*header
, DWORD
*width
,
83 int *height
, WORD
*bpp
, WORD
*compr
)
85 if (header
->biSize
== sizeof(BITMAPINFOHEADER
))
87 *width
= header
->biWidth
;
88 *height
= header
->biHeight
;
89 *bpp
= header
->biBitCount
;
90 *compr
= header
->biCompression
;
93 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
95 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)header
;
96 *width
= core
->bcWidth
;
97 *height
= core
->bcHeight
;
98 *bpp
= core
->bcBitCount
;
102 WARN(bitmap
, "(%ld): wrong size for header\n", header
->biSize
);
107 /***********************************************************************
108 * StretchDIBits16 (GDI.439)
110 INT16 WINAPI
StretchDIBits16(HDC16 hdc
, INT16 xDst
, INT16 yDst
, INT16 widthDst
,
111 INT16 heightDst
, INT16 xSrc
, INT16 ySrc
, INT16 widthSrc
,
112 INT16 heightSrc
, const VOID
*bits
,
113 const BITMAPINFO
*info
, UINT16 wUsage
, DWORD dwRop
)
115 return (INT16
)StretchDIBits32( hdc
, xDst
, yDst
, widthDst
, heightDst
,
116 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
,
117 info
, wUsage
, dwRop
);
121 /***********************************************************************
122 * StretchDIBits32 (GDI32.351)
124 INT32 WINAPI
StretchDIBits32(HDC32 hdc
, INT32 xDst
, INT32 yDst
, INT32 widthDst
,
125 INT32 heightDst
, INT32 xSrc
, INT32 ySrc
, INT32 widthSrc
,
126 INT32 heightSrc
, const void *bits
,
127 const BITMAPINFO
*info
, UINT32 wUsage
, DWORD dwRop
)
129 DC
*dc
= DC_GetDCPtr( hdc
);
130 if(!dc
) return FALSE
;
132 if(dc
->funcs
->pStretchDIBits
)
133 return dc
->funcs
->pStretchDIBits(dc
, xDst
, yDst
, widthDst
,
134 heightDst
, xSrc
, ySrc
, widthSrc
,
135 heightSrc
, bits
, info
, wUsage
,
137 else { /* use StretchBlt32 */
138 HBITMAP32 hBitmap
, hOldBitmap
;
141 hBitmap
= CreateDIBitmap32( hdc
, &info
->bmiHeader
, CBM_INIT
,
142 bits
, info
, wUsage
);
143 hdcMem
= CreateCompatibleDC32( hdc
);
144 hOldBitmap
= SelectObject32( hdcMem
, hBitmap
);
145 StretchBlt32( hdc
, xDst
, yDst
, widthDst
, heightDst
,
146 hdcMem
, xSrc
, ySrc
, widthSrc
, heightSrc
, dwRop
);
147 SelectObject32( hdcMem
, hOldBitmap
);
148 DeleteDC32( hdcMem
);
149 DeleteObject32( hBitmap
);
155 /***********************************************************************
156 * SetDIBits16 (GDI.440)
158 INT16 WINAPI
SetDIBits16( HDC16 hdc
, HBITMAP16 hbitmap
, UINT16 startscan
,
159 UINT16 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
162 return SetDIBits32( hdc
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
166 /******************************************************************************
167 * SetDIBits32 [GDI32.312] Sets pixels in a bitmap using colors from DIB
170 * hdc [I] Handle to device context
171 * hbitmap [I] Handle to bitmap
172 * startscan [I] Starting scan line
173 * lines [I] Number of scan lines
174 * bits [I] Array of bitmap bits
175 * info [I] Address of structure with data
176 * coloruse [I] Type of color indexes to use
179 * Success: Number of scan lines copied
182 INT32 WINAPI
SetDIBits32( HDC32 hdc
, HBITMAP32 hbitmap
, UINT32 startscan
,
183 UINT32 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
186 DIB_SETIMAGEBITS_DESCR descr
;
188 int height
, tmpheight
;
191 /* Check parameters */
193 descr
.dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
196 descr
.dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
197 if (!descr
.dc
) return 0;
199 if (!(bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
201 GDI_HEAP_UNLOCK( hdc
);
204 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &descr
.infoWidth
, &height
,
205 &descr
.infoBpp
, &descr
.compression
) == -1)
207 GDI_HEAP_UNLOCK( hbitmap
);
208 GDI_HEAP_UNLOCK( hdc
);
212 if (height
< 0) height
= -height
;
213 if (!lines
|| (startscan
>= height
))
215 GDI_HEAP_UNLOCK( hbitmap
);
216 GDI_HEAP_UNLOCK( hdc
);
219 if (startscan
+ lines
> height
) lines
= height
- startscan
;
221 if (descr
.infoBpp
<= 8)
223 descr
.colorMap
= X11DRV_DIB_BuildColorMap( descr
.dc
, coloruse
,
224 bmp
->bitmap
.bmBitsPixel
,
225 info
, &descr
.nColorMap
);
228 GDI_HEAP_UNLOCK( hbitmap
);
229 GDI_HEAP_UNLOCK( hdc
);
237 X11DRV_CreateBitmap(hbitmap
);
239 X11DRV_PHYSBITMAP
*pbitmap
= bmp
->DDBitmap
->physBitmap
;
244 descr
.lines
= tmpheight
>= 0 ? lines
: -lines
;
245 descr
.depth
= bmp
->bitmap
.bmBitsPixel
;
246 descr
.drawable
= pbitmap
->pixmap
;
247 descr
.gc
= BITMAP_GC(bmp
);
251 descr
.yDest
= height
- startscan
- lines
;
252 descr
.width
= bmp
->bitmap
.bmWidth
;
253 descr
.height
= lines
;
255 EnterCriticalSection( &X11DRV_CritSection
);
256 result
= CALL_LARGE_STACK( X11DRV_DIB_SetImageBits
, &descr
);
257 LeaveCriticalSection( &X11DRV_CritSection
);
259 if (descr
.colorMap
) HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
261 GDI_HEAP_UNLOCK( hdc
);
262 GDI_HEAP_UNLOCK( hbitmap
);
267 /***********************************************************************
268 * SetDIBitsToDevice16 (GDI.443)
270 INT16 WINAPI
SetDIBitsToDevice16(HDC16 hdc
, INT16 xDest
, INT16 yDest
, INT16 cx
,
271 INT16 cy
, INT16 xSrc
, INT16 ySrc
, UINT16 startscan
,
272 UINT16 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
275 return SetDIBitsToDevice32( hdc
, xDest
, yDest
, cx
, cy
, xSrc
, ySrc
,
276 startscan
, lines
, bits
, info
, coloruse
);
280 /***********************************************************************
281 * SetDIBitsToDevice32 (GDI32.313)
283 INT32 WINAPI
SetDIBitsToDevice32(HDC32 hdc
, INT32 xDest
, INT32 yDest
, DWORD cx
,
284 DWORD cy
, INT32 xSrc
, INT32 ySrc
, UINT32 startscan
,
285 UINT32 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
291 if (!(dc
= DC_GetDCPtr( hdc
))) return 0;
293 if(dc
->funcs
->pSetDIBitsToDevice
)
294 ret
= dc
->funcs
->pSetDIBitsToDevice( dc
, xDest
, yDest
, cx
, cy
, xSrc
,
295 ySrc
, startscan
, lines
, bits
,
298 FIXME(bitmap
, "unimplemented on hdc %08x\n", hdc
);
302 GDI_HEAP_UNLOCK( hdc
);
306 /***********************************************************************
307 * SetDIBColorTable16 (GDI.602)
309 UINT16 WINAPI
SetDIBColorTable16( HDC16 hdc
, UINT16 startpos
, UINT16 entries
,
312 return SetDIBColorTable32( hdc
, startpos
, entries
, colors
);
315 /***********************************************************************
316 * SetDIBColorTable32 (GDI32.311)
318 UINT32 WINAPI
SetDIBColorTable32( HDC32 hdc
, UINT32 startpos
, UINT32 entries
,
322 PALETTEENTRY
* palEntry
;
323 PALETTEOBJ
* palette
;
326 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
329 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
333 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
338 /* Transfer color info */
340 if (dc
->w
.bitsPerPixel
<= 8) {
341 palEntry
= palette
->logpalette
.palPalEntry
+ startpos
;
342 if (startpos
+ entries
> (1 << dc
->w
.bitsPerPixel
)) {
343 entries
= (1 << dc
->w
.bitsPerPixel
) - startpos
;
345 for (end
= colors
+ entries
; colors
< end
; palEntry
++, colors
++)
347 palEntry
->peRed
= colors
->rgbRed
;
348 palEntry
->peGreen
= colors
->rgbGreen
;
349 palEntry
->peBlue
= colors
->rgbBlue
;
354 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
358 /***********************************************************************
359 * GetDIBColorTable16 (GDI.603)
361 UINT16 WINAPI
GetDIBColorTable16( HDC16 hdc
, UINT16 startpos
, UINT16 entries
,
364 return GetDIBColorTable32( hdc
, startpos
, entries
, colors
);
367 /***********************************************************************
368 * GetDIBColorTable32 (GDI32.169)
370 UINT32 WINAPI
GetDIBColorTable32( HDC32 hdc
, UINT32 startpos
, UINT32 entries
,
374 PALETTEENTRY
* palEntry
;
375 PALETTEOBJ
* palette
;
378 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
381 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
385 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
390 /* Transfer color info */
392 if (dc
->w
.bitsPerPixel
<= 8) {
393 palEntry
= palette
->logpalette
.palPalEntry
+ startpos
;
394 if (startpos
+ entries
> (1 << dc
->w
.bitsPerPixel
)) {
395 entries
= (1 << dc
->w
.bitsPerPixel
) - startpos
;
397 for (end
= colors
+ entries
; colors
< end
; palEntry
++, colors
++)
399 colors
->rgbRed
= palEntry
->peRed
;
400 colors
->rgbGreen
= palEntry
->peGreen
;
401 colors
->rgbBlue
= palEntry
->peBlue
;
402 colors
->rgbReserved
= 0;
407 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
411 /***********************************************************************
412 * GetDIBits16 (GDI.441)
414 INT16 WINAPI
GetDIBits16( HDC16 hdc
, HBITMAP16 hbitmap
, UINT16 startscan
,
415 UINT16 lines
, LPSTR bits
, BITMAPINFO
* info
,
418 return GetDIBits32( hdc
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
422 /******************************************************************************
423 * GetDIBits32 [GDI32.170] Retrieves bits of bitmap and copies to buffer
426 * Success: Number of scan lines copied from bitmap
429 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
431 INT32 WINAPI
GetDIBits32(
432 HDC32 hdc
, /* [in] Handle to device context */
433 HBITMAP32 hbitmap
, /* [in] Handle to bitmap */
434 UINT32 startscan
, /* [in] First scan line to set in dest bitmap */
435 UINT32 lines
, /* [in] Number of scan lines to copy */
436 LPSTR bits
, /* [out] Address of array for bitmap bits */
437 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
438 UINT32 coloruse
) /* [in] RGB or palette index */
442 PALETTEENTRY
* palEntry
;
443 PALETTEOBJ
* palette
;
447 if (!lines
) return 0;
448 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
451 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
454 if (!(bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
456 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
458 GDI_HEAP_UNLOCK( hbitmap
);
462 /* Transfer color info */
464 if (info
->bmiHeader
.biBitCount
<=8) {
465 int colors
= info
->bmiHeader
.biClrUsed
;
466 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
467 colors
= 1 << info
->bmiHeader
.biBitCount
;
468 palEntry
= palette
->logpalette
.palPalEntry
;
469 for (i
= 0; i
< colors
; i
++, palEntry
++)
471 if (coloruse
== DIB_RGB_COLORS
)
473 info
->bmiColors
[i
].rgbRed
= palEntry
->peRed
;
474 info
->bmiColors
[i
].rgbGreen
= palEntry
->peGreen
;
475 info
->bmiColors
[i
].rgbBlue
= palEntry
->peBlue
;
476 info
->bmiColors
[i
].rgbReserved
= 0;
478 else ((WORD
*)info
->bmiColors
)[i
] = (WORD
)i
;
485 int pad
, yend
, xend
= bmp
->bitmap
.bmWidth
;
487 TRACE(bitmap
, "%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
488 lines
, bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmHeight
,
489 (int)info
->bmiHeader
.biWidth
, (int)info
->bmiHeader
.biHeight
, startscan
);
491 /* adjust number of scanlines to copy */
493 if( lines
> info
->bmiHeader
.biHeight
) lines
= info
->bmiHeader
.biHeight
;
494 yend
= startscan
+ lines
;
495 if( startscan
>= bmp
->bitmap
.bmHeight
)
497 GDI_HEAP_UNLOCK( hbitmap
);
498 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
501 if( yend
> bmp
->bitmap
.bmHeight
) yend
= bmp
->bitmap
.bmHeight
;
503 /* adjust scanline width */
505 pad
= info
->bmiHeader
.biWidth
- bmp
->bitmap
.bmWidth
;
508 /* bitmap is wider than DIB, copy only a part */
511 xend
= info
->bmiHeader
.biWidth
;
516 X11DRV_CreateBitmap(hbitmap
);
518 EnterCriticalSection( &X11DRV_CritSection
);
519 bmpImage
= (XImage
*)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage
, bmp
);
521 switch( info
->bmiHeader
.biBitCount
)
524 /* pad up to 32 bit */
525 pad
+= (4 - (info
->bmiHeader
.biWidth
& 3)) & 3;
526 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
528 for( x
= 0; x
< xend
; x
++ )
529 *bbits
++ = XGetPixel( bmpImage
, x
, y
);
534 pad
+= ((32 - (info
->bmiHeader
.biWidth
& 31)) / 8) & 3;
535 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
537 for( x
= 0; x
< xend
; x
++ ) {
538 if (!(x
&7)) *bbits
= 0;
539 *bbits
|= XGetPixel( bmpImage
, x
, y
)<<(7-(x
&7));
540 if ((x
&7)==7) bbits
++;
546 pad
+= ((8 - (info
->bmiHeader
.biWidth
& 7)) / 2) & 3;
547 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
549 for( x
= 0; x
< xend
; x
++ ) {
550 if (!(x
&1)) *bbits
= 0;
551 *bbits
|= XGetPixel( bmpImage
, x
, y
)<<(4*(1-(x
&1)));
552 if ((x
&1)==1) bbits
++;
559 pad
+= (4 - ((info
->bmiHeader
.biWidth
*2) & 3)) & 3;
560 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
562 for( x
= 0; x
< xend
; x
++ ) {
563 unsigned long pixel
=XGetPixel( bmpImage
, x
, y
);
564 *bbits
++ = pixel
& 0xff;
565 *bbits
++ = (pixel
>> 8) & 0xff;
571 pad
+= (4 - ((info
->bmiHeader
.biWidth
*3) & 3)) & 3;
572 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
574 for( x
= 0; x
< xend
; x
++ ) {
575 unsigned long pixel
=XGetPixel( bmpImage
, x
, y
);
576 *bbits
++ = (pixel
>>16) & 0xff;
577 *bbits
++ = (pixel
>> 8) & 0xff;
578 *bbits
++ = pixel
& 0xff;
584 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
586 for( x
= 0; x
< xend
; x
++ ) {
587 unsigned long pixel
=XGetPixel( bmpImage
, x
, y
);
588 *bbits
++ = (pixel
>>16) & 0xff;
589 *bbits
++ = (pixel
>> 8) & 0xff;
590 *bbits
++ = pixel
& 0xff;
595 WARN(bitmap
,"Unsupported depth %d\n",
596 info
->bmiHeader
.biBitCount
);
600 XDestroyImage( bmpImage
);
601 LeaveCriticalSection( &X11DRV_CritSection
);
603 info
->bmiHeader
.biCompression
= 0;
605 else if( info
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
607 /* fill in struct members */
609 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
610 info
->bmiHeader
.biHeight
= bmp
->bitmap
.bmHeight
;
611 info
->bmiHeader
.biPlanes
= 1;
612 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
613 info
->bmiHeader
.biSizeImage
= bmp
->bitmap
.bmHeight
*
614 DIB_GetDIBWidthBytes( bmp
->bitmap
.bmWidth
,
615 bmp
->bitmap
.bmBitsPixel
);
616 info
->bmiHeader
.biCompression
= 0;
619 GDI_HEAP_UNLOCK( hbitmap
);
620 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
625 /***********************************************************************
626 * CreateDIBitmap16 (GDI.442)
628 HBITMAP16 WINAPI
CreateDIBitmap16( HDC16 hdc
, const BITMAPINFOHEADER
* header
,
629 DWORD init
, LPCVOID bits
, const BITMAPINFO
* data
,
632 return CreateDIBitmap32( hdc
, header
, init
, bits
, data
, coloruse
);
636 /***********************************************************************
637 * CreateDIBitmap32 (GDI32.37)
639 HBITMAP32 WINAPI
CreateDIBitmap32( HDC32 hdc
, const BITMAPINFOHEADER
*header
,
640 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
650 if (DIB_GetBitmapInfo( header
, &width
, &height
, &bpp
, &compr
) == -1) return 0;
651 if (height
< 0) height
= -height
;
653 /* Check if we should create a monochrome or color bitmap. */
654 /* We create a monochrome bitmap only if it has exactly 2 */
655 /* colors, which are either black or white, nothing else. */
656 /* In all other cases, we create a color bitmap. */
658 if (bpp
!= 1) fColor
= TRUE
;
659 else if ((coloruse
!= DIB_RGB_COLORS
) ||
660 (init
!= CBM_INIT
) || !data
) fColor
= FALSE
;
663 if (data
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
665 RGBQUAD
*rgb
= data
->bmiColors
;
666 DWORD col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
667 if ((col
== RGB(0,0,0)) || (col
== RGB(0xff,0xff,0xff)))
670 col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
671 fColor
= ((col
!= RGB(0,0,0)) && (col
!= RGB(0xff,0xff,0xff)));
675 else if (data
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
677 RGBTRIPLE
*rgb
= ((BITMAPCOREINFO
*)data
)->bmciColors
;
678 DWORD col
= RGB( rgb
->rgbtRed
, rgb
->rgbtGreen
, rgb
->rgbtBlue
);
679 if ((col
== RGB(0,0,0)) || (col
== RGB(0xff,0xff,0xff)))
682 col
= RGB( rgb
->rgbtRed
, rgb
->rgbtGreen
, rgb
->rgbtBlue
);
683 fColor
= ((col
!= RGB(0,0,0)) && (col
!= RGB(0xff,0xff,0xff)));
689 WARN(bitmap
, "(%ld): wrong size for data\n",
690 data
->bmiHeader
.biSize
);
695 /* Now create the bitmap */
697 handle
= fColor
? CreateBitmap32( width
, height
, 1, screenDepth
, NULL
) :
698 CreateBitmap32( width
, height
, 1, 1, NULL
);
699 if (!handle
) return 0;
701 if (init
== CBM_INIT
)
702 SetDIBits32( hdc
, handle
, 0, height
, bits
, data
, coloruse
);
707 /***********************************************************************
708 * DIB_DoProtectDIBSection
710 static void DIB_DoProtectDIBSection( BITMAPOBJ
*bmp
, DWORD new_prot
)
712 DIBSECTION
*dib
= &bmp
->dib
->dibSection
;
713 INT32 effHeight
= dib
->dsBm
.bmHeight
>= 0? dib
->dsBm
.bmHeight
714 : -dib
->dsBm
.bmHeight
;
715 INT32 totalSize
= dib
->dsBmih
.biSizeImage
? dib
->dsBmih
.biSizeImage
716 : dib
->dsBm
.bmWidthBytes
* effHeight
;
719 VirtualProtect(dib
->dsBm
.bmBits
, totalSize
, new_prot
, &old_prot
);
720 TRACE(bitmap
, "Changed protection from %ld to %ld\n",
724 /***********************************************************************
725 * DIB_DoUpdateDIBSection
727 static void DIB_DoUpdateDIBSection( BITMAPOBJ
*bmp
, BOOL32 toDIB
)
729 DIBSECTIONOBJ
*dib
= bmp
->dib
;
730 DIB_SETIMAGEBITS_DESCR descr
;
732 if (DIB_GetBitmapInfo( &dib
->dibSection
.dsBmih
, &descr
.infoWidth
, &descr
.lines
,
733 &descr
.infoBpp
, &descr
.compression
) == -1)
737 descr
.image
= dib
->image
;
738 descr
.colorMap
= dib
->colorMap
;
739 descr
.nColorMap
= dib
->nColorMap
;
740 descr
.bits
= dib
->dibSection
.dsBm
.bmBits
;
741 descr
.depth
= bmp
->bitmap
.bmBitsPixel
;
744 descr
.drawable
= ((X11DRV_PHYSBITMAP
*)bmp
->DDBitmap
->physBitmap
)->pixmap
;
745 descr
.gc
= BITMAP_GC(bmp
);
750 descr
.width
= bmp
->bitmap
.bmWidth
;
751 descr
.height
= bmp
->bitmap
.bmHeight
;
755 TRACE(bitmap
, "Copying from Pixmap to DIB bits\n");
756 EnterCriticalSection( &X11DRV_CritSection
);
757 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits
, &descr
);
758 LeaveCriticalSection( &X11DRV_CritSection
);
762 TRACE(bitmap
, "Copying from DIB bits to Pixmap\n");
763 EnterCriticalSection( &X11DRV_CritSection
);
764 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits
, &descr
);
765 LeaveCriticalSection( &X11DRV_CritSection
);
769 /***********************************************************************
772 static BOOL32
DIB_FaultHandler( LPVOID res
, LPVOID addr
)
774 BOOL32 handled
= FALSE
;
777 bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( (HBITMAP32
)res
, BITMAP_MAGIC
);
778 if (!bmp
) return FALSE
;
781 switch (bmp
->dib
->status
)
784 TRACE( bitmap
, "called in status DIB_GdiMod\n" );
785 DIB_DoProtectDIBSection( bmp
, PAGE_READWRITE
);
786 DIB_DoUpdateDIBSection( bmp
, TRUE
);
787 DIB_DoProtectDIBSection( bmp
, PAGE_READONLY
);
788 bmp
->dib
->status
= DIB_InSync
;
793 TRACE( bitmap
, "called in status DIB_InSync\n" );
794 DIB_DoProtectDIBSection( bmp
, PAGE_READWRITE
);
795 bmp
->dib
->status
= DIB_AppMod
;
800 FIXME( bitmap
, "called in status DIB_AppMod: "
801 "this can't happen!\n" );
805 FIXME( bitmap
, "called in status DIB_NoHandler: "
806 "this can't happen!\n" );
810 GDI_HEAP_UNLOCK( (HBITMAP32
)res
);
814 /***********************************************************************
815 * DIB_UpdateDIBSection
817 void DIB_UpdateDIBSection( DC
*dc
, BOOL32 toDIB
)
821 /* Ensure this is a Compatible DC that has a DIB section selected */
824 if (!(dc
->w
.flags
& DC_MEMORY
)) return;
826 bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( dc
->w
.hBitmap
, BITMAP_MAGIC
);
831 GDI_HEAP_UNLOCK(dc
->w
.hBitmap
);
838 /* Prepare for access to the DIB by GDI functions */
840 switch (bmp
->dib
->status
)
844 DIB_DoUpdateDIBSection( bmp
, FALSE
);
848 TRACE( bitmap
, "fromDIB called in status DIB_GdiMod\n" );
853 TRACE( bitmap
, "fromDIB called in status DIB_InSync\n" );
858 TRACE( bitmap
, "fromDIB called in status DIB_AppMod\n" );
859 DIB_DoUpdateDIBSection( bmp
, FALSE
);
860 DIB_DoProtectDIBSection( bmp
, PAGE_READONLY
);
861 bmp
->dib
->status
= DIB_InSync
;
867 /* Acknowledge write access to the DIB by GDI functions */
869 switch (bmp
->dib
->status
)
873 DIB_DoUpdateDIBSection( bmp
, TRUE
);
877 TRACE( bitmap
, " toDIB called in status DIB_GdiMod\n" );
882 TRACE( bitmap
, " toDIB called in status DIB_InSync\n" );
883 DIB_DoProtectDIBSection( bmp
, PAGE_NOACCESS
);
884 bmp
->dib
->status
= DIB_GdiMod
;
888 FIXME( bitmap
, " toDIB called in status DIB_AppMod: "
889 "this can't happen!\n" );
895 GDI_HEAP_UNLOCK(dc
->w
.hBitmap
);
898 /***********************************************************************
899 * CreateDIBSection16 (GDI.489)
901 HBITMAP16 WINAPI
CreateDIBSection16 (HDC16 hdc
, BITMAPINFO
*bmi
, UINT16 usage
,
902 LPVOID
**bits
, HANDLE32 section
,
905 return CreateDIBSection32(hdc
, bmi
, usage
, bits
, section
, offset
);
908 /***********************************************************************
909 * CreateDIBSection32 (GDI32.36)
911 HBITMAP32 WINAPI
CreateDIBSection32 (HDC32 hdc
, BITMAPINFO
*bmi
, UINT32 usage
,
912 LPVOID
**bits
,HANDLE32 section
,
916 BITMAPOBJ
*bmp
= NULL
;
917 DIBSECTIONOBJ
*dib
= NULL
;
918 int *colorMap
= NULL
;
921 /* Fill BITMAP32 structure with DIB data */
922 BITMAPINFOHEADER
*bi
= &bmi
->bmiHeader
;
923 INT32 effHeight
, totalSize
;
926 TRACE(bitmap
, "format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
927 bi
->biWidth
, bi
->biHeight
, bi
->biPlanes
, bi
->biBitCount
,
928 bi
->biSizeImage
, bi
->biClrUsed
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
931 bm
.bmWidth
= bi
->biWidth
;
932 bm
.bmHeight
= bi
->biHeight
;
933 bm
.bmWidthBytes
= DIB_GetDIBWidthBytes(bm
.bmWidth
, bi
->biBitCount
);
934 bm
.bmPlanes
= bi
->biPlanes
;
935 bm
.bmBitsPixel
= bi
->biBitCount
;
938 /* Get storage location for DIB bits */
939 effHeight
= bm
.bmHeight
>= 0 ? bm
.bmHeight
: -bm
.bmHeight
;
940 totalSize
= bi
->biSizeImage
? bi
->biSizeImage
: bm
.bmWidthBytes
* effHeight
;
943 bm
.bmBits
= MapViewOfFile(section
, FILE_MAP_ALL_ACCESS
,
944 0L, offset
, totalSize
);
946 bm
.bmBits
= VirtualAlloc(NULL
, totalSize
,
947 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
949 /* Create Color Map */
950 if (bm
.bmBits
&& bm
.bmBitsPixel
<= 8)
952 DC
*dc
= hdc
? (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
) : NULL
;
953 if (hdc
&& !dc
) dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
956 colorMap
= X11DRV_DIB_BuildColorMap( dc
, usage
, bm
.bmBitsPixel
,
958 GDI_HEAP_UNLOCK(hdc
);
961 /* Allocate Memory for DIB and fill structure */
963 dib
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DIBSECTIONOBJ
));
966 dib
->dibSection
.dsBm
= bm
;
967 dib
->dibSection
.dsBmih
= *bi
;
968 /* FIXME: dib->dibSection.dsBitfields ??? */
969 dib
->dibSection
.dshSection
= section
;
970 dib
->dibSection
.dsOffset
= offset
;
972 dib
->status
= DIB_NoHandler
;
974 dib
->nColorMap
= nColorMap
;
975 dib
->colorMap
= colorMap
;
978 /* Create Device Dependent Bitmap and add DIB pointer */
981 res
= CreateDIBitmap32(hdc
, bi
, 0, NULL
, bmi
, usage
);
984 bmp
= (BITMAPOBJ
*) GDI_GetObjPtr(res
, BITMAP_MAGIC
);
990 X11DRV_CreateBitmap(res
);
997 XCREATEIMAGE( dib
->image
, bm
.bmWidth
, effHeight
, bmp
->bitmap
.bmBitsPixel
);
999 /* Clean up in case of errors */
1000 if (!res
|| !bmp
|| !dib
|| !bm
.bmBits
|| (bm
.bmBitsPixel
<= 8 && !colorMap
))
1002 TRACE(bitmap
, "got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
1003 res
, bmp
, dib
, bm
.bmBits
);
1007 UnmapViewOfFile(bm
.bmBits
), bm
.bmBits
= NULL
;
1009 VirtualFree(bm
.bmBits
, MEM_RELEASE
, 0L), bm
.bmBits
= NULL
;
1012 if (dib
&& dib
->image
) { XDestroyImage(dib
->image
); dib
->image
= NULL
; }
1013 if (colorMap
) { HeapFree(GetProcessHeap(), 0, colorMap
); colorMap
= NULL
; }
1014 if (dib
) { HeapFree(GetProcessHeap(), 0, dib
); dib
= NULL
; }
1015 if (res
) { DeleteObject32(res
); res
= 0; }
1018 /* Install fault handler, if possible */
1021 if (VIRTUAL_SetFaultHandler(bm
.bmBits
, DIB_FaultHandler
, (LPVOID
)res
))
1023 DIB_DoProtectDIBSection( bmp
, PAGE_READONLY
);
1024 if (dib
) dib
->status
= DIB_InSync
;
1028 /* Return BITMAP handle and storage location */
1029 if (res
) GDI_HEAP_UNLOCK(res
);
1030 if (bm
.bmBits
&& bits
) *bits
= bm
.bmBits
;
1034 /***********************************************************************
1035 * DIB_DeleteDIBSection
1037 void DIB_DeleteDIBSection( BITMAPOBJ
*bmp
)
1039 if (bmp
&& bmp
->dib
)
1041 DIBSECTIONOBJ
*dib
= bmp
->dib
;
1043 if (dib
->dibSection
.dsBm
.bmBits
)
1045 if (dib
->dibSection
.dshSection
)
1046 UnmapViewOfFile(dib
->dibSection
.dsBm
.bmBits
);
1048 VirtualFree(dib
->dibSection
.dsBm
.bmBits
, MEM_RELEASE
, 0L);
1052 XDestroyImage( dib
->image
);
1055 HeapFree(GetProcessHeap(), 0, dib
->colorMap
);
1057 HeapFree(GetProcessHeap(), 0, dib
);
1062 /***********************************************************************
1063 * DIB_FixColorsToLoadflags
1065 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1068 void DIB_FixColorsToLoadflags(BITMAPINFO
* bmi
, UINT32 loadflags
, BYTE pix
)
1071 COLORREF c_W
, c_S
, c_F
, c_L
, c_C
;
1075 if (bmi
->bmiHeader
.biBitCount
> 8) return;
1076 if (bmi
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
)) incr
= 4;
1077 else if (bmi
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
)) incr
= 3;
1079 WARN(bitmap
, "Wrong bitmap header size!\n");
1082 colors
= bmi
->bmiHeader
.biClrUsed
;
1083 if (!colors
&& (bmi
->bmiHeader
.biBitCount
<= 8))
1084 colors
= 1 << bmi
->bmiHeader
.biBitCount
;
1085 c_W
= GetSysColor32(COLOR_WINDOW
);
1086 c_S
= GetSysColor32(COLOR_3DSHADOW
);
1087 c_F
= GetSysColor32(COLOR_3DFACE
);
1088 c_L
= GetSysColor32(COLOR_3DLIGHT
);
1089 if (loadflags
& LR_LOADTRANSPARENT
) {
1090 switch (bmi
->bmiHeader
.biBitCount
) {
1091 case 1: pix
= pix
>> 7; break;
1092 case 4: pix
= pix
>> 4; break;
1095 WARN(bitmap
, "(%d): Unsupported depth\n", bmi
->bmiHeader
.biBitCount
);
1098 if (pix
>= colors
) {
1099 WARN(bitmap
, "pixel has color index greater than biClrUsed!\n");
1102 if (loadflags
& LR_LOADMAP3DCOLORS
) c_W
= c_F
;
1103 ptr
= (RGBQUAD
*)((char*)bmi
->bmiColors
+pix
*incr
);
1104 ptr
->rgbBlue
= GetBValue(c_W
);
1105 ptr
->rgbGreen
= GetGValue(c_W
);
1106 ptr
->rgbRed
= GetRValue(c_W
);
1108 if (loadflags
& LR_LOADMAP3DCOLORS
)
1109 for (i
=0; i
<colors
; i
++) {
1110 ptr
= (RGBQUAD
*)((char*)bmi
->bmiColors
+i
*incr
);
1111 c_C
= RGB(ptr
->rgbRed
, ptr
->rgbGreen
, ptr
->rgbBlue
);
1112 if (c_C
== RGB(128, 128, 128)) {
1113 ptr
->rgbRed
= GetRValue(c_S
);
1114 ptr
->rgbGreen
= GetGValue(c_S
);
1115 ptr
->rgbBlue
= GetBValue(c_S
);
1116 } else if (c_C
== RGB(192, 192, 192)) {
1117 ptr
->rgbRed
= GetRValue(c_F
);
1118 ptr
->rgbGreen
= GetGValue(c_F
);
1119 ptr
->rgbBlue
= GetBValue(c_F
);
1120 } else if (c_C
== RGB(223, 223, 223)) {
1121 ptr
->rgbRed
= GetRValue(c_L
);
1122 ptr
->rgbGreen
= GetGValue(c_L
);
1123 ptr
->rgbBlue
= GetBValue(c_L
);