gdi32: Graphics driver functions no longer need to be CDECL.
[wine/wine-gecko.git] / dlls / gdi32 / bitmap.c
blob36a04a71a367a7e0974e16bdd25ae48927a451ef
1 /*
2 * GDI bitmap objects
4 * Copyright 1993 Alexandre Julliard
5 * 1998 Huw D M Davies
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
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
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 LONG nulldrv_GetBitmapBits( HBITMAP bitmap, void *bits, LONG size )
55 BITMAPOBJ *bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP );
57 if (bmp->bitmap.bmBits) memcpy( bits, bmp->bitmap.bmBits, size );
58 else memset( bits, 0, size );
59 GDI_ReleaseObj( bitmap );
60 return size;
63 LONG nulldrv_SetBitmapBits( HBITMAP bitmap, const void *bits, LONG size )
65 BITMAPOBJ *bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP );
67 if (!bmp->bitmap.bmBits)
69 LONG total = bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes; /* alloc enough for entire bitmap */
70 if (!(bmp->bitmap.bmBits = HeapAlloc( GetProcessHeap(), 0, total )))
72 GDI_ReleaseObj( bitmap );
73 return 0;
75 if (size < total) memset( (char *)bmp->bitmap.bmBits + size, 0, total - size );
77 memcpy( bmp->bitmap.bmBits, bits, size );
78 GDI_ReleaseObj( bitmap );
79 return size;
82 INT nulldrv_GetDIBits( PHYSDEV dev, HBITMAP bitmap, UINT start, UINT lines, LPVOID bits,
83 BITMAPINFO *info, UINT coloruse )
85 /* FIXME: transfer bits from bmp->bitmap.bmBits */
86 return 0;
89 INT nulldrv_SetDIBits( PHYSDEV dev, HBITMAP bitmap, UINT start, UINT lines,
90 const void *bits, const BITMAPINFO *info, UINT coloruse )
92 /* FIXME: transfer bits to bmp->bitmap.bmBits */
93 return 0;
96 /***********************************************************************
97 * BITMAP_GetWidthBytes
99 * Return number of bytes taken by a scanline of 16-bit aligned Windows DDB
100 * data.
102 INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp )
104 switch(bpp)
106 case 1:
107 return 2 * ((bmWidth+15) >> 4);
109 case 24:
110 bmWidth *= 3; /* fall through */
111 case 8:
112 return bmWidth + (bmWidth & 1);
114 case 32:
115 return bmWidth * 4;
117 case 16:
118 case 15:
119 return bmWidth * 2;
121 case 4:
122 return 2 * ((bmWidth+3) >> 2);
124 default:
125 WARN("Unknown depth %d, please report.\n", bpp );
127 return -1;
131 /******************************************************************************
132 * CreateBitmap [GDI32.@]
134 * Creates a bitmap with the specified info.
136 * PARAMS
137 * width [I] bitmap width
138 * height [I] bitmap height
139 * planes [I] Number of color planes
140 * bpp [I] Number of bits to identify a color
141 * bits [I] Pointer to array containing color data
143 * RETURNS
144 * Success: Handle to bitmap
145 * Failure: 0
147 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
148 UINT bpp, LPCVOID bits )
150 BITMAP bm;
152 bm.bmType = 0;
153 bm.bmWidth = width;
154 bm.bmHeight = height;
155 bm.bmWidthBytes = BITMAP_GetWidthBytes( width, bpp );
156 bm.bmPlanes = planes;
157 bm.bmBitsPixel = bpp;
158 bm.bmBits = (LPVOID)bits;
160 return CreateBitmapIndirect( &bm );
163 /******************************************************************************
164 * CreateCompatibleBitmap [GDI32.@]
166 * Creates a bitmap compatible with the DC.
168 * PARAMS
169 * hdc [I] Handle to device context
170 * width [I] Width of bitmap
171 * height [I] Height of bitmap
173 * RETURNS
174 * Success: Handle to bitmap
175 * Failure: 0
177 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
179 HBITMAP hbmpRet = 0;
181 TRACE("(%p,%d,%d) =\n", hdc, width, height);
183 if (GetObjectType( hdc ) != OBJ_MEMDC)
185 hbmpRet = CreateBitmap(width, height,
186 GetDeviceCaps(hdc, PLANES),
187 GetDeviceCaps(hdc, BITSPIXEL),
188 NULL);
190 else /* Memory DC */
192 DIBSECTION dib;
193 HBITMAP bitmap = GetCurrentObject( hdc, OBJ_BITMAP );
194 INT size = GetObjectW( bitmap, sizeof(dib), &dib );
196 if (!size) return 0;
198 if (size == sizeof(BITMAP))
200 /* A device-dependent bitmap is selected in the DC */
201 hbmpRet = CreateBitmap(width, height,
202 dib.dsBm.bmPlanes,
203 dib.dsBm.bmBitsPixel,
204 NULL);
206 else
208 /* A DIB section is selected in the DC */
209 BITMAPINFO *bi;
210 void *bits;
212 /* Allocate memory for a BITMAPINFOHEADER structure and a
213 color table. The maximum number of colors in a color table
214 is 256 which corresponds to a bitmap with depth 8.
215 Bitmaps with higher depths don't have color tables. */
216 bi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
218 if (bi)
220 bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
221 bi->bmiHeader.biWidth = width;
222 bi->bmiHeader.biHeight = height;
223 bi->bmiHeader.biPlanes = dib.dsBmih.biPlanes;
224 bi->bmiHeader.biBitCount = dib.dsBmih.biBitCount;
225 bi->bmiHeader.biCompression = dib.dsBmih.biCompression;
226 bi->bmiHeader.biSizeImage = 0;
227 bi->bmiHeader.biXPelsPerMeter = dib.dsBmih.biXPelsPerMeter;
228 bi->bmiHeader.biYPelsPerMeter = dib.dsBmih.biYPelsPerMeter;
229 bi->bmiHeader.biClrUsed = dib.dsBmih.biClrUsed;
230 bi->bmiHeader.biClrImportant = dib.dsBmih.biClrImportant;
232 if (bi->bmiHeader.biCompression == BI_BITFIELDS)
234 /* Copy the color masks */
235 CopyMemory(bi->bmiColors, dib.dsBitfields, 3 * sizeof(DWORD));
237 else if (bi->bmiHeader.biBitCount <= 8)
239 /* Copy the color table */
240 GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
243 hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
244 HeapFree(GetProcessHeap(), 0, bi);
249 TRACE("\t\t%p\n", hbmpRet);
250 return hbmpRet;
254 /******************************************************************************
255 * CreateBitmapIndirect [GDI32.@]
257 * Creates a bitmap with the specified info.
259 * PARAMS
260 * bmp [I] Pointer to the bitmap info describing the bitmap
262 * RETURNS
263 * Success: Handle to bitmap
264 * Failure: NULL. Use GetLastError() to determine the cause.
266 * NOTES
267 * If a width or height of 0 are given, a 1x1 monochrome bitmap is returned.
269 HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
271 BITMAP bm;
272 BITMAPOBJ *bmpobj;
273 HBITMAP hbitmap;
275 if (!bmp || bmp->bmType)
277 SetLastError( ERROR_INVALID_PARAMETER );
278 return NULL;
281 if (bmp->bmWidth > 0x7ffffff || bmp->bmHeight > 0x7ffffff)
283 SetLastError( ERROR_INVALID_PARAMETER );
284 return 0;
287 bm = *bmp;
289 if (!bm.bmWidth || !bm.bmHeight)
291 return GetStockObject( DEFAULT_BITMAP );
293 else
295 if (bm.bmHeight < 0)
296 bm.bmHeight = -bm.bmHeight;
297 if (bm.bmWidth < 0)
298 bm.bmWidth = -bm.bmWidth;
301 if (bm.bmPlanes != 1)
303 FIXME("planes = %d\n", bm.bmPlanes);
304 SetLastError( ERROR_INVALID_PARAMETER );
305 return NULL;
308 /* Windows only uses 1, 4, 8, 16, 24 and 32 bpp */
309 if(bm.bmBitsPixel == 1) bm.bmBitsPixel = 1;
310 else if(bm.bmBitsPixel <= 4) bm.bmBitsPixel = 4;
311 else if(bm.bmBitsPixel <= 8) bm.bmBitsPixel = 8;
312 else if(bm.bmBitsPixel <= 16) bm.bmBitsPixel = 16;
313 else if(bm.bmBitsPixel <= 24) bm.bmBitsPixel = 24;
314 else if(bm.bmBitsPixel <= 32) bm.bmBitsPixel = 32;
315 else {
316 WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm.bmBitsPixel);
317 SetLastError(ERROR_INVALID_PARAMETER);
318 return NULL;
321 /* Windows ignores the provided bm.bmWidthBytes */
322 bm.bmWidthBytes = BITMAP_GetWidthBytes( bm.bmWidth, bm.bmBitsPixel );
323 /* XP doesn't allow to create bitmaps larger than 128 Mb */
324 if (bm.bmHeight > 128 * 1024 * 1024 / bm.bmWidthBytes)
326 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
327 return 0;
330 /* Create the BITMAPOBJ */
331 if (!(bmpobj = HeapAlloc( GetProcessHeap(), 0, sizeof(*bmpobj) )))
333 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
334 return 0;
337 bmpobj->size.cx = 0;
338 bmpobj->size.cy = 0;
339 bmpobj->bitmap = bm;
340 bmpobj->bitmap.bmBits = NULL;
341 bmpobj->funcs = &null_driver;
342 bmpobj->dib = NULL;
343 bmpobj->color_table = NULL;
344 bmpobj->nb_colors = 0;
346 if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs )))
348 HeapFree( GetProcessHeap(), 0, bmpobj );
349 return 0;
352 if (bm.bmBits)
353 SetBitmapBits( hbitmap, bm.bmHeight * bm.bmWidthBytes, bm.bmBits );
355 TRACE("%dx%d, %d colors returning %p\n", bm.bmWidth, bm.bmHeight,
356 1 << (bm.bmPlanes * bm.bmBitsPixel), hbitmap);
358 return hbitmap;
362 /***********************************************************************
363 * GetBitmapBits [GDI32.@]
365 * Copies bitmap bits of bitmap to buffer.
367 * RETURNS
368 * Success: Number of bytes copied
369 * Failure: 0
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 BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
377 LONG height, ret;
379 if (!bmp) return 0;
381 if (bmp->dib) /* simply copy the bits from the DIB */
383 DIBSECTION *dib = bmp->dib;
384 const char *src = dib->dsBm.bmBits;
385 INT width_bytes = BITMAP_GetWidthBytes(dib->dsBm.bmWidth, dib->dsBm.bmBitsPixel);
386 LONG max = width_bytes * bmp->bitmap.bmHeight;
388 if (!bits)
390 ret = max;
391 goto done;
394 if (count > max) count = max;
395 ret = count;
397 /* GetBitmapBits returns not 32-bit aligned data */
399 if (bmp->dib->dsBmih.biHeight >= 0) /* not top-down, need to flip contents vertically */
401 src += dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
402 while (count > 0)
404 src -= dib->dsBm.bmWidthBytes;
405 memcpy( bits, src, min( count, width_bytes ) );
406 bits = (char *)bits + width_bytes;
407 count -= width_bytes;
410 else
412 while (count > 0)
414 memcpy( bits, src, min( count, width_bytes ) );
415 src += dib->dsBm.bmWidthBytes;
416 bits = (char *)bits + width_bytes;
417 count -= width_bytes;
420 goto done;
423 /* If the bits vector is null, the function should return the read size */
424 if(bits == NULL)
426 ret = bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
427 goto done;
430 if (count < 0) {
431 WARN("(%d): Negative number of bytes passed???\n", count );
432 count = -count;
435 /* Only get entire lines */
436 height = count / bmp->bitmap.bmWidthBytes;
437 if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
438 count = height * bmp->bitmap.bmWidthBytes;
439 if (count == 0)
441 WARN("Less than one entire line requested\n");
442 ret = 0;
443 goto done;
447 TRACE("(%p, %d, %p) %dx%d %d colors fetched height: %d\n",
448 hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
449 1 << bmp->bitmap.bmBitsPixel, height );
451 ret = bmp->funcs->pGetBitmapBits( hbitmap, bits, count );
452 done:
453 GDI_ReleaseObj( hbitmap );
454 return ret;
458 /******************************************************************************
459 * SetBitmapBits [GDI32.@]
461 * Sets bits of color data for a bitmap.
463 * RETURNS
464 * Success: Number of bytes used in setting the bitmap bits
465 * Failure: 0
467 LONG WINAPI SetBitmapBits(
468 HBITMAP hbitmap, /* [in] Handle to bitmap */
469 LONG count, /* [in] Number of bytes in bitmap array */
470 LPCVOID bits) /* [in] Address of array with bitmap bits */
472 BITMAPOBJ *bmp;
473 LONG height, ret;
475 if (!bits) return 0;
477 bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
478 if (!bmp) return 0;
480 if (count < 0) {
481 WARN("(%d): Negative number of bytes passed???\n", count );
482 count = -count;
485 if (bmp->dib) /* simply copy the bits into the DIB */
487 DIBSECTION *dib = bmp->dib;
488 char *dest = dib->dsBm.bmBits;
489 LONG max = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
490 if (count > max) count = max;
491 ret = count;
493 if (bmp->dib->dsBmih.biHeight >= 0) /* not top-down, need to flip contents vertically */
495 dest += dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
496 while (count > 0)
498 dest -= dib->dsBm.bmWidthBytes;
499 memcpy( dest, bits, min( count, dib->dsBm.bmWidthBytes ) );
500 bits = (const char *)bits + dib->dsBm.bmWidthBytes;
501 count -= dib->dsBm.bmWidthBytes;
504 else memcpy( dest, bits, count );
506 GDI_ReleaseObj( hbitmap );
507 return ret;
510 /* Only get entire lines */
511 height = count / bmp->bitmap.bmWidthBytes;
512 if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
513 count = height * bmp->bitmap.bmWidthBytes;
515 TRACE("(%p, %d, %p) %dx%d %d colors fetched height: %d\n",
516 hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
517 1 << bmp->bitmap.bmBitsPixel, height );
519 ret = bmp->funcs->pSetBitmapBits( hbitmap, bits, count );
520 GDI_ReleaseObj( hbitmap );
521 return ret;
524 /**********************************************************************
525 * BITMAP_CopyBitmap
528 HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap)
530 HBITMAP res;
531 DIBSECTION dib;
532 BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
534 if (!bmp) return 0;
535 if (bmp->dib)
537 void *bits;
538 BITMAPINFO *bi;
539 HDC dc;
541 dib = *bmp->dib;
542 GDI_ReleaseObj( hbitmap );
543 dc = CreateCompatibleDC( NULL );
545 if (!dc) return 0;
546 if (!(bi = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ))))
548 DeleteDC( dc );
549 return 0;
551 bi->bmiHeader = dib.dsBmih;
553 /* Get the color table or the color masks */
554 GetDIBits( dc, hbitmap, 0, 0, NULL, bi, DIB_RGB_COLORS );
555 bi->bmiHeader.biHeight = dib.dsBmih.biHeight;
557 res = CreateDIBSection( dc, bi, DIB_RGB_COLORS, &bits, NULL, 0 );
558 if (res) SetDIBits( dc, res, 0, dib.dsBm.bmHeight, dib.dsBm.bmBits, bi, DIB_RGB_COLORS );
559 HeapFree( GetProcessHeap(), 0, bi );
560 DeleteDC( dc );
561 return res;
563 dib.dsBm = bmp->bitmap;
564 dib.dsBm.bmBits = NULL;
565 GDI_ReleaseObj( hbitmap );
567 res = CreateBitmapIndirect( &dib.dsBm );
568 if(res) {
569 char *buf = HeapAlloc( GetProcessHeap(), 0, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight );
570 GetBitmapBits (hbitmap, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight, buf);
571 SetBitmapBits (res, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight, buf);
572 HeapFree( GetProcessHeap(), 0, buf );
574 return res;
578 /***********************************************************************
579 * BITMAP_SetOwnerDC
581 * Set the type of DC that owns the bitmap. This is used when the
582 * bitmap is selected into a device to initialize the bitmap function
583 * table.
585 BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev )
587 BITMAPOBJ *bitmap;
588 BOOL ret = TRUE;
590 /* never set the owner of the stock bitmap since it can be selected in multiple DCs */
591 if (hbitmap == GetStockObject(DEFAULT_BITMAP)) return TRUE;
593 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE;
595 if (!bitmap->dib && bitmap->funcs != physdev->funcs)
597 /* we can only change from the null driver to some other driver */
598 if (bitmap->funcs == &null_driver)
600 if (physdev->funcs->pCreateBitmap)
602 ret = physdev->funcs->pCreateBitmap( physdev, hbitmap, bitmap->bitmap.bmBits );
603 if (ret) bitmap->funcs = physdev->funcs;
605 else
607 WARN( "Trying to select bitmap %p in DC that doesn't support it\n", hbitmap );
608 ret = FALSE;
611 else
613 FIXME( "Trying to select bitmap %p in different DC type\n", hbitmap );
614 ret = FALSE;
617 GDI_ReleaseObj( hbitmap );
618 return ret;
622 /***********************************************************************
623 * BITMAP_SelectObject
625 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
627 HGDIOBJ ret;
628 BITMAPOBJ *bitmap;
629 DC *dc;
630 PHYSDEV physdev = NULL, old_physdev = NULL;
632 if (!(dc = get_dc_ptr( hdc ))) return 0;
634 if (GetObjectType( hdc ) != OBJ_MEMDC)
636 ret = 0;
637 goto done;
639 ret = dc->hBitmap;
640 if (handle == dc->hBitmap) goto done; /* nothing to do */
642 if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
644 ret = 0;
645 goto done;
648 if (bitmap->header.selcount && (handle != GetStockObject(DEFAULT_BITMAP)))
650 WARN( "Bitmap already selected in another DC\n" );
651 GDI_ReleaseObj( handle );
652 ret = 0;
653 goto done;
656 old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
657 if(old_physdev == &dc->dibdrv.dev)
658 pop_dc_driver( dc, old_physdev );
660 if(bitmap->dib)
662 physdev = &dc->dibdrv.dev;
663 push_dc_driver( dc, physdev, physdev->funcs );
665 else
666 physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
668 if (!BITMAP_SetOwnerDC( handle, physdev ))
670 GDI_ReleaseObj( handle );
671 ret = 0;
672 goto done;
674 if (!physdev->funcs->pSelectBitmap( physdev, handle ))
676 GDI_ReleaseObj( handle );
677 ret = 0;
679 else
681 dc->hBitmap = handle;
682 GDI_inc_ref_count( handle );
683 dc->dirty = 0;
684 dc->vis_rect.left = 0;
685 dc->vis_rect.top = 0;
686 dc->vis_rect.right = bitmap->bitmap.bmWidth;
687 dc->vis_rect.bottom = bitmap->bitmap.bmHeight;
688 SetRectRgn( dc->hVisRgn, 0, 0, bitmap->bitmap.bmWidth, bitmap->bitmap.bmHeight);
689 GDI_ReleaseObj( handle );
690 DC_InitDC( dc );
691 GDI_dec_ref_count( ret );
694 done:
695 if(!ret)
697 if(physdev == &dc->dibdrv.dev) pop_dc_driver( dc, physdev );
698 if(old_physdev == &dc->dibdrv.dev) push_dc_driver( dc, old_physdev, old_physdev->funcs );
700 release_dc_ptr( dc );
701 return ret;
705 /***********************************************************************
706 * BITMAP_DeleteObject
708 static BOOL BITMAP_DeleteObject( HGDIOBJ handle )
710 const DC_FUNCTIONS *funcs;
711 BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
713 if (!bmp) return FALSE;
714 funcs = bmp->funcs;
715 GDI_ReleaseObj( handle );
717 funcs->pDeleteBitmap( handle );
719 if (!(bmp = free_gdi_handle( handle ))) return FALSE;
721 HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits );
723 if (bmp->dib)
725 DIBSECTION *dib = bmp->dib;
727 if (dib->dsBm.bmBits)
729 if (dib->dshSection)
731 SYSTEM_INFO SystemInfo;
732 GetSystemInfo( &SystemInfo );
733 UnmapViewOfFile( (char *)dib->dsBm.bmBits -
734 (dib->dsOffset % SystemInfo.dwAllocationGranularity) );
736 else if (!dib->dsOffset)
737 VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE );
739 HeapFree(GetProcessHeap(), 0, dib);
740 HeapFree(GetProcessHeap(), 0, bmp->color_table);
742 return HeapFree( GetProcessHeap(), 0, bmp );
746 /***********************************************************************
747 * BITMAP_GetObject
749 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
751 INT ret;
752 BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
754 if (!bmp) return 0;
756 if (!buffer) ret = sizeof(BITMAP);
757 else if (count < sizeof(BITMAP)) ret = 0;
758 else if (bmp->dib)
760 if (count >= sizeof(DIBSECTION))
762 DIBSECTION *dib = buffer;
763 *dib = *bmp->dib;
764 dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
765 ret = sizeof(DIBSECTION);
767 else /* if (count >= sizeof(BITMAP)) */
769 DIBSECTION *dib = bmp->dib;
770 memcpy( buffer, &dib->dsBm, sizeof(BITMAP) );
771 ret = sizeof(BITMAP);
774 else
776 memcpy( buffer, &bmp->bitmap, sizeof(BITMAP) );
777 ((BITMAP *) buffer)->bmBits = NULL;
778 ret = sizeof(BITMAP);
780 GDI_ReleaseObj( handle );
781 return ret;
785 /******************************************************************************
786 * CreateDiscardableBitmap [GDI32.@]
788 * Creates a discardable bitmap.
790 * RETURNS
791 * Success: Handle to bitmap
792 * Failure: NULL
794 HBITMAP WINAPI CreateDiscardableBitmap(
795 HDC hdc, /* [in] Handle to device context */
796 INT width, /* [in] Bitmap width */
797 INT height) /* [in] Bitmap height */
799 return CreateCompatibleBitmap( hdc, width, height );
803 /******************************************************************************
804 * GetBitmapDimensionEx [GDI32.@]
806 * Retrieves dimensions of a bitmap.
808 * RETURNS
809 * Success: TRUE
810 * Failure: FALSE
812 BOOL WINAPI GetBitmapDimensionEx(
813 HBITMAP hbitmap, /* [in] Handle to bitmap */
814 LPSIZE size) /* [out] Address of struct receiving dimensions */
816 BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
817 if (!bmp) return FALSE;
818 *size = bmp->size;
819 GDI_ReleaseObj( hbitmap );
820 return TRUE;
824 /******************************************************************************
825 * SetBitmapDimensionEx [GDI32.@]
827 * Assigns dimensions to a bitmap.
828 * MSDN says that this function will fail if hbitmap is a handle created by
829 * CreateDIBSection, but that's not true on Windows 2000.
831 * RETURNS
832 * Success: TRUE
833 * Failure: FALSE
835 BOOL WINAPI SetBitmapDimensionEx(
836 HBITMAP hbitmap, /* [in] Handle to bitmap */
837 INT x, /* [in] Bitmap width */
838 INT y, /* [in] Bitmap height */
839 LPSIZE prevSize) /* [out] Address of structure for orig dims */
841 BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
842 if (!bmp) return FALSE;
843 if (prevSize) *prevSize = bmp->size;
844 bmp->size.cx = x;
845 bmp->size.cy = y;
846 GDI_ReleaseObj( hbitmap );
847 return TRUE;