General tidy up of the MetaFile driver - make sure that everything
[wine] / objects / bitmap.c
1 /*
2  * GDI bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1998 Huw D M Davies
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "wine/winbase16.h"
12 #include "gdi.h"
13 #include "dc.h"
14 #include "bitmap.h"
15 #include "heap.h"
16 #include "global.h"
17 #include "sysmetrics.h"
18 #include "cursoricon.h"
19 #include "debug.h"
20 #include "monitor.h"
21 #include "wine/winuser16.h"
22
23 DECLARE_DEBUG_CHANNEL(bitmap)
24 DECLARE_DEBUG_CHANNEL(resource)
25
26 BITMAP_DRIVER *BITMAP_Driver = NULL;
27
28
29 /***********************************************************************
30  *           BITMAP_GetWidthBytes
31  *
32  * Return number of bytes taken by a scanline of 16-bit aligned Windows DDB
33  * data.
34  */
35 INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp )
36 {
37     switch(bpp)
38     {
39     case 1:
40         return 2 * ((bmWidth+15) >> 4);
41
42     case 24:
43         bmWidth *= 3; /* fall through */
44     case 8:
45         return bmWidth + (bmWidth & 1);
46
47     case 32:
48         return bmWidth * 4;
49
50     case 16:
51     case 15:
52         return bmWidth * 2;
53
54     case 4:
55         return 2 * ((bmWidth+3) >> 2);
56
57     default:
58         WARN(bitmap,"Unknown depth %d, please report.\n", bpp );
59     }
60     return -1;
61 }
62
63 /***********************************************************************
64  *           CreateUserBitmap16    (GDI.407)
65  */
66 HBITMAP16 WINAPI CreateUserBitmap16( INT16 width, INT16 height, UINT16 planes,
67                                      UINT16 bpp, LPCVOID bits )
68 {
69     return CreateBitmap16( width, height, planes, bpp, bits );
70 }
71
72 /***********************************************************************
73  *           CreateUserDiscardableBitmap16    (GDI.409)
74  */
75 HBITMAP16 WINAPI CreateUserDiscardableBitmap16( WORD dummy, 
76                                                 INT16 width, INT16 height )
77 {
78     return CreateUserBitmap16( width, height, 1, MONITOR_GetDepth(&MONITOR_PrimaryMonitor), NULL );
79 }
80
81
82 /***********************************************************************
83  *           CreateBitmap16    (GDI.48)
84  */
85 HBITMAP16 WINAPI CreateBitmap16( INT16 width, INT16 height, UINT16 planes,
86                                  UINT16 bpp, LPCVOID bits )
87 {
88     return CreateBitmap( width, height, planes, bpp, bits );
89 }
90
91
92 /******************************************************************************
93  * CreateBitmap32 [GDI32.25]  Creates a bitmap with the specified info
94  *
95  * PARAMS
96  *    width  [I] bitmap width
97  *    height [I] bitmap height
98  *    planes [I] Number of color planes
99  *    bpp    [I] Number of bits to identify a color
100  *    bits   [I] Pointer to array containing color data
101  *
102  * RETURNS
103  *    Success: Handle to bitmap
104  *    Failure: 0
105  */
106 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
107                                  UINT bpp, LPCVOID bits )
108 {
109     BITMAPOBJ *bmp;
110     HBITMAP hbitmap;
111
112     planes = (BYTE)planes;
113     bpp    = (BYTE)bpp;
114
115
116       /* Check parameters */
117     if (!height || !width) return 0;
118     if (planes != 1) {
119         FIXME(bitmap, "planes = %d\n", planes);
120         return 0;
121     }
122     if (height < 0) height = -height;
123     if (width < 0) width = -width;
124
125       /* Create the BITMAPOBJ */
126     hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
127     if (!hbitmap) return 0;
128
129     TRACE(bitmap, "%dx%d, %d colors returning %08x\n", width, height,
130           1 << (planes*bpp), hbitmap);
131
132     bmp = (BITMAPOBJ *) GDI_HEAP_LOCK( hbitmap );
133
134     bmp->size.cx = 0;
135     bmp->size.cy = 0;
136     bmp->bitmap.bmType = 0;
137     bmp->bitmap.bmWidth = width;
138     bmp->bitmap.bmHeight = height;
139     bmp->bitmap.bmPlanes = planes;
140     bmp->bitmap.bmBitsPixel = bpp;
141     bmp->bitmap.bmWidthBytes = BITMAP_GetWidthBytes( width, bpp );
142     bmp->bitmap.bmBits = NULL;
143
144     bmp->DDBitmap = NULL;
145     bmp->dib = NULL;
146
147     if (bits) /* Set bitmap bits */
148         SetBitmapBits( hbitmap, height * bmp->bitmap.bmWidthBytes,
149                          bits );
150     GDI_HEAP_UNLOCK( hbitmap );
151     return hbitmap;
152 }
153
154
155 /***********************************************************************
156  *           CreateCompatibleBitmap16    (GDI.51)
157  */
158 HBITMAP16 WINAPI CreateCompatibleBitmap16(HDC16 hdc, INT16 width, INT16 height)
159 {
160     return CreateCompatibleBitmap( hdc, width, height );
161 }
162
163
164 /******************************************************************************
165  * CreateCompatibleBitmap32 [GDI32.30]  Creates a bitmap compatible with the DC
166  *
167  * PARAMS
168  *    hdc    [I] Handle to device context
169  *    width  [I] Width of bitmap
170  *    height [I] Height of bitmap
171  *
172  * RETURNS
173  *    Success: Handle to bitmap
174  *    Failure: 0
175  */
176 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
177 {
178     HBITMAP hbmpRet = 0;
179     DC *dc;
180
181     TRACE(bitmap, "(%04x,%d,%d) = \n", hdc, width, height );
182     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
183     if ((width >= 0x10000) || (height >= 0x10000)) {
184         FIXME(bitmap,"got bad width %d or height %d, please look for reason\n",
185               width, height );
186     } else {
187         hbmpRet = CreateBitmap( width, height, 1, dc->w.bitsPerPixel, NULL );
188         if(dc->funcs->pCreateBitmap)
189             dc->funcs->pCreateBitmap( hbmpRet );
190     }
191     TRACE(bitmap,"\t\t%04x\n", hbmpRet);
192     GDI_HEAP_UNLOCK(hdc);
193     return hbmpRet;
194 }
195
196
197 /***********************************************************************
198  *           CreateBitmapIndirect16    (GDI.49)
199  */
200 HBITMAP16 WINAPI CreateBitmapIndirect16( const BITMAP16 * bmp )
201 {
202     return CreateBitmap16( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
203                            bmp->bmBitsPixel, PTR_SEG_TO_LIN( bmp->bmBits ) );
204 }
205
206
207 /******************************************************************************
208  * CreateBitmapIndirect32 [GDI32.26]  Creates a bitmap with the specifies info
209  *
210  * RETURNS
211  *    Success: Handle to bitmap
212  *    Failure: NULL
213  */
214 HBITMAP WINAPI CreateBitmapIndirect(
215     const BITMAP * bmp) /* [in] Pointer to the bitmap data */
216 {
217     return CreateBitmap( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
218                            bmp->bmBitsPixel, bmp->bmBits );
219 }
220
221
222 /***********************************************************************
223  *           GetBitmapBits16    (GDI.74)
224  */
225 LONG WINAPI GetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPVOID buffer )
226 {
227     return GetBitmapBits( hbitmap, count, buffer );
228 }
229
230
231 /***********************************************************************
232  * GetBitmapBits32 [GDI32.143]  Copies bitmap bits of bitmap to buffer
233  * 
234  * RETURNS
235  *    Success: Number of bytes copied
236  *    Failure: 0
237  */
238 LONG WINAPI GetBitmapBits(
239     HBITMAP hbitmap, /* [in]  Handle to bitmap */
240     LONG count,        /* [in]  Number of bytes to copy */
241     LPVOID bits)       /* [out] Pointer to buffer to receive bits */
242 {
243     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
244     LONG height, ret;
245     
246     if (!bmp) return 0;
247
248     if (count < 0) {
249         WARN(bitmap, "(%ld): Negative number of bytes passed???\n", count );
250         count = -count;
251     }
252
253     /* Only get entire lines */
254     height = count / bmp->bitmap.bmWidthBytes;
255     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
256     count = height * bmp->bitmap.bmWidthBytes;
257     if (count == 0)
258       {
259         WARN(bitmap, "Less then one entire line requested\n");
260         GDI_HEAP_UNLOCK( hbitmap );
261         return 0;
262       }
263
264
265     TRACE(bitmap, "(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
266             hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
267             1 << bmp->bitmap.bmBitsPixel, height );
268
269     if(bmp->DDBitmap) { 
270
271         TRACE(bitmap, "Calling device specific BitmapBits\n");
272         if(bmp->DDBitmap->funcs->pBitmapBits)
273             ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
274                                                     DDB_GET);
275         else {
276             ERR(bitmap, "BitmapBits == NULL??\n");
277             ret = 0;
278         }       
279
280     } else {
281
282         if(!bmp->bitmap.bmBits) {
283             WARN(bitmap, "Bitmap is empty\n");
284             ret = 0;
285         } else {
286             memcpy(bits, bmp->bitmap.bmBits, count);
287             ret = count;
288         }
289
290     }
291
292     GDI_HEAP_UNLOCK( hbitmap );
293     return ret;
294 }
295
296
297 /***********************************************************************
298  *           SetBitmapBits16    (GDI.106)
299  */
300 LONG WINAPI SetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPCVOID buffer )
301 {
302     return SetBitmapBits( hbitmap, count, buffer );
303 }
304
305
306 /******************************************************************************
307  * SetBitmapBits32 [GDI32.303]  Sets bits of color data for a bitmap
308  *
309  * RETURNS
310  *    Success: Number of bytes used in setting the bitmap bits
311  *    Failure: 0
312  */
313 LONG WINAPI SetBitmapBits(
314     HBITMAP hbitmap, /* [in] Handle to bitmap */
315     LONG count,        /* [in] Number of bytes in bitmap array */
316     LPCVOID bits)      /* [in] Address of array with bitmap bits */
317 {
318     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
319     LONG height, ret;
320     
321     if (!bmp) return 0;
322
323     if (count < 0) {
324         WARN(bitmap, "(%ld): Negative number of bytes passed???\n", count );
325         count = -count;
326     }
327
328     /* Only get entire lines */
329     height = count / bmp->bitmap.bmWidthBytes;
330     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
331     count = height * bmp->bitmap.bmWidthBytes;
332
333     TRACE(bitmap, "(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
334             hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
335             1 << bmp->bitmap.bmBitsPixel, height );
336
337     if(bmp->DDBitmap) {
338
339         TRACE(bitmap, "Calling device specific BitmapBits\n");
340         if(bmp->DDBitmap->funcs->pBitmapBits)
341             ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, (void *) bits,
342                                                     count, DDB_SET);
343         else {
344             ERR(bitmap, "BitmapBits == NULL??\n");
345             ret = 0;
346         }
347         
348     } else {
349
350         if(!bmp->bitmap.bmBits) /* Alloc enough for entire bitmap */
351             bmp->bitmap.bmBits = HeapAlloc( GetProcessHeap(), 0, count );
352         if(!bmp->bitmap.bmBits) {
353             WARN(bitmap, "Unable to allocate bit buffer\n");
354             ret = 0;
355         } else {
356             memcpy(bmp->bitmap.bmBits, bits, count);
357             ret = count;
358         }
359     }
360
361     GDI_HEAP_UNLOCK( hbitmap );
362     return ret;
363 }
364
365 /***********************************************************************
366  * LoadImage16 [USER.389]
367  *
368  */
369 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
370                              INT16 desiredx, INT16 desiredy, UINT16 loadflags)
371 {
372     LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
373     return LoadImageA( hinst, nameStr, type, 
374                        desiredx, desiredy, loadflags );
375 }
376
377 /**********************************************************************
378  *          LoadImageA    (USER32.365)
379  * 
380  * FIXME: implementation lacks some features, see LR_ defines in windows.h
381  */
382
383 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
384                               INT desiredx, INT desiredy, UINT loadflags)
385 {
386     HANDLE res;
387     LPWSTR u_name;
388
389     if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
390     else u_name=(LPWSTR)name;
391     res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
392     if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
393     return res;
394 }
395
396
397 /******************************************************************************
398  * LoadImageW [USER32.366]  Loads an icon, cursor, or bitmap
399  *
400  * PARAMS
401  *    hinst     [I] Handle of instance that contains image
402  *    name      [I] Name of image
403  *    type      [I] Type of image
404  *    desiredx  [I] Desired width
405  *    desiredy  [I] Desired height
406  *    loadflags [I] Load flags
407  *
408  * RETURNS
409  *    Success: Handle to newly loaded image
410  *    Failure: NULL
411  *
412  * FIXME: Implementation lacks some features, see LR_ defines in windows.h
413  */
414 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
415                 INT desiredx, INT desiredy, UINT loadflags )
416 {
417     if (HIWORD(name)) {
418         TRACE(resource,"(0x%04x,%p,%d,%d,%d,0x%08x)\n",
419               hinst,name,type,desiredx,desiredy,loadflags);
420     } else {
421         TRACE(resource,"(0x%04x,%p,%d,%d,%d,0x%08x)\n",
422               hinst,name,type,desiredx,desiredy,loadflags);
423     }
424     if (loadflags & LR_DEFAULTSIZE) {
425         if (type == IMAGE_ICON) {
426             if (!desiredx) desiredx = SYSMETRICS_CXICON;
427             if (!desiredy) desiredy = SYSMETRICS_CYICON;
428         } else if (type == IMAGE_CURSOR) {
429             if (!desiredx) desiredx = SYSMETRICS_CXCURSOR;
430             if (!desiredy) desiredy = SYSMETRICS_CYCURSOR;
431         }
432     }
433     if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
434     switch (type) {
435     case IMAGE_BITMAP:
436         return BITMAP_Load( hinst, name, loadflags );
437
438     case IMAGE_ICON:
439         {
440         HDC hdc = GetDC(0);
441         UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
442         ReleaseDC(0, hdc);
443
444         return CURSORICON_Load(hinst, name, desiredx, desiredy,
445                                  MIN(16, palEnts), FALSE, loadflags);
446         }
447
448     case IMAGE_CURSOR:
449         return CURSORICON_Load(hinst, name, desiredx, desiredy,
450                                  1, TRUE, loadflags);
451     }
452     return 0;
453 }
454
455
456 /**********************************************************************
457  *              BITMAP_CopyBitmap
458  *
459  */
460 HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap)
461 {
462     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
463     HBITMAP res = 0;
464     BITMAP bm;
465
466     if(!bmp) return 0;
467
468     bm = bmp->bitmap;
469     bm.bmBits = NULL;
470     res = CreateBitmapIndirect(&bm);
471
472     if(res) {
473         char *buf = HeapAlloc( GetProcessHeap(), 0, bm.bmWidthBytes *
474                                bm.bmHeight );
475         GetBitmapBits (hbitmap, bm.bmWidthBytes * bm.bmHeight, buf);
476         SetBitmapBits (res, bm.bmWidthBytes * bm.bmHeight, buf);
477         HeapFree( GetProcessHeap(), 0, buf );
478     }
479
480     GDI_HEAP_UNLOCK( hbitmap );
481     return res;
482 }
483
484 /******************************************************************************
485  * CopyImage16 [USER.390]  Creates new image and copies attributes to it
486  *
487  */
488 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
489                              INT16 desiredy, UINT16 flags )
490 {
491     return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
492                                 (INT)desiredy, (UINT)flags);
493 }
494
495 /******************************************************************************
496  * CopyImage32 [USER32.61]  Creates new image and copies attributes to it
497  *
498  * PARAMS
499  *    hnd      [I] Handle to image to copy
500  *    type     [I] Type of image to copy
501  *    desiredx [I] Desired width of new image
502  *    desiredy [I] Desired height of new image
503  *    flags    [I] Copy flags
504  *
505  * RETURNS
506  *    Success: Handle to newly created image
507  *    Failure: NULL
508  *
509  * FIXME: implementation still lacks nearly all features, see LR_*
510  * defines in windows.h
511  */
512 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
513                              INT desiredy, UINT flags )
514 {
515     switch (type)
516     {
517         case IMAGE_BITMAP:
518                 return BITMAP_CopyBitmap(hnd);
519         case IMAGE_ICON:
520                 return CopyIcon(hnd);
521         case IMAGE_CURSOR:
522                 return CopyCursor(hnd);
523     }
524     return 0;
525 }
526
527 /**********************************************************************
528  *       BITMAP_Load
529  */
530 HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
531 {
532     HBITMAP hbitmap = 0;
533     HDC hdc;
534     HRSRC hRsrc;
535     HGLOBAL handle;
536     char *ptr = NULL;
537     BITMAPINFO *info, *fix_info=NULL;
538     HGLOBAL hFix;
539     int size;
540
541     if (!(loadflags & LR_LOADFROMFILE)) {
542       if (!instance)  /* OEM bitmap */
543       {
544           HDC hdc;
545           DC *dc;
546
547           if (HIWORD((int)name)) return 0;
548           hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
549           dc = DC_GetDCPtr( hdc );
550           if(dc->funcs->pLoadOEMResource)
551               hbitmap = dc->funcs->pLoadOEMResource( LOWORD((int)name), 
552                                                      OEM_BITMAP );
553           GDI_HEAP_UNLOCK( hdc );
554           DeleteDC( hdc );
555           return hbitmap;
556       }
557
558       if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
559       if (!(handle = LoadResource( instance, hRsrc ))) return 0;
560
561       if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
562     }
563     else
564     {
565         if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
566         info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
567     }
568     size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
569     if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
570     if (fix_info) {
571       BYTE pix;
572
573       memcpy(fix_info, info, size);
574       pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
575       DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
576       if ((hdc = GetDC(0)) != 0) {
577         char *bits = (char *)info + size;
578         if (loadflags & LR_CREATEDIBSECTION) {
579           DIBSECTION dib;
580           hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
581           GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
582           SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info, 
583                     DIB_RGB_COLORS);
584         }
585         else {
586           hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
587                                       bits, fix_info, DIB_RGB_COLORS );
588         }
589         ReleaseDC( 0, hdc );
590       }
591       GlobalUnlock(hFix);
592       GlobalFree(hFix);
593     }
594     if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
595     return hbitmap;
596 }
597
598
599 /******************************************************************************
600  * LoadBitmapW [USER32.358]  Loads bitmap from the executable file
601  *
602  * RETURNS
603  *    Success: Handle to specified bitmap
604  *    Failure: NULL
605  */
606 HBITMAP WINAPI LoadBitmapW(
607     HINSTANCE instance, /* [in] Handle to application instance */
608     LPCWSTR name)         /* [in] Address of bitmap resource name */
609 {
610     return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
611 }
612
613 /**********************************************************************
614  *          LoadBitmapA   (USER32.357)
615  */
616 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
617 {
618     return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
619 }
620
621 /**********************************************************************
622  *          LoadBitmap16    (USER.175)
623  */
624 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
625 {
626     LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
627     return LoadBitmapA( instance, nameStr );
628 }
629
630
631
632 /***********************************************************************
633  *           BITMAP_DeleteObject
634  */
635 BOOL BITMAP_DeleteObject( HBITMAP16 hbitmap, BITMAPOBJ * bmp )
636 {
637     if( bmp->DDBitmap ) {
638         if( bmp->DDBitmap->funcs->pDeleteObject )
639             bmp->DDBitmap->funcs->pDeleteObject( hbitmap );
640     }
641
642     if( bmp->bitmap.bmBits )
643         HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits );
644
645     DIB_DeleteDIBSection( bmp );
646
647     return GDI_FreeObject( hbitmap );
648 }
649
650         
651 /***********************************************************************
652  *           BITMAP_GetObject16
653  */
654 INT16 BITMAP_GetObject16( BITMAPOBJ * bmp, INT16 count, LPVOID buffer )
655 {
656     if (bmp->dib)
657     {
658         if ( count <= sizeof(BITMAP16) )
659         {
660             BITMAP *bmp32 = &bmp->dib->dsBm;
661             BITMAP16 bmp16;
662             bmp16.bmType       = bmp32->bmType;
663             bmp16.bmWidth      = bmp32->bmWidth;
664             bmp16.bmHeight     = bmp32->bmHeight;
665             bmp16.bmWidthBytes = bmp32->bmWidthBytes;
666             bmp16.bmPlanes     = bmp32->bmPlanes;
667             bmp16.bmBitsPixel  = bmp32->bmBitsPixel;
668             bmp16.bmBits       = (SEGPTR)0;
669             memcpy( buffer, &bmp16, count );
670             return count;
671         }
672         else
673         {
674             FIXME(bitmap, "not implemented for DIBs: count %d\n", count);
675             return 0;
676         }
677     }
678     else
679     {
680         BITMAP16 bmp16;
681         bmp16.bmType       = bmp->bitmap.bmType;
682         bmp16.bmWidth      = bmp->bitmap.bmWidth;
683         bmp16.bmHeight     = bmp->bitmap.bmHeight;
684         bmp16.bmWidthBytes = bmp->bitmap.bmWidthBytes;
685         bmp16.bmPlanes     = bmp->bitmap.bmPlanes;
686         bmp16.bmBitsPixel  = bmp->bitmap.bmBitsPixel;
687         bmp16.bmBits       = (SEGPTR)0;
688         if (count > sizeof(bmp16)) count = sizeof(bmp16);
689         memcpy( buffer, &bmp16, count );
690         return count;
691     }
692 }
693     
694
695 /***********************************************************************
696  *           BITMAP_GetObject32
697  */
698 INT BITMAP_GetObject( BITMAPOBJ * bmp, INT count, LPVOID buffer )
699 {
700     if (bmp->dib)
701     {
702         if (count < sizeof(DIBSECTION))
703         {
704             if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
705         }
706         else
707         {
708             if (count > sizeof(DIBSECTION)) count = sizeof(DIBSECTION);
709         }
710
711         memcpy( buffer, bmp->dib, count );
712         return count;
713     }
714     else
715     {
716         if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
717         memcpy( buffer, &bmp->bitmap, count );
718         return count;
719     }
720 }
721     
722
723 /***********************************************************************
724  *           CreateDiscardableBitmap16    (GDI.156)
725  */
726 HBITMAP16 WINAPI CreateDiscardableBitmap16( HDC16 hdc, INT16 width,
727                                             INT16 height )
728 {
729     return CreateCompatibleBitmap16( hdc, width, height );
730 }
731
732
733 /******************************************************************************
734  * CreateDiscardableBitmap32 [GDI32.38]  Creates a discardable bitmap
735  *
736  * RETURNS
737  *    Success: Handle to bitmap
738  *    Failure: NULL
739  */
740 HBITMAP WINAPI CreateDiscardableBitmap(
741     HDC hdc,    /* [in] Handle to device context */
742     INT width,  /* [in] Bitmap width */
743     INT height) /* [in] Bitmap height */
744 {
745     return CreateCompatibleBitmap( hdc, width, height );
746 }
747
748
749 /***********************************************************************
750  *           GetBitmapDimensionEx16    (GDI.468)
751  *
752  * NOTES
753  *    Can this call GetBitmapDimensionEx32?
754  */
755 BOOL16 WINAPI GetBitmapDimensionEx16( HBITMAP16 hbitmap, LPSIZE16 size )
756 {
757     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
758     if (!bmp) return FALSE;
759     CONV_SIZE32TO16( &bmp->size, size );
760     GDI_HEAP_UNLOCK( hbitmap );
761     return TRUE;
762 }
763
764
765 /******************************************************************************
766  * GetBitmapDimensionEx32 [GDI32.144]  Retrieves dimensions of a bitmap
767  *
768  * RETURNS
769  *    Success: TRUE
770  *    Failure: FALSE
771  */
772 BOOL WINAPI GetBitmapDimensionEx(
773     HBITMAP hbitmap, /* [in]  Handle to bitmap */
774     LPSIZE size)     /* [out] Address of struct receiving dimensions */
775 {
776     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
777     if (!bmp) return FALSE;
778     *size = bmp->size;
779     GDI_HEAP_UNLOCK( hbitmap );
780     return TRUE;
781 }
782
783
784 /***********************************************************************
785  *           GetBitmapDimension    (GDI.162)
786  */
787 DWORD WINAPI GetBitmapDimension16( HBITMAP16 hbitmap )
788 {
789     SIZE16 size;
790     if (!GetBitmapDimensionEx16( hbitmap, &size )) return 0;
791     return MAKELONG( size.cx, size.cy );
792 }
793
794
795 /***********************************************************************
796  *           SetBitmapDimensionEx16    (GDI.478)
797  */
798 BOOL16 WINAPI SetBitmapDimensionEx16( HBITMAP16 hbitmap, INT16 x, INT16 y,
799                                       LPSIZE16 prevSize )
800 {
801     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
802     if (!bmp) return FALSE;
803     if (prevSize) CONV_SIZE32TO16( &bmp->size, prevSize );
804     bmp->size.cx = x;
805     bmp->size.cy = y;
806     GDI_HEAP_UNLOCK( hbitmap );
807     return TRUE;
808 }
809
810
811 /******************************************************************************
812  * SetBitmapDimensionEx32 [GDI32.304]  Assignes dimensions to a bitmap
813  *
814  * RETURNS
815  *    Success: TRUE
816  *    Failure: FALSE
817  */
818 BOOL WINAPI SetBitmapDimensionEx(
819     HBITMAP hbitmap, /* [in]  Handle to bitmap */
820     INT x,           /* [in]  Bitmap width */
821     INT y,           /* [in]  Bitmap height */
822     LPSIZE prevSize) /* [out] Address of structure for orig dims */
823 {
824     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
825     if (!bmp) return FALSE;
826     if (prevSize) *prevSize = bmp->size;
827     bmp->size.cx = x;
828     bmp->size.cy = y;
829     GDI_HEAP_UNLOCK( hbitmap );
830     return TRUE;
831 }
832
833
834 /***********************************************************************
835  *           SetBitmapDimension    (GDI.163)
836  */
837 DWORD WINAPI SetBitmapDimension16( HBITMAP16 hbitmap, INT16 x, INT16 y )
838 {
839     SIZE16 size;
840     if (!SetBitmapDimensionEx16( hbitmap, x, y, &size )) return 0;
841     return MAKELONG( size.cx, size.cy );
842 }
843