]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkpixmap-win32.c
static correct-ness, underscore prefixing of library internal functions
[~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       GDK_NOTE (MISC, g_print ("... colormap NULL\n"));
235     }
236   else
237     {
238       draw_impl->colormap = GDK_DRAWABLE_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->colormap;
239       if (draw_impl->colormap == NULL)
240         draw_impl->colormap = gdk_colormap_get_system ();
241       GDK_NOTE (MISC, g_print ("... colormap %p\n", draw_impl->colormap));
242
243       if (depth == 8)
244         {
245           iUsage = DIB_PAL_COLORS;
246           for (i = 0; i < 256; i++)
247             bmi.u.bmiIndices[i] = i;
248         }
249       else
250         {
251           if (depth != visual->depth)
252             g_warning ("gdk_pixmap_new: depth %d doesn't match display depth %d",
253                        depth, visual->depth);
254           if (depth == 16)
255             {
256               bmi.u.bmiMasks[0] = visual->red_mask;
257               bmi.u.bmiMasks[1] = visual->green_mask;
258               bmi.u.bmiMasks[2] = visual->blue_mask;
259             }
260         }
261     }
262   if ((draw_impl->handle = CreateDIBSection (hdc, (BITMAPINFO *) &bmi,
263                                              iUsage, (PVOID *) &bits,
264                                              NULL, 0)) == NULL)
265     {
266       WIN32_GDI_FAILED ("CreateDIBSection");
267       ReleaseDC (GDK_WINDOW_HWND (window), hdc);
268       g_object_unref ((GObject *) pixmap);
269       return NULL;
270     }
271   ReleaseDC (GDK_WINDOW_HWND (window), hdc);
272
273   GDK_NOTE (MISC, g_print ("... = %#x\n",
274                            (guint) GDK_PIXMAP_HBITMAP (pixmap)));
275
276   gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
277
278   return pixmap;
279 }
280
281 static unsigned char mirror[256] = {
282   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
283   0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
284   0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
285   0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
286   0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
287   0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
288   0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
289   0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
290   0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
291   0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
292   0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
293   0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
294   0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
295   0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
296   0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
297   0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
298   0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
299   0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
300   0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
301   0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
302   0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
303   0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
304   0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
305   0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
306   0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
307   0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
308   0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
309   0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
310   0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
311   0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
312   0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
313   0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
314 };
315
316 GdkPixmap *
317 gdk_bitmap_create_from_data (GdkWindow   *window,
318                              const gchar *data,
319                              gint         width,
320                              gint         height)
321 {
322   GdkPixmap *pixmap;
323   GdkDrawableImplWin32 *draw_impl;
324   GdkPixmapImplWin32 *pix_impl;
325   gint i, j, bpl, aligned_bpl;
326   guchar *bits;
327
328   g_return_val_if_fail (data != NULL, NULL);
329   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
330   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
331
332   if (!window)
333     window = _gdk_parent_root;
334
335   if (GDK_WINDOW_DESTROYED (window))
336     return NULL;
337
338   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
339   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
340   pix_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
341   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
342
343   pix_impl->is_foreign = FALSE;
344   pix_impl->width = width;
345   pix_impl->height = height;
346   GDK_PIXMAP_OBJECT (pixmap)->depth = 1;
347
348   bpl = ((width - 1) / 8 + 1);
349   aligned_bpl = ((bpl - 1) / 2 + 1) * 2;
350   bits = g_malloc (aligned_bpl * height);
351   for (i = 0; i < height; i++)
352     for (j = 0; j < bpl; j++)
353       bits[i*aligned_bpl + j] = mirror[(guchar) data[i*bpl + j]];
354
355   draw_impl->handle = CreateBitmap (width, height, 1, 1, bits);
356
357   GDK_NOTE (MISC, g_print ("gdk_bitmap_create_from_data: %dx%d = %#x\n",
358                            width, height,
359                            (guint) GDK_PIXMAP_HBITMAP (pixmap)));
360
361   g_free (bits);
362
363   draw_impl->colormap = NULL;
364   gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
365
366   return pixmap;
367 }
368
369 GdkPixmap*
370 gdk_pixmap_create_from_data (GdkWindow   *window,
371                              const gchar *data,
372                              gint         width,
373                              gint         height,
374                              gint         depth,
375                              GdkColor    *fg,
376                              GdkColor    *bg)
377 {
378   /* Oh wow. I struggled with dozens of lines of code trying to get
379    * this right using a monochrome Win32 bitmap created from data, and
380    * a colour DIB section as the result, trying setting pens,
381    * background colors, whatnot and BitBlt:ing.  Nope. Then finally I
382    * realized it's much easier to do it using gdk...:
383    */
384
385   GdkPixmap *result;
386   GdkPixmap *source;
387   GdkGC *gc;
388
389   if (GDK_WINDOW_DESTROYED (window))
390     return NULL;
391
392   result = gdk_pixmap_new (window, width, height, depth);
393   source = gdk_bitmap_create_from_data (window, data, width, height);
394   gc = gdk_gc_new (result);
395
396   gdk_gc_set_foreground (gc, fg);
397   gdk_gc_set_background (gc, bg);
398   gdk_draw_drawable (result, gc, source, 0, 0, 0, 0, width, height);
399   gdk_drawable_unref (source);
400   gdk_gc_unref (gc);
401
402   GDK_NOTE (MISC, g_print ("gdk_pixmap_create_from_data: %dx%dx%d = %#x\n",
403                            width, height, depth,
404                            (guint) GDK_PIXMAP_HBITMAP (result)));
405
406   return result;
407 }
408
409 GdkPixmap*
410 gdk_pixmap_foreign_new (GdkNativeWindow anid)
411 {
412   GdkPixmap *pixmap;
413   GdkDrawableImplWin32 *draw_impl;
414   GdkPixmapImplWin32 *pix_impl;
415   HBITMAP hbitmap;
416   SIZE size;
417   unsigned int w_ret, h_ret;
418
419   /* check to make sure we were passed a HBITMAP */
420   g_return_val_if_fail(GetObjectType ((HGDIOBJ) anid) == OBJ_BITMAP, NULL);
421
422   /* set the pixmap to the passed in value */
423   hbitmap = (HBITMAP) anid;
424
425   /* get information about the bitmap to fill in the structure for
426      the gdk window */
427   GetBitmapDimensionEx (hbitmap, &size);
428   w_ret = size.cx;
429   h_ret = size.cy;
430
431   /* allocate a new gdk pixmap */
432   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
433   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
434   pix_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
435   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
436   
437   draw_impl->handle = hbitmap;
438   draw_impl->colormap = NULL;
439   pix_impl->width = w_ret;
440   pix_impl->height = h_ret;
441
442   gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
443
444   return pixmap;
445 }