Release 970804
[wine] / objects / bitmap.c
1 /*
2  * GDI bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <X11/Xlib.h>
11 #include <X11/Xutil.h>
12 #include "gdi.h"
13 #include "callback.h"
14 #include "dc.h"
15 #include "bitmap.h"
16 #include "heap.h"
17 #include "stddebug.h"
18 #include "debug.h"
19
20 #ifdef PRELIMINARY_WING16_SUPPORT
21 #include <sys/types.h>
22 #include <sys/ipc.h>
23 #include <sys/shm.h>
24 #endif
25
26   /* GCs used for B&W and color bitmap operations */
27 GC BITMAP_monoGC = 0, BITMAP_colorGC = 0;
28
29 extern void CLIPPING_UpdateGCRegion( DC * dc );  /* objects/clipping.c */
30
31
32 /***********************************************************************
33  *           CreateBitmap16    (GDI.48)
34  */
35 HBITMAP16 CreateBitmap16( INT16 width, INT16 height, UINT16 planes,
36                           UINT16 bpp, LPCVOID bits )
37 {
38     return CreateBitmap32( width, height, planes, bpp, bits );
39 }
40
41
42 /***********************************************************************
43  *           CreateBitmap32    (GDI32.25)
44  */
45 HBITMAP32 CreateBitmap32( INT32 width, INT32 height, UINT32 planes,
46                           UINT32 bpp, LPCVOID bits )
47 {
48     BITMAPOBJ * bmpObjPtr;
49     HBITMAP32 hbitmap;
50
51     planes = (BYTE)planes;
52     bpp    = (BYTE)bpp;
53
54     dprintf_gdi( stddeb, "CreateBitmap: %dx%d, %d colors\n", 
55                  width, height, 1 << (planes*bpp) );
56
57       /* Check parameters */
58     if (!height || !width || planes != 1) return 0;
59     if ((bpp != 1) && (bpp != screenDepth)) return 0;
60     if (height < 0) height = -height;
61     if (width < 0) width = -width;
62
63       /* Create the BITMAPOBJ */
64     hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
65     if (!hbitmap) return 0;
66     bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_LIN_ADDR( hbitmap );
67
68     bmpObjPtr->size.cx = 0;
69     bmpObjPtr->size.cy = 0;
70     bmpObjPtr->bitmap.bmType = 0;
71     bmpObjPtr->bitmap.bmWidth = (INT16)width;
72     bmpObjPtr->bitmap.bmHeight = (INT16)height;
73     bmpObjPtr->bitmap.bmPlanes = (BYTE)planes;
74     bmpObjPtr->bitmap.bmBitsPixel = (BYTE)bpp;
75     bmpObjPtr->bitmap.bmWidthBytes = (INT16)BITMAP_WIDTH_BYTES( width, bpp );
76     bmpObjPtr->bitmap.bmBits = NULL;
77
78       /* Create the pixmap */
79     bmpObjPtr->pixmap = XCreatePixmap(display, rootWindow, width, height, bpp);
80     if (!bmpObjPtr->pixmap)
81     {
82         GDI_HEAP_FREE( hbitmap );
83         hbitmap = 0;
84     }
85     else if (bits)  /* Set bitmap bits */
86         SetBitmapBits32( hbitmap, height * bmpObjPtr->bitmap.bmWidthBytes,
87                          bits );
88     return hbitmap;
89 }
90
91
92 /***********************************************************************
93  *           CreateCompatibleBitmap16    (GDI.51)
94  */
95 HBITMAP16 CreateCompatibleBitmap16( HDC16 hdc, INT16 width, INT16 height )
96 {
97     return CreateCompatibleBitmap32( hdc, width, height );
98 }
99
100
101 /***********************************************************************
102  *           CreateCompatibleBitmap32    (GDI32.30)
103  */
104 HBITMAP32 CreateCompatibleBitmap32( HDC32 hdc, INT32 width, INT32 height )
105 {
106     HBITMAP32 hbmpRet = 0;
107     DC *dc;
108
109     dprintf_gdi( stddeb, "CreateCompatibleBitmap(%04x,%d,%d) = \n", 
110                  hdc, width, height );
111     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
112     hbmpRet = CreateBitmap32( width, height, 1, dc->w.bitsPerPixel, NULL );
113     dprintf_gdi(stddeb,"\t\t%04x\n", hbmpRet);
114     return hbmpRet;
115 }
116
117
118 /***********************************************************************
119  *           CreateBitmapIndirect16    (GDI.49)
120  */
121 HBITMAP16 CreateBitmapIndirect16( const BITMAP16 * bmp )
122 {
123     return CreateBitmap16( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
124                            bmp->bmBitsPixel, PTR_SEG_TO_LIN( bmp->bmBits ) );
125 }
126
127
128 /***********************************************************************
129  *           CreateBitmapIndirect32    (GDI32.26)
130  */
131 HBITMAP32 CreateBitmapIndirect32( const BITMAP32 * bmp )
132 {
133     return CreateBitmap32( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
134                            bmp->bmBitsPixel, bmp->bmBits );
135 }
136
137
138 /***********************************************************************
139  *           GetBitmapBits16    (GDI.74)
140  */
141 LONG GetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPVOID buffer )
142 {
143     return GetBitmapBits32( hbitmap, count, buffer );
144 }
145
146
147 /***********************************************************************
148  *           GetBitmapBits32    (GDI32.143)
149  */
150 LONG GetBitmapBits32( HBITMAP32 hbitmap, LONG count, LPVOID buffer )
151 {
152     BITMAPOBJ * bmp;
153     LONG height,widthbytes;
154     XImage * image;
155     LPBYTE tmpbuffer,tbuf;
156     int h,w,pad;
157     
158     /* KLUDGE! */
159     if (count < 0) {
160         fprintf(stderr, "Negative number of bytes (%ld) passed to GetBitmapBits???\n", count );
161         count = -count;
162     }
163     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
164     if (!bmp) return 0;
165
166       /* Only get entire lines */
167     height = count / bmp->bitmap.bmWidthBytes;
168     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
169     dprintf_bitmap(stddeb, "GetBitmapBits: %dx%d %d colors %p fetched height: %ld\n",
170             bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
171             1 << bmp->bitmap.bmBitsPixel, buffer, height );
172     if (!height) return 0;
173
174     switch (bmp->bitmap.bmBitsPixel) {
175     case 1:
176         if (!(bmp->bitmap.bmWidth & 15))
177                 pad = 0;
178         else
179                 pad = ((16 - (bmp->bitmap.bmWidth & 15)) + 7) / 8;
180         break;
181     case 4:
182         if (!(bmp->bitmap.bmWidth & 3))
183             pad = 0;
184         else
185             pad = ((4 - (bmp->bitmap.bmWidth & 3)) + 1) / 2;
186         break;
187     case 8:
188         pad = (2 - (bmp->bitmap.bmWidth & 1)) & 1;
189         break;
190     case 15:
191     case 16:
192         pad = 0; /* we have 16bit alignment already */
193         break;
194     case 24:
195         pad = (bmp->bitmap.bmWidth*3) & 1;
196         break;
197     default:
198         fprintf(stderr,"GetBitMapBits32: unknown depth %d, please report.\n",
199                 bmp->bitmap.bmBitsPixel
200         );
201         return 0;
202     }
203
204     widthbytes  = DIB_GetXImageWidthBytes(bmp->bitmap.bmWidth,bmp->bitmap.bmBitsPixel);
205     tmpbuffer   = (LPBYTE)xmalloc(widthbytes*height);
206     image = XCreateImage( display, DefaultVisualOfScreen(screen),
207                   bmp->bitmap.bmBitsPixel, ZPixmap, 0, tmpbuffer,
208                   bmp->bitmap.bmWidth,height,32,widthbytes
209     );
210     
211     CallTo32_LargeStack( (int(*)())XGetSubImage, 11,
212                          display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
213                          height, AllPlanes, ZPixmap, image, 0, 0 );
214
215     /* copy XImage to 16 bit padded image buffer with real bitsperpixel */
216
217     tbuf = buffer;
218     switch (bmp->bitmap.bmBitsPixel)
219     {
220     case 1:
221         for (h=0;h<height;h++)
222         {
223             *tbuf = 0;
224             for (w=0;w<bmp->bitmap.bmWidth;w++)
225             {
226                 if ((w%8) == 0)
227                     *tbuf = 0;
228                 *tbuf |= XGetPixel(image,w,h)<<(7-(w&7));
229                 if ((w&7) == 7) ++tbuf;
230             }
231             tbuf += pad;
232         }
233         break;
234     case 4:
235         for (h=0;h<height;h++)
236         {
237             for (w=0;w<bmp->bitmap.bmWidth;w++)
238             {
239                 if (!(w & 1)) *tbuf = XGetPixel( image, w, h) << 4;
240                 else *tbuf++ |= XGetPixel( image, w, h) & 0x0f;
241             }
242             tbuf += pad;
243         }
244         break;
245     case 8:
246         for (h=0;h<height;h++)
247         {
248             for (w=0;w<bmp->bitmap.bmWidth;w++)
249                 *tbuf++ = XGetPixel(image,w,h);
250             tbuf += pad;
251         }
252         break;
253     case 15:
254     case 16:
255         for (h=0;h<height;h++)
256         {
257             for (w=0;w<bmp->bitmap.bmWidth;w++)
258             {
259                 long pixel = XGetPixel(image,w,h);
260
261                 *tbuf++ = pixel & 0xff;
262                 *tbuf++ = (pixel>>8) & 0xff;
263             }
264         }
265         break;
266     case 24:
267         for (h=0;h<height;h++)
268         {
269             for (w=0;w<bmp->bitmap.bmWidth;w++)
270             {
271                 long pixel = XGetPixel(image,w,h);
272
273                 *tbuf++ = pixel & 0xff;
274                 *tbuf++ = (pixel>> 8) & 0xff;
275                 *tbuf++ = (pixel>>16) & 0xff;
276             }
277             tbuf += pad;
278         }
279     }
280     XDestroyImage( image ); /* frees tbuffer too */
281     return height * bmp->bitmap.bmWidthBytes;
282 }
283
284
285 /***********************************************************************
286  *           SetBitmapBits16    (GDI.106)
287  */
288 LONG SetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPCVOID buffer )
289 {
290     return SetBitmapBits32( hbitmap, count, buffer );
291 }
292
293
294 /***********************************************************************
295  *           SetBitmapBits32    (GDI32.303)
296  */
297 LONG SetBitmapBits32( HBITMAP32 hbitmap, LONG count, LPCVOID buffer )
298 {
299     BITMAPOBJ * bmp;
300     LONG height;
301     XImage * image;
302     LPBYTE sbuf,tmpbuffer;
303     int w,h,pad,widthbytes;
304     
305     /* KLUDGE! */
306     if (count < 0) {
307         fprintf(stderr, "Negative number of bytes (%ld) passed to SetBitmapBits???\n", count );
308         count = -count;
309     }
310     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
311     if (!bmp) return 0;
312
313     dprintf_bitmap(stddeb, "SetBitmapBits: %dx%d %d colors %p\n",
314             bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
315             1 << bmp->bitmap.bmBitsPixel, buffer );
316
317       /* Only set entire lines */
318     height = count / bmp->bitmap.bmWidthBytes;
319     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
320     if (!height) return 0;
321         
322     switch (bmp->bitmap.bmBitsPixel) {
323     case 1:
324         if (!(bmp->bitmap.bmWidth & 15))
325                 pad = 0;
326         else
327                 pad = ((16 - (bmp->bitmap.bmWidth & 15)) + 7) / 8;
328         break;
329     case 4:
330         if (!(bmp->bitmap.bmWidth & 3))
331             pad = 0;
332         else
333             pad = ((4 - (bmp->bitmap.bmWidth & 3)) + 1) / 2;
334         break;
335     case 8:
336         pad = (2 - (bmp->bitmap.bmWidth & 1)) & 1;
337         break;
338     case 15:
339     case 16:
340         pad = 0; /* we have 16bit alignment already */
341         break;
342     case 24:
343         pad = (bmp->bitmap.bmWidth*3) & 1;
344         break;
345     default:
346         fprintf(stderr,"SetBitMapBits32: unknown depth %d, please report.\n",
347                 bmp->bitmap.bmBitsPixel
348         );
349         return 0;
350     }
351     sbuf = (LPBYTE)buffer;
352
353     widthbytes  = DIB_GetXImageWidthBytes(bmp->bitmap.bmWidth,bmp->bitmap.bmBitsPixel);
354     tmpbuffer   = (LPBYTE)xmalloc(widthbytes*height);
355     image = XCreateImage( display, DefaultVisualOfScreen(screen),
356                   bmp->bitmap.bmBitsPixel, ZPixmap, 0, tmpbuffer,
357                   bmp->bitmap.bmWidth,height,32,widthbytes
358     );
359     
360     /* copy 16 bit padded image buffer with real bitsperpixel to XImage */
361     sbuf = (LPBYTE)buffer;
362     switch (bmp->bitmap.bmBitsPixel)
363     {
364     case 1:
365         for (h=0;h<height;h++)
366         {
367             for (w=0;w<bmp->bitmap.bmWidth;w++)
368             {
369                 XPutPixel(image,w,h,(sbuf[0]>>(7-(w&7))) & 1);
370                 if ((w&7) == 7)
371                     sbuf++;
372             }
373             sbuf += pad;
374         }
375         break;
376     case 4:
377         for (h=0;h<height;h++)
378         {
379             for (w=0;w<bmp->bitmap.bmWidth;w++)
380             {
381                 if (!(w & 1)) XPutPixel( image, w, h, *sbuf >> 4 );
382                 else XPutPixel( image, w, h, *sbuf++ & 0xf );
383             }
384             sbuf += pad;
385         }
386         break;
387     case 8:
388         for (h=0;h<height;h++)
389         {
390             for (w=0;w<bmp->bitmap.bmWidth;w++)
391                 XPutPixel(image,w,h,*sbuf++);
392             sbuf += pad;
393         }
394         break;
395     case 15:
396     case 16:
397         for (h=0;h<height;h++)
398         {
399             for (w=0;w<bmp->bitmap.bmWidth;w++)
400             {
401                 XPutPixel(image,w,h,sbuf[1]*256+sbuf[0]);
402                 sbuf+=2;
403             }
404         }
405         break;
406     case 24: 
407         for (h=0;h<height;h++)
408         {
409             for (w=0;w<bmp->bitmap.bmWidth;w++)
410             {
411                 XPutPixel(image,w,h,(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
412                 sbuf += 3;
413             }
414             sbuf += pad;
415         }
416         break;
417     }
418
419     CallTo32_LargeStack( XPutImage, 10,
420                          display, bmp->pixmap, BITMAP_GC(bmp), image, 0, 0,
421                          0, 0, bmp->bitmap.bmWidth, height );
422     XDestroyImage( image ); /* frees tmpbuffer too */
423     return height * bmp->bitmap.bmWidthBytes;
424 }
425
426 /**********************************************************************
427  *          LoadImageA    (USER32.364)
428  * FIXME: implementation still lacks nearly all features, see LR_*
429  * defines in windows.h
430  */
431
432 HANDLE32 LoadImage32A(
433         HINSTANCE32 hinst,LPCSTR name,UINT32 type,INT32 desiredx,
434         INT32 desiredy,UINT32 loadflags
435 ) {
436         if (HIWORD(name)) {
437                 dprintf_resource(stddeb,"LoadImage32A(0x%04x,%s,%d,%d,%d,0x%08x)\n",
438                         hinst,name,type,desiredx,desiredy,loadflags
439                 );
440         } else {
441                 dprintf_resource(stddeb,"LoadImage32A(0x%04x,%p,%d,%d,%d,0x%08x)\n",
442                         hinst,name,type,desiredx,desiredy,loadflags
443                 );
444         }
445         switch (type) {
446         case IMAGE_BITMAP:
447                 return LoadBitmap32A(hinst,name);
448         case IMAGE_ICON:
449                 return LoadIcon32A(hinst,name);
450         case IMAGE_CURSOR:
451                 return LoadCursor32A(hinst,name);
452         }
453         return 0;
454 }
455
456 /**********************************************************************
457  *          CopyImage32    (USER32.60)
458  *
459  * FIXME: implementation still lacks nearly all features, see LR_*
460  * defines in windows.h
461  */
462 HANDLE32 CopyImage32( HANDLE32 hnd, UINT32 type, INT32 desiredx,
463                       INT32 desiredy, UINT32 flags )
464 {
465     switch (type)
466     {
467         case IMAGE_BITMAP:
468                 return hnd;     /* FIXME ... need to copy here */
469         case IMAGE_ICON:
470                 return CopyIcon32(hnd);
471         case IMAGE_CURSOR:
472                 return CopyCursor32(hnd);
473     }
474     return 0;
475 }
476
477
478 /**********************************************************************
479  *          LoadBitmap16    (USER.175)
480  */
481 HBITMAP16 LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
482 {
483     HBITMAP32 hbitmap = 0;
484     HDC32 hdc;
485     HRSRC16 hRsrc;
486     HGLOBAL16 handle;
487     BITMAPINFO *info;
488
489     if (HIWORD(name))
490     {
491         char *str = (char *)PTR_SEG_TO_LIN( name );
492         dprintf_bitmap( stddeb, "LoadBitmap16(%04x,'%s')\n", instance, str );
493         if (str[0] == '#') name = (SEGPTR)(DWORD)(WORD)atoi( str + 1 );
494     }
495     else
496         dprintf_bitmap( stddeb, "LoadBitmap16(%04x,%04x)\n",
497                         instance, LOWORD(name) );
498
499     if (!instance)  /* OEM bitmap */
500     {
501         if (HIWORD((int)name)) return 0;
502         return OBM_LoadBitmap( LOWORD((int)name) );
503     }
504
505     if (!(hRsrc = FindResource16( instance, name, RT_BITMAP ))) return 0;
506     if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
507
508     info = (BITMAPINFO *)LockResource16( handle );
509     if ((hdc = GetDC32(0)) != 0)
510     {
511         char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
512         hbitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
513                                     bits, info, DIB_RGB_COLORS );
514         ReleaseDC32( 0, hdc );
515     }
516     FreeResource16( handle );
517     return hbitmap;
518 }
519
520 /**********************************************************************
521  *          LoadBitmap32W   (USER32.357)
522  */
523 HBITMAP32 LoadBitmap32W( HINSTANCE32 instance, LPCWSTR name )
524 {
525     HBITMAP32 hbitmap = 0;
526     HDC32 hdc;
527     HRSRC32 hRsrc;
528     HGLOBAL32 handle;
529     BITMAPINFO *info;
530
531     if (!instance)  /* OEM bitmap */
532     {
533         if (HIWORD((int)name)) return 0;
534         return OBM_LoadBitmap( LOWORD((int)name) );
535     }
536
537     if (!(hRsrc = FindResource32W( instance, name,
538                 (LPWSTR)RT_BITMAP ))) return 0;
539     if (!(handle = LoadResource32( instance, hRsrc ))) return 0;
540
541     info = (BITMAPINFO *)LockResource32( handle );
542     if ((hdc = GetDC32(0)) != 0)
543     {
544         char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
545         hbitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
546                                     bits, info, DIB_RGB_COLORS );
547         ReleaseDC32( 0, hdc );
548     }
549     return hbitmap;
550 }
551
552
553 /**********************************************************************
554  *          LoadBitmap32A   (USER32.356)
555  */
556 HBITMAP32 LoadBitmap32A( HINSTANCE32 instance, LPCSTR name )
557 {
558     HBITMAP32 res;
559     if (!HIWORD(name)) res = LoadBitmap32W( instance, (LPWSTR)name );
560     else
561     {
562         LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
563         res = LoadBitmap32W( instance, uni );
564         HeapFree( GetProcessHeap(), 0, uni );
565     }
566     return res;
567 }
568
569
570 /***********************************************************************
571  *           BITMAP_DeleteObject
572  */
573 BOOL32 BITMAP_DeleteObject( HBITMAP16 hbitmap, BITMAPOBJ * bmp )
574 {
575 #ifdef PRELIMINARY_WING16_SUPPORT
576     if( bmp->bitmap.bmBits )
577         XShmDetach( display, (XShmSegmentInfo*)bmp->bitmap.bmBits );
578 #endif
579
580     XFreePixmap( display, bmp->pixmap );
581 #ifdef PRELIMINARY_WING16_SUPPORT
582     if( bmp->bitmap.bmBits )
583     {
584     __ShmBitmapCtl* p = (__ShmBitmapCtl*)bmp->bitmap.bmBits;
585       WORD          sel = HIWORD(p->bits);
586       unsigned long l, limit = GetSelectorLimit(sel);
587
588       for( l = 0; l < limit; l += 0x10000, sel += __AHINCR )
589            FreeSelector(sel);
590       shmctl(p->si.shmid, IPC_RMID, NULL); 
591       shmdt(p->si.shmaddr);  /* already marked for destruction */
592     }
593 #endif
594     return GDI_FreeObject( hbitmap );
595 }
596
597         
598 /***********************************************************************
599  *           BITMAP_GetObject16
600  */
601 INT16 BITMAP_GetObject16( BITMAPOBJ * bmp, INT16 count, LPVOID buffer )
602 {
603     if (count > sizeof(bmp->bitmap)) count = sizeof(bmp->bitmap);
604     memcpy( buffer, &bmp->bitmap, count );
605     return count;
606 }
607     
608
609 /***********************************************************************
610  *           BITMAP_GetObject32
611  */
612 INT32 BITMAP_GetObject32( BITMAPOBJ * bmp, INT32 count, LPVOID buffer )
613 {
614     BITMAP32 bmp32;
615     bmp32.bmType       = bmp->bitmap.bmType;
616     bmp32.bmWidth      = bmp->bitmap.bmWidth;
617     bmp32.bmHeight     = bmp->bitmap.bmHeight;
618     bmp32.bmWidthBytes = bmp->bitmap.bmWidthBytes;
619     bmp32.bmPlanes     = bmp->bitmap.bmPlanes;
620     bmp32.bmBitsPixel  = bmp->bitmap.bmBitsPixel;
621     bmp32.bmBits       = NULL;
622     if (count > sizeof(bmp32)) count = sizeof(bmp32);
623     memcpy( buffer, &bmp32, count );
624     return count;
625 }
626     
627
628
629 /***********************************************************************
630  *           CreateDiscardableBitmap16    (GDI.156)
631  */
632 HBITMAP16 CreateDiscardableBitmap16( HDC16 hdc, INT16 width, INT16 height )
633 {
634     return CreateCompatibleBitmap16( hdc, width, height );
635 }
636
637
638 /***********************************************************************
639  *           CreateDiscardableBitmap32    (GDI32.38)
640  */
641 HBITMAP32 CreateDiscardableBitmap32( HDC32 hdc, INT32 width, INT32 height )
642 {
643     return CreateCompatibleBitmap32( hdc, width, height );
644 }
645
646
647 /***********************************************************************
648  *           GetBitmapDimensionEx16    (GDI.468)
649  */
650 BOOL16 GetBitmapDimensionEx16( HBITMAP16 hbitmap, LPSIZE16 size )
651 {
652     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
653     if (!bmp) return FALSE;
654     *size = bmp->size;
655     return TRUE;
656 }
657
658
659 /***********************************************************************
660  *           GetBitmapDimensionEx32    (GDI32.144)
661  */
662 BOOL32 GetBitmapDimensionEx32( HBITMAP32 hbitmap, LPSIZE32 size )
663 {
664     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
665     if (!bmp) return FALSE;
666     size->cx = (INT32)bmp->size.cx;
667     size->cy = (INT32)bmp->size.cy;
668     return TRUE;
669 }
670
671
672 /***********************************************************************
673  *           GetBitmapDimension    (GDI.162)
674  */
675 DWORD GetBitmapDimension( HBITMAP16 hbitmap )
676 {
677     SIZE16 size;
678     if (!GetBitmapDimensionEx16( hbitmap, &size )) return 0;
679     return MAKELONG( size.cx, size.cy );
680 }
681
682
683 /***********************************************************************
684  *           SetBitmapDimensionEx16    (GDI.478)
685  */
686 BOOL16 SetBitmapDimensionEx16( HBITMAP16 hbitmap, INT16 x, INT16 y,
687                                LPSIZE16 prevSize )
688 {
689     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
690     if (!bmp) return FALSE;
691     if (prevSize) *prevSize = bmp->size;
692     bmp->size.cx = x;
693     bmp->size.cy = y;
694     return TRUE;
695 }
696
697
698 /***********************************************************************
699  *           SetBitmapDimensionEx32    (GDI32.304)
700  */
701 BOOL32 SetBitmapDimensionEx32( HBITMAP32 hbitmap, INT32 x, INT32 y,
702                                LPSIZE32 prevSize )
703 {
704     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
705     if (!bmp) return FALSE;
706     if (prevSize) CONV_SIZE16TO32( &bmp->size, prevSize );
707     bmp->size.cx = (INT16)x;
708     bmp->size.cy = (INT16)y;
709     return TRUE;
710 }
711
712
713 /***********************************************************************
714  *           SetBitmapDimension    (GDI.163)
715  */
716 DWORD SetBitmapDimension( HBITMAP16 hbitmap, INT16 x, INT16 y )
717 {
718     SIZE16 size;
719     if (!SetBitmapDimensionEx16( hbitmap, x, y, &size )) return 0;
720     return MAKELONG( size.cx, size.cy );
721 }