Back to home page

Wine source

 
 

    


401710d7 Alexan*0001 /*
                0002  * GDI bitmap objects
                0003  *
                0004  * Copyright 1993 Alexandre Julliard
87f87bf6 Huw D.*0005  *           1998 Huw D M Davies
0799c1a7 Alexan*0006  *
                0007  * This library is free software; you can redistribute it and/or
                0008  * modify it under the terms of the GNU Lesser General Public
                0009  * License as published by the Free Software Foundation; either
                0010  * version 2.1 of the License, or (at your option) any later version.
                0011  *
                0012  * This library is distributed in the hope that it will be useful,
                0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                0015  * Lesser General Public License for more details.
                0016  *
                0017  * You should have received a copy of the GNU Lesser General Public
                0018  * License along with this library; if not, write to the Free Software
360a3f91 Jonath*0019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
a2f2e019 Alexan*0020  */
d90840e1 Alexan*0021 
75b8f888 Alexan*0022 #include <stdarg.h>
8d24ae6d Alexan*0023 #include <stdlib.h>
84c70f55 Alexan*0024 #include <string.h>
317af320 Marcus*0025 
75b8f888 Alexan*0026 #include "windef.h"
                0027 #include "winbase.h"
                0028 #include "wingdi.h"
6ec42c0c Alexan*0029 #include "gdi_private.h"
0799c1a7 Alexan*0030 #include "wine/debug.h"
670cdc45 Alexan*0031 
0799c1a7 Alexan*0032 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
b4b9fae6 Patrik*0033 
77b9918e Alexan*0034 
a1e31397 Alexan*0035 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc );
68d19b95 Alexan*0036 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
f0387109 Alexan*0037 static BOOL BITMAP_DeleteObject( HGDIOBJ handle );
d8a9244f Alexan*0038 
                0039 static const struct gdi_obj_funcs bitmap_funcs =
                0040 {
                0041     BITMAP_SelectObject,  /* pSelectObject */
                0042     BITMAP_GetObject,     /* pGetObjectA */
                0043     BITMAP_GetObject,     /* pGetObjectW */
                0044     NULL,                 /* pUnrealizeObject */
                0045     BITMAP_DeleteObject   /* pDeleteObject */
                0046 };
                0047 
122b5bf7 Alexan*0048 
46ea8b3f Alexan*0049 /******************************************************************************
783a3954 Jon Gr*0050  * CreateBitmap [GDI32.@]
                0051  *
                0052  * Creates a bitmap with the specified info.
46ea8b3f Alexan*0053  *
                0054  * PARAMS
                0055  *    width  [I] bitmap width
                0056  *    height [I] bitmap height
                0057  *    planes [I] Number of color planes
                0058  *    bpp    [I] Number of bits to identify a color
                0059  *    bits   [I] Pointer to array containing color data
                0060  *
                0061  * RETURNS
                0062  *    Success: Handle to bitmap
87f87bf6 Huw D.*0063  *    Failure: 0
21979019 Alexan*0064  */
a3960292 Alexan*0065 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
853cb86f Jon Gr*0066                              UINT bpp, LPCVOID bits )
401710d7 Alexan*0067 {
853cb86f Jon Gr*0068     BITMAP bm;
7ebe1a41 Alexan*0069 
853cb86f Jon Gr*0070     bm.bmType = 0;
                0071     bm.bmWidth = width;
                0072     bm.bmHeight = height;
d33e0d2c Alexan*0073     bm.bmWidthBytes = get_bitmap_stride( width, bpp );
853cb86f Jon Gr*0074     bm.bmPlanes = planes;
                0075     bm.bmBitsPixel = bpp;
                0076     bm.bmBits = (LPVOID)bits;
8d24ae6d Alexan*0077 
853cb86f Jon Gr*0078     return CreateBitmapIndirect( &bm );
401710d7 Alexan*0079 }
                0080 
46ea8b3f Alexan*0081 /******************************************************************************
783a3954 Jon Gr*0082  * CreateCompatibleBitmap [GDI32.@]
                0083  *
                0084  * Creates a bitmap compatible with the DC.
46ea8b3f Alexan*0085  *
                0086  * PARAMS
                0087  *    hdc    [I] Handle to device context
                0088  *    width  [I] Width of bitmap
                0089  *    height [I] Height of bitmap
                0090  *
                0091  * RETURNS
                0092  *    Success: Handle to bitmap
87f87bf6 Huw D.*0093  *    Failure: 0
a2f2e019 Alexan*0094  */
a3960292 Alexan*0095 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
a2f2e019 Alexan*0096 {
9ecc1e07 Alexan*0097     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
                0098     BITMAPINFO *bi = (BITMAPINFO *)buffer;
                0099     DIBSECTION dib;
d90840e1 Alexan*0100 
9ecc1e07 Alexan*0101     TRACE("(%p,%d,%d)\n", hdc, width, height);
0dd2910e Michae*0102 
b962fca7 Alexan*0103     if (GetObjectType( hdc ) != OBJ_MEMDC)
9ecc1e07 Alexan*0104         return CreateBitmap( width, height,
                0105                              GetDeviceCaps(hdc, PLANES), GetDeviceCaps(hdc, BITSPIXEL), NULL );
                0106 
                0107     switch (GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(dib), &dib ))
0dd2910e Michae*0108     {
9ecc1e07 Alexan*0109     case sizeof(BITMAP): /* A device-dependent bitmap is selected in the DC */
                0110         return CreateBitmap( width, height, dib.dsBm.bmPlanes, dib.dsBm.bmBitsPixel, NULL );
                0111 
                0112     case sizeof(DIBSECTION): /* A DIB section is selected in the DC */
                0113         bi->bmiHeader = dib.dsBmih;
                0114         bi->bmiHeader.biWidth  = width;
                0115         bi->bmiHeader.biHeight = height;
                0116         if (dib.dsBmih.biCompression == BI_BITFIELDS)  /* copy the color masks */
                0117             memcpy(bi->bmiColors, dib.dsBitfields, sizeof(dib.dsBitfields));
                0118         else if (dib.dsBmih.biBitCount <= 8)  /* copy the color table */
                0119             GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
                0120         return CreateDIBSection( hdc, bi, DIB_RGB_COLORS, NULL, NULL, 0 );
                0121 
                0122     default:
                0123         return 0;
b89525fb Alexan*0124     }
a2f2e019 Alexan*0125 }
                0126 
                0127 
46ea8b3f Alexan*0128 /******************************************************************************
783a3954 Jon Gr*0129  * CreateBitmapIndirect [GDI32.@]
                0130  *
853cb86f Jon Gr*0131  * Creates a bitmap with the specified info.
                0132  *
                0133  * PARAMS
                0134  *  bmp [I] Pointer to the bitmap info describing the bitmap
46ea8b3f Alexan*0135  *
                0136  * RETURNS
                0137  *    Success: Handle to bitmap
853cb86f Jon Gr*0138  *    Failure: NULL. Use GetLastError() to determine the cause.
                0139  *
                0140  * NOTES
2e5cb7aa FrédÃ*0141  *  If a width or height of 0 is given, a 1x1 monochrome bitmap is returned.
401710d7 Alexan*0142  */
853cb86f Jon Gr*0143 HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
d90840e1 Alexan*0144 {
853cb86f Jon Gr*0145     BITMAP bm;
                0146     BITMAPOBJ *bmpobj;
                0147     HBITMAP hbitmap;
82973cfb Huw D.*0148     INT dib_stride;
                0149     SIZE_T size;
853cb86f Jon Gr*0150 
0510a7a5 Dmitry*0151     if (!bmp || bmp->bmType)
853cb86f Jon Gr*0152     {
                0153         SetLastError( ERROR_INVALID_PARAMETER );
                0154         return NULL;
                0155     }
                0156 
d5456de0 Dmitry*0157     if (bmp->bmWidth > 0x7ffffff || bmp->bmHeight > 0x7ffffff)
                0158     {
                0159         SetLastError( ERROR_INVALID_PARAMETER );
                0160         return 0;
                0161     }
                0162 
853cb86f Jon Gr*0163     bm = *bmp;
                0164 
                0165     if (!bm.bmWidth || !bm.bmHeight)
                0166     {
0510a7a5 Dmitry*0167         return GetStockObject( DEFAULT_BITMAP );
853cb86f Jon Gr*0168     }
                0169     else
                0170     {
                0171         if (bm.bmHeight < 0)
                0172             bm.bmHeight = -bm.bmHeight;
                0173         if (bm.bmWidth < 0)
                0174             bm.bmWidth = -bm.bmWidth;
                0175     }
                0176 
0510a7a5 Dmitry*0177     if (bm.bmPlanes != 1)
                0178     {
                0179         FIXME("planes = %d\n", bm.bmPlanes);
                0180         SetLastError( ERROR_INVALID_PARAMETER );
                0181         return NULL;
                0182     }
                0183 
d5d8a5be Stefan*0184     /* Windows only uses 1, 4, 8, 16, 24 and 32 bpp */
                0185     if(bm.bmBitsPixel == 1)         bm.bmBitsPixel = 1;
                0186     else if(bm.bmBitsPixel <= 4)    bm.bmBitsPixel = 4;
                0187     else if(bm.bmBitsPixel <= 8)    bm.bmBitsPixel = 8;
                0188     else if(bm.bmBitsPixel <= 16)   bm.bmBitsPixel = 16;
                0189     else if(bm.bmBitsPixel <= 24)   bm.bmBitsPixel = 24;
                0190     else if(bm.bmBitsPixel <= 32)   bm.bmBitsPixel = 32;
                0191     else {
                0192         WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm.bmBitsPixel);
                0193         SetLastError(ERROR_INVALID_PARAMETER);
                0194         return NULL;
                0195     }
                0196 
0457b0c3 Dmitry*0197     /* Windows ignores the provided bm.bmWidthBytes */
d33e0d2c Alexan*0198     bm.bmWidthBytes = get_bitmap_stride( bm.bmWidth, bm.bmBitsPixel );
82973cfb Huw D.*0199 
                0200     dib_stride = get_dib_stride( bm.bmWidth, bm.bmBitsPixel );
                0201     size = dib_stride * bm.bmHeight;
                0202     /* Check for overflow (dib_stride itself must be ok because of the constraint on bm.bmWidth above). */
                0203     if (dib_stride != size / bm.bmHeight)
d5456de0 Dmitry*0204     {
82973cfb Huw D.*0205         SetLastError( ERROR_INVALID_PARAMETER );
d5456de0 Dmitry*0206         return 0;
                0207     }
0457b0c3 Dmitry*0208 
311c53db Alexan*0209     /* Create the BITMAPOBJ */
e896af40 Alexan*0210     if (!(bmpobj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmpobj) )))
853cb86f Jon Gr*0211     {
                0212         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
311c53db Alexan*0213         return 0;
853cb86f Jon Gr*0214     }
                0215 
71ea68b6 Alexan*0216     bmpobj->dib.dsBm = bm;
82973cfb Huw D.*0217     bmpobj->dib.dsBm.bmBits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
                0218     if (!bmpobj->dib.dsBm.bmBits)
                0219     {
                0220         HeapFree( GetProcessHeap(), 0, bmpobj );
                0221         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
                0222         return 0;
                0223     }
853cb86f Jon Gr*0224 
df357093 Alexan*0225     if (!(hbitmap = alloc_gdi_handle( bmpobj, OBJ_BITMAP, &bitmap_funcs )))
311c53db Alexan*0226     {
82973cfb Huw D.*0227         HeapFree( GetProcessHeap(), 0, bmpobj->dib.dsBm.bmBits );
311c53db Alexan*0228         HeapFree( GetProcessHeap(), 0, bmpobj );
                0229         return 0;
                0230     }
                0231 
853cb86f Jon Gr*0232     if (bm.bmBits)
                0233         SetBitmapBits( hbitmap, bm.bmHeight * bm.bmWidthBytes, bm.bmBits );
                0234 
9969b8de Huw D.*0235     TRACE("%dx%d, bpp %d planes %d: returning %p\n", bm.bmWidth, bm.bmHeight,
                0236           bm.bmBitsPixel, bm.bmPlanes, hbitmap);
311c53db Alexan*0237 
853cb86f Jon Gr*0238     return hbitmap;
21979019 Alexan*0239 }
                0240 
                0241 
                0242 /***********************************************************************
783a3954 Jon Gr*0243  * GetBitmapBits [GDI32.@]
                0244  *
                0245  * Copies bitmap bits of bitmap to buffer.
9a624916 Vincen*0246  *
46ea8b3f Alexan*0247  * RETURNS
                0248  *    Success: Number of bytes copied
                0249  *    Failure: 0
d90840e1 Alexan*0250  */
a3960292 Alexan*0251 LONG WINAPI GetBitmapBits(
                0252     HBITMAP hbitmap, /* [in]  Handle to bitmap */
46ea8b3f Alexan*0253     LONG count,        /* [in]  Number of bytes to copy */
87f87bf6 Huw D.*0254     LPVOID bits)       /* [out] Pointer to buffer to receive bits */
401710d7 Alexan*0255 {
1724c735 Alexan*0256     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
                0257     BITMAPINFO *info = (BITMAPINFO *)buffer;
                0258     struct gdi_image_bits src_bits;
                0259     struct bitblt_coords src;
                0260     int dst_stride, max, ret;
5811a2cc Alexan*0261     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
9a624916 Vincen*0262 
87f87bf6 Huw D.*0263     if (!bmp) return 0;
9a624916 Vincen*0264 
71ea68b6 Alexan*0265     dst_stride = get_bitmap_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel );
                0266     ret = max = dst_stride * bmp->dib.dsBm.bmHeight;
1724c735 Alexan*0267     if (!bits) goto done;
5c323a54 Bruno *0268     if (count < 0 || count > max) count = max;
1724c735 Alexan*0269     ret = count;
                0270 
                0271     src.visrect.left = 0;
71ea68b6 Alexan*0272     src.visrect.right = bmp->dib.dsBm.bmWidth;
1724c735 Alexan*0273     src.visrect.top = 0;
                0274     src.visrect.bottom = (count + dst_stride - 1) / dst_stride;
                0275     src.x = src.y = 0;
                0276     src.width = src.visrect.right - src.visrect.left;
                0277     src.height = src.visrect.bottom - src.visrect.top;
                0278 
cf85fb14 Alexan*0279     if (!get_image_from_bitmap( bmp, info, &src_bits, &src ))
1724c735 Alexan*0280     {
                0281         const char *src_ptr = src_bits.ptr;
a4f0415a Huw D.*0282         int src_stride = info->bmiHeader.biSizeImage / abs( info->bmiHeader.biHeight );
140eabf3 Dmitry*0283 
1724c735 Alexan*0284         /* GetBitmapBits returns 16-bit aligned data */
7e2be17d Alexan*0285 
1724c735 Alexan*0286         if (info->bmiHeader.biHeight > 0)
7e2be17d Alexan*0287         {
1724c735 Alexan*0288             src_ptr += (info->bmiHeader.biHeight - 1) * src_stride;
                0289             src_stride = -src_stride;
140eabf3 Dmitry*0290         }
1724c735 Alexan*0291         src_ptr += src.visrect.top * src_stride;
                0292 
                0293         if (src_stride == dst_stride) memcpy( bits, src_ptr, count );
                0294         else while (count > 0)
140eabf3 Dmitry*0295         {
1724c735 Alexan*0296             memcpy( bits, src_ptr, min( count, dst_stride ) );
                0297             src_ptr += src_stride;
                0298             bits = (char *)bits + dst_stride;
                0299             count -= dst_stride;
7e2be17d Alexan*0300         }
1724c735 Alexan*0301         if (src_bits.free) src_bits.free( &src_bits );
2a2321bb Alexan*0302     }
1724c735 Alexan*0303     else ret = 0;
87f87bf6 Huw D.*0304 
1724c735 Alexan*0305 done:
2a2321bb Alexan*0306     GDI_ReleaseObj( hbitmap );
87f87bf6 Huw D.*0307     return ret;
401710d7 Alexan*0308 }
                0309 
                0310 
46ea8b3f Alexan*0311 /******************************************************************************
783a3954 Jon Gr*0312  * SetBitmapBits [GDI32.@]
                0313  *
                0314  * Sets bits of color data for a bitmap.
46ea8b3f Alexan*0315  *
                0316  * RETURNS
                0317  *    Success: Number of bytes used in setting the bitmap bits
                0318  *    Failure: 0
401710d7 Alexan*0319  */
a3960292 Alexan*0320 LONG WINAPI SetBitmapBits(
                0321     HBITMAP hbitmap, /* [in] Handle to bitmap */
46ea8b3f Alexan*0322     LONG count,        /* [in] Number of bytes in bitmap array */
87f87bf6 Huw D.*0323     LPCVOID bits)      /* [in] Address of array with bitmap bits */
401710d7 Alexan*0324 {
10784991 Alexan*0325     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
                0326     BITMAPINFO *info = (BITMAPINFO *)buffer;
c7b45aa8 Dmitry*0327     BITMAPOBJ *bmp;
10784991 Alexan*0328     DWORD err;
                0329     int i, src_stride, dst_stride;
                0330     struct bitblt_coords src, dst;
                0331     struct gdi_image_bits src_bits;
cb82c45b Huw D.*0332     HRGN clip = NULL;
9a624916 Vincen*0333 
c7b45aa8 Dmitry*0334     if (!bits) return 0;
                0335 
                0336     bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
                0337     if (!bmp) return 0;
87f87bf6 Huw D.*0338 
ade697e8 Alexan*0339     if (count < 0) {
a0b260e7 Michae*0340     WARN("(%d): Negative number of bytes passed???\n", count );
ade697e8 Alexan*0341     count = -count;
                0342     }
aca05783 Alexan*0343 
71ea68b6 Alexan*0344     src_stride = get_bitmap_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel );
                0345     count = min( count, src_stride * bmp->dib.dsBm.bmHeight );
10784991 Alexan*0346 
71ea68b6 Alexan*0347     dst_stride = get_dib_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel );
10784991 Alexan*0348 
                0349     src.visrect.left   = src.x = 0;
                0350     src.visrect.top    = src.y = 0;
71ea68b6 Alexan*0351     src.visrect.right  = src.width = bmp->dib.dsBm.bmWidth;
cb82c45b Huw D.*0352     src.visrect.bottom = src.height = (count + src_stride - 1 ) / src_stride;
10784991 Alexan*0353     dst = src;
                0354 
cb82c45b Huw D.*0355     if (count % src_stride)
                0356     {
                0357         HRGN last_row;
71ea68b6 Alexan*0358         int extra_pixels = ((count % src_stride) << 3) / bmp->dib.dsBm.bmBitsPixel;
cb82c45b Huw D.*0359 
71ea68b6 Alexan*0360         if ((count % src_stride << 3) % bmp->dib.dsBm.bmBitsPixel)
cb82c45b Huw D.*0361             FIXME( "Unhandled partial pixel\n" );
                0362         clip = CreateRectRgn( src.visrect.left, src.visrect.top,
                0363                               src.visrect.right, src.visrect.bottom - 1 );
                0364         last_row = CreateRectRgn( src.visrect.left, src.visrect.bottom - 1,
                0365                                   src.visrect.left + extra_pixels, src.visrect.bottom );
                0366         CombineRgn( clip, clip, last_row, RGN_OR );
                0367         DeleteObject( last_row );
                0368     }
10784991 Alexan*0369 
                0370     TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n",
71ea68b6 Alexan*0371           hbitmap, count, bits, bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmHeight,
                0372           bmp->dib.dsBm.bmBitsPixel, src.height );
02d81485 Alexan*0373 
10784991 Alexan*0374     if (src_stride == dst_stride)
                0375     {
                0376         src_bits.ptr = (void *)bits;
                0377         src_bits.is_copy = FALSE;
                0378         src_bits.free = NULL;
                0379     }
                0380     else
                0381     {
                0382         if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride )))
02d81485 Alexan*0383         {
10784991 Alexan*0384             GDI_ReleaseObj( hbitmap );
                0385             return 0;
02d81485 Alexan*0386         }
10784991 Alexan*0387         src_bits.is_copy = TRUE;
                0388         src_bits.free = free_heap_bits;
cb82c45b Huw D.*0389         for (i = 0; i < count / src_stride; i++)
10784991 Alexan*0390             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, src_stride );
cb82c45b Huw D.*0391         if (count % src_stride)
                0392             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, count % src_stride );
02d81485 Alexan*0393     }
                0394 
10784991 Alexan*0395     /* query the color info */
                0396     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
                0397     info->bmiHeader.biPlanes        = 1;
71ea68b6 Alexan*0398     info->bmiHeader.biBitCount      = bmp->dib.dsBm.bmBitsPixel;
10784991 Alexan*0399     info->bmiHeader.biCompression   = BI_RGB;
                0400     info->bmiHeader.biXPelsPerMeter = 0;
                0401     info->bmiHeader.biYPelsPerMeter = 0;
                0402     info->bmiHeader.biClrUsed       = 0;
                0403     info->bmiHeader.biClrImportant  = 0;
                0404     info->bmiHeader.biWidth         = 0;
                0405     info->bmiHeader.biHeight        = 0;
                0406     info->bmiHeader.biSizeImage     = 0;
7c4c233d Alexan*0407     err = put_image_into_bitmap( bmp, 0, info, NULL, NULL, NULL );
77b9918e Alexan*0408 
10784991 Alexan*0409     if (!err || err == ERROR_BAD_FORMAT)
                0410     {
71ea68b6 Alexan*0411         info->bmiHeader.biWidth     = bmp->dib.dsBm.bmWidth;
70d8341a Alexan*0412         info->bmiHeader.biHeight    = -dst.height;
                0413         info->bmiHeader.biSizeImage = dst.height * dst_stride;
7c4c233d Alexan*0414         err = put_image_into_bitmap( bmp, clip, info, &src_bits, &src, &dst );
10784991 Alexan*0415     }
                0416     if (err) count = 0;
84c70f55 Alexan*0417 
cb82c45b Huw D.*0418     if (clip) DeleteObject( clip );
10784991 Alexan*0419     if (src_bits.free) src_bits.free( &src_bits );
2a2321bb Alexan*0420     GDI_ReleaseObj( hbitmap );
10784991 Alexan*0421     return count;
401710d7 Alexan*0422 }
                0423 
d8a9244f Alexan*0424 
                0425 /***********************************************************************
                0426  *           BITMAP_SelectObject
                0427  */
a1e31397 Alexan*0428 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
d8a9244f Alexan*0429 {
4227bf4a Alexan*0430     HGDIOBJ ret;
a1e31397 Alexan*0431     BITMAPOBJ *bitmap;
                0432     DC *dc;
592bfd52 Alexan*0433     PHYSDEV physdev;
d8a9244f Alexan*0434 
630c976f Alexan*0435     if (!(dc = get_dc_ptr( hdc ))) return 0;
a1e31397 Alexan*0436 
                0437     if (GetObjectType( hdc ) != OBJ_MEMDC)
                0438     {
                0439         ret = 0;
                0440         goto done;
                0441     }
4227bf4a Alexan*0442     ret = dc->hBitmap;
d8a9244f Alexan*0443     if (handle == dc->hBitmap) goto done;  /* nothing to do */
                0444 
5811a2cc Alexan*0445     if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
630c976f Alexan*0446     {
                0447         ret = 0;
                0448         goto done;
                0449     }
                0450 
b95dd7e8 Alexan*0451     if (handle != GetStockObject(DEFAULT_BITMAP) && GDI_get_ref_count( handle ))
d8a9244f Alexan*0452     {
                0453         WARN( "Bitmap already selected in another DC\n" );
630c976f Alexan*0454         GDI_ReleaseObj( handle );
a1e31397 Alexan*0455         ret = 0;
                0456         goto done;
d8a9244f Alexan*0457     }
                0458 
294faf5e Alexan*0459     if (bitmap->dib.dsBm.bmBitsPixel != 1 &&
                0460         bitmap->dib.dsBm.bmBitsPixel != GetDeviceCaps( hdc, BITSPIXEL ))
                0461     {
                0462         WARN( "Wrong format bitmap %u bpp\n", bitmap->dib.dsBm.bmBitsPixel );
                0463         GDI_ReleaseObj( handle );
                0464         ret = 0;
                0465         goto done;
                0466     }
                0467 
592bfd52 Alexan*0468     physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
adc63287 Alexan*0469     if (!physdev->funcs->pSelectBitmap( physdev, handle ))
630c976f Alexan*0470     {
                0471         GDI_ReleaseObj( handle );
                0472         ret = 0;
                0473     }
                0474     else
d8a9244f Alexan*0475     {
d1f73181 Alexan*0476         dc->hBitmap = handle;
af6c0a09 Alexan*0477         GDI_inc_ref_count( handle );
d88ff791 Alexan*0478         dc->dirty = 0;
69c8f0b6 Alexan*0479         dc->vis_rect.left   = 0;
                0480         dc->vis_rect.top    = 0;
71ea68b6 Alexan*0481         dc->vis_rect.right  = bitmap->dib.dsBm.bmWidth;
                0482         dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
41e5bc06 Alexan*0483         dc->device_rect = dc->vis_rect;
630c976f Alexan*0484         GDI_ReleaseObj( handle );
b89525fb Alexan*0485         DC_InitDC( dc );
af6c0a09 Alexan*0486         GDI_dec_ref_count( ret );
d8a9244f Alexan*0487     }
4227bf4a Alexan*0488 
d8a9244f Alexan*0489  done:
a1e31397 Alexan*0490     release_dc_ptr( dc );
d8a9244f Alexan*0491     return ret;
                0492 }
                0493 
                0494 
401710d7 Alexan*0495 /***********************************************************************
7cbe6572 Alexan*0496  *           BITMAP_DeleteObject
401710d7 Alexan*0497  */
f0387109 Alexan*0498 static BOOL BITMAP_DeleteObject( HGDIOBJ handle )
401710d7 Alexan*0499 {
592bfd52 Alexan*0500     BITMAPOBJ *bmp = free_gdi_handle( handle );
f0387109 Alexan*0501 
                0502     if (!bmp) return FALSE;
71ea68b6 Alexan*0503     HeapFree( GetProcessHeap(), 0, bmp->dib.dsBm.bmBits );
1def41b9 Huw D.*0504     HeapFree( GetProcessHeap(), 0, bmp );
                0505     return TRUE;
401710d7 Alexan*0506 }
                0507 
e21c15e3 Alexan*0508 
401710d7 Alexan*0509 /***********************************************************************
2d6457c1 Patrik*0510  *           BITMAP_GetObject
d90840e1 Alexan*0511  */
68d19b95 Alexan*0512 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
d90840e1 Alexan*0513 {
a51b2c8b Alexan*0514     INT ret = 0;
5811a2cc Alexan*0515     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
d8a9244f Alexan*0516 
68d19b95 Alexan*0517     if (!bmp) return 0;
140eabf3 Dmitry*0518 
68d19b95 Alexan*0519     if (!buffer) ret = sizeof(BITMAP);
a51b2c8b Alexan*0520     else if (count >= sizeof(BITMAP))
a845b88e Alexan*0521     {
71ea68b6 Alexan*0522         BITMAP *bitmap = buffer;
                0523         *bitmap = bmp->dib.dsBm;
                0524         bitmap->bmBits = NULL;
68d19b95 Alexan*0525         ret = sizeof(BITMAP);
a845b88e Alexan*0526     }
68d19b95 Alexan*0527     GDI_ReleaseObj( handle );
                0528     return ret;
d90840e1 Alexan*0529 }
9a624916 Vincen*0530 
d90840e1 Alexan*0531 
46ea8b3f Alexan*0532 /******************************************************************************
783a3954 Jon Gr*0533  * CreateDiscardableBitmap [GDI32.@]
                0534  *
                0535  * Creates a discardable bitmap.
46ea8b3f Alexan*0536  *
                0537  * RETURNS
                0538  *    Success: Handle to bitmap
                0539  *    Failure: NULL
36ca1368 Alexan*0540  */
a3960292 Alexan*0541 HBITMAP WINAPI CreateDiscardableBitmap(
                0542     HDC hdc,    /* [in] Handle to device context */
                0543     INT width,  /* [in] Bitmap width */
                0544     INT height) /* [in] Bitmap height */
36ca1368 Alexan*0545 {
a3960292 Alexan*0546     return CreateCompatibleBitmap( hdc, width, height );
36ca1368 Alexan*0547 }
401710d7 Alexan*0548 
e2bfa4c7 Alexan*0549 
46ea8b3f Alexan*0550 /******************************************************************************
783a3954 Jon Gr*0551  * GetBitmapDimensionEx [GDI32.@]
                0552  *
                0553  * Retrieves dimensions of a bitmap.
46ea8b3f Alexan*0554  *
                0555  * RETURNS
                0556  *    Success: TRUE
                0557  *    Failure: FALSE
e2bfa4c7 Alexan*0558  */
a3960292 Alexan*0559 BOOL WINAPI GetBitmapDimensionEx(
                0560     HBITMAP hbitmap, /* [in]  Handle to bitmap */
                0561     LPSIZE size)     /* [out] Address of struct receiving dimensions */
e2bfa4c7 Alexan*0562 {
5811a2cc Alexan*0563     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
e2bfa4c7 Alexan*0564     if (!bmp) return FALSE;
87f87bf6 Huw D.*0565     *size = bmp->size;
2a2321bb Alexan*0566     GDI_ReleaseObj( hbitmap );
e2bfa4c7 Alexan*0567     return TRUE;
                0568 }
                0569 
                0570 
46ea8b3f Alexan*0571 /******************************************************************************
783a3954 Jon Gr*0572  * SetBitmapDimensionEx [GDI32.@]
                0573  *
                0574  * Assigns dimensions to a bitmap.
0dd2910e Michae*0575  * MSDN says that this function will fail if hbitmap is a handle created by
                0576  * CreateDIBSection, but that's not true on Windows 2000.
46ea8b3f Alexan*0577  *
                0578  * RETURNS
                0579  *    Success: TRUE
                0580  *    Failure: FALSE
                0581  */
a3960292 Alexan*0582 BOOL WINAPI SetBitmapDimensionEx(
                0583     HBITMAP hbitmap, /* [in]  Handle to bitmap */
                0584     INT x,           /* [in]  Bitmap width */
                0585     INT y,           /* [in]  Bitmap height */
                0586     LPSIZE prevSize) /* [out] Address of structure for orig dims */
e2bfa4c7 Alexan*0587 {
5811a2cc Alexan*0588     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
e2bfa4c7 Alexan*0589     if (!bmp) return FALSE;
87f87bf6 Huw D.*0590     if (prevSize) *prevSize = bmp->size;
                0591     bmp->size.cx = x;
                0592     bmp->size.cy = y;
2a2321bb Alexan*0593     GDI_ReleaseObj( hbitmap );
e2bfa4c7 Alexan*0594     return TRUE;
                0595 }