]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkpixmap-win32.c
gdk/gdk.def Update.
[~andy/gtk] / gdk / win32 / gdkpixmap-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-1999 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "gdkpixmap.h"
35 #include "gdkinternals.h"
36 #include "gdkprivate-win32.h"
37
38 static void gdk_pixmap_impl_win32_get_size   (GdkDrawable        *drawable,
39                                               gint               *width,
40                                               gint               *height);
41
42 static void gdk_pixmap_impl_win32_init       (GdkPixmapImplWin32      *pixmap);
43 static void gdk_pixmap_impl_win32_class_init (GdkPixmapImplWin32Class *klass);
44 static void gdk_pixmap_impl_win32_finalize   (GObject                 *object);
45
46 static gpointer parent_class = NULL;
47
48 GType
49 gdk_pixmap_impl_win32_get_type (void)
50 {
51   static GType object_type = 0;
52
53   if (!object_type)
54     {
55       static const GTypeInfo object_info =
56       {
57         sizeof (GdkPixmapImplWin32Class),
58         (GBaseInitFunc) NULL,
59         (GBaseFinalizeFunc) NULL,
60         (GClassInitFunc) gdk_pixmap_impl_win32_class_init,
61         NULL,           /* class_finalize */
62         NULL,           /* class_data */
63         sizeof (GdkPixmapImplWin32),
64         0,              /* n_preallocs */
65         (GInstanceInitFunc) gdk_pixmap_impl_win32_init,
66       };
67       
68       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_WIN32,
69                                             "GdkPixmapImplWin32",
70                                             &object_info, 0);
71     }
72   
73   return object_type;
74 }
75
76 GType
77 _gdk_pixmap_impl_get_type (void)
78 {
79   return gdk_pixmap_impl_win32_get_type ();
80 }
81
82 static void
83 gdk_pixmap_impl_win32_init (GdkPixmapImplWin32 *impl)
84 {
85   impl->width = 1;
86   impl->height = 1;
87 }
88
89 static void
90 gdk_pixmap_impl_win32_class_init (GdkPixmapImplWin32Class *klass)
91 {
92   GObjectClass *object_class = G_OBJECT_CLASS (klass);
93   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
94   
95   parent_class = g_type_class_peek_parent (klass);
96
97   object_class->finalize = gdk_pixmap_impl_win32_finalize;
98
99   drawable_class->get_size = gdk_pixmap_impl_win32_get_size;
100 }
101
102 static void
103 gdk_pixmap_impl_win32_finalize (GObject *object)
104 {
105   GdkPixmapImplWin32 *impl = GDK_PIXMAP_IMPL_WIN32 (object);
106   GdkPixmap *wrapper = GDK_PIXMAP (GDK_DRAWABLE_IMPL_WIN32 (impl)->wrapper);
107
108   GDK_NOTE (MISC, g_print ("gdk_pixmap_impl_win32_finalize: %#x\n",
109                            (guint) GDK_PIXMAP_HBITMAP (wrapper)));
110
111   if (!DeleteObject (GDK_PIXMAP_HBITMAP (wrapper)))
112     WIN32_GDI_FAILED ("DeleteObject");
113
114   gdk_win32_handle_table_remove (GDK_PIXMAP_HBITMAP (wrapper));
115
116   G_OBJECT_CLASS (parent_class)->finalize (object);
117 }
118
119 static void
120 gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable,
121                                 gint        *width,
122                                 gint        *height)
123 {
124   if (width)
125     *width = GDK_PIXMAP_IMPL_WIN32 (drawable)->width;
126   if (height)
127     *height = GDK_PIXMAP_IMPL_WIN32 (drawable)->height;
128 }
129
130 GdkPixmap*
131 gdk_pixmap_new (GdkWindow *window,
132                 gint       width,
133                 gint       height,
134                 gint       depth)
135 {
136   GdkPixmap *pixmap;
137   GdkDrawableImplWin32 *draw_impl;
138   GdkPixmapImplWin32 *pix_impl;
139   GdkVisual *visual;
140
141   struct {
142     BITMAPINFOHEADER bmiHeader;
143     union {
144       WORD bmiIndices[256];
145       DWORD bmiMasks[3];
146       RGBQUAD bmiColors[256];
147     } u;
148   } bmi;
149   UINT iUsage;
150   HDC hdc;
151
152   guchar *bits;
153   gint i;
154
155   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
156   g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
157 #if 1
158   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
159 #else
160   /* HB: Not The Right Thing to do, but a nice way to debug
161    * the backing store facility without immediate crashes ...
162    */
163   if (width == 0 || height == 0)
164     {
165       g_warning("gdk_pixmap_new: size requested: %ld %ld", width, height);
166       /* testing: where does it crash next? */
167       if (width == 0) width = 1;
168       if (height == 0) height = 1;
169     }
170 #endif
171
172   if (!window)
173     window = gdk_parent_root;
174
175   if (GDK_WINDOW_DESTROYED (window))
176     return NULL;
177
178   visual = gdk_drawable_get_visual (window);
179
180   if (depth == -1)
181     depth = gdk_drawable_get_depth (GDK_DRAWABLE (window));
182
183   GDK_NOTE (MISC, g_print ("gdk_pixmap_new: %dx%dx%d\n",
184                            width, height, depth));
185
186   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
187   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
188   pix_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
189   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
190   
191   pix_impl->is_foreign = FALSE;
192   pix_impl->width = width;
193   pix_impl->height = height;
194   GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
195
196   if ((hdc = GetDC (GDK_WINDOW_HWND (window))) == NULL)
197     {
198       WIN32_GDI_FAILED ("GetDC");
199       g_object_unref ((GObject *) pixmap);
200       return NULL;
201     }
202
203   bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
204   bmi.bmiHeader.biWidth = width;
205   bmi.bmiHeader.biHeight = -height;
206   bmi.bmiHeader.biPlanes = 1;
207   if (depth == 15)
208     bmi.bmiHeader.biBitCount = 16;
209   else
210     bmi.bmiHeader.biBitCount = depth;
211   if (depth == 16)
212     bmi.bmiHeader.biCompression = BI_BITFIELDS;
213   else
214     bmi.bmiHeader.biCompression = BI_RGB;
215   bmi.bmiHeader.biSizeImage = 0;
216   bmi.bmiHeader.biXPelsPerMeter =
217     bmi.bmiHeader.biYPelsPerMeter = 0;
218   bmi.bmiHeader.biClrUsed = 0;
219   bmi.bmiHeader.biClrImportant = 0;
220
221   iUsage = DIB_RGB_COLORS;
222   if (depth == 1)
223     {
224       bmi.u.bmiColors[0].rgbBlue =
225         bmi.u.bmiColors[0].rgbGreen =
226         bmi.u.bmiColors[0].rgbRed = 0x00;
227       bmi.u.bmiColors[0].rgbReserved = 0x00;
228
229       bmi.u.bmiColors[1].rgbBlue =
230         bmi.u.bmiColors[1].rgbGreen =
231         bmi.u.bmiColors[1].rgbRed = 0xFF;
232       bmi.u.bmiColors[1].rgbReserved = 0x00;
233       draw_impl->colormap = NULL;
234     }
235   else
236     {
237       draw_impl->colormap = GDK_DRAWABLE_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->colormap;
238       if (draw_impl->colormap == NULL)
239         draw_impl->colormap = gdk_colormap_get_system ();
240
241       if (depth == 8)
242         {
243           iUsage = DIB_PAL_COLORS;
244           for (i = 0; i < 256; i++)
245             bmi.u.bmiIndices[i] = i;
246         }
247       else
248         {
249           if (depth != visual->depth)
250             g_warning ("gdk_pixmap_new: depth %d doesn't match display depth %d",
251                        depth, visual->depth);
252           if (depth == 16)
253             {
254               bmi.u.bmiMasks[0] = visual->red_mask;
255               bmi.u.bmiMasks[1] = visual->green_mask;
256               bmi.u.bmiMasks[2] = visual->blue_mask;
257             }
258         }
259     }
260   if ((draw_impl->handle = CreateDIBSection (hdc, (BITMAPINFO *) &bmi,
261                                              iUsage, (PVOID *) &bits,
262                                              NULL, 0)) == NULL)
263     {
264       WIN32_GDI_FAILED ("CreateDIBSection");
265       ReleaseDC (GDK_WINDOW_HWND (window), hdc);
266       g_object_unref ((GObject *) pixmap);
267       return NULL;
268     }
269   ReleaseDC (GDK_WINDOW_HWND (window), hdc);
270
271   GDK_NOTE (MISC, g_print ("... = %#x\n",
272                            (guint) GDK_PIXMAP_HBITMAP (pixmap)));
273
274   gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
275
276   return pixmap;
277 }
278
279 static unsigned char mirror[256] = {
280   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
281   0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
282   0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
283   0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
284   0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
285   0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
286   0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
287   0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
288   0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
289   0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
290   0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
291   0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
292   0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
293   0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
294   0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
295   0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
296   0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
297   0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
298   0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
299   0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
300   0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
301   0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
302   0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
303   0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
304   0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
305   0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
306   0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
307   0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
308   0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
309   0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
310   0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
311   0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
312 };
313
314 GdkPixmap *
315 gdk_bitmap_create_from_data (GdkWindow   *window,
316                              const gchar *data,
317                              gint         width,
318                              gint         height)
319 {
320   GdkPixmap *pixmap;
321   GdkDrawableImplWin32 *draw_impl;
322   GdkPixmapImplWin32 *pix_impl;
323   gint i, j, bpl, aligned_bpl;
324   guchar *bits;
325
326   g_return_val_if_fail (data != NULL, NULL);
327   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
328   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
329
330   if (!window)
331     window = gdk_parent_root;
332
333   if (GDK_WINDOW_DESTROYED (window))
334     return NULL;
335
336   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
337   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
338   pix_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
339   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
340
341   pix_impl->is_foreign = FALSE;
342   pix_impl->width = width;
343   pix_impl->height = height;
344   GDK_PIXMAP_OBJECT (pixmap)->depth = 1;
345
346   bpl = ((width - 1) / 8 + 1);
347   aligned_bpl = ((bpl - 1) / 2 + 1) * 2;
348   bits = g_malloc (aligned_bpl * height);
349   for (i = 0; i < height; i++)
350     for (j = 0; j < bpl; j++)
351       bits[i*aligned_bpl + j] = mirror[(guchar) data[i*bpl + j]];
352
353   draw_impl->handle = CreateBitmap (width, height, 1, 1, bits);
354
355   GDK_NOTE (MISC, g_print ("gdk_bitmap_create_from_data: %dx%d = %#x\n",
356                            width, height,
357                            (guint) GDK_PIXMAP_HBITMAP (pixmap)));
358
359   g_free (bits);
360
361   draw_impl->colormap = NULL;
362   gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
363
364   return pixmap;
365 }
366
367 GdkPixmap*
368 gdk_pixmap_create_from_data (GdkWindow   *window,
369                              const gchar *data,
370                              gint         width,
371                              gint         height,
372                              gint         depth,
373                              GdkColor    *fg,
374                              GdkColor    *bg)
375 {
376   /* Oh wow. I struggled with dozens of lines of code trying to get
377    * this right using a monochrome Win32 bitmap created from data, and
378    * a colour DIB section as the result, trying setting pens,
379    * background colors, whatnot and BitBlt:ing.  Nope. Then finally I
380    * realized it's much easier to do it using gdk...:
381    */
382
383   GdkPixmap *result = gdk_pixmap_new (window, width, height, depth);
384   GdkPixmap *source = gdk_bitmap_create_from_data (window, data, width, height);
385   GdkGC *gc = gdk_gc_new (result);
386   gdk_gc_set_foreground (gc, fg);
387   gdk_gc_set_background (gc, bg);
388   gdk_draw_drawable (result, gc, source, 0, 0, 0, 0, width, height);
389   gdk_drawable_unref (source);
390   gdk_gc_unref (gc);
391
392   GDK_NOTE (MISC, g_print ("gdk_pixmap_create_from_data: %dx%dx%d = %#x\n",
393                            width, height, depth,
394                            (guint) GDK_PIXMAP_HBITMAP (result)));
395
396   return result;
397 }
398
399 GdkPixmap*
400 gdk_pixmap_foreign_new (GdkNativeWindow anid)
401 {
402   GdkPixmap *pixmap;
403   GdkDrawableImplWin32 *draw_impl;
404   GdkPixmapImplWin32 *pix_impl;
405   HBITMAP hbitmap;
406   SIZE size;
407   unsigned int w_ret, h_ret;
408
409   /* check to make sure we were passed a HBITMAP */
410   g_return_val_if_fail(GetObjectType ((HGDIOBJ) anid) == OBJ_BITMAP, NULL);
411
412   /* set the pixmap to the passed in value */
413   hbitmap = (HBITMAP) anid;
414
415   /* get information about the bitmap to fill in the structure for
416      the gdk window */
417   GetBitmapDimensionEx (hbitmap, &size);
418   w_ret = size.cx;
419   h_ret = size.cy;
420
421   /* allocate a new gdk pixmap */
422   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
423   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
424   pix_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
425   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
426   
427   draw_impl->handle = hbitmap;
428   draw_impl->colormap = NULL;
429   pix_impl->width = w_ret;
430   pix_impl->height = h_ret;
431
432   gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
433
434   return pixmap;
435 }