4 * Copyright 1993 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "gdi_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
35 static HGDIOBJ
BITMAP_SelectObject( HGDIOBJ handle
, HDC hdc
);
36 static INT
BITMAP_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
37 static BOOL
BITMAP_DeleteObject( HGDIOBJ handle
);
39 static const struct gdi_obj_funcs bitmap_funcs
=
41 BITMAP_SelectObject
, /* pSelectObject */
42 BITMAP_GetObject
, /* pGetObjectA */
43 BITMAP_GetObject
, /* pGetObjectW */
44 NULL
, /* pUnrealizeObject */
45 BITMAP_DeleteObject
/* pDeleteObject */
49 /***********************************************************************
50 * null driver fallback implementations
53 DWORD
nulldrv_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
54 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
59 if (!hbitmap
) return ERROR_NOT_SUPPORTED
;
60 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return ERROR_INVALID_HANDLE
;
62 if (bmp
->bitmap
.bmBits
|| !bits
)
64 ret
= dib_driver
.pGetImage( 0, hbitmap
, info
, bits
, src
);
66 else if (!(ret
= dib_driver
.pGetImage( 0, hbitmap
, info
, NULL
, src
)))
68 info
->bmiHeader
.biHeight
= -(src
->visrect
.bottom
- src
->visrect
.top
);
69 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
71 /* make the source rectangle relative to the returned bits */
72 src
->y
-= src
->visrect
.top
;
73 offset_rect( &src
->visrect
, 0, -src
->visrect
.top
);
75 /* return all-zero bits */
76 bits
->ptr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, info
->bmiHeader
.biSizeImage
);
78 bits
->free
= free_heap_bits
;
80 GDI_ReleaseObj( hbitmap
);
84 DWORD
nulldrv_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
85 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
86 struct bitblt_coords
*dst
, DWORD rop
)
90 if (!hbitmap
) return ERROR_SUCCESS
;
94 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return ERROR_INVALID_HANDLE
;
95 if (!bmp
->bitmap
.bmBits
)
97 int width_bytes
= get_dib_stride( bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmBitsPixel
);
98 if (!(bmp
->bitmap
.bmBits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
99 bmp
->bitmap
.bmHeight
* width_bytes
)))
101 GDI_ReleaseObj( hbitmap
);
102 return ERROR_OUTOFMEMORY
;
105 GDI_ReleaseObj( hbitmap
);
107 return dib_driver
.pPutImage( NULL
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
111 /******************************************************************************
112 * CreateBitmap [GDI32.@]
114 * Creates a bitmap with the specified info.
117 * width [I] bitmap width
118 * height [I] bitmap height
119 * planes [I] Number of color planes
120 * bpp [I] Number of bits to identify a color
121 * bits [I] Pointer to array containing color data
124 * Success: Handle to bitmap
127 HBITMAP WINAPI
CreateBitmap( INT width
, INT height
, UINT planes
,
128 UINT bpp
, LPCVOID bits
)
134 bm
.bmHeight
= height
;
135 bm
.bmWidthBytes
= get_bitmap_stride( width
, bpp
);
136 bm
.bmPlanes
= planes
;
137 bm
.bmBitsPixel
= bpp
;
138 bm
.bmBits
= (LPVOID
)bits
;
140 return CreateBitmapIndirect( &bm
);
143 /******************************************************************************
144 * CreateCompatibleBitmap [GDI32.@]
146 * Creates a bitmap compatible with the DC.
149 * hdc [I] Handle to device context
150 * width [I] Width of bitmap
151 * height [I] Height of bitmap
154 * Success: Handle to bitmap
157 HBITMAP WINAPI
CreateCompatibleBitmap( HDC hdc
, INT width
, INT height
)
161 TRACE("(%p,%d,%d) =\n", hdc
, width
, height
);
163 if (GetObjectType( hdc
) != OBJ_MEMDC
)
165 hbmpRet
= CreateBitmap(width
, height
,
166 GetDeviceCaps(hdc
, PLANES
),
167 GetDeviceCaps(hdc
, BITSPIXEL
),
173 HBITMAP bitmap
= GetCurrentObject( hdc
, OBJ_BITMAP
);
174 INT size
= GetObjectW( bitmap
, sizeof(dib
), &dib
);
178 if (size
== sizeof(BITMAP
))
180 /* A device-dependent bitmap is selected in the DC */
181 hbmpRet
= CreateBitmap(width
, height
,
183 dib
.dsBm
.bmBitsPixel
,
188 /* A DIB section is selected in the DC */
192 /* Allocate memory for a BITMAPINFOHEADER structure and a
193 color table. The maximum number of colors in a color table
194 is 256 which corresponds to a bitmap with depth 8.
195 Bitmaps with higher depths don't have color tables. */
196 bi
= HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
200 bi
->bmiHeader
.biSize
= sizeof(bi
->bmiHeader
);
201 bi
->bmiHeader
.biWidth
= width
;
202 bi
->bmiHeader
.biHeight
= height
;
203 bi
->bmiHeader
.biPlanes
= dib
.dsBmih
.biPlanes
;
204 bi
->bmiHeader
.biBitCount
= dib
.dsBmih
.biBitCount
;
205 bi
->bmiHeader
.biCompression
= dib
.dsBmih
.biCompression
;
206 bi
->bmiHeader
.biSizeImage
= 0;
207 bi
->bmiHeader
.biXPelsPerMeter
= dib
.dsBmih
.biXPelsPerMeter
;
208 bi
->bmiHeader
.biYPelsPerMeter
= dib
.dsBmih
.biYPelsPerMeter
;
209 bi
->bmiHeader
.biClrUsed
= dib
.dsBmih
.biClrUsed
;
210 bi
->bmiHeader
.biClrImportant
= dib
.dsBmih
.biClrImportant
;
212 if (bi
->bmiHeader
.biCompression
== BI_BITFIELDS
)
214 /* Copy the color masks */
215 CopyMemory(bi
->bmiColors
, dib
.dsBitfields
, 3 * sizeof(DWORD
));
217 else if (bi
->bmiHeader
.biBitCount
<= 8)
219 /* Copy the color table */
220 GetDIBColorTable(hdc
, 0, 256, bi
->bmiColors
);
223 hbmpRet
= CreateDIBSection(hdc
, bi
, DIB_RGB_COLORS
, &bits
, NULL
, 0);
224 HeapFree(GetProcessHeap(), 0, bi
);
229 TRACE("\t\t%p\n", hbmpRet
);
234 /******************************************************************************
235 * CreateBitmapIndirect [GDI32.@]
237 * Creates a bitmap with the specified info.
240 * bmp [I] Pointer to the bitmap info describing the bitmap
243 * Success: Handle to bitmap
244 * Failure: NULL. Use GetLastError() to determine the cause.
247 * If a width or height of 0 are given, a 1x1 monochrome bitmap is returned.
249 HBITMAP WINAPI
CreateBitmapIndirect( const BITMAP
*bmp
)
255 if (!bmp
|| bmp
->bmType
)
257 SetLastError( ERROR_INVALID_PARAMETER
);
261 if (bmp
->bmWidth
> 0x7ffffff || bmp
->bmHeight
> 0x7ffffff)
263 SetLastError( ERROR_INVALID_PARAMETER
);
269 if (!bm
.bmWidth
|| !bm
.bmHeight
)
271 return GetStockObject( DEFAULT_BITMAP
);
276 bm
.bmHeight
= -bm
.bmHeight
;
278 bm
.bmWidth
= -bm
.bmWidth
;
281 if (bm
.bmPlanes
!= 1)
283 FIXME("planes = %d\n", bm
.bmPlanes
);
284 SetLastError( ERROR_INVALID_PARAMETER
);
288 /* Windows only uses 1, 4, 8, 16, 24 and 32 bpp */
289 if(bm
.bmBitsPixel
== 1) bm
.bmBitsPixel
= 1;
290 else if(bm
.bmBitsPixel
<= 4) bm
.bmBitsPixel
= 4;
291 else if(bm
.bmBitsPixel
<= 8) bm
.bmBitsPixel
= 8;
292 else if(bm
.bmBitsPixel
<= 16) bm
.bmBitsPixel
= 16;
293 else if(bm
.bmBitsPixel
<= 24) bm
.bmBitsPixel
= 24;
294 else if(bm
.bmBitsPixel
<= 32) bm
.bmBitsPixel
= 32;
296 WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm
.bmBitsPixel
);
297 SetLastError(ERROR_INVALID_PARAMETER
);
301 /* Windows ignores the provided bm.bmWidthBytes */
302 bm
.bmWidthBytes
= get_bitmap_stride( bm
.bmWidth
, bm
.bmBitsPixel
);
303 /* XP doesn't allow to create bitmaps larger than 128 Mb */
304 if (bm
.bmHeight
> 128 * 1024 * 1024 / bm
.bmWidthBytes
)
306 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
310 /* Create the BITMAPOBJ */
311 if (!(bmpobj
= HeapAlloc( GetProcessHeap(), 0, sizeof(*bmpobj
) )))
313 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
320 bmpobj
->bitmap
.bmBits
= NULL
;
321 bmpobj
->funcs
= &null_driver
;
323 bmpobj
->color_table
= NULL
;
324 bmpobj
->nb_colors
= 0;
326 if (!(hbitmap
= alloc_gdi_handle( &bmpobj
->header
, OBJ_BITMAP
, &bitmap_funcs
)))
328 HeapFree( GetProcessHeap(), 0, bmpobj
);
333 SetBitmapBits( hbitmap
, bm
.bmHeight
* bm
.bmWidthBytes
, bm
.bmBits
);
335 TRACE("%dx%d, bpp %d planes %d: returning %p\n", bm
.bmWidth
, bm
.bmHeight
,
336 bm
.bmBitsPixel
, bm
.bmPlanes
, hbitmap
);
342 /* convenience wrapper for GetImage to retrieve the full contents of a bitmap */
343 BOOL
get_bitmap_image( HBITMAP hbitmap
, BITMAPINFO
*info
, struct gdi_image_bits
*bits
)
345 struct bitblt_coords src
;
347 BITMAPOBJ
*bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
351 src
.visrect
.left
= src
.x
= 0;
352 src
.visrect
.top
= src
.y
= 0;
353 src
.visrect
.right
= src
.width
= bmp
->bitmap
.bmWidth
;
354 src
.visrect
.bottom
= src
.height
= bmp
->bitmap
.bmHeight
;
355 ret
= !bmp
->funcs
->pGetImage( NULL
, hbitmap
, info
, bits
, &src
);
356 GDI_ReleaseObj( hbitmap
);
362 /***********************************************************************
363 * GetBitmapBits [GDI32.@]
365 * Copies bitmap bits of bitmap to buffer.
368 * Success: Number of bytes copied
371 LONG WINAPI
GetBitmapBits(
372 HBITMAP hbitmap
, /* [in] Handle to bitmap */
373 LONG count
, /* [in] Number of bytes to copy */
374 LPVOID bits
) /* [out] Pointer to buffer to receive bits */
376 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
377 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
378 struct gdi_image_bits src_bits
;
379 struct bitblt_coords src
;
380 int dst_stride
, max
, ret
;
381 BITMAPOBJ
*bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
382 const struct gdi_dc_funcs
*funcs
;
385 funcs
= get_bitmap_funcs( bmp
);
387 if (bmp
->dib
) dst_stride
= get_bitmap_stride( bmp
->dib
->dsBmih
.biWidth
, bmp
->dib
->dsBmih
.biBitCount
);
388 else dst_stride
= get_bitmap_stride( bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmBitsPixel
);
390 ret
= max
= dst_stride
* bmp
->bitmap
.bmHeight
;
391 if (!bits
) goto done
;
392 if (count
> max
) count
= max
;
395 src
.visrect
.left
= 0;
396 src
.visrect
.right
= bmp
->bitmap
.bmWidth
;
398 src
.visrect
.bottom
= (count
+ dst_stride
- 1) / dst_stride
;
400 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
401 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
403 if (!funcs
->pGetImage( NULL
, hbitmap
, info
, &src_bits
, &src
))
405 const char *src_ptr
= src_bits
.ptr
;
406 int src_stride
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
408 /* GetBitmapBits returns 16-bit aligned data */
410 if (info
->bmiHeader
.biHeight
> 0)
412 src_ptr
+= (info
->bmiHeader
.biHeight
- 1) * src_stride
;
413 src_stride
= -src_stride
;
415 src_ptr
+= src
.visrect
.top
* src_stride
;
417 if (src_stride
== dst_stride
) memcpy( bits
, src_ptr
, count
);
418 else while (count
> 0)
420 memcpy( bits
, src_ptr
, min( count
, dst_stride
) );
421 src_ptr
+= src_stride
;
422 bits
= (char *)bits
+ dst_stride
;
425 if (src_bits
.free
) src_bits
.free( &src_bits
);
430 GDI_ReleaseObj( hbitmap
);
435 /******************************************************************************
436 * SetBitmapBits [GDI32.@]
438 * Sets bits of color data for a bitmap.
441 * Success: Number of bytes used in setting the bitmap bits
444 LONG WINAPI
SetBitmapBits(
445 HBITMAP hbitmap
, /* [in] Handle to bitmap */
446 LONG count
, /* [in] Number of bytes in bitmap array */
447 LPCVOID bits
) /* [in] Address of array with bitmap bits */
449 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
450 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
453 int i
, src_stride
, dst_stride
;
454 struct bitblt_coords src
, dst
;
455 struct gdi_image_bits src_bits
;
457 const struct gdi_dc_funcs
*funcs
;
461 bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
464 funcs
= get_bitmap_funcs( bmp
);
467 WARN("(%d): Negative number of bytes passed???\n", count
);
471 if (bmp
->dib
) src_stride
= get_bitmap_stride( bmp
->dib
->dsBmih
.biWidth
, bmp
->dib
->dsBmih
.biBitCount
);
472 else src_stride
= get_bitmap_stride( bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmBitsPixel
);
473 count
= min( count
, src_stride
* bmp
->bitmap
.bmHeight
);
475 dst_stride
= get_dib_stride( bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmBitsPixel
);
477 src
.visrect
.left
= src
.x
= 0;
478 src
.visrect
.top
= src
.y
= 0;
479 src
.visrect
.right
= src
.width
= bmp
->bitmap
.bmWidth
;
480 src
.visrect
.bottom
= src
.height
= (count
+ src_stride
- 1 ) / src_stride
;
483 if (count
% src_stride
)
486 int extra_pixels
= ((count
% src_stride
) << 3) / bmp
->bitmap
.bmBitsPixel
;
488 if ((count
% src_stride
<< 3) % bmp
->bitmap
.bmBitsPixel
)
489 FIXME( "Unhandled partial pixel\n" );
490 clip
= CreateRectRgn( src
.visrect
.left
, src
.visrect
.top
,
491 src
.visrect
.right
, src
.visrect
.bottom
- 1 );
492 last_row
= CreateRectRgn( src
.visrect
.left
, src
.visrect
.bottom
- 1,
493 src
.visrect
.left
+ extra_pixels
, src
.visrect
.bottom
);
494 CombineRgn( clip
, clip
, last_row
, RGN_OR
);
495 DeleteObject( last_row
);
498 TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n",
499 hbitmap
, count
, bits
, bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmHeight
,
500 bmp
->bitmap
.bmBitsPixel
, src
.height
);
502 if (src_stride
== dst_stride
)
504 src_bits
.ptr
= (void *)bits
;
505 src_bits
.is_copy
= FALSE
;
506 src_bits
.free
= NULL
;
510 if (!(src_bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, dst
.height
* dst_stride
)))
512 GDI_ReleaseObj( hbitmap
);
515 src_bits
.is_copy
= TRUE
;
516 src_bits
.free
= free_heap_bits
;
517 for (i
= 0; i
< count
/ src_stride
; i
++)
518 memcpy( (char *)src_bits
.ptr
+ i
* dst_stride
, (char *)bits
+ i
* src_stride
, src_stride
);
519 if (count
% src_stride
)
520 memcpy( (char *)src_bits
.ptr
+ i
* dst_stride
, (char *)bits
+ i
* src_stride
, count
% src_stride
);
523 /* query the color info */
524 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
525 info
->bmiHeader
.biPlanes
= 1;
526 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
527 info
->bmiHeader
.biCompression
= BI_RGB
;
528 info
->bmiHeader
.biXPelsPerMeter
= 0;
529 info
->bmiHeader
.biYPelsPerMeter
= 0;
530 info
->bmiHeader
.biClrUsed
= 0;
531 info
->bmiHeader
.biClrImportant
= 0;
532 info
->bmiHeader
.biWidth
= 0;
533 info
->bmiHeader
.biHeight
= 0;
534 info
->bmiHeader
.biSizeImage
= 0;
535 err
= funcs
->pPutImage( NULL
, hbitmap
, 0, info
, NULL
, NULL
, NULL
, SRCCOPY
);
537 if (!err
|| err
== ERROR_BAD_FORMAT
)
539 info
->bmiHeader
.biPlanes
= 1;
540 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
541 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
542 info
->bmiHeader
.biHeight
= -dst
.height
;
543 info
->bmiHeader
.biSizeImage
= dst
.height
* dst_stride
;
544 err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, info
, &src_bits
, &src
, &dst
, SRCCOPY
);
548 if (clip
) DeleteObject( clip
);
549 if (src_bits
.free
) src_bits
.free( &src_bits
);
550 GDI_ReleaseObj( hbitmap
);
554 /**********************************************************************
558 HBITMAP
BITMAP_CopyBitmap(HBITMAP hbitmap
)
562 BITMAPOBJ
*bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
572 GDI_ReleaseObj( hbitmap
);
573 dc
= CreateCompatibleDC( NULL
);
576 if (!(bi
= HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] ))))
581 bi
->bmiHeader
= dib
.dsBmih
;
583 /* Get the color table or the color masks */
584 GetDIBits( dc
, hbitmap
, 0, 0, NULL
, bi
, DIB_RGB_COLORS
);
585 bi
->bmiHeader
.biHeight
= dib
.dsBmih
.biHeight
;
587 res
= CreateDIBSection( dc
, bi
, DIB_RGB_COLORS
, &bits
, NULL
, 0 );
588 if (res
) SetDIBits( dc
, res
, 0, dib
.dsBm
.bmHeight
, dib
.dsBm
.bmBits
, bi
, DIB_RGB_COLORS
);
589 HeapFree( GetProcessHeap(), 0, bi
);
593 dib
.dsBm
= bmp
->bitmap
;
594 dib
.dsBm
.bmBits
= NULL
;
595 GDI_ReleaseObj( hbitmap
);
597 res
= CreateBitmapIndirect( &dib
.dsBm
);
599 char *buf
= HeapAlloc( GetProcessHeap(), 0, dib
.dsBm
.bmWidthBytes
* dib
.dsBm
.bmHeight
);
600 GetBitmapBits (hbitmap
, dib
.dsBm
.bmWidthBytes
* dib
.dsBm
.bmHeight
, buf
);
601 SetBitmapBits (res
, dib
.dsBm
.bmWidthBytes
* dib
.dsBm
.bmHeight
, buf
);
602 HeapFree( GetProcessHeap(), 0, buf
);
608 static void set_initial_bitmap_bits( HBITMAP hbitmap
, BITMAPOBJ
*bmp
)
610 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
611 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
613 if (!bmp
->bitmap
.bmBits
) return;
614 if (bmp
->funcs
->pPutImage
== nulldrv_PutImage
) return;
616 get_ddb_bitmapinfo( bmp
, info
);
617 SetDIBits( 0, hbitmap
, 0, bmp
->bitmap
.bmHeight
, bmp
->bitmap
.bmBits
, info
, DIB_RGB_COLORS
);
618 HeapFree( GetProcessHeap(), 0, bmp
->bitmap
.bmBits
);
619 bmp
->bitmap
.bmBits
= NULL
;
622 /***********************************************************************
625 * Set the type of DC that owns the bitmap. This is used when the
626 * bitmap is selected into a device to initialize the bitmap function
629 BOOL
BITMAP_SetOwnerDC( HBITMAP hbitmap
, PHYSDEV physdev
)
634 /* never set the owner of the stock bitmap since it can be selected in multiple DCs */
635 if (hbitmap
== GetStockObject(DEFAULT_BITMAP
)) return TRUE
;
637 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return FALSE
;
639 if (!bitmap
->dib
&& bitmap
->funcs
!= physdev
->funcs
)
641 /* we can only change from the null driver to some other driver */
642 if (bitmap
->funcs
== &null_driver
)
644 if (physdev
->funcs
->pCreateBitmap
)
646 ret
= physdev
->funcs
->pCreateBitmap( physdev
, hbitmap
);
649 bitmap
->funcs
= physdev
->funcs
;
650 set_initial_bitmap_bits( hbitmap
, bitmap
);
655 WARN( "Trying to select bitmap %p in DC that doesn't support it\n", hbitmap
);
661 FIXME( "Trying to select bitmap %p in different DC type\n", hbitmap
);
665 GDI_ReleaseObj( hbitmap
);
670 /***********************************************************************
671 * BITMAP_SelectObject
673 static HGDIOBJ
BITMAP_SelectObject( HGDIOBJ handle
, HDC hdc
)
678 PHYSDEV physdev
= NULL
, old_physdev
= NULL
;
680 if (!(dc
= get_dc_ptr( hdc
))) return 0;
682 if (GetObjectType( hdc
) != OBJ_MEMDC
)
688 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
690 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
696 if (bitmap
->header
.selcount
&& (handle
!= GetStockObject(DEFAULT_BITMAP
)))
698 WARN( "Bitmap already selected in another DC\n" );
699 GDI_ReleaseObj( handle
);
704 old_physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
705 if(old_physdev
== dc
->dibdrv
)
706 old_physdev
= pop_dc_driver( &dc
->physDev
);
710 physdev
= dc
->dibdrv
;
711 if (physdev
) push_dc_driver( &dc
->physDev
, physdev
, physdev
->funcs
);
714 if (!dib_driver
.pCreateDC( &dc
->physDev
, NULL
, NULL
, NULL
, NULL
)) goto done
;
715 dc
->dibdrv
= physdev
= dc
->physDev
;
719 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
721 if (!BITMAP_SetOwnerDC( handle
, physdev
))
723 GDI_ReleaseObj( handle
);
727 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
729 GDI_ReleaseObj( handle
);
734 dc
->hBitmap
= handle
;
735 GDI_inc_ref_count( handle
);
737 dc
->vis_rect
.left
= 0;
738 dc
->vis_rect
.top
= 0;
739 dc
->vis_rect
.right
= bitmap
->bitmap
.bmWidth
;
740 dc
->vis_rect
.bottom
= bitmap
->bitmap
.bmHeight
;
741 SetRectRgn( dc
->hVisRgn
, 0, 0, bitmap
->bitmap
.bmWidth
, bitmap
->bitmap
.bmHeight
);
742 GDI_ReleaseObj( handle
);
744 GDI_dec_ref_count( ret
);
750 if (physdev
&& physdev
== dc
->dibdrv
)
751 pop_dc_driver( &dc
->physDev
);
752 if (old_physdev
&& old_physdev
== dc
->dibdrv
)
753 push_dc_driver( &dc
->physDev
, old_physdev
, old_physdev
->funcs
);
755 release_dc_ptr( dc
);
760 /***********************************************************************
761 * BITMAP_DeleteObject
763 static BOOL
BITMAP_DeleteObject( HGDIOBJ handle
)
765 const DC_FUNCTIONS
*funcs
;
766 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
768 if (!bmp
) return FALSE
;
770 GDI_ReleaseObj( handle
);
772 funcs
->pDeleteBitmap( handle
);
774 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
776 HeapFree( GetProcessHeap(), 0, bmp
->bitmap
.bmBits
);
780 DIBSECTION
*dib
= bmp
->dib
;
782 if (dib
->dsBm
.bmBits
)
786 SYSTEM_INFO SystemInfo
;
787 GetSystemInfo( &SystemInfo
);
788 UnmapViewOfFile( (char *)dib
->dsBm
.bmBits
-
789 (dib
->dsOffset
% SystemInfo
.dwAllocationGranularity
) );
791 else if (!dib
->dsOffset
)
792 VirtualFree(dib
->dsBm
.bmBits
, 0L, MEM_RELEASE
);
794 HeapFree(GetProcessHeap(), 0, dib
);
795 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
797 return HeapFree( GetProcessHeap(), 0, bmp
);
801 /***********************************************************************
804 static INT
BITMAP_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
807 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
811 if (!buffer
) ret
= sizeof(BITMAP
);
812 else if (count
< sizeof(BITMAP
)) ret
= 0;
815 if (count
>= sizeof(DIBSECTION
))
817 DIBSECTION
*dib
= buffer
;
819 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
820 ret
= sizeof(DIBSECTION
);
822 else /* if (count >= sizeof(BITMAP)) */
824 DIBSECTION
*dib
= bmp
->dib
;
825 memcpy( buffer
, &dib
->dsBm
, sizeof(BITMAP
) );
826 ret
= sizeof(BITMAP
);
831 memcpy( buffer
, &bmp
->bitmap
, sizeof(BITMAP
) );
832 ((BITMAP
*) buffer
)->bmBits
= NULL
;
833 ret
= sizeof(BITMAP
);
835 GDI_ReleaseObj( handle
);
840 /******************************************************************************
841 * CreateDiscardableBitmap [GDI32.@]
843 * Creates a discardable bitmap.
846 * Success: Handle to bitmap
849 HBITMAP WINAPI
CreateDiscardableBitmap(
850 HDC hdc
, /* [in] Handle to device context */
851 INT width
, /* [in] Bitmap width */
852 INT height
) /* [in] Bitmap height */
854 return CreateCompatibleBitmap( hdc
, width
, height
);
858 /******************************************************************************
859 * GetBitmapDimensionEx [GDI32.@]
861 * Retrieves dimensions of a bitmap.
867 BOOL WINAPI
GetBitmapDimensionEx(
868 HBITMAP hbitmap
, /* [in] Handle to bitmap */
869 LPSIZE size
) /* [out] Address of struct receiving dimensions */
871 BITMAPOBJ
* bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
872 if (!bmp
) return FALSE
;
874 GDI_ReleaseObj( hbitmap
);
879 /******************************************************************************
880 * SetBitmapDimensionEx [GDI32.@]
882 * Assigns dimensions to a bitmap.
883 * MSDN says that this function will fail if hbitmap is a handle created by
884 * CreateDIBSection, but that's not true on Windows 2000.
890 BOOL WINAPI
SetBitmapDimensionEx(
891 HBITMAP hbitmap
, /* [in] Handle to bitmap */
892 INT x
, /* [in] Bitmap width */
893 INT y
, /* [in] Bitmap height */
894 LPSIZE prevSize
) /* [out] Address of structure for orig dims */
896 BITMAPOBJ
* bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
897 if (!bmp
) return FALSE
;
898 if (prevSize
) *prevSize
= bmp
->size
;
901 GDI_ReleaseObj( hbitmap
);