source: trunk/third/gtk2/gdk/win32/gdkpixmap-win32.c @ 18785

Revision 18785, 14.6 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18784, which included commits to RCS files with non-trunk default branches.
Line 
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
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 <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32#include "gdkpixmap.h"
33#include "gdkdisplay.h"
34
35#include "gdkprivate-win32.h"
36
37static void gdk_pixmap_impl_win32_get_size   (GdkDrawable        *drawable,
38                                              gint               *width,
39                                              gint               *height);
40
41static void gdk_pixmap_impl_win32_init       (GdkPixmapImplWin32      *pixmap);
42static void gdk_pixmap_impl_win32_class_init (GdkPixmapImplWin32Class *klass);
43static void gdk_pixmap_impl_win32_finalize   (GObject                 *object);
44
45static gpointer parent_class = NULL;
46
47GType
48_gdk_pixmap_impl_win32_get_type (void)
49{
50  static GType object_type = 0;
51
52  if (!object_type)
53    {
54      static const GTypeInfo object_info =
55      {
56        sizeof (GdkPixmapImplWin32Class),
57        (GBaseInitFunc) NULL,
58        (GBaseFinalizeFunc) NULL,
59        (GClassInitFunc) gdk_pixmap_impl_win32_class_init,
60        NULL,           /* class_finalize */
61        NULL,           /* class_data */
62        sizeof (GdkPixmapImplWin32),
63        0,              /* n_preallocs */
64        (GInstanceInitFunc) gdk_pixmap_impl_win32_init,
65      };
66     
67      object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_WIN32,
68                                            "GdkPixmapImplWin32",
69                                            &object_info, 0);
70    }
71 
72  return object_type;
73}
74
75GType
76_gdk_pixmap_impl_get_type (void)
77{
78  return _gdk_pixmap_impl_win32_get_type ();
79}
80
81static void
82gdk_pixmap_impl_win32_init (GdkPixmapImplWin32 *impl)
83{
84  impl->width = 1;
85  impl->height = 1;
86}
87
88static void
89gdk_pixmap_impl_win32_class_init (GdkPixmapImplWin32Class *klass)
90{
91  GObjectClass *object_class = G_OBJECT_CLASS (klass);
92  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
93 
94  parent_class = g_type_class_peek_parent (klass);
95
96  object_class->finalize = gdk_pixmap_impl_win32_finalize;
97
98  drawable_class->get_size = gdk_pixmap_impl_win32_get_size;
99}
100
101static void
102gdk_pixmap_impl_win32_finalize (GObject *object)
103{
104  GdkPixmapImplWin32 *impl = GDK_PIXMAP_IMPL_WIN32 (object);
105  GdkPixmap *wrapper = GDK_PIXMAP (GDK_DRAWABLE_IMPL_WIN32 (impl)->wrapper);
106  GdkImage *image = impl->image;
107
108  GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_impl_win32_finalize: %p\n",
109                             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  image->windowing_data = NULL;
117  g_object_unref (image);
118
119  G_OBJECT_CLASS (parent_class)->finalize (object);
120}
121
122static void
123gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable,
124                                gint        *width,
125                                gint        *height)
126{
127  if (width)
128    *width = GDK_PIXMAP_IMPL_WIN32 (drawable)->width;
129  if (height)
130    *height = GDK_PIXMAP_IMPL_WIN32 (drawable)->height;
131}
132
133GdkPixmap*
134gdk_pixmap_new (GdkDrawable *drawable,
135                gint         width,
136                gint         height,
137                gint         depth)
138{
139  struct {
140    BITMAPINFOHEADER bmiHeader;
141    union {
142      WORD bmiIndices[256];
143      DWORD bmiMasks[3];
144      RGBQUAD bmiColors[256];
145    } u;
146  } bmi;
147  UINT iUsage;
148  HDC hdc;
149  HWND hwnd;
150  HPALETTE holdpal = NULL;
151  HBITMAP hbitmap;
152  GdkPixmap *pixmap;
153  GdkDrawableImplWin32 *drawable_impl;
154  GdkPixmapImplWin32 *pixmap_impl;
155  GdkColormap *cmap;
156  guchar *bits;
157  gint i;
158  gint window_depth;
159
160  g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
161  g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
162  g_return_val_if_fail ((width != 0) && (height != 0), NULL);
163
164  if (!drawable)
165    drawable = _gdk_parent_root;
166
167  if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
168    return NULL;
169
170  window_depth = gdk_drawable_get_depth (GDK_DRAWABLE (drawable));
171  if (depth == -1)
172    depth = window_depth;
173
174  GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_new: %dx%dx%d drawable=%p\n",
175                             width, height, depth, drawable));
176
177  pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
178  drawable_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
179  pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
180  drawable_impl->wrapper = GDK_DRAWABLE (pixmap);
181 
182  pixmap_impl->is_foreign = FALSE;
183  pixmap_impl->width = width;
184  pixmap_impl->height = height;
185  GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
186
187  if (depth == window_depth)
188    {
189      cmap = gdk_drawable_get_colormap (drawable);
190      if (cmap)
191        gdk_drawable_set_colormap (pixmap, cmap);
192    }
193 
194  if (GDK_IS_WINDOW (drawable))
195    hwnd = GDK_WINDOW_HWND (drawable);
196  else
197    hwnd = GDK_WINDOW_HWND (_gdk_parent_root);
198  if ((hdc = GetDC (hwnd)) == NULL)
199    {
200      WIN32_GDI_FAILED ("GetDC");
201      g_object_unref ((GObject *) pixmap);
202      return NULL;
203    }
204
205  bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
206  bmi.bmiHeader.biWidth = width;
207  bmi.bmiHeader.biHeight = -height;
208  bmi.bmiHeader.biPlanes = 1;
209  switch (depth)
210    {
211    case 1:
212    case 24:
213    case 32:
214      bmi.bmiHeader.biBitCount = depth;
215      break;
216
217    case 4:
218      bmi.bmiHeader.biBitCount = 4;
219      break;
220     
221    case 5:
222    case 6:
223    case 7:
224    case 8:
225      bmi.bmiHeader.biBitCount = 8;
226      break;
227     
228    case 15:
229    case 16:
230      bmi.bmiHeader.biBitCount = 16;
231      break;
232
233    default:
234      g_warning ("gdk_win32_pixmap_new: depth = %d", depth);
235      g_assert_not_reached ();
236    }
237
238  if (bmi.bmiHeader.biBitCount == 16)
239    bmi.bmiHeader.biCompression = BI_BITFIELDS;
240  else
241    bmi.bmiHeader.biCompression = BI_RGB;
242
243  bmi.bmiHeader.biSizeImage = 0;
244  bmi.bmiHeader.biXPelsPerMeter =
245    bmi.bmiHeader.biYPelsPerMeter = 0;
246  bmi.bmiHeader.biClrUsed = 0;
247  bmi.bmiHeader.biClrImportant = 0;
248
249  iUsage = DIB_RGB_COLORS;
250  if (depth == 1)
251    {
252      bmi.u.bmiColors[0].rgbBlue =
253        bmi.u.bmiColors[0].rgbGreen =
254        bmi.u.bmiColors[0].rgbRed = 0x00;
255      bmi.u.bmiColors[0].rgbReserved = 0x00;
256
257      bmi.u.bmiColors[1].rgbBlue =
258        bmi.u.bmiColors[1].rgbGreen =
259        bmi.u.bmiColors[1].rgbRed = 0xFF;
260      bmi.u.bmiColors[1].rgbReserved = 0x00;
261    }
262  else
263    {
264      if (depth <= 8 && drawable_impl->colormap != NULL)
265        {
266          GdkColormapPrivateWin32 *cmapp =
267            GDK_WIN32_COLORMAP_DATA (drawable_impl->colormap);
268          gint k;
269
270          if ((holdpal = SelectPalette (hdc, cmapp->hpal, FALSE)) == NULL)
271            WIN32_GDI_FAILED ("SelectPalette");
272          else if ((k = RealizePalette (hdc)) == GDI_ERROR)
273            WIN32_GDI_FAILED ("RealizePalette");
274          else if (k > 0)
275            GDK_NOTE (PIXMAP_OR_COLORMAP, g_print ("_gdk_win32_pixmap_new: realized %p: %d colors\n",
276                                                   cmapp->hpal, k));
277
278          iUsage = DIB_PAL_COLORS;
279          for (i = 0; i < 256; i++)
280            bmi.u.bmiIndices[i] = i;
281        }
282      else if (bmi.bmiHeader.biBitCount == 16)
283        {
284          GdkVisual *visual = gdk_visual_get_system ();
285
286          bmi.u.bmiMasks[0] = visual->red_mask;
287          bmi.u.bmiMasks[1] = visual->green_mask;
288          bmi.u.bmiMasks[2] = visual->blue_mask;
289        }
290    }
291
292  hbitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bmi,
293                              iUsage, (PVOID *) &bits, NULL, 0);
294  if (holdpal != NULL)
295    SelectPalette (hdc, holdpal, FALSE);
296
297  if (!ReleaseDC (hwnd, hdc))
298    WIN32_GDI_FAILED ("ReleaseDC");
299
300  GDK_NOTE (PIXMAP, g_print ("...=%p bits=%p pixmap=%p\n", hbitmap, bits, pixmap));
301
302  if (hbitmap == NULL)
303    {
304      WIN32_GDI_FAILED ("CreateDIBSection");
305      g_object_unref ((GObject *) pixmap);
306      return NULL;
307    }
308
309  drawable_impl->handle = hbitmap;
310  pixmap_impl->image = _gdk_win32_setup_pixmap_image (pixmap, drawable,
311                                                      width, height,
312                                                      depth, bits);
313
314  gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
315
316  return pixmap;
317}
318
319static unsigned char mirror[256] = {
320  0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
321  0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
322  0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
323  0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
324  0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
325  0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
326  0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
327  0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
328  0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
329  0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
330  0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
331  0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
332  0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
333  0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
334  0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
335  0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
336  0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
337  0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
338  0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
339  0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
340  0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
341  0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
342  0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
343  0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
344  0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
345  0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
346  0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
347  0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
348  0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
349  0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
350  0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
351  0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
352};
353
354GdkPixmap *
355gdk_bitmap_create_from_data (GdkDrawable *drawable,
356                             const gchar *data,
357                             gint         width,
358                             gint         height)
359{
360  GdkPixmap *pixmap;
361  GdkPixmapImplWin32 *pixmap_impl;
362  gint i, j, data_bpl, image_bpl;
363  guchar *bits;
364
365  g_return_val_if_fail (data != NULL, NULL);
366  g_return_val_if_fail ((width != 0) && (height != 0), NULL);
367  g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
368
369  if (!drawable)
370    drawable = _gdk_parent_root;
371
372  if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
373    return NULL;
374
375  pixmap = gdk_pixmap_new (drawable, width, height, 1);
376
377  if (pixmap == NULL)
378    return NULL;
379
380  pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
381  bits = pixmap_impl->image->mem;
382  data_bpl = ((width - 1) / 8 + 1);
383  image_bpl = pixmap_impl->image->bpl;
384
385  for (i = 0; i < height; i++)
386    for (j = 0; j < data_bpl; j++)
387      bits[i*image_bpl + j] = mirror[(guchar) data[i*data_bpl + j]];
388
389  GDK_NOTE (PIXMAP, g_print ("gdk_bitmap_create_from_data: %dx%d=%p\n",
390                             width, height, GDK_PIXMAP_HBITMAP (pixmap)));
391
392  return pixmap;
393}
394
395GdkPixmap*
396gdk_pixmap_create_from_data (GdkDrawable *drawable,
397                             const gchar *data,
398                             gint         width,
399                             gint         height,
400                             gint         depth,
401                             GdkColor    *fg,
402                             GdkColor    *bg)
403{
404  /* Oh wow. I struggled with dozens of lines of code trying to get
405   * this right using a monochrome Win32 bitmap created from data, and
406   * a colour DIB section as the result, trying setting pens,
407   * background colors, whatnot and BitBlt:ing.  Nope. Then finally I
408   * realized it's much easier to do it using gdk...:
409   */
410
411  GdkPixmap *result;
412  GdkPixmap *source;
413  GdkGC *gc;
414
415  g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
416  g_return_val_if_fail (data != NULL, NULL);
417  g_return_val_if_fail (fg != NULL, NULL);
418  g_return_val_if_fail (bg != NULL, NULL);
419  g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
420  g_return_val_if_fail ((width != 0) && (height != 0), NULL);
421
422  if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
423    return NULL;
424
425  result = gdk_pixmap_new (drawable, width, height, depth);
426  source = gdk_bitmap_create_from_data (drawable, data, width, height);
427  gc = gdk_gc_new (result);
428
429  gdk_gc_set_foreground (gc, fg);
430  gdk_gc_set_background (gc, bg);
431  _gdk_win32_blit
432    (TRUE,
433     GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (result)->impl),
434     gc, source, 0, 0, 0, 0, width, height);
435  gdk_drawable_unref (source);
436  gdk_gc_unref (gc);
437
438  GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_create_from_data: %dx%dx%d=%p\n",
439                             width, height, depth,
440                             GDK_PIXMAP_HBITMAP (result)));
441
442  return result;
443}
444
445GdkPixmap *
446gdk_pixmap_foreign_new_for_display (GdkDisplay      *display,
447                                    GdkNativeWindow  anid)
448{
449  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
450  g_return_val_if_fail (display == _gdk_display, NULL);
451
452  return gdk_pixmap_foreign_new (anid);
453}
454
455GdkPixmap*
456gdk_pixmap_foreign_new (GdkNativeWindow anid)
457{
458  GdkPixmap *pixmap;
459  GdkDrawableImplWin32 *draw_impl;
460  GdkPixmapImplWin32 *pix_impl;
461  HBITMAP hbitmap;
462  SIZE size;
463
464  /* Check to make sure we were passed a HBITMAP */
465  g_return_val_if_fail (GetObjectType ((HGDIOBJ) anid) == OBJ_BITMAP, NULL);
466
467  hbitmap = (HBITMAP) anid;
468
469  /* Get information about the bitmap to fill in the structure for the
470   * GDK window.
471   */
472  GetBitmapDimensionEx (hbitmap, &size);
473
474  /* Allocate a new GDK pixmap */
475  pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
476  draw_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
477  pix_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
478  draw_impl->wrapper = GDK_DRAWABLE (pixmap);
479 
480  draw_impl->handle = hbitmap;
481  draw_impl->colormap = NULL;
482  pix_impl->width = size.cx;
483  pix_impl->height = size.cy;
484  pix_impl->image =
485    _gdk_win32_setup_pixmap_image (pixmap, _gdk_parent_root,
486                                   size.cx, size.cy,
487                                   gdk_visual_get_system ()->depth,
488                                   NULL);
489
490  gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
491
492  return pixmap;
493}
494
495GdkPixmap*
496gdk_pixmap_lookup (GdkNativeWindow anid)
497{
498  return (GdkPixmap*) gdk_win32_handle_table_lookup (anid);
499}
500
501GdkPixmap*
502gdk_pixmap_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
503{
504  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
505  g_return_val_if_fail (display == _gdk_display, NULL);
506
507  return gdk_pixmap_lookup (anid);
508}
Note: See TracBrowser for help on using the repository browser.