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 /* Origin for DIBitmap is bottom left ! */
146 StretchBlt32( hdc
, xDst
, yDst
, widthDst
, heightDst
,
147 hdcMem
, xSrc
, info
->bmiHeader
.biHeight
- heightSrc
- ySrc
,
148 widthSrc
, heightSrc
, dwRop
);
149 SelectObject32( hdcMem
, hOldBitmap
);
150 DeleteDC32( hdcMem
);
151 DeleteObject32( hBitmap
);
157 /***********************************************************************
158 * SetDIBits16 (GDI.440)
160 INT16 WINAPI
SetDIBits16( HDC16 hdc
, HBITMAP16 hbitmap
, UINT16 startscan
,
161 UINT16 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
164 return SetDIBits32( hdc
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
168 /******************************************************************************
169 * SetDIBits32 [GDI32.312] Sets pixels in a bitmap using colors from DIB
172 * hdc [I] Handle to device context
173 * hbitmap [I] Handle to bitmap
174 * startscan [I] Starting scan line
175 * lines [I] Number of scan lines
176 * bits [I] Array of bitmap bits
177 * info [I] Address of structure with data
178 * coloruse [I] Type of color indexes to use
181 * Success: Number of scan lines copied
184 INT32 WINAPI
SetDIBits32( HDC32 hdc
, HBITMAP32 hbitmap
, UINT32 startscan
,
185 UINT32 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
188 DIB_SETIMAGEBITS_DESCR descr
;
190 int height
, tmpheight
;
193 /* Check parameters */
195 descr
.dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
198 descr
.dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
199 if (!descr
.dc
) return 0;
201 if (!(bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
203 GDI_HEAP_UNLOCK( hdc
);
206 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &descr
.infoWidth
, &height
,
207 &descr
.infoBpp
, &descr
.compression
) == -1)
209 GDI_HEAP_UNLOCK( hbitmap
);
210 GDI_HEAP_UNLOCK( hdc
);
214 if (height
< 0) height
= -height
;
215 if (!lines
|| (startscan
>= height
))
217 GDI_HEAP_UNLOCK( hbitmap
);
218 GDI_HEAP_UNLOCK( hdc
);
221 if (startscan
+ lines
> height
) lines
= height
- startscan
;
223 if (descr
.infoBpp
<= 8)
225 descr
.colorMap
= X11DRV_DIB_BuildColorMap( descr
.dc
, coloruse
,
226 bmp
->bitmap
.bmBitsPixel
,
227 info
, &descr
.nColorMap
);
230 GDI_HEAP_UNLOCK( hbitmap
);
231 GDI_HEAP_UNLOCK( hdc
);
239 X11DRV_CreateBitmap(hbitmap
);
241 X11DRV_PHYSBITMAP
*pbitmap
= bmp
->DDBitmap
->physBitmap
;
246 descr
.lines
= tmpheight
>= 0 ? lines
: -lines
;
247 descr
.depth
= bmp
->bitmap
.bmBitsPixel
;
248 descr
.drawable
= pbitmap
->pixmap
;
249 descr
.gc
= BITMAP_GC(bmp
);
253 descr
.yDest
= height
- startscan
- lines
;
254 descr
.width
= bmp
->bitmap
.bmWidth
;
255 descr
.height
= lines
;
257 EnterCriticalSection( &X11DRV_CritSection
);
258 result
= CALL_LARGE_STACK( X11DRV_DIB_SetImageBits
, &descr
);
259 LeaveCriticalSection( &X11DRV_CritSection
);
261 if (descr
.colorMap
) HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
263 GDI_HEAP_UNLOCK( hdc
);
264 GDI_HEAP_UNLOCK( hbitmap
);
269 /***********************************************************************
270 * SetDIBitsToDevice16 (GDI.443)
272 INT16 WINAPI
SetDIBitsToDevice16(HDC16 hdc
, INT16 xDest
, INT16 yDest
, INT16 cx
,
273 INT16 cy
, INT16 xSrc
, INT16 ySrc
, UINT16 startscan
,
274 UINT16 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
277 return SetDIBitsToDevice32( hdc
, xDest
, yDest
, cx
, cy
, xSrc
, ySrc
,
278 startscan
, lines
, bits
, info
, coloruse
);
282 /***********************************************************************
283 * SetDIBitsToDevice32 (GDI32.313)
285 INT32 WINAPI
SetDIBitsToDevice32(HDC32 hdc
, INT32 xDest
, INT32 yDest
, DWORD cx
,
286 DWORD cy
, INT32 xSrc
, INT32 ySrc
, UINT32 startscan
,
287 UINT32 lines
, LPCVOID bits
, const BITMAPINFO
*info
,
293 if (!(dc
= DC_GetDCPtr( hdc
))) return 0;
295 if(dc
->funcs
->pSetDIBitsToDevice
)
296 ret
= dc
->funcs
->pSetDIBitsToDevice( dc
, xDest
, yDest
, cx
, cy
, xSrc
,
297 ySrc
, startscan
, lines
, bits
,
300 FIXME(bitmap
, "unimplemented on hdc %08x\n", hdc
);
304 GDI_HEAP_UNLOCK( hdc
);
308 /***********************************************************************
309 * SetDIBColorTable16 (GDI.602)
311 UINT16 WINAPI
SetDIBColorTable16( HDC16 hdc
, UINT16 startpos
, UINT16 entries
,
314 return SetDIBColorTable32( hdc
, startpos
, entries
, colors
);
317 /***********************************************************************
318 * SetDIBColorTable32 (GDI32.311)
320 UINT32 WINAPI
SetDIBColorTable32( HDC32 hdc
, UINT32 startpos
, UINT32 entries
,
324 PALETTEENTRY
* palEntry
;
325 PALETTEOBJ
* palette
;
328 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
331 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
335 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
340 /* Transfer color info */
342 if (dc
->w
.bitsPerPixel
<= 8) {
343 palEntry
= palette
->logpalette
.palPalEntry
+ startpos
;
344 if (startpos
+ entries
> (1 << dc
->w
.bitsPerPixel
)) {
345 entries
= (1 << dc
->w
.bitsPerPixel
) - startpos
;
347 for (end
= colors
+ entries
; colors
< end
; palEntry
++, colors
++)
349 palEntry
->peRed
= colors
->rgbRed
;
350 palEntry
->peGreen
= colors
->rgbGreen
;
351 palEntry
->peBlue
= colors
->rgbBlue
;
356 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
360 /***********************************************************************
361 * GetDIBColorTable16 (GDI.603)
363 UINT16 WINAPI
GetDIBColorTable16( HDC16 hdc
, UINT16 startpos
, UINT16 entries
,
366 return GetDIBColorTable32( hdc
, startpos
, entries
, colors
);
369 /***********************************************************************
370 * GetDIBColorTable32 (GDI32.169)
372 UINT32 WINAPI
GetDIBColorTable32( HDC32 hdc
, UINT32 startpos
, UINT32 entries
,
376 PALETTEENTRY
* palEntry
;
377 PALETTEOBJ
* palette
;
380 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
383 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
387 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
392 /* Transfer color info */
394 if (dc
->w
.bitsPerPixel
<= 8) {
395 palEntry
= palette
->logpalette
.palPalEntry
+ startpos
;
396 if (startpos
+ entries
> (1 << dc
->w
.bitsPerPixel
)) {
397 entries
= (1 << dc
->w
.bitsPerPixel
) - startpos
;
399 for (end
= colors
+ entries
; colors
< end
; palEntry
++, colors
++)
401 colors
->rgbRed
= palEntry
->peRed
;
402 colors
->rgbGreen
= palEntry
->peGreen
;
403 colors
->rgbBlue
= palEntry
->peBlue
;
404 colors
->rgbReserved
= 0;
409 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
413 /***********************************************************************
414 * GetDIBits16 (GDI.441)
416 INT16 WINAPI
GetDIBits16( HDC16 hdc
, HBITMAP16 hbitmap
, UINT16 startscan
,
417 UINT16 lines
, LPSTR bits
, BITMAPINFO
* info
,
420 return GetDIBits32( hdc
, hbitmap
, startscan
, lines
, bits
, info
, coloruse
);
424 /******************************************************************************
425 * GetDIBits32 [GDI32.170] Retrieves bits of bitmap and copies to buffer
428 * Success: Number of scan lines copied from bitmap
431 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
433 INT32 WINAPI
GetDIBits32(
434 HDC32 hdc
, /* [in] Handle to device context */
435 HBITMAP32 hbitmap
, /* [in] Handle to bitmap */
436 UINT32 startscan
, /* [in] First scan line to set in dest bitmap */
437 UINT32 lines
, /* [in] Number of scan lines to copy */
438 LPSTR bits
, /* [out] Address of array for bitmap bits */
439 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
440 UINT32 coloruse
) /* [in] RGB or palette index */
444 PALETTEENTRY
* palEntry
;
445 PALETTEOBJ
* palette
;
449 if (!lines
) return 0;
450 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
453 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
456 if (!(bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
458 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->w
.hPalette
, PALETTE_MAGIC
)))
460 GDI_HEAP_UNLOCK( hbitmap
);
464 /* Transfer color info (FIXME) */
466 if (info
&& (info
->bmiHeader
.biBitCount
<= 8) &&
467 (bmp
->bitmap
.bmBitsPixel
<= 8))
469 int colors
= 1 << info
->bmiHeader
.biBitCount
;
470 info
->bmiHeader
.biClrUsed
= 0;
471 palEntry
= palette
->logpalette
.palPalEntry
;
472 for (i
= 0; i
< colors
; i
++, palEntry
++)
474 if (coloruse
== DIB_RGB_COLORS
)
476 info
->bmiColors
[i
].rgbRed
= palEntry
->peRed
;
477 info
->bmiColors
[i
].rgbGreen
= palEntry
->peGreen
;
478 info
->bmiColors
[i
].rgbBlue
= palEntry
->peBlue
;
479 info
->bmiColors
[i
].rgbReserved
= 0;
481 else ((WORD
*)info
->bmiColors
)[i
] = (WORD
)i
;
488 int pad
, yend
, xend
= bmp
->bitmap
.bmWidth
;
490 TRACE(bitmap
, "%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
491 lines
, bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmHeight
,
492 (int)info
->bmiHeader
.biWidth
, (int)info
->bmiHeader
.biHeight
, startscan
);
494 /* adjust number of scanlines to copy */
496 if( lines
> info
->bmiHeader
.biHeight
) lines
= info
->bmiHeader
.biHeight
;
497 yend
= startscan
+ lines
;
498 if( startscan
>= bmp
->bitmap
.bmHeight
)
500 GDI_HEAP_UNLOCK( hbitmap
);
501 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
504 if( yend
> bmp
->bitmap
.bmHeight
) yend
= bmp
->bitmap
.bmHeight
;
506 /* adjust scanline width */
508 pad
= info
->bmiHeader
.biWidth
- bmp
->bitmap
.bmWidth
;
511 /* bitmap is wider than DIB, copy only a part */
514 xend
= info
->bmiHeader
.biWidth
;
519 X11DRV_CreateBitmap(hbitmap
);
521 EnterCriticalSection( &X11DRV_CritSection
);
522 bmpImage
= (XImage
*)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage
, bmp
);
524 switch( info
->bmiHeader
.biBitCount
)
527 /* pad up to 32 bit */
528 pad
+= (4 - (info
->bmiHeader
.biWidth
& 3)) & 3;
529 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
531 for( x
= 0; x
< xend
; x
++ )
532 *bbits
++ = XGetPixel( bmpImage
, x
, y
);
537 pad
+= ((32 - (info
->bmiHeader
.biWidth
& 31)) / 8) & 3;
538 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
540 for( x
= 0; x
< xend
; x
++ ) {
541 if (!(x
&7)) *bbits
= 0;
542 *bbits
|= XGetPixel( bmpImage
, x
, y
)<<(7-(x
&7));
543 if ((x
&7)==7) bbits
++;
549 pad
+= ((8 - (info
->bmiHeader
.biWidth
& 7)) / 2) & 3;
550 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
552 for( x
= 0; x
< xend
; x
++ ) {
553 if (!(x
&1)) *bbits
= 0;
554 *bbits
|= XGetPixel( bmpImage
, x
, y
)<<(4*(1-(x
&1)));
555 if ((x
&1)==1) bbits
++;
562 pad
+= (4 - ((info
->bmiHeader
.biWidth
*2) & 3)) & 3;
563 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
565 for( x
= 0; x
< xend
; x
++ ) {
566 unsigned long pixel
=XGetPixel( bmpImage
, x
, y
);
567 *bbits
++ = pixel
& 0xff;
568 *bbits
++ = (pixel
>> 8) & 0xff;
574 pad
+= (4 - ((info
->bmiHeader
.biWidth
*3) & 3)) & 3;
575 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
577 for( x
= 0; x
< xend
; x
++ ) {
578 unsigned long pixel
=XGetPixel( bmpImage
, x
, y
);
579 *bbits
++ = (pixel
>>16) & 0xff;
580 *bbits
++ = (pixel
>> 8) & 0xff;
581 *bbits
++ = pixel
& 0xff;
587 for( y
= yend
- 1; (int)y
>= (int)startscan
; y
-- )
589 for( x
= 0; x
< xend
; x
++ ) {
590 unsigned long pixel
=XGetPixel( bmpImage
, x
, y
);
591 *bbits
++ = (pixel
>>16) & 0xff;
592 *bbits
++ = (pixel
>> 8) & 0xff;
593 *bbits
++ = pixel
& 0xff;
598 WARN(bitmap
,"Unsupported depth %d\n",
599 info
->bmiHeader
.biBitCount
);
603 XDestroyImage( bmpImage
);
604 LeaveCriticalSection( &X11DRV_CritSection
);
606 info
->bmiHeader
.biCompression
= 0;
608 else if( info
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
610 /* fill in struct members */
612 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
613 info
->bmiHeader
.biHeight
= bmp
->bitmap
.bmHeight
;
614 info
->bmiHeader
.biPlanes
= 1;
615 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
616 info
->bmiHeader
.biSizeImage
= bmp
->bitmap
.bmHeight
*
617 DIB_GetDIBWidthBytes( bmp
->bitmap
.bmWidth
,
618 bmp
->bitmap
.bmBitsPixel
);
619 info
->bmiHeader
.biCompression
= 0;
622 GDI_HEAP_UNLOCK( hbitmap
);
623 GDI_HEAP_UNLOCK( dc
->w
.hPalette
);
628 /***********************************************************************
629 * CreateDIBitmap16 (GDI.442)
631 HBITMAP16 WINAPI
CreateDIBitmap16( HDC16 hdc
, const BITMAPINFOHEADER
* header
,
632 DWORD init
, LPCVOID bits
, const BITMAPINFO
* data
,
635 return CreateDIBitmap32( hdc
, header
, init
, bits
, data
, coloruse
);
639 /***********************************************************************
640 * CreateDIBitmap32 (GDI32.37)
642 HBITMAP32 WINAPI
CreateDIBitmap32( HDC32 hdc
, const BITMAPINFOHEADER
*header
,
643 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
653 if (DIB_GetBitmapInfo( header
, &width
, &height
, &bpp
, &compr
) == -1) return 0;
654 if (height
< 0) height
= -height
;
656 /* Check if we should create a monochrome or color bitmap. */
657 /* We create a monochrome bitmap only if it has exactly 2 */
658 /* colors, which are either black or white, nothing else. */
659 /* In all other cases, we create a color bitmap. */
661 if (bpp
!= 1) fColor
= TRUE
;
662 else if ((coloruse
!= DIB_RGB_COLORS
) ||
663 (init
!= CBM_INIT
) || !data
) fColor
= FALSE
;
666 if (data
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
668 RGBQUAD
*rgb
= data
->bmiColors
;
669 DWORD col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
670 if ((col
== RGB(0,0,0)) || (col
== RGB(0xff,0xff,0xff)))
673 col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
674 fColor
= ((col
!= RGB(0,0,0)) && (col
!= RGB(0xff,0xff,0xff)));
678 else if (data
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
680 RGBTRIPLE
*rgb
= ((BITMAPCOREINFO
*)data
)->bmciColors
;
681 DWORD col
= RGB( rgb
->rgbtRed
, rgb
->rgbtGreen
, rgb
->rgbtBlue
);
682 if ((col
== RGB(0,0,0)) || (col
== RGB(0xff,0xff,0xff)))
685 col
= RGB( rgb
->rgbtRed
, rgb
->rgbtGreen
, rgb
->rgbtBlue
);
686 fColor
= ((col
!= RGB(0,0,0)) && (col
!= RGB(0xff,0xff,0xff)));
692 WARN(bitmap
, "(%ld): wrong size for data\n",
693 data
->bmiHeader
.biSize
);
698 /* Now create the bitmap */
700 handle
= fColor
? CreateBitmap32( width
, height
, 1, screenDepth
, NULL
) :
701 CreateBitmap32( width
, height
, 1, 1, NULL
);
702 if (!handle
) return 0;
704 if (init
== CBM_INIT
)
705 SetDIBits32( hdc
, handle
, 0, height
, bits
, data
, coloruse
);
710 /***********************************************************************
711 * DIB_DoProtectDIBSection
713 static void DIB_DoProtectDIBSection( BITMAPOBJ
*bmp
, DWORD new_prot
)
715 DIBSECTION
*dib
= &bmp
->dib
->dibSection
;
716 INT32 effHeight
= dib
->dsBm
.bmHeight
>= 0? dib
->dsBm
.bmHeight
717 : -dib
->dsBm
.bmHeight
;
718 INT32 totalSize
= dib
->dsBmih
.biSizeImage
? dib
->dsBmih
.biSizeImage
719 : dib
->dsBm
.bmWidthBytes
* effHeight
;
722 VirtualProtect(dib
->dsBm
.bmBits
, totalSize
, new_prot
, &old_prot
);
723 TRACE(bitmap
, "Changed protection from %ld to %ld\n",
727 /***********************************************************************
728 * DIB_DoUpdateDIBSection
730 static void DIB_DoUpdateDIBSection( BITMAPOBJ
*bmp
, BOOL32 toDIB
)
732 DIBSECTIONOBJ
*dib
= bmp
->dib
;
733 DIB_SETIMAGEBITS_DESCR descr
;
735 if (DIB_GetBitmapInfo( &dib
->dibSection
.dsBmih
, &descr
.infoWidth
, &descr
.lines
,
736 &descr
.infoBpp
, &descr
.compression
) == -1)
740 descr
.image
= dib
->image
;
741 descr
.colorMap
= dib
->colorMap
;
742 descr
.nColorMap
= dib
->nColorMap
;
743 descr
.bits
= dib
->dibSection
.dsBm
.bmBits
;
744 descr
.depth
= bmp
->bitmap
.bmBitsPixel
;
747 descr
.drawable
= ((X11DRV_PHYSBITMAP
*)bmp
->DDBitmap
->physBitmap
)->pixmap
;
748 descr
.gc
= BITMAP_GC(bmp
);
753 descr
.width
= bmp
->bitmap
.bmWidth
;
754 descr
.height
= bmp
->bitmap
.bmHeight
;
758 TRACE(bitmap
, "Copying from Pixmap to DIB bits\n");
759 EnterCriticalSection( &X11DRV_CritSection
);
760 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits
, &descr
);
761 LeaveCriticalSection( &X11DRV_CritSection
);
765 TRACE(bitmap
, "Copying from DIB bits to Pixmap\n");
766 EnterCriticalSection( &X11DRV_CritSection
);
767 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits
, &descr
);
768 LeaveCriticalSection( &X11DRV_CritSection
);
772 /***********************************************************************
775 static BOOL32
DIB_FaultHandler( LPVOID res
, LPVOID addr
)
777 BOOL32 handled
= FALSE
;
780 bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( (HBITMAP32
)res
, BITMAP_MAGIC
);
781 if (!bmp
) return FALSE
;
784 switch (bmp
->dib
->status
)
787 TRACE( bitmap
, "called in status DIB_GdiMod\n" );
788 DIB_DoProtectDIBSection( bmp
, PAGE_READWRITE
);
789 DIB_DoUpdateDIBSection( bmp
, TRUE
);
790 DIB_DoProtectDIBSection( bmp
, PAGE_READONLY
);
791 bmp
->dib
->status
= DIB_InSync
;
796 TRACE( bitmap
, "called in status DIB_InSync\n" );
797 DIB_DoProtectDIBSection( bmp
, PAGE_READWRITE
);
798 bmp
->dib
->status
= DIB_AppMod
;
803 FIXME( bitmap
, "called in status DIB_AppMod: "
804 "this can't happen!\n" );
808 FIXME( bitmap
, "called in status DIB_NoHandler: "
809 "this can't happen!\n" );
813 GDI_HEAP_UNLOCK( (HBITMAP32
)res
);
817 /***********************************************************************
818 * DIB_UpdateDIBSection
820 void DIB_UpdateDIBSection( DC
*dc
, BOOL32 toDIB
)
824 /* Ensure this is a Compatible DC that has a DIB section selected */
827 if (!(dc
->w
.flags
& DC_MEMORY
)) return;
829 bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( dc
->w
.hBitmap
, BITMAP_MAGIC
);
834 GDI_HEAP_UNLOCK(dc
->w
.hBitmap
);
841 /* Prepare for access to the DIB by GDI functions */
843 switch (bmp
->dib
->status
)
847 DIB_DoUpdateDIBSection( bmp
, FALSE
);
851 TRACE( bitmap
, "fromDIB called in status DIB_GdiMod\n" );
856 TRACE( bitmap
, "fromDIB called in status DIB_InSync\n" );
861 TRACE( bitmap
, "fromDIB called in status DIB_AppMod\n" );
862 DIB_DoUpdateDIBSection( bmp
, FALSE
);
863 DIB_DoProtectDIBSection( bmp
, PAGE_READONLY
);
864 bmp
->dib
->status
= DIB_InSync
;
870 /* Acknowledge write access to the DIB by GDI functions */
872 switch (bmp
->dib
->status
)
876 DIB_DoUpdateDIBSection( bmp
, TRUE
);
880 TRACE( bitmap
, " toDIB called in status DIB_GdiMod\n" );
885 TRACE( bitmap
, " toDIB called in status DIB_InSync\n" );
886 DIB_DoProtectDIBSection( bmp
, PAGE_NOACCESS
);
887 bmp
->dib
->status
= DIB_GdiMod
;
891 FIXME( bitmap
, " toDIB called in status DIB_AppMod: "
892 "this can't happen!\n" );
898 GDI_HEAP_UNLOCK(dc
->w
.hBitmap
);
901 /***********************************************************************
902 * CreateDIBSection16 (GDI.489)
904 HBITMAP16 WINAPI
CreateDIBSection16 (HDC16 hdc
, BITMAPINFO
*bmi
, UINT16 usage
,
905 LPVOID
**bits
, HANDLE32 section
,
908 return CreateDIBSection32(hdc
, bmi
, usage
, bits
, section
, offset
);
911 /***********************************************************************
912 * CreateDIBSection32 (GDI32.36)
914 HBITMAP32 WINAPI
CreateDIBSection32 (HDC32 hdc
, BITMAPINFO
*bmi
, UINT32 usage
,
915 LPVOID
**bits
,HANDLE32 section
,
919 BITMAPOBJ
*bmp
= NULL
;
920 DIBSECTIONOBJ
*dib
= NULL
;
921 int *colorMap
= NULL
;
924 /* Fill BITMAP32 structure with DIB data */
925 BITMAPINFOHEADER
*bi
= &bmi
->bmiHeader
;
926 INT32 effHeight
, totalSize
;
929 TRACE(bitmap
, "format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
930 bi
->biWidth
, bi
->biHeight
, bi
->biPlanes
, bi
->biBitCount
,
931 bi
->biSizeImage
, bi
->biClrUsed
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
934 bm
.bmWidth
= bi
->biWidth
;
935 bm
.bmHeight
= bi
->biHeight
;
936 bm
.bmWidthBytes
= DIB_GetDIBWidthBytes(bm
.bmWidth
, bi
->biBitCount
);
937 bm
.bmPlanes
= bi
->biPlanes
;
938 bm
.bmBitsPixel
= bi
->biBitCount
;
941 /* Get storage location for DIB bits */
942 effHeight
= bm
.bmHeight
>= 0 ? bm
.bmHeight
: -bm
.bmHeight
;
943 totalSize
= bi
->biSizeImage
? bi
->biSizeImage
: bm
.bmWidthBytes
* effHeight
;
946 bm
.bmBits
= MapViewOfFile(section
, FILE_MAP_ALL_ACCESS
,
947 0L, offset
, totalSize
);
949 bm
.bmBits
= VirtualAlloc(NULL
, totalSize
,
950 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
952 /* Create Color Map */
953 if (bm
.bmBits
&& bm
.bmBitsPixel
<= 8)
955 DC
*dc
= hdc
? (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
) : NULL
;
956 if (hdc
&& !dc
) dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
959 colorMap
= X11DRV_DIB_BuildColorMap( dc
, usage
, bm
.bmBitsPixel
,
961 GDI_HEAP_UNLOCK(hdc
);
964 /* Allocate Memory for DIB and fill structure */
966 dib
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DIBSECTIONOBJ
));
969 dib
->dibSection
.dsBm
= bm
;
970 dib
->dibSection
.dsBmih
= *bi
;
971 /* FIXME: dib->dibSection.dsBitfields ??? */
972 dib
->dibSection
.dshSection
= section
;
973 dib
->dibSection
.dsOffset
= offset
;
975 dib
->status
= DIB_NoHandler
;
977 dib
->nColorMap
= nColorMap
;
978 dib
->colorMap
= colorMap
;
981 /* Create Device Dependent Bitmap and add DIB pointer */
984 res
= CreateDIBitmap32(hdc
, bi
, 0, NULL
, bmi
, usage
);
987 bmp
= (BITMAPOBJ
*) GDI_GetObjPtr(res
, BITMAP_MAGIC
);
993 X11DRV_CreateBitmap(res
);
1000 XCREATEIMAGE( dib
->image
, bm
.bmWidth
, effHeight
, bmp
->bitmap
.bmBitsPixel
);
1002 /* Clean up in case of errors */
1003 if (!res
|| !bmp
|| !dib
|| !bm
.bmBits
|| (bm
.bmBitsPixel
<= 8 && !colorMap
))
1005 TRACE(bitmap
, "got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
1006 res
, bmp
, dib
, bm
.bmBits
);
1010 UnmapViewOfFile(bm
.bmBits
), bm
.bmBits
= NULL
;
1012 VirtualFree(bm
.bmBits
, MEM_RELEASE
, 0L), bm
.bmBits
= NULL
;
1015 if (dib
&& dib
->image
) { XDestroyImage(dib
->image
); dib
->image
= NULL
; }
1016 if (colorMap
) { HeapFree(GetProcessHeap(), 0, colorMap
); colorMap
= NULL
; }
1017 if (dib
) { HeapFree(GetProcessHeap(), 0, dib
); dib
= NULL
; }
1018 if (res
) { DeleteObject32(res
); res
= 0; }
1021 /* Install fault handler, if possible */
1024 if (VIRTUAL_SetFaultHandler(bm
.bmBits
, DIB_FaultHandler
, (LPVOID
)res
))
1026 DIB_DoProtectDIBSection( bmp
, PAGE_READONLY
);
1027 if (dib
) dib
->status
= DIB_InSync
;
1031 /* Return BITMAP handle and storage location */
1032 if (res
) GDI_HEAP_UNLOCK(res
);
1033 if (bm
.bmBits
&& bits
) *bits
= bm
.bmBits
;
1037 /***********************************************************************
1038 * DIB_DeleteDIBSection
1040 void DIB_DeleteDIBSection( BITMAPOBJ
*bmp
)
1042 if (bmp
&& bmp
->dib
)
1044 DIBSECTIONOBJ
*dib
= bmp
->dib
;
1046 if (dib
->dibSection
.dsBm
.bmBits
)
1048 if (dib
->dibSection
.dshSection
)
1049 UnmapViewOfFile(dib
->dibSection
.dsBm
.bmBits
);
1051 VirtualFree(dib
->dibSection
.dsBm
.bmBits
, MEM_RELEASE
, 0L);
1055 XDestroyImage( dib
->image
);
1058 HeapFree(GetProcessHeap(), 0, dib
->colorMap
);
1060 HeapFree(GetProcessHeap(), 0, dib
);
1065 /***********************************************************************
1066 * DIB_FixColorsToLoadflags
1068 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1071 void DIB_FixColorsToLoadflags(BITMAPINFO
* bmi
, UINT32 loadflags
, BYTE pix
)
1074 COLORREF c_W
, c_S
, c_F
, c_L
, c_C
;
1078 if (bmi
->bmiHeader
.biBitCount
> 8) return;
1079 if (bmi
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
)) incr
= 4;
1080 else if (bmi
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
)) incr
= 3;
1082 WARN(bitmap
, "Wrong bitmap header size!\n");
1085 colors
= bmi
->bmiHeader
.biClrUsed
;
1086 if (!colors
&& (bmi
->bmiHeader
.biBitCount
<= 8))
1087 colors
= 1 << bmi
->bmiHeader
.biBitCount
;
1088 c_W
= GetSysColor32(COLOR_WINDOW
);
1089 c_S
= GetSysColor32(COLOR_3DSHADOW
);
1090 c_F
= GetSysColor32(COLOR_3DFACE
);
1091 c_L
= GetSysColor32(COLOR_3DLIGHT
);
1092 if (loadflags
& LR_LOADTRANSPARENT
) {
1093 switch (bmi
->bmiHeader
.biBitCount
) {
1094 case 1: pix
= pix
>> 7; break;
1095 case 4: pix
= pix
>> 4; break;
1098 WARN(bitmap
, "(%d): Unsupported depth\n", bmi
->bmiHeader
.biBitCount
);
1101 if (pix
>= colors
) {
1102 WARN(bitmap
, "pixel has color index greater than biClrUsed!\n");
1105 if (loadflags
& LR_LOADMAP3DCOLORS
) c_W
= c_F
;
1106 ptr
= (RGBQUAD
*)((char*)bmi
->bmiColors
+pix
*incr
);
1107 ptr
->rgbBlue
= GetBValue(c_W
);
1108 ptr
->rgbGreen
= GetGValue(c_W
);
1109 ptr
->rgbRed
= GetRValue(c_W
);
1111 if (loadflags
& LR_LOADMAP3DCOLORS
)
1112 for (i
=0; i
<colors
; i
++) {
1113 ptr
= (RGBQUAD
*)((char*)bmi
->bmiColors
+i
*incr
);
1114 c_C
= RGB(ptr
->rgbRed
, ptr
->rgbGreen
, ptr
->rgbBlue
);
1115 if (c_C
== RGB(128, 128, 128)) {
1116 ptr
->rgbRed
= GetRValue(c_S
);
1117 ptr
->rgbGreen
= GetGValue(c_S
);
1118 ptr
->rgbBlue
= GetBValue(c_S
);
1119 } else if (c_C
== RGB(192, 192, 192)) {
1120 ptr
->rgbRed
= GetRValue(c_F
);
1121 ptr
->rgbGreen
= GetGValue(c_F
);
1122 ptr
->rgbBlue
= GetBValue(c_F
);
1123 } else if (c_C
== RGB(223, 223, 223)) {
1124 ptr
->rgbRed
= GetRValue(c_L
);
1125 ptr
->rgbGreen
= GetGValue(c_L
);
1126 ptr
->rgbBlue
= GetBValue(c_L
);