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
)
56 if (!hbitmap
) return ERROR_NOT_SUPPORTED
;
57 return dib_driver
.pGetImage( 0, hbitmap
, info
, bits
, src
);
60 DWORD
nulldrv_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
61 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
62 struct bitblt_coords
*dst
, DWORD rop
)
64 if (!hbitmap
) return ERROR_SUCCESS
;
65 return dib_driver
.pPutImage( NULL
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
68 BOOL
nulldrv_CopyBitmap( HBITMAP src
, HBITMAP dst
)
71 BITMAPOBJ
*src_bmp
= GDI_GetObjPtr( src
, OBJ_BITMAP
);
73 if (!src_bmp
) return FALSE
;
74 if (src_bmp
->dib
.dsBm
.bmBits
)
76 BITMAPOBJ
*dst_bmp
= GDI_GetObjPtr( dst
, OBJ_BITMAP
);
77 int stride
= get_dib_stride( dst_bmp
->dib
.dsBm
.bmWidth
, dst_bmp
->dib
.dsBm
.bmBitsPixel
);
78 dst_bmp
->dib
.dsBm
.bmBits
= HeapAlloc( GetProcessHeap(), 0, dst_bmp
->dib
.dsBm
.bmHeight
* stride
);
79 if (dst_bmp
->dib
.dsBm
.bmBits
)
80 memcpy( dst_bmp
->dib
.dsBm
.bmBits
, src_bmp
->dib
.dsBm
.bmBits
, dst_bmp
->dib
.dsBm
.bmHeight
* stride
);
83 GDI_ReleaseObj( dst
);
85 GDI_ReleaseObj( src
);
90 /******************************************************************************
91 * CreateBitmap [GDI32.@]
93 * Creates a bitmap with the specified info.
96 * width [I] bitmap width
97 * height [I] bitmap height
98 * planes [I] Number of color planes
99 * bpp [I] Number of bits to identify a color
100 * bits [I] Pointer to array containing color data
103 * Success: Handle to bitmap
106 HBITMAP WINAPI
CreateBitmap( INT width
, INT height
, UINT planes
,
107 UINT bpp
, LPCVOID bits
)
113 bm
.bmHeight
= height
;
114 bm
.bmWidthBytes
= get_bitmap_stride( width
, bpp
);
115 bm
.bmPlanes
= planes
;
116 bm
.bmBitsPixel
= bpp
;
117 bm
.bmBits
= (LPVOID
)bits
;
119 return CreateBitmapIndirect( &bm
);
122 /******************************************************************************
123 * CreateCompatibleBitmap [GDI32.@]
125 * Creates a bitmap compatible with the DC.
128 * hdc [I] Handle to device context
129 * width [I] Width of bitmap
130 * height [I] Height of bitmap
133 * Success: Handle to bitmap
136 HBITMAP WINAPI
CreateCompatibleBitmap( HDC hdc
, INT width
, INT height
)
138 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
139 BITMAPINFO
*bi
= (BITMAPINFO
*)buffer
;
142 TRACE("(%p,%d,%d)\n", hdc
, width
, height
);
144 if (GetObjectType( hdc
) != OBJ_MEMDC
)
145 return CreateBitmap( width
, height
,
146 GetDeviceCaps(hdc
, PLANES
), GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
148 switch (GetObjectW( GetCurrentObject( hdc
, OBJ_BITMAP
), sizeof(dib
), &dib
))
150 case sizeof(BITMAP
): /* A device-dependent bitmap is selected in the DC */
151 return CreateBitmap( width
, height
, dib
.dsBm
.bmPlanes
, dib
.dsBm
.bmBitsPixel
, NULL
);
153 case sizeof(DIBSECTION
): /* A DIB section is selected in the DC */
154 bi
->bmiHeader
= dib
.dsBmih
;
155 bi
->bmiHeader
.biWidth
= width
;
156 bi
->bmiHeader
.biHeight
= height
;
157 if (dib
.dsBmih
.biCompression
== BI_BITFIELDS
) /* copy the color masks */
158 memcpy(bi
->bmiColors
, dib
.dsBitfields
, sizeof(dib
.dsBitfields
));
159 else if (dib
.dsBmih
.biBitCount
<= 8) /* copy the color table */
160 GetDIBColorTable(hdc
, 0, 256, bi
->bmiColors
);
161 return CreateDIBSection( hdc
, bi
, DIB_RGB_COLORS
, NULL
, NULL
, 0 );
169 /******************************************************************************
170 * CreateBitmapIndirect [GDI32.@]
172 * Creates a bitmap with the specified info.
175 * bmp [I] Pointer to the bitmap info describing the bitmap
178 * Success: Handle to bitmap
179 * Failure: NULL. Use GetLastError() to determine the cause.
182 * If a width or height of 0 are given, a 1x1 monochrome bitmap is returned.
184 HBITMAP WINAPI
CreateBitmapIndirect( const BITMAP
*bmp
)
190 if (!bmp
|| bmp
->bmType
)
192 SetLastError( ERROR_INVALID_PARAMETER
);
196 if (bmp
->bmWidth
> 0x7ffffff || bmp
->bmHeight
> 0x7ffffff)
198 SetLastError( ERROR_INVALID_PARAMETER
);
204 if (!bm
.bmWidth
|| !bm
.bmHeight
)
206 return GetStockObject( DEFAULT_BITMAP
);
211 bm
.bmHeight
= -bm
.bmHeight
;
213 bm
.bmWidth
= -bm
.bmWidth
;
216 if (bm
.bmPlanes
!= 1)
218 FIXME("planes = %d\n", bm
.bmPlanes
);
219 SetLastError( ERROR_INVALID_PARAMETER
);
223 /* Windows only uses 1, 4, 8, 16, 24 and 32 bpp */
224 if(bm
.bmBitsPixel
== 1) bm
.bmBitsPixel
= 1;
225 else if(bm
.bmBitsPixel
<= 4) bm
.bmBitsPixel
= 4;
226 else if(bm
.bmBitsPixel
<= 8) bm
.bmBitsPixel
= 8;
227 else if(bm
.bmBitsPixel
<= 16) bm
.bmBitsPixel
= 16;
228 else if(bm
.bmBitsPixel
<= 24) bm
.bmBitsPixel
= 24;
229 else if(bm
.bmBitsPixel
<= 32) bm
.bmBitsPixel
= 32;
231 WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm
.bmBitsPixel
);
232 SetLastError(ERROR_INVALID_PARAMETER
);
236 /* Windows ignores the provided bm.bmWidthBytes */
237 bm
.bmWidthBytes
= get_bitmap_stride( bm
.bmWidth
, bm
.bmBitsPixel
);
238 /* XP doesn't allow to create bitmaps larger than 128 Mb */
239 if (bm
.bmHeight
> 128 * 1024 * 1024 / bm
.bmWidthBytes
)
241 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
245 /* Create the BITMAPOBJ */
246 if (!(bmpobj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmpobj
) )))
248 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
252 bmpobj
->dib
.dsBm
= bm
;
253 bmpobj
->dib
.dsBm
.bmBits
= NULL
;
254 bmpobj
->funcs
= &null_driver
;
256 if (!(hbitmap
= alloc_gdi_handle( &bmpobj
->header
, OBJ_BITMAP
, &bitmap_funcs
)))
258 HeapFree( GetProcessHeap(), 0, bmpobj
);
263 SetBitmapBits( hbitmap
, bm
.bmHeight
* bm
.bmWidthBytes
, bm
.bmBits
);
265 TRACE("%dx%d, bpp %d planes %d: returning %p\n", bm
.bmWidth
, bm
.bmHeight
,
266 bm
.bmBitsPixel
, bm
.bmPlanes
, hbitmap
);
272 /***********************************************************************
273 * GetBitmapBits [GDI32.@]
275 * Copies bitmap bits of bitmap to buffer.
278 * Success: Number of bytes copied
281 LONG WINAPI
GetBitmapBits(
282 HBITMAP hbitmap
, /* [in] Handle to bitmap */
283 LONG count
, /* [in] Number of bytes to copy */
284 LPVOID bits
) /* [out] Pointer to buffer to receive bits */
286 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
287 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
288 struct gdi_image_bits src_bits
;
289 struct bitblt_coords src
;
290 int dst_stride
, max
, ret
;
291 BITMAPOBJ
*bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
295 dst_stride
= get_bitmap_stride( bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmBitsPixel
);
296 ret
= max
= dst_stride
* bmp
->dib
.dsBm
.bmHeight
;
297 if (!bits
) goto done
;
298 if (count
> max
) count
= max
;
301 src
.visrect
.left
= 0;
302 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
304 src
.visrect
.bottom
= (count
+ dst_stride
- 1) / dst_stride
;
306 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
307 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
309 if (!bmp
->funcs
->pGetImage( NULL
, hbitmap
, info
, &src_bits
, &src
))
311 const char *src_ptr
= src_bits
.ptr
;
312 int src_stride
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
314 /* GetBitmapBits returns 16-bit aligned data */
316 if (info
->bmiHeader
.biHeight
> 0)
318 src_ptr
+= (info
->bmiHeader
.biHeight
- 1) * src_stride
;
319 src_stride
= -src_stride
;
321 src_ptr
+= src
.visrect
.top
* src_stride
;
323 if (src_stride
== dst_stride
) memcpy( bits
, src_ptr
, count
);
324 else while (count
> 0)
326 memcpy( bits
, src_ptr
, min( count
, dst_stride
) );
327 src_ptr
+= src_stride
;
328 bits
= (char *)bits
+ dst_stride
;
331 if (src_bits
.free
) src_bits
.free( &src_bits
);
336 GDI_ReleaseObj( hbitmap
);
341 /******************************************************************************
342 * SetBitmapBits [GDI32.@]
344 * Sets bits of color data for a bitmap.
347 * Success: Number of bytes used in setting the bitmap bits
350 LONG WINAPI
SetBitmapBits(
351 HBITMAP hbitmap
, /* [in] Handle to bitmap */
352 LONG count
, /* [in] Number of bytes in bitmap array */
353 LPCVOID bits
) /* [in] Address of array with bitmap bits */
355 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
356 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
359 int i
, src_stride
, dst_stride
;
360 struct bitblt_coords src
, dst
;
361 struct gdi_image_bits src_bits
;
366 bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
370 WARN("(%d): Negative number of bytes passed???\n", count
);
374 src_stride
= get_bitmap_stride( bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmBitsPixel
);
375 count
= min( count
, src_stride
* bmp
->dib
.dsBm
.bmHeight
);
377 dst_stride
= get_dib_stride( bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmBitsPixel
);
379 src
.visrect
.left
= src
.x
= 0;
380 src
.visrect
.top
= src
.y
= 0;
381 src
.visrect
.right
= src
.width
= bmp
->dib
.dsBm
.bmWidth
;
382 src
.visrect
.bottom
= src
.height
= (count
+ src_stride
- 1 ) / src_stride
;
385 if (count
% src_stride
)
388 int extra_pixels
= ((count
% src_stride
) << 3) / bmp
->dib
.dsBm
.bmBitsPixel
;
390 if ((count
% src_stride
<< 3) % bmp
->dib
.dsBm
.bmBitsPixel
)
391 FIXME( "Unhandled partial pixel\n" );
392 clip
= CreateRectRgn( src
.visrect
.left
, src
.visrect
.top
,
393 src
.visrect
.right
, src
.visrect
.bottom
- 1 );
394 last_row
= CreateRectRgn( src
.visrect
.left
, src
.visrect
.bottom
- 1,
395 src
.visrect
.left
+ extra_pixels
, src
.visrect
.bottom
);
396 CombineRgn( clip
, clip
, last_row
, RGN_OR
);
397 DeleteObject( last_row
);
400 TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n",
401 hbitmap
, count
, bits
, bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmHeight
,
402 bmp
->dib
.dsBm
.bmBitsPixel
, src
.height
);
404 if (src_stride
== dst_stride
)
406 src_bits
.ptr
= (void *)bits
;
407 src_bits
.is_copy
= FALSE
;
408 src_bits
.free
= NULL
;
412 if (!(src_bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, dst
.height
* dst_stride
)))
414 GDI_ReleaseObj( hbitmap
);
417 src_bits
.is_copy
= TRUE
;
418 src_bits
.free
= free_heap_bits
;
419 for (i
= 0; i
< count
/ src_stride
; i
++)
420 memcpy( (char *)src_bits
.ptr
+ i
* dst_stride
, (char *)bits
+ i
* src_stride
, src_stride
);
421 if (count
% src_stride
)
422 memcpy( (char *)src_bits
.ptr
+ i
* dst_stride
, (char *)bits
+ i
* src_stride
, count
% src_stride
);
425 /* query the color info */
426 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
427 info
->bmiHeader
.biPlanes
= 1;
428 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
429 info
->bmiHeader
.biCompression
= BI_RGB
;
430 info
->bmiHeader
.biXPelsPerMeter
= 0;
431 info
->bmiHeader
.biYPelsPerMeter
= 0;
432 info
->bmiHeader
.biClrUsed
= 0;
433 info
->bmiHeader
.biClrImportant
= 0;
434 info
->bmiHeader
.biWidth
= 0;
435 info
->bmiHeader
.biHeight
= 0;
436 info
->bmiHeader
.biSizeImage
= 0;
437 err
= bmp
->funcs
->pPutImage( NULL
, hbitmap
, 0, info
, NULL
, NULL
, NULL
, SRCCOPY
);
439 if (!err
|| err
== ERROR_BAD_FORMAT
)
441 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
442 info
->bmiHeader
.biHeight
= -dst
.height
;
443 info
->bmiHeader
.biSizeImage
= dst
.height
* dst_stride
;
444 err
= bmp
->funcs
->pPutImage( NULL
, hbitmap
, clip
, info
, &src_bits
, &src
, &dst
, SRCCOPY
);
448 if (clip
) DeleteObject( clip
);
449 if (src_bits
.free
) src_bits
.free( &src_bits
);
450 GDI_ReleaseObj( hbitmap
);
455 static void set_initial_bitmap_bits( HBITMAP hbitmap
, BITMAPOBJ
*bmp
)
457 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
458 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
459 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
460 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
462 struct gdi_image_bits bits
;
463 struct bitblt_coords src
, dst
;
465 if (!bmp
->dib
.dsBm
.bmBits
) return;
466 if (bmp
->funcs
->pPutImage
== nulldrv_PutImage
) return;
468 get_ddb_bitmapinfo( bmp
, src_info
);
470 bits
.ptr
= bmp
->dib
.dsBm
.bmBits
;
471 bits
.is_copy
= FALSE
;
477 src
.width
= bmp
->dib
.dsBm
.bmWidth
;
478 src
.height
= bmp
->dib
.dsBm
.bmHeight
;
479 src
.visrect
.left
= 0;
481 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
482 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
485 copy_bitmapinfo( dst_info
, src_info
);
487 err
= bmp
->funcs
->pPutImage( NULL
, hbitmap
, 0, dst_info
, &bits
, &src
, &dst
, 0 );
488 if (err
== ERROR_BAD_FORMAT
)
490 err
= convert_bits( src_info
, &src
, dst_info
, &bits
, FALSE
);
491 if (!err
) err
= bmp
->funcs
->pPutImage( NULL
, hbitmap
, 0, dst_info
, &bits
, &src
, &dst
, 0 );
492 if (bits
.free
) bits
.free( &bits
);
496 /***********************************************************************
499 * Set the type of DC that owns the bitmap. This is used when the
500 * bitmap is selected into a device to initialize the bitmap function
503 static BOOL
BITMAP_SetOwnerDC( HBITMAP hbitmap
, PHYSDEV physdev
)
508 /* never set the owner of the stock bitmap since it can be selected in multiple DCs */
509 if (hbitmap
== GetStockObject(DEFAULT_BITMAP
)) return TRUE
;
511 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return FALSE
;
513 if (bitmap
->funcs
!= physdev
->funcs
)
515 /* we can only change from the null driver to some other driver */
516 if (bitmap
->funcs
== &null_driver
)
518 if (physdev
->funcs
->pCreateBitmap
)
520 ret
= physdev
->funcs
->pCreateBitmap( physdev
, hbitmap
);
523 bitmap
->funcs
= physdev
->funcs
;
524 set_initial_bitmap_bits( hbitmap
, bitmap
);
527 else bitmap
->funcs
= &dib_driver
; /* use the DIB driver to emulate DDB support */
531 FIXME( "Trying to select bitmap %p in different DC type\n", hbitmap
);
535 GDI_ReleaseObj( hbitmap
);
540 /***********************************************************************
541 * BITMAP_SelectObject
543 static HGDIOBJ
BITMAP_SelectObject( HGDIOBJ handle
, HDC hdc
)
548 PHYSDEV physdev
= NULL
, old_physdev
= NULL
, pathdev
= NULL
;
550 if (!(dc
= get_dc_ptr( hdc
))) return 0;
552 if (GetObjectType( hdc
) != OBJ_MEMDC
)
558 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
560 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
566 if (bitmap
->header
.selcount
&& (handle
!= GetStockObject(DEFAULT_BITMAP
)))
568 WARN( "Bitmap already selected in another DC\n" );
569 GDI_ReleaseObj( handle
);
574 if (dc
->physDev
->funcs
== &path_driver
) pathdev
= pop_dc_driver( &dc
->physDev
);
576 old_physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
577 if(old_physdev
== dc
->dibdrv
)
578 old_physdev
= pop_dc_driver( &dc
->physDev
);
580 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
581 if (physdev
->funcs
== &null_driver
)
583 physdev
= dc
->dibdrv
;
584 if (physdev
) push_dc_driver( &dc
->physDev
, physdev
, physdev
->funcs
);
587 if (!dib_driver
.pCreateDC( &dc
->physDev
, NULL
, NULL
, NULL
, NULL
)) goto done
;
588 dc
->dibdrv
= physdev
= dc
->physDev
;
592 if (!BITMAP_SetOwnerDC( handle
, physdev
))
594 GDI_ReleaseObj( handle
);
598 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
600 GDI_ReleaseObj( handle
);
605 dc
->hBitmap
= handle
;
606 GDI_inc_ref_count( handle
);
608 dc
->vis_rect
.left
= 0;
609 dc
->vis_rect
.top
= 0;
610 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
611 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
612 GDI_ReleaseObj( handle
);
614 GDI_dec_ref_count( ret
);
620 if (physdev
&& physdev
== dc
->dibdrv
)
621 pop_dc_driver( &dc
->physDev
);
622 if (old_physdev
&& old_physdev
== dc
->dibdrv
)
623 push_dc_driver( &dc
->physDev
, old_physdev
, old_physdev
->funcs
);
625 if (pathdev
) push_dc_driver( &dc
->physDev
, pathdev
, pathdev
->funcs
);
626 release_dc_ptr( dc
);
631 /***********************************************************************
632 * BITMAP_DeleteObject
634 static BOOL
BITMAP_DeleteObject( HGDIOBJ handle
)
636 const struct gdi_dc_funcs
*funcs
;
637 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
639 if (!bmp
) return FALSE
;
641 GDI_ReleaseObj( handle
);
643 funcs
->pDeleteBitmap( handle
);
645 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
647 HeapFree( GetProcessHeap(), 0, bmp
->dib
.dsBm
.bmBits
);
648 return HeapFree( GetProcessHeap(), 0, bmp
);
652 /***********************************************************************
655 static INT
BITMAP_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
658 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
662 if (!buffer
) ret
= sizeof(BITMAP
);
663 else if (count
>= sizeof(BITMAP
))
665 BITMAP
*bitmap
= buffer
;
666 *bitmap
= bmp
->dib
.dsBm
;
667 bitmap
->bmBits
= NULL
;
668 ret
= sizeof(BITMAP
);
670 GDI_ReleaseObj( handle
);
675 /******************************************************************************
676 * CreateDiscardableBitmap [GDI32.@]
678 * Creates a discardable bitmap.
681 * Success: Handle to bitmap
684 HBITMAP WINAPI
CreateDiscardableBitmap(
685 HDC hdc
, /* [in] Handle to device context */
686 INT width
, /* [in] Bitmap width */
687 INT height
) /* [in] Bitmap height */
689 return CreateCompatibleBitmap( hdc
, width
, height
);
693 /******************************************************************************
694 * GetBitmapDimensionEx [GDI32.@]
696 * Retrieves dimensions of a bitmap.
702 BOOL WINAPI
GetBitmapDimensionEx(
703 HBITMAP hbitmap
, /* [in] Handle to bitmap */
704 LPSIZE size
) /* [out] Address of struct receiving dimensions */
706 BITMAPOBJ
* bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
707 if (!bmp
) return FALSE
;
709 GDI_ReleaseObj( hbitmap
);
714 /******************************************************************************
715 * SetBitmapDimensionEx [GDI32.@]
717 * Assigns dimensions to a bitmap.
718 * MSDN says that this function will fail if hbitmap is a handle created by
719 * CreateDIBSection, but that's not true on Windows 2000.
725 BOOL WINAPI
SetBitmapDimensionEx(
726 HBITMAP hbitmap
, /* [in] Handle to bitmap */
727 INT x
, /* [in] Bitmap width */
728 INT y
, /* [in] Bitmap height */
729 LPSIZE prevSize
) /* [out] Address of structure for orig dims */
731 BITMAPOBJ
* bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
);
732 if (!bmp
) return FALSE
;
733 if (prevSize
) *prevSize
= bmp
->size
;
736 GDI_ReleaseObj( hbitmap
);