winex11: Force the alpha channel to zero for mono->color blits.
[wine] / dlls / gdi32 / bitmap.c
1 /*
2  * GDI bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1998 Huw D M Davies
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "gdi_private.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
33
34
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 );
38
39 static const struct gdi_obj_funcs bitmap_funcs =
40 {
41     BITMAP_SelectObject,  /* pSelectObject */
42     BITMAP_GetObject,     /* pGetObjectA */
43     BITMAP_GetObject,     /* pGetObjectW */
44     NULL,                 /* pUnrealizeObject */
45     BITMAP_DeleteObject   /* pDeleteObject */
46 };
47
48
49 /***********************************************************************
50  *           null driver fallback implementations
51  */
52
53 DWORD nulldrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
54                         struct gdi_image_bits *bits, struct bitblt_coords *src )
55 {
56     BITMAPOBJ *bmp;
57     DWORD ret;
58
59     if (!hbitmap) return ERROR_NOT_SUPPORTED;
60     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return ERROR_INVALID_HANDLE;
61
62     if (bmp->bitmap.bmBits || !bits)
63     {
64         ret = dib_driver.pGetImage( 0, hbitmap, info, bits, src );
65     }
66     else if (!(ret = dib_driver.pGetImage( 0, hbitmap, info, NULL, src )))
67     {
68         info->bmiHeader.biHeight = -(src->visrect.bottom - src->visrect.top);
69         info->bmiHeader.biSizeImage = get_dib_image_size( info );
70
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 );
74
75         /* return all-zero bits */
76         bits->ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage );
77         bits->is_copy = TRUE;
78         bits->free = free_heap_bits;
79     }
80     GDI_ReleaseObj( hbitmap );
81     return ret;
82 }
83
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 )
87 {
88     BITMAPOBJ *bmp;
89
90     if (!hbitmap) return ERROR_SUCCESS;
91
92     if (bits)
93     {
94         if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return ERROR_INVALID_HANDLE;
95         if (!bmp->bitmap.bmBits)
96         {
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 )))
100             {
101                 GDI_ReleaseObj( hbitmap );
102                 return ERROR_OUTOFMEMORY;
103             }
104         }
105         GDI_ReleaseObj( hbitmap );
106     }
107     return dib_driver.pPutImage( NULL, hbitmap, clip, info, bits, src, dst, rop );
108 }
109
110
111 /******************************************************************************
112  * CreateBitmap [GDI32.@]
113  *
114  * Creates a bitmap with the specified info.
115  *
116  * PARAMS
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
122  *
123  * RETURNS
124  *    Success: Handle to bitmap
125  *    Failure: 0
126  */
127 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
128                              UINT bpp, LPCVOID bits )
129 {
130     BITMAP bm;
131
132     bm.bmType = 0;
133     bm.bmWidth = width;
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;
139
140     return CreateBitmapIndirect( &bm );
141 }
142
143 /******************************************************************************
144  * CreateCompatibleBitmap [GDI32.@]
145  *
146  * Creates a bitmap compatible with the DC.
147  *
148  * PARAMS
149  *    hdc    [I] Handle to device context
150  *    width  [I] Width of bitmap
151  *    height [I] Height of bitmap
152  *
153  * RETURNS
154  *    Success: Handle to bitmap
155  *    Failure: 0
156  */
157 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
158 {
159     HBITMAP hbmpRet = 0;
160
161     TRACE("(%p,%d,%d) =\n", hdc, width, height);
162
163     if (GetObjectType( hdc ) != OBJ_MEMDC)
164     {
165         hbmpRet = CreateBitmap(width, height,
166                                GetDeviceCaps(hdc, PLANES),
167                                GetDeviceCaps(hdc, BITSPIXEL),
168                                NULL);
169     }
170     else  /* Memory DC */
171     {
172         DIBSECTION dib;
173         HBITMAP bitmap = GetCurrentObject( hdc, OBJ_BITMAP );
174         INT size = GetObjectW( bitmap, sizeof(dib), &dib );
175
176         if (!size) return 0;
177
178         if (size == sizeof(BITMAP))
179         {
180             /* A device-dependent bitmap is selected in the DC */
181             hbmpRet = CreateBitmap(width, height,
182                                    dib.dsBm.bmPlanes,
183                                    dib.dsBm.bmBitsPixel,
184                                    NULL);
185         }
186         else
187         {
188             /* A DIB section is selected in the DC */
189             BITMAPINFO *bi;
190             void *bits;
191
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));
197
198             if (bi)
199             {
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;
211
212                 if (bi->bmiHeader.biCompression == BI_BITFIELDS)
213                 {
214                     /* Copy the color masks */
215                     CopyMemory(bi->bmiColors, dib.dsBitfields, 3 * sizeof(DWORD));
216                 }
217                 else if (bi->bmiHeader.biBitCount <= 8)
218                 {
219                     /* Copy the color table */
220                     GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
221                 }
222
223                 hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
224                 HeapFree(GetProcessHeap(), 0, bi);
225             }
226         }
227     }
228
229     TRACE("\t\t%p\n", hbmpRet);
230     return hbmpRet;
231 }
232
233
234 /******************************************************************************
235  * CreateBitmapIndirect [GDI32.@]
236  *
237  * Creates a bitmap with the specified info.
238  *
239  * PARAMS
240  *  bmp [I] Pointer to the bitmap info describing the bitmap
241  *
242  * RETURNS
243  *    Success: Handle to bitmap
244  *    Failure: NULL. Use GetLastError() to determine the cause.
245  *
246  * NOTES
247  *  If a width or height of 0 are given, a 1x1 monochrome bitmap is returned.
248  */
249 HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
250 {
251     BITMAP bm;
252     BITMAPOBJ *bmpobj;
253     HBITMAP hbitmap;
254
255     if (!bmp || bmp->bmType)
256     {
257         SetLastError( ERROR_INVALID_PARAMETER );
258         return NULL;
259     }
260
261     if (bmp->bmWidth > 0x7ffffff || bmp->bmHeight > 0x7ffffff)
262     {
263         SetLastError( ERROR_INVALID_PARAMETER );
264         return 0;
265     }
266
267     bm = *bmp;
268
269     if (!bm.bmWidth || !bm.bmHeight)
270     {
271         return GetStockObject( DEFAULT_BITMAP );
272     }
273     else
274     {
275         if (bm.bmHeight < 0)
276             bm.bmHeight = -bm.bmHeight;
277         if (bm.bmWidth < 0)
278             bm.bmWidth = -bm.bmWidth;
279     }
280
281     if (bm.bmPlanes != 1)
282     {
283         FIXME("planes = %d\n", bm.bmPlanes);
284         SetLastError( ERROR_INVALID_PARAMETER );
285         return NULL;
286     }
287
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;
295     else {
296         WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm.bmBitsPixel);
297         SetLastError(ERROR_INVALID_PARAMETER);
298         return NULL;
299     }
300
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)
305     {
306         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
307         return 0;
308     }
309
310     /* Create the BITMAPOBJ */
311     if (!(bmpobj = HeapAlloc( GetProcessHeap(), 0, sizeof(*bmpobj) )))
312     {
313         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
314         return 0;
315     }
316
317     bmpobj->size.cx = 0;
318     bmpobj->size.cy = 0;
319     bmpobj->bitmap = bm;
320     bmpobj->bitmap.bmBits = NULL;
321     bmpobj->funcs = &null_driver;
322     bmpobj->dib = NULL;
323     bmpobj->color_table = NULL;
324     bmpobj->nb_colors = 0;
325
326     if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs )))
327     {
328         HeapFree( GetProcessHeap(), 0, bmpobj );
329         return 0;
330     }
331
332     if (bm.bmBits)
333         SetBitmapBits( hbitmap, bm.bmHeight * bm.bmWidthBytes, bm.bmBits );
334
335     TRACE("%dx%d, %d colors returning %p\n", bm.bmWidth, bm.bmHeight,
336           1 << (bm.bmPlanes * bm.bmBitsPixel), hbitmap);
337
338     return hbitmap;
339 }
340
341
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 )
344 {
345     struct bitblt_coords src;
346     BOOL ret = FALSE;
347     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
348
349     if (bmp)
350     {
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 );
357     }
358     return ret;
359 }
360
361
362 /***********************************************************************
363  * GetBitmapBits [GDI32.@]
364  *
365  * Copies bitmap bits of bitmap to buffer.
366  *
367  * RETURNS
368  *    Success: Number of bytes copied
369  *    Failure: 0
370  */
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 */
375 {
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;
383
384     if (!bmp) return 0;
385     funcs = get_bitmap_funcs( bmp );
386
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 );
389
390     ret = max = dst_stride * bmp->bitmap.bmHeight;
391     if (!bits) goto done;
392     if (count > max) count = max;
393     ret = count;
394
395     src.visrect.left = 0;
396     src.visrect.right = bmp->bitmap.bmWidth;
397     src.visrect.top = 0;
398     src.visrect.bottom = (count + dst_stride - 1) / dst_stride;
399     src.x = src.y = 0;
400     src.width = src.visrect.right - src.visrect.left;
401     src.height = src.visrect.bottom - src.visrect.top;
402
403     if (!funcs->pGetImage( NULL, hbitmap, info, &src_bits, &src ))
404     {
405         const char *src_ptr = src_bits.ptr;
406         int src_stride = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
407
408         /* GetBitmapBits returns 16-bit aligned data */
409
410         if (info->bmiHeader.biHeight > 0)
411         {
412             src_ptr += (info->bmiHeader.biHeight - 1) * src_stride;
413             src_stride = -src_stride;
414         }
415         src_ptr += src.visrect.top * src_stride;
416
417         if (src_stride == dst_stride) memcpy( bits, src_ptr, count );
418         else while (count > 0)
419         {
420             memcpy( bits, src_ptr, min( count, dst_stride ) );
421             src_ptr += src_stride;
422             bits = (char *)bits + dst_stride;
423             count -= dst_stride;
424         }
425         if (src_bits.free) src_bits.free( &src_bits );
426     }
427     else ret = 0;
428
429 done:
430     GDI_ReleaseObj( hbitmap );
431     return ret;
432 }
433
434
435 /******************************************************************************
436  * SetBitmapBits [GDI32.@]
437  *
438  * Sets bits of color data for a bitmap.
439  *
440  * RETURNS
441  *    Success: Number of bytes used in setting the bitmap bits
442  *    Failure: 0
443  */
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 */
448 {
449     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
450     BITMAPINFO *info = (BITMAPINFO *)buffer;
451     BITMAPOBJ *bmp;
452     DWORD err;
453     int i, src_stride, dst_stride;
454     struct bitblt_coords src, dst;
455     struct gdi_image_bits src_bits;
456     HRGN clip = NULL;
457     const struct gdi_dc_funcs *funcs;
458
459     if (!bits) return 0;
460
461     bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
462     if (!bmp) return 0;
463
464     funcs = get_bitmap_funcs( bmp );
465
466     if (count < 0) {
467         WARN("(%d): Negative number of bytes passed???\n", count );
468         count = -count;
469     }
470
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 );
474
475     dst_stride = get_dib_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
476
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;
481     dst = src;
482
483     if (count % src_stride)
484     {
485         HRGN last_row;
486         int extra_pixels = ((count % src_stride) << 3) / bmp->bitmap.bmBitsPixel;
487
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 );
496     }
497
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 );
501
502     if (src_stride == dst_stride)
503     {
504         src_bits.ptr = (void *)bits;
505         src_bits.is_copy = FALSE;
506         src_bits.free = NULL;
507     }
508     else
509     {
510         if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride )))
511         {
512             GDI_ReleaseObj( hbitmap );
513             return 0;
514         }
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 );
521     }
522
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 );
536
537     if (!err || err == ERROR_BAD_FORMAT)
538     {
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 );
545     }
546     if (err) count = 0;
547
548     if (clip) DeleteObject( clip );
549     if (src_bits.free) src_bits.free( &src_bits );
550     GDI_ReleaseObj( hbitmap );
551     return count;
552 }
553
554 /**********************************************************************
555  *              BITMAP_CopyBitmap
556  *
557  */
558 HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap)
559 {
560     HBITMAP res;
561     DIBSECTION dib;
562     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
563
564     if (!bmp) return 0;
565     if (bmp->dib)
566     {
567         void *bits;
568         BITMAPINFO *bi;
569         HDC dc;
570
571         dib = *bmp->dib;
572         GDI_ReleaseObj( hbitmap );
573         dc = CreateCompatibleDC( NULL );
574
575         if (!dc) return 0;
576         if (!(bi = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ))))
577         {
578             DeleteDC( dc );
579             return 0;
580         }
581         bi->bmiHeader = dib.dsBmih;
582
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;
586
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 );
590         DeleteDC( dc );
591         return res;
592     }
593     dib.dsBm = bmp->bitmap;
594     dib.dsBm.bmBits = NULL;
595     GDI_ReleaseObj( hbitmap );
596
597     res = CreateBitmapIndirect( &dib.dsBm );
598     if(res) {
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 );
603     }
604     return res;
605 }
606
607
608 static void set_initial_bitmap_bits( HBITMAP hbitmap, BITMAPOBJ *bmp )
609 {
610     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
611     BITMAPINFO *info = (BITMAPINFO *)buffer;
612
613     if (!bmp->bitmap.bmBits) return;
614     if (bmp->funcs->pPutImage == nulldrv_PutImage) return;
615
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;
620 }
621
622 /***********************************************************************
623  *           BITMAP_SetOwnerDC
624  *
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
627  * table.
628  */
629 BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev )
630 {
631     BITMAPOBJ *bitmap;
632     BOOL ret = TRUE;
633
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;
636
637     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE;
638
639     if (!bitmap->dib && bitmap->funcs != physdev->funcs)
640     {
641         /* we can only change from the null driver to some other driver */
642         if (bitmap->funcs == &null_driver)
643         {
644             if (physdev->funcs->pCreateBitmap)
645             {
646                 ret = physdev->funcs->pCreateBitmap( physdev, hbitmap );
647                 if (ret)
648                 {
649                     bitmap->funcs = physdev->funcs;
650                     set_initial_bitmap_bits( hbitmap, bitmap );
651                 }
652             }
653             else
654             {
655                 WARN( "Trying to select bitmap %p in DC that doesn't support it\n", hbitmap );
656                 ret = FALSE;
657             }
658         }
659         else
660         {
661             FIXME( "Trying to select bitmap %p in different DC type\n", hbitmap );
662             ret = FALSE;
663         }
664     }
665     GDI_ReleaseObj( hbitmap );
666     return ret;
667 }
668
669
670 /***********************************************************************
671  *           BITMAP_SelectObject
672  */
673 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
674 {
675     HGDIOBJ ret;
676     BITMAPOBJ *bitmap;
677     DC *dc;
678     PHYSDEV physdev = NULL, old_physdev = NULL;
679
680     if (!(dc = get_dc_ptr( hdc ))) return 0;
681
682     if (GetObjectType( hdc ) != OBJ_MEMDC)
683     {
684         ret = 0;
685         goto done;
686     }
687     ret = dc->hBitmap;
688     if (handle == dc->hBitmap) goto done;  /* nothing to do */
689
690     if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
691     {
692         ret = 0;
693         goto done;
694     }
695
696     if (bitmap->header.selcount && (handle != GetStockObject(DEFAULT_BITMAP)))
697     {
698         WARN( "Bitmap already selected in another DC\n" );
699         GDI_ReleaseObj( handle );
700         ret = 0;
701         goto done;
702     }
703
704     old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
705     if(old_physdev == dc->dibdrv)
706         old_physdev = pop_dc_driver( &dc->physDev );
707
708     if(bitmap->dib)
709     {
710         physdev = dc->dibdrv;
711         if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs );
712         else
713         {
714             if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done;
715             dc->dibdrv = physdev = dc->physDev;
716         }
717     }
718     else
719         physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
720
721     if (!BITMAP_SetOwnerDC( handle, physdev ))
722     {
723         GDI_ReleaseObj( handle );
724         ret = 0;
725         goto done;
726     }
727     if (!physdev->funcs->pSelectBitmap( physdev, handle ))
728     {
729         GDI_ReleaseObj( handle );
730         ret = 0;
731     }
732     else
733     {
734         dc->hBitmap = handle;
735         GDI_inc_ref_count( handle );
736         dc->dirty = 0;
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 );
743         DC_InitDC( dc );
744         GDI_dec_ref_count( ret );
745     }
746
747  done:
748     if(!ret)
749     {
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 );
754     }
755     release_dc_ptr( dc );
756     return ret;
757 }
758
759
760 /***********************************************************************
761  *           BITMAP_DeleteObject
762  */
763 static BOOL BITMAP_DeleteObject( HGDIOBJ handle )
764 {
765     const DC_FUNCTIONS *funcs;
766     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
767
768     if (!bmp) return FALSE;
769     funcs = bmp->funcs;
770     GDI_ReleaseObj( handle );
771
772     funcs->pDeleteBitmap( handle );
773
774     if (!(bmp = free_gdi_handle( handle ))) return FALSE;
775
776     HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits );
777
778     if (bmp->dib)
779     {
780         DIBSECTION *dib = bmp->dib;
781
782         if (dib->dsBm.bmBits)
783         {
784             if (dib->dshSection)
785             {
786                 SYSTEM_INFO SystemInfo;
787                 GetSystemInfo( &SystemInfo );
788                 UnmapViewOfFile( (char *)dib->dsBm.bmBits -
789                                  (dib->dsOffset % SystemInfo.dwAllocationGranularity) );
790             }
791             else if (!dib->dsOffset)
792                 VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE );
793         }
794         HeapFree(GetProcessHeap(), 0, dib);
795         HeapFree(GetProcessHeap(), 0, bmp->color_table);
796     }
797     return HeapFree( GetProcessHeap(), 0, bmp );
798 }
799
800
801 /***********************************************************************
802  *           BITMAP_GetObject
803  */
804 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
805 {
806     INT ret;
807     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
808
809     if (!bmp) return 0;
810
811     if (!buffer) ret = sizeof(BITMAP);
812     else if (count < sizeof(BITMAP)) ret = 0;
813     else if (bmp->dib)
814     {
815         if (count >= sizeof(DIBSECTION))
816         {
817             DIBSECTION *dib = buffer;
818             *dib = *bmp->dib;
819             dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
820             ret = sizeof(DIBSECTION);
821         }
822         else /* if (count >= sizeof(BITMAP)) */
823         {
824             DIBSECTION *dib = bmp->dib;
825             memcpy( buffer, &dib->dsBm, sizeof(BITMAP) );
826             ret = sizeof(BITMAP);
827         }
828     }
829     else
830     {
831         memcpy( buffer, &bmp->bitmap, sizeof(BITMAP) );
832         ((BITMAP *) buffer)->bmBits = NULL;
833         ret = sizeof(BITMAP);
834     }
835     GDI_ReleaseObj( handle );
836     return ret;
837 }
838
839
840 /******************************************************************************
841  * CreateDiscardableBitmap [GDI32.@]
842  *
843  * Creates a discardable bitmap.
844  *
845  * RETURNS
846  *    Success: Handle to bitmap
847  *    Failure: NULL
848  */
849 HBITMAP WINAPI CreateDiscardableBitmap(
850     HDC hdc,    /* [in] Handle to device context */
851     INT width,  /* [in] Bitmap width */
852     INT height) /* [in] Bitmap height */
853 {
854     return CreateCompatibleBitmap( hdc, width, height );
855 }
856
857
858 /******************************************************************************
859  * GetBitmapDimensionEx [GDI32.@]
860  *
861  * Retrieves dimensions of a bitmap.
862  *
863  * RETURNS
864  *    Success: TRUE
865  *    Failure: FALSE
866  */
867 BOOL WINAPI GetBitmapDimensionEx(
868     HBITMAP hbitmap, /* [in]  Handle to bitmap */
869     LPSIZE size)     /* [out] Address of struct receiving dimensions */
870 {
871     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
872     if (!bmp) return FALSE;
873     *size = bmp->size;
874     GDI_ReleaseObj( hbitmap );
875     return TRUE;
876 }
877
878
879 /******************************************************************************
880  * SetBitmapDimensionEx [GDI32.@]
881  *
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.
885  *
886  * RETURNS
887  *    Success: TRUE
888  *    Failure: FALSE
889  */
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 */
895 {
896     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
897     if (!bmp) return FALSE;
898     if (prevSize) *prevSize = bmp->size;
899     bmp->size.cx = x;
900     bmp->size.cy = y;
901     GDI_ReleaseObj( hbitmap );
902     return TRUE;
903 }