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