Release 0.5
[wine/multimedia.git] / objects / bitmap.c
blobffec3e9a7609d2a0723f3d344e4cdd8e7cdecdba
1 /*
2 * GDI bitmap objects
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include "gdi.h"
11 /* A GDI bitmap object contains a handle to a packed BITMAP,
12 * which is stored on the global heap.
13 * A packed BITMAP is a BITMAP structure followed by the bitmap bits.
16 /* Handle of the bitmap selected by default in a memory DC */
17 HBITMAP BITMAP_hbitmapMemDC;
19 /* List of supported depths */
20 static int depthCount;
21 static int * depthList;
23 /* List of GC used for bitmap to pixmap operations (one for each depth) */
24 static GC * bitmapGC;
27 /***********************************************************************
28 * BITMAP_Init
30 BOOL BITMAP_Init()
32 int i;
33 Pixmap tmpPixmap;
35 depthList = XListDepths( XT_display, DefaultScreen(XT_display),
36 &depthCount );
37 if (!depthList || !depthCount) return FALSE;
38 if (!(bitmapGC = (GC *) malloc( depthCount * sizeof(GC) ))) return FALSE;
40 /* Create the necessary GCs */
42 for (i = 0; i < depthCount; i++)
44 tmpPixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
45 1, 1, depthList[i] );
46 if (tmpPixmap)
48 bitmapGC[i] = XCreateGC( XT_display, tmpPixmap, 0, NULL );
49 XSetGraphicsExposures( XT_display, bitmapGC[i], False );
50 XFreePixmap( XT_display, tmpPixmap );
52 else bitmapGC[i] = 0;
55 BITMAP_hbitmapMemDC = CreateBitmap( 1, 1, 1, 1, NULL );
56 return (BITMAP_hbitmapMemDC != 0);
60 /***********************************************************************
61 * BITMAP_FindGCForDepth
63 * Return a GC appropriate for operations with the given depth.
65 GC BITMAP_FindGCForDepth( int depth )
67 int i;
68 for (i = 0; i < depthCount; i++)
69 if (depthList[i] == depth) return bitmapGC[i];
70 return 0;
74 /***********************************************************************
75 * BITMAP_BmpToImage
77 * Create an XImage pointing to the bitmap data.
79 XImage * BITMAP_BmpToImage( BITMAP * bmp, void * bmpData )
81 XImage * image;
83 image = XCreateImage( XT_display, DefaultVisualOfScreen(XT_screen),
84 bmp->bmBitsPixel, ZPixmap, 0, bmpData,
85 bmp->bmWidth, bmp->bmHeight, 16, bmp->bmWidthBytes );
86 if (!image) return 0;
87 image->byte_order = MSBFirst;
88 image->bitmap_bit_order = MSBFirst;
89 image->bitmap_unit = 16;
90 _XInitImageFuncPtrs(image);
91 return image;
95 /***********************************************************************
96 * BITMAP_CopyToPixmap
98 * Copy the content of the bitmap to the pixmap. Both must have the same depth.
100 BOOL BITMAP_CopyToPixmap( BITMAP * bmp, Pixmap pixmap,
101 int x, int y, int width, int height )
103 GC gc;
104 XImage * image;
106 gc = BITMAP_FindGCForDepth( bmp->bmBitsPixel );
107 if (!gc) return FALSE;
109 image = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
110 if (!image) return FALSE;
112 #ifdef DEBUG_GDI
113 printf( "BITMAP_CopyToPixmap: %dx%d %d colors -> %d,%d %dx%d\n",
114 bmp->bmWidth, bmp->bmHeight, 1 << bmp->bmBitsPixel, x, y, width, height );
115 #endif
116 XPutImage(XT_display, pixmap, gc, image, 0, 0, x, y, width, height);
117 image->data = NULL;
118 XDestroyImage( image );
119 return TRUE;
123 /***********************************************************************
124 * BITMAP_CopyFromPixmap
126 * Copy the content of the pixmap to the bitmap. Both must have
127 * the same dimensions and depth.
129 BOOL BITMAP_CopyFromPixmap( BITMAP * bmp, Pixmap pixmap )
131 XImage *image = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
132 if (!image) return FALSE;
134 #ifdef DEBUG_GDI
135 printf( "BITMAP_CopyFromPixmap: %dx%d %d colors\n",
136 bmp->bmWidth, bmp->bmHeight, 1 << bmp->bmBitsPixel );
137 #endif
138 XGetSubImage( XT_display, pixmap, 0, 0, bmp->bmWidth, bmp->bmHeight,
139 AllPlanes, ZPixmap, image, 0, 0 );
140 image->data = NULL;
141 XDestroyImage( image );
142 return TRUE;
146 /***********************************************************************
147 * CreateBitmap (GDI.48)
149 HBITMAP CreateBitmap( short width, short height,
150 BYTE planes, BYTE bpp, LPSTR bits )
152 BITMAP bitmap = { 0, width, height, 0, planes, bpp, bits };
153 #ifdef DEBUG_GDI
154 printf( "CreateBitmap: %dx%d, %d colors\n",
155 width, height, 1 << (planes*bpp) );
156 #endif
157 if (!width || !height) return 0;
158 if ((planes != 1) && (bpp != 1)) return 0;
159 bitmap.bmWidthBytes = (width * bpp + 15) / 16 * 2;
160 return CreateBitmapIndirect( &bitmap );
164 /***********************************************************************
165 * CreateCompatibleBitmap (GDI.51)
167 HBITMAP CreateCompatibleBitmap( HDC hdc, short width, short height )
169 HBITMAP hbitmap;
170 DC * dc;
171 #ifdef DEBUG_GDI
172 printf( "CreateCompatibleBitmap: %d %dx%d\n", hdc, width, height );
173 #endif
174 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
175 if (!dc) return 0;
176 hbitmap = CreateBitmap( width, height, dc->w.planes, dc->w.bitsPerPixel, NULL);
177 return hbitmap;
181 /***********************************************************************
182 * CreateBitmapIndirect (GDI.49)
184 HBITMAP CreateBitmapIndirect( BITMAP * bmp )
186 BITMAPOBJ * bmpObjPtr;
187 char * bmpPtr;
188 HBITMAP hbitmap;
189 int size = bmp->bmPlanes * bmp->bmHeight * bmp->bmWidthBytes;
191 /* Create the BITMAPOBJ */
193 hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
194 if (!hbitmap) return 0;
195 bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_ADDR( hbitmap );
197 /* Create the bitmap in global heap */
199 bmpObjPtr->hBitmap = GlobalAlloc( GMEM_MOVEABLE, sizeof(BITMAP) + size );
200 if (!bmpObjPtr->hBitmap)
202 GDI_FreeObject( hbitmap );
203 return 0;
205 bmpPtr = (char *) GlobalLock( bmpObjPtr->hBitmap );
206 memcpy( bmpPtr, bmp, sizeof(BITMAP) );
207 ((BITMAP *)bmpPtr)->bmBits = NULL;
208 if (bmp->bmBits) memcpy( bmpPtr + sizeof(BITMAP), bmp->bmBits, size );
209 GlobalUnlock( bmpObjPtr->hBitmap );
211 bmpObjPtr->bSelected = FALSE;
212 bmpObjPtr->hdc = 0;
213 bmpObjPtr->size.cx = 0;
214 bmpObjPtr->size.cy = 0;
215 return hbitmap;
219 /***********************************************************************
220 * BITMAP_GetSetBitmapBits
222 LONG BITMAP_GetSetBitmapBits( HBITMAP hbitmap, LONG count,
223 LPSTR buffer, int set )
225 BITMAPOBJ * bmpObjPtr;
226 BITMAP * bmp;
227 DC * dc = NULL;
228 int maxSize;
230 if (!count) return 0;
231 bmpObjPtr = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
232 if (!bmpObjPtr) return 0;
233 if (!(bmp = (BITMAP *) GlobalLock( bmpObjPtr->hBitmap ))) return 0;
235 if (bmpObjPtr->bSelected)
236 dc = (DC *) GDI_GetObjPtr( bmpObjPtr->hdc, DC_MAGIC );
238 maxSize = bmp->bmPlanes * bmp->bmHeight * bmp->bmWidthBytes;
239 if (count > maxSize) count = maxSize;
241 if (set)
243 memcpy( bmp+1, buffer, count );
244 if (dc) BITMAP_CopyToPixmap( bmp, dc->u.x.drawable,
245 0, 0, bmp->bmWidth, bmp->bmHeight );
247 else
249 if (dc) BITMAP_CopyFromPixmap( bmp, dc->u.x.drawable );
250 memcpy( buffer, bmp+1, count );
252 GlobalUnlock( bmpObjPtr->hBitmap );
253 return hbitmap;
257 /***********************************************************************
258 * GetBitmapBits (GDI.74)
260 LONG GetBitmapBits( HBITMAP hbitmap, LONG count, LPSTR buffer )
262 return BITMAP_GetSetBitmapBits( hbitmap, count, buffer, 0 );
266 /***********************************************************************
267 * SetBitmapBits (GDI.106)
269 LONG SetBitmapBits( HBITMAP hbitmap, LONG count, LPSTR buffer )
271 return BITMAP_GetSetBitmapBits( hbitmap, count, buffer, 1 );
275 /***********************************************************************
276 * BMP_DeleteObject
278 BOOL BMP_DeleteObject( HBITMAP hbitmap, BITMAPOBJ * bitmap )
280 /* Free bitmap on global heap */
281 GlobalFree( bitmap->hBitmap );
282 return GDI_FreeObject( hbitmap );
286 /***********************************************************************
287 * BMP_GetObject
289 int BMP_GetObject( BITMAPOBJ * bitmap, int count, LPSTR buffer )
291 char * bmpPtr = (char *) GlobalLock( bitmap->hBitmap );
292 if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
293 memcpy( buffer, bmpPtr, count );
294 GlobalUnlock( bitmap->hBitmap );
295 return count;
299 /***********************************************************************
300 * BITMAP_UnselectBitmap
302 * Unselect the bitmap from the DC. Used by SelectObject and DeleteDC.
304 BOOL BITMAP_UnselectBitmap( DC * dc )
306 BITMAPOBJ * bmp;
307 BITMAP * bmpPtr;
309 if (!dc->w.hBitmap) return TRUE;
310 bmp = (BITMAPOBJ *) GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
311 if (!bmp) return FALSE;
313 if (!(bmpPtr = (BITMAP *) GlobalLock( bmp->hBitmap ))) return FALSE;
315 BITMAP_CopyFromPixmap( bmpPtr, dc->u.x.drawable );
316 XFreePixmap( XT_display, dc->u.x.drawable );
317 bmp->bSelected = FALSE;
318 bmp->hdc = 0;
319 GlobalUnlock( bmp->hBitmap );
320 return TRUE;
324 /***********************************************************************
325 * BITMAP_SelectObject
327 HBITMAP BITMAP_SelectObject( HDC hdc, DC * dc, HBITMAP hbitmap,
328 BITMAPOBJ * bitmap )
330 BITMAP * bmp;
331 HBITMAP prevHandle = dc->w.hBitmap;
333 if (!(dc->w.flags & DC_MEMORY)) return 0;
334 if (bitmap->bSelected && hbitmap != BITMAP_hbitmapMemDC) return 0;
335 if (!(bmp = (BITMAP *) GlobalLock( bitmap->hBitmap ))) return 0;
337 /* Make sure the bitmap has the right format */
339 if ((bmp->bmPlanes != 1) || !BITMAP_FindGCForDepth( bmp->bmBitsPixel ))
341 GlobalUnlock( bitmap->hBitmap );
342 return 0;
345 /* Unselect the previous bitmap */
347 if (!BITMAP_UnselectBitmap( dc ))
349 GlobalUnlock( bitmap->hBitmap );
350 return 0;
353 /* Create the pixmap */
355 dc->u.x.drawable = XCreatePixmap( XT_display,
356 DefaultRootWindow( XT_display ),
357 bmp->bmWidth, bmp->bmHeight,
358 bmp->bmBitsPixel );
359 dc->w.DCSizeX = bmp->bmWidth;
360 dc->w.DCSizeY = bmp->bmHeight;
361 BITMAP_CopyToPixmap( bmp, dc->u.x.drawable,
362 0, 0, bmp->bmWidth, bmp->bmHeight );
364 /* Change GC depth if needed */
366 if (dc->w.bitsPerPixel != bmp->bmBitsPixel)
368 XFreeGC( XT_display, dc->u.x.gc );
369 dc->u.x.gc = XCreateGC( XT_display, dc->u.x.drawable, 0, NULL );
370 dc->w.bitsPerPixel = bmp->bmBitsPixel;
371 DC_SetDeviceInfo( hdc, dc );
374 GlobalUnlock( bitmap->hBitmap );
375 dc->w.hBitmap = hbitmap;
376 bitmap->bSelected = TRUE;
377 bitmap->hdc = hdc;
378 return prevHandle;
382 /***********************************************************************
383 * GetBitmapDimensionEx (GDI.468)
385 BOOL GetBitmapDimensionEx( HBITMAP hbitmap, LPSIZE size )
387 BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
388 if (!bmp) return FALSE;
389 *size = bmp->size;
390 return TRUE;
394 /***********************************************************************
395 * GetBitmapDimension (GDI.162)
397 DWORD GetBitmapDimension( HBITMAP hbitmap )
399 SIZE size;
400 if (!GetBitmapDimensionEx( hbitmap, &size )) return 0;
401 return size.cx | (size.cy << 16);
404 /***********************************************************************
405 * SetBitmapDimensionEx (GDI.478)
407 BOOL SetBitmapDimensionEx( HBITMAP hbitmap, short x, short y, LPSIZE prevSize )
409 BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
410 if (!bmp) return FALSE;
411 if (prevSize) *prevSize = bmp->size;
412 bmp->size.cx = x;
413 bmp->size.cy = y;
414 return TRUE;
418 /***********************************************************************
419 * SetBitmapDimension (GDI.163)
421 DWORD SetBitmapDimension( HBITMAP hbitmap, short x, short y )
423 SIZE size;
424 if (!SetBitmapDimensionEx( hbitmap, x, y, &size )) return 0;
425 return size.cx | (size.cy << 16);