1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2002 Tor Lillqvist
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.
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.
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.
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/.
33 #include "gdkpixmap.h"
34 #include "gdkdisplay.h"
35 #include "gdkscreen.h"
37 #include "gdkprivate-win32.h"
39 static void gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable,
43 static void gdk_pixmap_impl_win32_init (GdkPixmapImplWin32 *pixmap);
44 static void gdk_pixmap_impl_win32_class_init (GdkPixmapImplWin32Class *klass);
45 static void gdk_pixmap_impl_win32_finalize (GObject *object);
47 static gpointer parent_class = NULL;
50 _gdk_pixmap_impl_win32_get_type (void)
52 static GType object_type = 0;
56 const GTypeInfo object_info =
58 sizeof (GdkPixmapImplWin32Class),
60 (GBaseFinalizeFunc) NULL,
61 (GClassInitFunc) gdk_pixmap_impl_win32_class_init,
62 NULL, /* class_finalize */
63 NULL, /* class_data */
64 sizeof (GdkPixmapImplWin32),
66 (GInstanceInitFunc) gdk_pixmap_impl_win32_init,
69 object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_WIN32,
78 _gdk_pixmap_impl_get_type (void)
80 return _gdk_pixmap_impl_win32_get_type ();
84 gdk_pixmap_impl_win32_init (GdkPixmapImplWin32 *impl)
91 gdk_pixmap_impl_win32_class_init (GdkPixmapImplWin32Class *klass)
93 GObjectClass *object_class = G_OBJECT_CLASS (klass);
94 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
96 parent_class = g_type_class_peek_parent (klass);
98 object_class->finalize = gdk_pixmap_impl_win32_finalize;
100 drawable_class->get_size = gdk_pixmap_impl_win32_get_size;
104 gdk_pixmap_impl_win32_finalize (GObject *object)
106 GdkPixmapImplWin32 *impl = GDK_PIXMAP_IMPL_WIN32 (object);
107 GdkPixmap *wrapper = GDK_PIXMAP (GDK_DRAWABLE_IMPL_WIN32 (impl)->wrapper);
109 GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_impl_win32_finalize: %p\n",
110 GDK_PIXMAP_HBITMAP (wrapper)));
112 _gdk_win32_drawable_finish (GDK_DRAWABLE (object));
114 GDI_CALL (DeleteObject, (GDK_PIXMAP_HBITMAP (wrapper)));
116 gdk_win32_handle_table_remove (GDK_PIXMAP_HBITMAP (wrapper));
118 G_OBJECT_CLASS (parent_class)->finalize (object);
122 gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable,
127 *width = GDK_PIXMAP_IMPL_WIN32 (drawable)->width;
129 *height = GDK_PIXMAP_IMPL_WIN32 (drawable)->height;
133 _gdk_pixmap_new (GdkDrawable *drawable,
139 BITMAPINFOHEADER bmiHeader;
141 WORD bmiIndices[256];
143 RGBQUAD bmiColors[256];
149 HPALETTE holdpal = NULL;
152 GdkDrawableImplWin32 *drawable_impl;
153 GdkPixmapImplWin32 *pixmap_impl;
159 g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
160 g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
161 g_return_val_if_fail ((width != 0) && (height != 0), NULL);
164 drawable = _gdk_root;
166 if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
169 window_depth = gdk_drawable_get_depth (GDK_DRAWABLE (drawable));
171 depth = window_depth;
173 GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_new: %dx%dx%d drawable=%p\n",
174 width, height, depth, drawable));
176 pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
177 drawable_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
178 pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
179 drawable_impl->wrapper = GDK_DRAWABLE (pixmap);
181 pixmap_impl->is_foreign = FALSE;
182 pixmap_impl->width = width;
183 pixmap_impl->height = height;
184 GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
186 if (depth == window_depth)
188 cmap = gdk_drawable_get_colormap (drawable);
190 gdk_drawable_set_colormap (pixmap, cmap);
193 if (GDK_IS_WINDOW (drawable))
194 hwnd = GDK_WINDOW_HWND (drawable);
196 hwnd = GetDesktopWindow ();
197 if ((hdc = GetDC (hwnd)) == NULL)
199 WIN32_GDI_FAILED ("GetDC");
200 g_object_unref ((GObject *) pixmap);
204 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
205 bmi.bmiHeader.biWidth = width;
206 bmi.bmiHeader.biHeight = -height;
207 bmi.bmiHeader.biPlanes = 1;
213 bmi.bmiHeader.biBitCount = _gdk_windowing_get_bits_for_depth (gdk_display_get_default (), depth);
217 bmi.bmiHeader.biBitCount = 4;
224 bmi.bmiHeader.biBitCount = 8;
229 bmi.bmiHeader.biBitCount = 16;
233 g_warning ("gdk_win32_pixmap_new: depth = %d", depth);
234 g_assert_not_reached ();
237 if (bmi.bmiHeader.biBitCount == 16)
238 bmi.bmiHeader.biCompression = BI_BITFIELDS;
240 bmi.bmiHeader.biCompression = BI_RGB;
242 bmi.bmiHeader.biSizeImage = 0;
243 bmi.bmiHeader.biXPelsPerMeter =
244 bmi.bmiHeader.biYPelsPerMeter = 0;
245 bmi.bmiHeader.biClrUsed = 0;
246 bmi.bmiHeader.biClrImportant = 0;
248 iUsage = DIB_RGB_COLORS;
251 bmi.u.bmiColors[0].rgbBlue =
252 bmi.u.bmiColors[0].rgbGreen =
253 bmi.u.bmiColors[0].rgbRed = 0x00;
254 bmi.u.bmiColors[0].rgbReserved = 0x00;
256 bmi.u.bmiColors[1].rgbBlue =
257 bmi.u.bmiColors[1].rgbGreen =
258 bmi.u.bmiColors[1].rgbRed = 0xFF;
259 bmi.u.bmiColors[1].rgbReserved = 0x00;
263 if (depth <= 8 && drawable_impl->colormap != NULL)
265 GdkColormapPrivateWin32 *cmapp =
266 GDK_WIN32_COLORMAP_DATA (drawable_impl->colormap);
269 if ((holdpal = SelectPalette (hdc, cmapp->hpal, FALSE)) == NULL)
270 WIN32_GDI_FAILED ("SelectPalette");
271 else if ((k = RealizePalette (hdc)) == GDI_ERROR)
272 WIN32_GDI_FAILED ("RealizePalette");
274 GDK_NOTE (PIXMAP_OR_COLORMAP, g_print ("_gdk_win32_pixmap_new: realized %p: %d colors\n",
277 iUsage = DIB_PAL_COLORS;
278 for (i = 0; i < 256; i++)
279 bmi.u.bmiIndices[i] = i;
281 else if (bmi.bmiHeader.biBitCount == 16)
283 GdkVisual *visual = gdk_visual_get_system ();
285 bmi.u.bmiMasks[0] = visual->red_mask;
286 bmi.u.bmiMasks[1] = visual->green_mask;
287 bmi.u.bmiMasks[2] = visual->blue_mask;
291 hbitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bmi,
292 iUsage, (PVOID *) &bits, NULL, 0);
294 SelectPalette (hdc, holdpal, FALSE);
296 GDI_CALL (ReleaseDC, (hwnd, hdc));
298 GDK_NOTE (PIXMAP, g_print ("... =%p bits=%p pixmap=%p\n", hbitmap, bits, pixmap));
302 WIN32_GDI_FAILED ("CreateDIBSection");
303 g_object_unref ((GObject *) pixmap);
307 drawable_impl->handle = hbitmap;
308 pixmap_impl->bits = bits;
310 gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
315 static const unsigned char mirror[256] = {
316 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
317 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
318 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
319 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
320 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
321 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
322 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
323 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
324 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
325 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
326 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
327 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
328 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
329 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
330 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
331 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
332 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
333 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
334 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
335 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
336 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
337 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
338 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
339 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
340 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
341 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
342 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
343 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
344 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
345 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
346 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
347 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
351 _gdk_bitmap_create_from_data (GdkDrawable *drawable,
357 GdkPixmapImplWin32 *pixmap_impl;
358 gint i, j, data_bpl, pixmap_bpl;
361 g_return_val_if_fail (data != NULL, NULL);
362 g_return_val_if_fail ((width != 0) && (height != 0), NULL);
363 g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
366 drawable = _gdk_root;
367 else if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
370 pixmap = gdk_pixmap_new (drawable, width, height, 1);
375 pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
376 bits = pixmap_impl->bits;
377 data_bpl = ((width - 1) / 8 + 1);
378 pixmap_bpl = ((width - 1)/32 + 1)*4;
380 for (i = 0; i < height; i++)
381 for (j = 0; j < data_bpl; j++)
382 bits[i*pixmap_bpl + j] = mirror[(guchar) data[i*data_bpl + j]];
384 GDK_NOTE (PIXMAP, g_print ("gdk_bitmap_create_from_data: %dx%d=%p\n",
385 width, height, GDK_PIXMAP_HBITMAP (pixmap)));
391 _gdk_pixmap_create_from_data (GdkDrawable *drawable,
399 /* Oh wow. I struggled with dozens of lines of code trying to get
400 * this right using a monochrome Win32 bitmap created from data, and
401 * a colour DIB section as the result, trying setting pens,
402 * background colors, whatnot and BitBlt:ing. Nope. Then finally I
403 * realized it's much easier to do it using gdk...:
410 g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
411 g_return_val_if_fail (data != NULL, NULL);
412 g_return_val_if_fail (fg != NULL, NULL);
413 g_return_val_if_fail (bg != NULL, NULL);
414 g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
415 g_return_val_if_fail ((width != 0) && (height != 0), NULL);
417 if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
420 result = gdk_pixmap_new (drawable, width, height, depth);
421 source = gdk_bitmap_create_from_data (drawable, data, width, height);
422 gc = gdk_gc_new (result);
424 gdk_gc_set_foreground (gc, fg);
425 gdk_gc_set_background (gc, bg);
428 GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (result)->impl),
429 gc, source, 0, 0, 0, 0, width, height);
430 g_object_unref (source);
433 GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_create_from_data: %dx%dx%d=%p\n",
434 width, height, depth,
435 GDK_PIXMAP_HBITMAP (result)));
441 gdk_pixmap_foreign_new_for_display (GdkDisplay *display,
442 GdkNativeWindow anid)
444 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
445 g_return_val_if_fail (display == _gdk_display, NULL);
447 return gdk_pixmap_foreign_new (anid);
451 gdk_pixmap_foreign_new_for_screen (GdkScreen *screen,
452 GdkNativeWindow anid,
457 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
459 return gdk_pixmap_foreign_new (anid);
463 gdk_pixmap_foreign_new (GdkNativeWindow anid)
466 GdkDrawableImplWin32 *draw_impl;
467 GdkPixmapImplWin32 *pix_impl;
471 /* Check to make sure we were passed a HBITMAP */
472 g_return_val_if_fail (GetObjectType ((HGDIOBJ) anid) == OBJ_BITMAP, NULL);
474 hbitmap = (HBITMAP) anid;
476 /* Get information about the bitmap to fill in the structure for the
479 GetBitmapDimensionEx (hbitmap, &size);
481 /* Allocate a new GDK pixmap */
482 pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
483 draw_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
484 pix_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
485 draw_impl->wrapper = GDK_DRAWABLE (pixmap);
487 draw_impl->handle = hbitmap;
488 draw_impl->colormap = NULL;
489 pix_impl->width = size.cx;
490 pix_impl->height = size.cy;
491 pix_impl->bits = NULL;
493 gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
499 gdk_pixmap_lookup (GdkNativeWindow anid)
501 return (GdkPixmap*) gdk_win32_handle_table_lookup (anid);
505 gdk_pixmap_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
507 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
508 g_return_val_if_fail (display == _gdk_display, NULL);
510 return gdk_pixmap_lookup (anid);