wined3d: Pass a gl_info pointer to select_fragment_implementation().
[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     int height, width_bytes;
58
59     if (!hbitmap) return ERROR_NOT_SUPPORTED;
60     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return ERROR_INVALID_HANDLE;
61
62     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
63     info->bmiHeader.biPlanes        = 1;
64     info->bmiHeader.biBitCount      = bmp->bitmap.bmBitsPixel;
65     info->bmiHeader.biCompression   = BI_RGB;
66     info->bmiHeader.biXPelsPerMeter = 0;
67     info->bmiHeader.biYPelsPerMeter = 0;
68     info->bmiHeader.biClrUsed       = 0;
69     info->bmiHeader.biClrImportant  = 0;
70     if (bmp->bitmap.bmBitsPixel == 16)
71     {
72         DWORD *masks = (DWORD *)info->bmiColors;
73         masks[0] = 0x7c00;
74         masks[1] = 0x03e0;
75         masks[2] = 0x001f;
76         info->bmiHeader.biCompression = BI_BITFIELDS;
77     }
78     if (!bits) goto done;
79
80     height = src->visrect.bottom - src->visrect.top;
81     width_bytes = get_dib_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
82     info->bmiHeader.biWidth     = bmp->bitmap.bmWidth;
83     info->bmiHeader.biHeight    = -height;
84     info->bmiHeader.biSizeImage = height * width_bytes;
85
86     /* make the source rectangle relative to the returned bits */
87     src->y -= src->visrect.top;
88     offset_rect( &src->visrect, 0, -src->visrect.top );
89
90     if (bmp->bitmap.bmBits && bmp->bitmap.bmWidthBytes == width_bytes)
91     {
92         bits->ptr = (char *)bmp->bitmap.bmBits + src->visrect.top * width_bytes;
93         bits->is_copy = FALSE;
94         bits->free = NULL;
95     }
96     else
97     {
98         bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
99         bits->is_copy = TRUE;
100         bits->free = free_heap_bits;
101         if (bmp->bitmap.bmBits)
102         {
103             /* fixup the line alignment */
104             char *src = bmp->bitmap.bmBits, *dst = bits->ptr;
105             for ( ; height > 0; height--, src += bmp->bitmap.bmWidthBytes, dst += width_bytes)
106             {
107                 memcpy( dst, src, bmp->bitmap.bmWidthBytes );
108                 memset( dst + bmp->bitmap.bmWidthBytes, 0, width_bytes - bmp->bitmap.bmWidthBytes );
109             }
110         }
111         else memset( bits->ptr, 0, info->bmiHeader.biSizeImage );
112     }
113 done:
114     GDI_ReleaseObj( hbitmap );
115     return ERROR_SUCCESS;
116 }
117
118 DWORD nulldrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
119                         const struct gdi_image_bits *bits, struct bitblt_coords *src,
120                         struct bitblt_coords *dst, DWORD rop )
121 {
122     BITMAPOBJ *bmp;
123
124     if (!hbitmap) return ERROR_SUCCESS;
125     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return ERROR_INVALID_HANDLE;
126
127     if (info->bmiHeader.biPlanes != 1) goto update_format;
128     if (info->bmiHeader.biBitCount != bmp->bitmap.bmBitsPixel) goto update_format;
129     /* FIXME: check color masks */
130
131     if (bits)
132     {
133         int i, width_bytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
134         unsigned char *dst_bits, *src_bits;
135
136         if ((src->width != dst->width) || (src->height != dst->height))
137         {
138             GDI_ReleaseObj( hbitmap );
139             return ERROR_TRANSFORM_NOT_SUPPORTED;
140         }
141         if (src->visrect.left > 0 || src->visrect.right < bmp->bitmap.bmWidth ||
142             dst->visrect.left > 0 || dst->visrect.right < bmp->bitmap.bmWidth)
143         {
144             FIXME( "setting partial rows not supported\n" );
145             GDI_ReleaseObj( hbitmap );
146             return ERROR_NOT_SUPPORTED;
147         }
148         if (clip)
149         {
150             FIXME( "clip region not supported\n" );
151             GDI_ReleaseObj( hbitmap );
152             return ERROR_NOT_SUPPORTED;
153         }
154
155         if (!bmp->bitmap.bmBits &&
156             !(bmp->bitmap.bmBits = HeapAlloc( GetProcessHeap(), 0,
157                                               bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes )))
158         {
159             GDI_ReleaseObj( hbitmap );
160             return ERROR_OUTOFMEMORY;
161         }
162         src_bits = bits->ptr;
163         if (info->bmiHeader.biHeight > 0)
164         {
165             src_bits += (info->bmiHeader.biHeight - 1 - src->visrect.top) * width_bytes;
166             width_bytes = -width_bytes;
167         }
168         else
169             src_bits += src->visrect.top * width_bytes;
170
171         dst_bits = (unsigned char *)bmp->bitmap.bmBits + dst->visrect.top * bmp->bitmap.bmWidthBytes;
172         if (width_bytes != bmp->bitmap.bmWidthBytes)
173         {
174             for (i = 0; i < dst->visrect.bottom - dst->visrect.top; i++)
175             {
176                 memcpy( dst_bits, src_bits, min( abs(width_bytes), bmp->bitmap.bmWidthBytes ));
177                 src_bits += width_bytes;
178                 dst_bits += bmp->bitmap.bmWidthBytes;
179             }
180         }
181         else memcpy( dst_bits, src_bits, width_bytes * (dst->visrect.bottom - dst->visrect.top) );
182     }
183     GDI_ReleaseObj( hbitmap );
184     return ERROR_SUCCESS;
185
186 update_format:
187     info->bmiHeader.biPlanes   = 1;
188     info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
189     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
190     GDI_ReleaseObj( hbitmap );
191     return ERROR_BAD_FORMAT;
192 }
193
194
195 /******************************************************************************
196  * CreateBitmap [GDI32.@]
197  *
198  * Creates a bitmap with the specified info.
199  *
200  * PARAMS
201  *    width  [I] bitmap width
202  *    height [I] bitmap height
203  *    planes [I] Number of color planes
204  *    bpp    [I] Number of bits to identify a color
205  *    bits   [I] Pointer to array containing color data
206  *
207  * RETURNS
208  *    Success: Handle to bitmap
209  *    Failure: 0
210  */
211 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
212                              UINT bpp, LPCVOID bits )
213 {
214     BITMAP bm;
215
216     bm.bmType = 0;
217     bm.bmWidth = width;
218     bm.bmHeight = height;
219     bm.bmWidthBytes = get_bitmap_stride( width, bpp );
220     bm.bmPlanes = planes;
221     bm.bmBitsPixel = bpp;
222     bm.bmBits = (LPVOID)bits;
223
224     return CreateBitmapIndirect( &bm );
225 }
226
227 /******************************************************************************
228  * CreateCompatibleBitmap [GDI32.@]
229  *
230  * Creates a bitmap compatible with the DC.
231  *
232  * PARAMS
233  *    hdc    [I] Handle to device context
234  *    width  [I] Width of bitmap
235  *    height [I] Height of bitmap
236  *
237  * RETURNS
238  *    Success: Handle to bitmap
239  *    Failure: 0
240  */
241 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
242 {
243     HBITMAP hbmpRet = 0;
244
245     TRACE("(%p,%d,%d) =\n", hdc, width, height);
246
247     if (GetObjectType( hdc ) != OBJ_MEMDC)
248     {
249         hbmpRet = CreateBitmap(width, height,
250                                GetDeviceCaps(hdc, PLANES),
251                                GetDeviceCaps(hdc, BITSPIXEL),
252                                NULL);
253     }
254     else  /* Memory DC */
255     {
256         DIBSECTION dib;
257         HBITMAP bitmap = GetCurrentObject( hdc, OBJ_BITMAP );
258         INT size = GetObjectW( bitmap, sizeof(dib), &dib );
259
260         if (!size) return 0;
261
262         if (size == sizeof(BITMAP))
263         {
264             /* A device-dependent bitmap is selected in the DC */
265             hbmpRet = CreateBitmap(width, height,
266                                    dib.dsBm.bmPlanes,
267                                    dib.dsBm.bmBitsPixel,
268                                    NULL);
269         }
270         else
271         {
272             /* A DIB section is selected in the DC */
273             BITMAPINFO *bi;
274             void *bits;
275
276             /* Allocate memory for a BITMAPINFOHEADER structure and a
277                color table. The maximum number of colors in a color table
278                is 256 which corresponds to a bitmap with depth 8.
279                Bitmaps with higher depths don't have color tables. */
280             bi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
281
282             if (bi)
283             {
284                 bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
285                 bi->bmiHeader.biWidth         = width;
286                 bi->bmiHeader.biHeight        = height;
287                 bi->bmiHeader.biPlanes        = dib.dsBmih.biPlanes;
288                 bi->bmiHeader.biBitCount      = dib.dsBmih.biBitCount;
289                 bi->bmiHeader.biCompression   = dib.dsBmih.biCompression;
290                 bi->bmiHeader.biSizeImage     = 0;
291                 bi->bmiHeader.biXPelsPerMeter = dib.dsBmih.biXPelsPerMeter;
292                 bi->bmiHeader.biYPelsPerMeter = dib.dsBmih.biYPelsPerMeter;
293                 bi->bmiHeader.biClrUsed       = dib.dsBmih.biClrUsed;
294                 bi->bmiHeader.biClrImportant  = dib.dsBmih.biClrImportant;
295
296                 if (bi->bmiHeader.biCompression == BI_BITFIELDS)
297                 {
298                     /* Copy the color masks */
299                     CopyMemory(bi->bmiColors, dib.dsBitfields, 3 * sizeof(DWORD));
300                 }
301                 else if (bi->bmiHeader.biBitCount <= 8)
302                 {
303                     /* Copy the color table */
304                     GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
305                 }
306
307                 hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
308                 HeapFree(GetProcessHeap(), 0, bi);
309             }
310         }
311     }
312
313     TRACE("\t\t%p\n", hbmpRet);
314     return hbmpRet;
315 }
316
317
318 /******************************************************************************
319  * CreateBitmapIndirect [GDI32.@]
320  *
321  * Creates a bitmap with the specified info.
322  *
323  * PARAMS
324  *  bmp [I] Pointer to the bitmap info describing the bitmap
325  *
326  * RETURNS
327  *    Success: Handle to bitmap
328  *    Failure: NULL. Use GetLastError() to determine the cause.
329  *
330  * NOTES
331  *  If a width or height of 0 are given, a 1x1 monochrome bitmap is returned.
332  */
333 HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
334 {
335     BITMAP bm;
336     BITMAPOBJ *bmpobj;
337     HBITMAP hbitmap;
338
339     if (!bmp || bmp->bmType)
340     {
341         SetLastError( ERROR_INVALID_PARAMETER );
342         return NULL;
343     }
344
345     if (bmp->bmWidth > 0x7ffffff || bmp->bmHeight > 0x7ffffff)
346     {
347         SetLastError( ERROR_INVALID_PARAMETER );
348         return 0;
349     }
350
351     bm = *bmp;
352
353     if (!bm.bmWidth || !bm.bmHeight)
354     {
355         return GetStockObject( DEFAULT_BITMAP );
356     }
357     else
358     {
359         if (bm.bmHeight < 0)
360             bm.bmHeight = -bm.bmHeight;
361         if (bm.bmWidth < 0)
362             bm.bmWidth = -bm.bmWidth;
363     }
364
365     if (bm.bmPlanes != 1)
366     {
367         FIXME("planes = %d\n", bm.bmPlanes);
368         SetLastError( ERROR_INVALID_PARAMETER );
369         return NULL;
370     }
371
372     /* Windows only uses 1, 4, 8, 16, 24 and 32 bpp */
373     if(bm.bmBitsPixel == 1)         bm.bmBitsPixel = 1;
374     else if(bm.bmBitsPixel <= 4)    bm.bmBitsPixel = 4;
375     else if(bm.bmBitsPixel <= 8)    bm.bmBitsPixel = 8;
376     else if(bm.bmBitsPixel <= 16)   bm.bmBitsPixel = 16;
377     else if(bm.bmBitsPixel <= 24)   bm.bmBitsPixel = 24;
378     else if(bm.bmBitsPixel <= 32)   bm.bmBitsPixel = 32;
379     else {
380         WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm.bmBitsPixel);
381         SetLastError(ERROR_INVALID_PARAMETER);
382         return NULL;
383     }
384
385     /* Windows ignores the provided bm.bmWidthBytes */
386     bm.bmWidthBytes = get_bitmap_stride( bm.bmWidth, bm.bmBitsPixel );
387     /* XP doesn't allow to create bitmaps larger than 128 Mb */
388     if (bm.bmHeight > 128 * 1024 * 1024 / bm.bmWidthBytes)
389     {
390         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
391         return 0;
392     }
393
394     /* Create the BITMAPOBJ */
395     if (!(bmpobj = HeapAlloc( GetProcessHeap(), 0, sizeof(*bmpobj) )))
396     {
397         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
398         return 0;
399     }
400
401     bmpobj->size.cx = 0;
402     bmpobj->size.cy = 0;
403     bmpobj->bitmap = bm;
404     bmpobj->bitmap.bmBits = NULL;
405     bmpobj->funcs = &null_driver;
406     bmpobj->dib = NULL;
407     bmpobj->color_table = NULL;
408     bmpobj->nb_colors = 0;
409
410     if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs )))
411     {
412         HeapFree( GetProcessHeap(), 0, bmpobj );
413         return 0;
414     }
415
416     if (bm.bmBits)
417         SetBitmapBits( hbitmap, bm.bmHeight * bm.bmWidthBytes, bm.bmBits );
418
419     TRACE("%dx%d, %d colors returning %p\n", bm.bmWidth, bm.bmHeight,
420           1 << (bm.bmPlanes * bm.bmBitsPixel), hbitmap);
421
422     return hbitmap;
423 }
424
425
426 /* convenience wrapper for GetImage to retrieve the full contents of a bitmap */
427 BOOL get_bitmap_image( HBITMAP hbitmap, BITMAPINFO *info, struct gdi_image_bits *bits )
428 {
429     struct bitblt_coords src;
430     BOOL ret = FALSE;
431     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
432
433     if (bmp)
434     {
435         src.visrect.left   = src.x = 0;
436         src.visrect.top    = src.y = 0;
437         src.visrect.right  = src.width = bmp->bitmap.bmWidth;
438         src.visrect.bottom = src.height = bmp->bitmap.bmHeight;
439         ret = !bmp->funcs->pGetImage( NULL, hbitmap, info, bits, &src );
440         GDI_ReleaseObj( hbitmap );
441     }
442     return ret;
443 }
444
445
446 /***********************************************************************
447  * GetBitmapBits [GDI32.@]
448  *
449  * Copies bitmap bits of bitmap to buffer.
450  *
451  * RETURNS
452  *    Success: Number of bytes copied
453  *    Failure: 0
454  */
455 LONG WINAPI GetBitmapBits(
456     HBITMAP hbitmap, /* [in]  Handle to bitmap */
457     LONG count,        /* [in]  Number of bytes to copy */
458     LPVOID bits)       /* [out] Pointer to buffer to receive bits */
459 {
460     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
461     BITMAPINFO *info = (BITMAPINFO *)buffer;
462     struct gdi_image_bits src_bits;
463     struct bitblt_coords src;
464     int dst_stride, max, ret;
465     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
466     const struct gdi_dc_funcs *funcs;
467
468     if (!bmp) return 0;
469     funcs = get_bitmap_funcs( bmp );
470
471     if (bmp->dib) dst_stride = get_bitmap_stride( bmp->dib->dsBmih.biWidth, bmp->dib->dsBmih.biBitCount );
472     else dst_stride = get_bitmap_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
473
474     ret = max = dst_stride * bmp->bitmap.bmHeight;
475     if (!bits) goto done;
476     if (count > max) count = max;
477     ret = count;
478
479     src.visrect.left = 0;
480     src.visrect.right = bmp->bitmap.bmWidth;
481     src.visrect.top = 0;
482     src.visrect.bottom = (count + dst_stride - 1) / dst_stride;
483     src.x = src.y = 0;
484     src.width = src.visrect.right - src.visrect.left;
485     src.height = src.visrect.bottom - src.visrect.top;
486
487     if (!funcs->pGetImage( NULL, hbitmap, info, &src_bits, &src ))
488     {
489         const char *src_ptr = src_bits.ptr;
490         int src_stride = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
491
492         /* GetBitmapBits returns 16-bit aligned data */
493
494         if (info->bmiHeader.biHeight > 0)
495         {
496             src_ptr += (info->bmiHeader.biHeight - 1) * src_stride;
497             src_stride = -src_stride;
498         }
499         src_ptr += src.visrect.top * src_stride;
500
501         if (src_stride == dst_stride) memcpy( bits, src_ptr, count );
502         else while (count > 0)
503         {
504             memcpy( bits, src_ptr, min( count, dst_stride ) );
505             src_ptr += src_stride;
506             bits = (char *)bits + dst_stride;
507             count -= dst_stride;
508         }
509         if (src_bits.free) src_bits.free( &src_bits );
510     }
511     else ret = 0;
512
513 done:
514     GDI_ReleaseObj( hbitmap );
515     return ret;
516 }
517
518
519 /******************************************************************************
520  * SetBitmapBits [GDI32.@]
521  *
522  * Sets bits of color data for a bitmap.
523  *
524  * RETURNS
525  *    Success: Number of bytes used in setting the bitmap bits
526  *    Failure: 0
527  */
528 LONG WINAPI SetBitmapBits(
529     HBITMAP hbitmap, /* [in] Handle to bitmap */
530     LONG count,        /* [in] Number of bytes in bitmap array */
531     LPCVOID bits)      /* [in] Address of array with bitmap bits */
532 {
533     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
534     BITMAPINFO *info = (BITMAPINFO *)buffer;
535     BITMAPOBJ *bmp;
536     DWORD err;
537     int i, src_stride, dst_stride;
538     struct bitblt_coords src, dst;
539     struct gdi_image_bits src_bits;
540     HRGN clip = NULL;
541     const struct gdi_dc_funcs *funcs;
542
543     if (!bits) return 0;
544
545     bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
546     if (!bmp) return 0;
547
548     funcs = get_bitmap_funcs( bmp );
549
550     if (count < 0) {
551         WARN("(%d): Negative number of bytes passed???\n", count );
552         count = -count;
553     }
554
555     if (bmp->dib) src_stride = get_bitmap_stride( bmp->dib->dsBmih.biWidth, bmp->dib->dsBmih.biBitCount );
556     else src_stride = get_bitmap_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
557     count = min( count, src_stride * bmp->bitmap.bmHeight );
558
559     dst_stride = get_dib_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
560
561     src.visrect.left   = src.x = 0;
562     src.visrect.top    = src.y = 0;
563     src.visrect.right  = src.width = bmp->bitmap.bmWidth;
564     src.visrect.bottom = src.height = (count + src_stride - 1 ) / src_stride;
565     dst = src;
566
567     if (count % src_stride)
568     {
569         HRGN last_row;
570         int extra_pixels = ((count % src_stride) << 3) / bmp->bitmap.bmBitsPixel;
571
572         if ((count % src_stride << 3) % bmp->bitmap.bmBitsPixel)
573             FIXME( "Unhandled partial pixel\n" );
574         clip = CreateRectRgn( src.visrect.left, src.visrect.top,
575                               src.visrect.right, src.visrect.bottom - 1 );
576         last_row = CreateRectRgn( src.visrect.left, src.visrect.bottom - 1,
577                                   src.visrect.left + extra_pixels, src.visrect.bottom );
578         CombineRgn( clip, clip, last_row, RGN_OR );
579         DeleteObject( last_row );
580     }
581
582     TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n",
583           hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
584           bmp->bitmap.bmBitsPixel, src.height );
585
586     if (src_stride == dst_stride)
587     {
588         src_bits.ptr = (void *)bits;
589         src_bits.is_copy = FALSE;
590         src_bits.free = NULL;
591     }
592     else
593     {
594         if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride )))
595         {
596             GDI_ReleaseObj( hbitmap );
597             return 0;
598         }
599         src_bits.is_copy = TRUE;
600         src_bits.free = free_heap_bits;
601         for (i = 0; i < count / src_stride; i++)
602             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, src_stride );
603         if (count % src_stride)
604             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, count % src_stride );
605     }
606
607     /* query the color info */
608     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
609     info->bmiHeader.biPlanes        = 1;
610     info->bmiHeader.biBitCount      = bmp->bitmap.bmBitsPixel;
611     info->bmiHeader.biCompression   = BI_RGB;
612     info->bmiHeader.biXPelsPerMeter = 0;
613     info->bmiHeader.biYPelsPerMeter = 0;
614     info->bmiHeader.biClrUsed       = 0;
615     info->bmiHeader.biClrImportant  = 0;
616     info->bmiHeader.biWidth         = 0;
617     info->bmiHeader.biHeight        = 0;
618     info->bmiHeader.biSizeImage     = 0;
619     err = funcs->pPutImage( NULL, hbitmap, 0, info, NULL, NULL, NULL, SRCCOPY );
620
621     if (!err || err == ERROR_BAD_FORMAT)
622     {
623         info->bmiHeader.biPlanes        = 1;
624         info->bmiHeader.biBitCount      = bmp->bitmap.bmBitsPixel;
625         info->bmiHeader.biWidth         = bmp->bitmap.bmWidth;
626         info->bmiHeader.biHeight        = -dst.height;
627         info->bmiHeader.biSizeImage     = dst.height * dst_stride;
628         err = funcs->pPutImage( NULL, hbitmap, clip, info, &src_bits, &src, &dst, SRCCOPY );
629     }
630     if (err) count = 0;
631
632     if (clip) DeleteObject( clip );
633     if (src_bits.free) src_bits.free( &src_bits );
634     GDI_ReleaseObj( hbitmap );
635     return count;
636 }
637
638 /**********************************************************************
639  *              BITMAP_CopyBitmap
640  *
641  */
642 HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap)
643 {
644     HBITMAP res;
645     DIBSECTION dib;
646     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
647
648     if (!bmp) return 0;
649     if (bmp->dib)
650     {
651         void *bits;
652         BITMAPINFO *bi;
653         HDC dc;
654
655         dib = *bmp->dib;
656         GDI_ReleaseObj( hbitmap );
657         dc = CreateCompatibleDC( NULL );
658
659         if (!dc) return 0;
660         if (!(bi = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ))))
661         {
662             DeleteDC( dc );
663             return 0;
664         }
665         bi->bmiHeader = dib.dsBmih;
666
667         /* Get the color table or the color masks */
668         GetDIBits( dc, hbitmap, 0, 0, NULL, bi, DIB_RGB_COLORS );
669         bi->bmiHeader.biHeight = dib.dsBmih.biHeight;
670
671         res = CreateDIBSection( dc, bi, DIB_RGB_COLORS, &bits, NULL, 0 );
672         if (res) SetDIBits( dc, res, 0, dib.dsBm.bmHeight, dib.dsBm.bmBits, bi, DIB_RGB_COLORS );
673         HeapFree( GetProcessHeap(), 0, bi );
674         DeleteDC( dc );
675         return res;
676     }
677     dib.dsBm = bmp->bitmap;
678     dib.dsBm.bmBits = NULL;
679     GDI_ReleaseObj( hbitmap );
680
681     res = CreateBitmapIndirect( &dib.dsBm );
682     if(res) {
683         char *buf = HeapAlloc( GetProcessHeap(), 0, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight );
684         GetBitmapBits (hbitmap, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight, buf);
685         SetBitmapBits (res, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight, buf);
686         HeapFree( GetProcessHeap(), 0, buf );
687     }
688     return res;
689 }
690
691
692 static void set_initial_bitmap_bits( HBITMAP hbitmap, BITMAPOBJ *bmp )
693 {
694     if (!bmp->bitmap.bmBits) return;
695     SetBitmapBits( hbitmap, bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes, bmp->bitmap.bmBits );
696 }
697
698 /***********************************************************************
699  *           BITMAP_SetOwnerDC
700  *
701  * Set the type of DC that owns the bitmap. This is used when the
702  * bitmap is selected into a device to initialize the bitmap function
703  * table.
704  */
705 BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev )
706 {
707     BITMAPOBJ *bitmap;
708     BOOL ret = TRUE;
709
710     /* never set the owner of the stock bitmap since it can be selected in multiple DCs */
711     if (hbitmap == GetStockObject(DEFAULT_BITMAP)) return TRUE;
712
713     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE;
714
715     if (!bitmap->dib && bitmap->funcs != physdev->funcs)
716     {
717         /* we can only change from the null driver to some other driver */
718         if (bitmap->funcs == &null_driver)
719         {
720             if (physdev->funcs->pCreateBitmap)
721             {
722                 ret = physdev->funcs->pCreateBitmap( physdev, hbitmap );
723                 if (ret)
724                 {
725                     bitmap->funcs = physdev->funcs;
726                     set_initial_bitmap_bits( hbitmap, bitmap );
727                 }
728             }
729             else
730             {
731                 WARN( "Trying to select bitmap %p in DC that doesn't support it\n", hbitmap );
732                 ret = FALSE;
733             }
734         }
735         else
736         {
737             FIXME( "Trying to select bitmap %p in different DC type\n", hbitmap );
738             ret = FALSE;
739         }
740     }
741     GDI_ReleaseObj( hbitmap );
742     return ret;
743 }
744
745
746 /***********************************************************************
747  *           BITMAP_SelectObject
748  */
749 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
750 {
751     HGDIOBJ ret;
752     BITMAPOBJ *bitmap;
753     DC *dc;
754     PHYSDEV physdev = NULL, old_physdev = NULL;
755
756     if (!(dc = get_dc_ptr( hdc ))) return 0;
757
758     if (GetObjectType( hdc ) != OBJ_MEMDC)
759     {
760         ret = 0;
761         goto done;
762     }
763     ret = dc->hBitmap;
764     if (handle == dc->hBitmap) goto done;  /* nothing to do */
765
766     if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
767     {
768         ret = 0;
769         goto done;
770     }
771
772     if (bitmap->header.selcount && (handle != GetStockObject(DEFAULT_BITMAP)))
773     {
774         WARN( "Bitmap already selected in another DC\n" );
775         GDI_ReleaseObj( handle );
776         ret = 0;
777         goto done;
778     }
779
780     old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
781     if(old_physdev == &dc->dibdrv.dev)
782         pop_dc_driver( dc, old_physdev );
783
784     if(bitmap->dib)
785     {
786         physdev = &dc->dibdrv.dev;
787         push_dc_driver( dc, physdev, physdev->funcs );
788     }
789     else
790         physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
791
792     if (!BITMAP_SetOwnerDC( handle, physdev ))
793     {
794         GDI_ReleaseObj( handle );
795         ret = 0;
796         goto done;
797     }
798     if (!physdev->funcs->pSelectBitmap( physdev, handle ))
799     {
800         GDI_ReleaseObj( handle );
801         ret = 0;
802     }
803     else
804     {
805         dc->hBitmap = handle;
806         GDI_inc_ref_count( handle );
807         dc->dirty = 0;
808         dc->vis_rect.left   = 0;
809         dc->vis_rect.top    = 0;
810         dc->vis_rect.right  = bitmap->bitmap.bmWidth;
811         dc->vis_rect.bottom = bitmap->bitmap.bmHeight;
812         SetRectRgn( dc->hVisRgn, 0, 0, bitmap->bitmap.bmWidth, bitmap->bitmap.bmHeight);
813         GDI_ReleaseObj( handle );
814         DC_InitDC( dc );
815         GDI_dec_ref_count( ret );
816     }
817
818  done:
819     if(!ret)
820     {
821         if(physdev == &dc->dibdrv.dev) pop_dc_driver( dc, physdev );
822         if(old_physdev == &dc->dibdrv.dev) push_dc_driver( dc, old_physdev, old_physdev->funcs );
823     }
824     release_dc_ptr( dc );
825     return ret;
826 }
827
828
829 /***********************************************************************
830  *           BITMAP_DeleteObject
831  */
832 static BOOL BITMAP_DeleteObject( HGDIOBJ handle )
833 {
834     const DC_FUNCTIONS *funcs;
835     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
836
837     if (!bmp) return FALSE;
838     funcs = bmp->funcs;
839     GDI_ReleaseObj( handle );
840
841     funcs->pDeleteBitmap( handle );
842
843     if (!(bmp = free_gdi_handle( handle ))) return FALSE;
844
845     HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits );
846
847     if (bmp->dib)
848     {
849         DIBSECTION *dib = bmp->dib;
850
851         if (dib->dsBm.bmBits)
852         {
853             if (dib->dshSection)
854             {
855                 SYSTEM_INFO SystemInfo;
856                 GetSystemInfo( &SystemInfo );
857                 UnmapViewOfFile( (char *)dib->dsBm.bmBits -
858                                  (dib->dsOffset % SystemInfo.dwAllocationGranularity) );
859             }
860             else if (!dib->dsOffset)
861                 VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE );
862         }
863         HeapFree(GetProcessHeap(), 0, dib);
864         HeapFree(GetProcessHeap(), 0, bmp->color_table);
865     }
866     return HeapFree( GetProcessHeap(), 0, bmp );
867 }
868
869
870 /***********************************************************************
871  *           BITMAP_GetObject
872  */
873 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
874 {
875     INT ret;
876     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
877
878     if (!bmp) return 0;
879
880     if (!buffer) ret = sizeof(BITMAP);
881     else if (count < sizeof(BITMAP)) ret = 0;
882     else if (bmp->dib)
883     {
884         if (count >= sizeof(DIBSECTION))
885         {
886             DIBSECTION *dib = buffer;
887             *dib = *bmp->dib;
888             dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
889             ret = sizeof(DIBSECTION);
890         }
891         else /* if (count >= sizeof(BITMAP)) */
892         {
893             DIBSECTION *dib = bmp->dib;
894             memcpy( buffer, &dib->dsBm, sizeof(BITMAP) );
895             ret = sizeof(BITMAP);
896         }
897     }
898     else
899     {
900         memcpy( buffer, &bmp->bitmap, sizeof(BITMAP) );
901         ((BITMAP *) buffer)->bmBits = NULL;
902         ret = sizeof(BITMAP);
903     }
904     GDI_ReleaseObj( handle );
905     return ret;
906 }
907
908
909 /******************************************************************************
910  * CreateDiscardableBitmap [GDI32.@]
911  *
912  * Creates a discardable bitmap.
913  *
914  * RETURNS
915  *    Success: Handle to bitmap
916  *    Failure: NULL
917  */
918 HBITMAP WINAPI CreateDiscardableBitmap(
919     HDC hdc,    /* [in] Handle to device context */
920     INT width,  /* [in] Bitmap width */
921     INT height) /* [in] Bitmap height */
922 {
923     return CreateCompatibleBitmap( hdc, width, height );
924 }
925
926
927 /******************************************************************************
928  * GetBitmapDimensionEx [GDI32.@]
929  *
930  * Retrieves dimensions of a bitmap.
931  *
932  * RETURNS
933  *    Success: TRUE
934  *    Failure: FALSE
935  */
936 BOOL WINAPI GetBitmapDimensionEx(
937     HBITMAP hbitmap, /* [in]  Handle to bitmap */
938     LPSIZE size)     /* [out] Address of struct receiving dimensions */
939 {
940     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
941     if (!bmp) return FALSE;
942     *size = bmp->size;
943     GDI_ReleaseObj( hbitmap );
944     return TRUE;
945 }
946
947
948 /******************************************************************************
949  * SetBitmapDimensionEx [GDI32.@]
950  *
951  * Assigns dimensions to a bitmap.
952  * MSDN says that this function will fail if hbitmap is a handle created by
953  * CreateDIBSection, but that's not true on Windows 2000.
954  *
955  * RETURNS
956  *    Success: TRUE
957  *    Failure: FALSE
958  */
959 BOOL WINAPI SetBitmapDimensionEx(
960     HBITMAP hbitmap, /* [in]  Handle to bitmap */
961     INT x,           /* [in]  Bitmap width */
962     INT y,           /* [in]  Bitmap height */
963     LPSIZE prevSize) /* [out] Address of structure for orig dims */
964 {
965     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
966     if (!bmp) return FALSE;
967     if (prevSize) *prevSize = bmp->size;
968     bmp->size.cx = x;
969     bmp->size.cy = y;
970     GDI_ReleaseObj( hbitmap );
971     return TRUE;
972 }