]> Pileus Git - ~andy/gtk/blobdiff - gdk/win32/gdkimage-win32.c
gdk/win32/gdkpixmap-win32.c (gdk_pixmap_new, gdk_bitmap_create_from_data,
[~andy/gtk] / gdk / win32 / gdkimage-win32.c
index 8b8c4190ea2ea30eb4ccee636ae5d86122f908ad..8f3da52b025bdf23a87a335be62fc93be167775b 100644 (file)
 /* GDK - The GIMP Drawing Kit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1998-2002 Tor Lillqvist
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 /*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include "config.h"
+#include "gdkimage.h"
+#include "gdkpixmap.h"
+#include "gdkscreen.h" /* gdk_screen_get_default() */
+#include "gdkprivate-win32.h"
 
-#include <gdk/gdk.h>
-#include "gdkprivate.h"
-
-static void gdk_image_put_normal (GdkDrawable *drawable,
-                                 GdkGC       *gc,
-                                 GdkImage    *image,
-                                 gint         xsrc,
-                                 gint         ysrc,
-                                 gint         xdest,
-                                 gint         ydest,
-                                 gint         width,
-                                 gint         height);
 static GList *image_list = NULL;
+static gpointer parent_class = NULL;
 
-void
-gdk_image_exit (void)
+static void gdk_win32_image_destroy (GdkImage      *image);
+static void gdk_image_init          (GdkImage      *image);
+static void gdk_image_class_init    (GdkImageClass *klass);
+static void gdk_image_finalize      (GObject       *object);
+
+GType
+gdk_image_get_type (void)
 {
-  GdkImage *image;
+  static GType object_type = 0;
 
-  while (image_list)
+  if (!object_type)
     {
-      image = image_list->data;
-      gdk_image_destroy (image);
+      static const GTypeInfo object_info =
+      {
+        sizeof (GdkImageClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gdk_image_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (GdkImage),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) gdk_image_init,
+      };
+      
+      object_type = g_type_register_static (G_TYPE_OBJECT,
+                                            "GdkImage",
+                                            &object_info, 0);
     }
+  
+  return object_type;
 }
 
-GdkImage *
-gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h)
-/*
- * Desc: create a new bitmap image
- */
+static void
+gdk_image_init (GdkImage *image)
 {
-  Visual *xvisual;
-  GdkImage *image;
-  GdkImagePrivate *private;
-  struct {
-    BITMAPINFOHEADER bmiHeader;
-    union {
-      WORD bmiIndices[2];
-      RGBQUAD bmiColors[2];
-    } u;
-  } bmi;
-  char *bits;
-  int bpl = (w-1)/8 + 1;
-  int bpl32 = ((w-1)/32 + 1)*4;
-
-  private = g_new(GdkImagePrivate, 1);
-  image = (GdkImage *) private;
-  private->image_put = gdk_image_put_normal;
-  image->type = GDK_IMAGE_SHARED;
-  image->visual = visual;
-  image->width = w;
-  image->height = h;
-  image->depth = 1;
-  xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+  image->windowing_data = NULL;
+}
 
-  GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
-  
-  bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
-  bmi.bmiHeader.biWidth = w;
-  bmi.bmiHeader.biHeight = -h;
-  bmi.bmiHeader.biPlanes = 1;
-  bmi.bmiHeader.biBitCount = 1;
-  bmi.bmiHeader.biCompression = BI_RGB;
-  bmi.bmiHeader.biSizeImage = 0;
-  bmi.bmiHeader.biXPelsPerMeter =
-    bmi.bmiHeader.biYPelsPerMeter = 0;
-  bmi.bmiHeader.biClrUsed = 0;
-  bmi.bmiHeader.biClrImportant = 0;
-  
-  bmi.u.bmiColors[0].rgbBlue = 
-    bmi.u.bmiColors[0].rgbGreen = 
-    bmi.u.bmiColors[0].rgbRed = 0x00;
-  bmi.u.bmiColors[0].rgbReserved = 0x00;
-
-  bmi.u.bmiColors[1].rgbBlue = 
-    bmi.u.bmiColors[1].rgbGreen = 
-    bmi.u.bmiColors[1].rgbRed = 0xFF;
-  bmi.u.bmiColors[1].rgbReserved = 0x00;
-  
-  private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi,
-                                     DIB_RGB_COLORS, &bits, NULL, 0);
-  if (bpl != bpl32)
-    {
-      /* Win32 expects scanlines in DIBs to be 32 bit aligned */
-      int i;
-      for (i = 0; i < h; i++)
-       memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl);
-    }
-  else
-    memmove (bits, data, bpl*h);
-  image->mem = bits;
-  image->bpl = bpl32;
-  image->byte_order = GDK_MSB_FIRST;
+static void
+gdk_image_class_init (GdkImageClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  image->bpp = 1;
-  return(image);
-} /* gdk_image_new_bitmap() */
+  parent_class = g_type_class_peek_parent (klass);
 
-void
-gdk_image_init (void)
-{
+  object_class->finalize = gdk_image_finalize;
 }
 
-static GdkImage*
-gdk_image_new_with_depth (GdkImageType  type,
-                         GdkVisual    *visual,
-                         gint          width,
-                         gint          height,
-                         gint          depth)
+static void
+gdk_image_finalize (GObject *object)
 {
-  GdkImage *image;
-  GdkImagePrivate *private;
-  Visual *xvisual;
-  struct {
-    BITMAPINFOHEADER bmiHeader;
-    union {
-      WORD bmiIndices[256];
-      DWORD bmiMasks[3];
-      RGBQUAD bmiColors[256];
-    } u;
-  } bmi;
-  UINT iUsage;
-  int i;
-
-  if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
-    type = GDK_IMAGE_SHARED;
-
-  GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d %s\n",
-                          width, height, depth,
-                          (type == GDK_IMAGE_SHARED ? "shared" :
-                           (type == GDK_IMAGE_SHARED_PIXMAP ? "shared_pixmap" :
-                            "???"))));
-
-  private = g_new (GdkImagePrivate, 1);
-  image = (GdkImage*) private;
-
-  private->image_put = NULL;
-
-  image->type = type;
-  image->visual = visual;
-  image->width = width;
-  image->height = height;
-  image->depth = depth;
-  
-  xvisual = ((GdkVisualPrivate*) visual)->xvisual;
-  
-  private->image_put = gdk_image_put_normal;
-      
-  bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
-  bmi.bmiHeader.biWidth = width;
-  bmi.bmiHeader.biHeight = -height;
-  bmi.bmiHeader.biPlanes = 1;
-  if (depth == 15)
-    bmi.bmiHeader.biBitCount = 16;
-  else
-    bmi.bmiHeader.biBitCount = depth;
-#if 1
-  if (depth == 16)
-    bmi.bmiHeader.biCompression = BI_BITFIELDS;
-  else
-#endif
-    bmi.bmiHeader.biCompression = BI_RGB;
-  bmi.bmiHeader.biSizeImage = 0;
-  bmi.bmiHeader.biXPelsPerMeter =
-    bmi.bmiHeader.biYPelsPerMeter = 0;
-  bmi.bmiHeader.biClrUsed = 0;
-  bmi.bmiHeader.biClrImportant = 0;
-
-  if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
-    {
-      iUsage = DIB_PAL_COLORS;
-      for (i = 0; i < 256; i++)
-       bmi.u.bmiIndices[i] = i;
-    }
-  else
-    {
-      if (depth == 1)
-       {
-         bmi.u.bmiColors[0].rgbBlue = 
-           bmi.u.bmiColors[0].rgbGreen =
-           bmi.u.bmiColors[0].rgbRed = 0x00;
-         bmi.u.bmiColors[0].rgbReserved = 0x00;
-
-         bmi.u.bmiColors[1].rgbBlue = 
-           bmi.u.bmiColors[1].rgbGreen =
-           bmi.u.bmiColors[1].rgbRed = 0xFF;
-         bmi.u.bmiColors[1].rgbReserved = 0x00;
+  GdkImage *image = GDK_IMAGE (object);
 
-       }
-#if 1
-      else if (depth == 16)
-       {
-         bmi.u.bmiMasks[0] = visual->red_mask;
-         bmi.u.bmiMasks[1] = visual->green_mask;
-         bmi.u.bmiMasks[2] = visual->blue_mask;
-       }
-#endif
-      iUsage = DIB_RGB_COLORS;
-    }
+  gdk_win32_image_destroy (image);
+  
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
 
-  private->ximage =
-    CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage,
-                     &image->mem, NULL, 0);
+void
+_gdk_image_exit (void)
+{
+  GdkImage *image;
 
-  if (private->ximage == NULL)
+  while (image_list)
     {
-      g_warning ("gdk_image_new_with_depth: CreateDIBSection failed");
-      g_free (image);
-      return NULL;
+      image = image_list->data;
+      gdk_win32_image_destroy (image);
     }
+}
 
+GdkImage *
+_gdk_win32_setup_pixmap_image (GdkPixmap   *pixmap,
+                              GdkDrawable *drawable,
+                              gint         width,
+                              gint         height,
+                              gint         depth,
+                              guchar      *bits)
+{
+  GdkImage *image;
+
+  image = g_object_new (gdk_image_get_type (), NULL);
+  image->windowing_data = pixmap;
+  image->type = GDK_IMAGE_SHARED;
+  image->visual = gdk_drawable_get_visual (drawable);
+  image->byte_order = GDK_LSB_FIRST;
+  image->width = width;
+  image->height = height;
+  image->depth = depth;
   switch (depth)
     {
     case 1:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
     case 8:
       image->bpp = 1;
       break;
@@ -255,350 +143,206 @@ gdk_image_new_with_depth (GdkImageType  type,
       image->bpp = 4;
       break;
     default:
-      g_warning ("gdk_image_new_with_depth: depth = %d", depth);
+      g_warning ("_gdk_win32_setup_pixmap_image: depth=%d", image->depth);
       g_assert_not_reached ();
     }
-  image->byte_order = GDK_LSB_FIRST;
   if (depth == 1)
-    image->bpl = ((width-1)/32 + 1)*4;
+    image->bpl = ((width - 1)/32 + 1)*4;
+  else if (depth == 4)
+    image->bpl = ((width - 1)/8 + 1)*4;
   else
     image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
-
-  GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
-                          private->ximage, image->mem, image->bpl));
+  image->bits_per_pixel = image->depth;
+  image->mem = bits;
 
   return image;
 }
 
-GdkImage*
-gdk_image_new (GdkImageType  type,
-              GdkVisual    *visual,
-              gint          width,
-              gint          height)
-{
-  return gdk_image_new_with_depth (type, visual, width, height, visual->depth);
-}
-
-GdkImage*
-gdk_image_bitmap_new (GdkImageType  type,
-                     GdkVisual    *visual,
-                     gint          width,
-                     gint          height)
-{
-  return gdk_image_new_with_depth (type, visual, width, height, 1);
-}
-
-GdkImage*
-gdk_image_get (GdkWindow *window,
-              gint       x,
-              gint       y,
-              gint       width,
-              gint       height)
+GdkImage *
+gdk_image_new_bitmap (GdkVisual *visual,
+                     gpointer   data,
+                     gint       w,
+                     gint       h)
 {
+  GdkPixmap *pixmap;
   GdkImage *image;
-  GdkImagePrivate *private;
-  GdkWindowPrivate *win_private;
-  HDC hdc, memdc;
-  struct {
-    BITMAPINFOHEADER bmiHeader;
-    union {
-      WORD bmiIndices[256];
-      DWORD bmiMasks[3];
-      RGBQUAD bmiColors[256];
-    } u;
-  } bmi;
-  HGDIOBJ oldbitmap1, oldbitmap2;
-  UINT iUsage;
-  BITMAP bm;
-  int i;
-
-  g_return_val_if_fail (window != NULL, NULL);
-
-  win_private = (GdkWindowPrivate *) window;
-  if (win_private->destroyed)
-    return NULL;
+  gint data_bpl = (w-1)/8 + 1;
+  gint i;
 
-  GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n",
-                          win_private->xwindow, width, height, x, y));
+  pixmap = gdk_pixmap_new (NULL, w, h, 1);
 
-  private = g_new (GdkImagePrivate, 1);
-  image = (GdkImage*) private;
-
-  private->image_put = gdk_image_put_normal;
+  if (pixmap == NULL)
+    return NULL;
 
-  image->type = GDK_IMAGE_SHARED;
-  image->visual = gdk_window_get_visual (window);
-  image->width = width;
-  image->height = height;
+  image = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl)->image;
 
-  /* This function is called both to blit from a window and from
-   * a pixmap.
-   */
-  if (win_private->window_type == GDK_WINDOW_PIXMAP)
+  GDK_NOTE (IMAGE, g_print ("gdk_image_new_bitmap: %dx%d=%p\n",
+                           w, h, GDK_PIXMAP_HBITMAP (pixmap)));
+  
+  if (data_bpl != image->bpl)
     {
-      if ((hdc = CreateCompatibleDC (NULL)) == NULL)
-       {
-         g_warning ("gdk_image_get: CreateCompatibleDC #1 failed");
-         g_free (image);
-         return NULL;
-       }
-      if ((oldbitmap1 = SelectObject (hdc, win_private->xwindow)) == NULL)
-       {
-         g_warning ("gdk_image_get: SelectObject #1 failed");
-         DeleteDC (hdc);
-         g_free (image);
-         return NULL;
-       }
-      GetObject (win_private->xwindow, sizeof (BITMAP), &bm);
-      GDK_NOTE (MISC,
-               g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n",
-                        bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel));
-      image->depth = bm.bmBitsPixel;
-      if (image->depth <= 8)
-       {
-         iUsage = DIB_PAL_COLORS;
-         for (i = 0; i < 256; i++)
-           bmi.u.bmiIndices[i] = i;
-       }
-      else
-       iUsage = DIB_RGB_COLORS;
+      for (i = 0; i < h; i++)
+       memmove ((guchar *) image->mem + i*image->bpl, ((guchar *) data) + i*data_bpl, data_bpl);
     }
   else
-    {
-      if ((hdc = GetDC (win_private->xwindow)) == NULL)
-       {
-         g_warning ("gdk_image_get: GetDC failed");
-         g_free (image);
-         return NULL;
-       }
-      image->depth = gdk_visual_get_system ()->depth;
-      if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
-       {
-         iUsage = DIB_PAL_COLORS;
-         for (i = 0; i < 256; i++)
-           bmi.u.bmiIndices[i] = i;
-       }
-      else
-       iUsage = DIB_RGB_COLORS;
-    }
+    memmove (image->mem, data, data_bpl*h);
 
-  if ((memdc = CreateCompatibleDC (hdc)) == NULL)
-    {
-      g_warning ("gdk_image_get: CreateCompatibleDC #2 failed");
-      if (win_private->window_type == GDK_WINDOW_PIXMAP)
-       {
-         SelectObject (hdc, oldbitmap1);
-         DeleteDC (hdc);
-       }
-      else
-       {
-         ReleaseDC (win_private->xwindow, hdc);
-       }
-      g_free (image);
-      return NULL;
-    }
+  return image;
+}
 
-  bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
-  bmi.bmiHeader.biWidth = width;
-  bmi.bmiHeader.biHeight = -height;
-  bmi.bmiHeader.biPlanes = 1;
-  bmi.bmiHeader.biBitCount = image->depth;
-  if (image->depth == 16)
-    {
-      bmi.bmiHeader.biCompression = BI_BITFIELDS;
-      if (image->visual == NULL)
-       {
-         /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */
-         bmi.u.bmiMasks[0] = 0xf800;
-         bmi.u.bmiMasks[1] = 0x07e0;
-         bmi.u.bmiMasks[2] = 0x001f;
-       }
-      else
-       {
-         bmi.u.bmiMasks[0] = image->visual->red_mask;
-         bmi.u.bmiMasks[1] = image->visual->green_mask;
-         bmi.u.bmiMasks[2] = image->visual->blue_mask;
-       }
-    }
-  else
-    bmi.bmiHeader.biCompression = BI_RGB;
-  bmi.bmiHeader.biSizeImage = 0;
-  bmi.bmiHeader.biXPelsPerMeter =
-    bmi.bmiHeader.biYPelsPerMeter = 0;
-  bmi.bmiHeader.biClrUsed = 0;
-  bmi.bmiHeader.biClrImportant = 0;
-
-  if ((private->ximage =
-       CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
-                        &image->mem, NULL, 0)) == NULL)
-    {
-      g_warning ("gdk_image_get: CreateDIBSection failed");
-      DeleteDC (memdc);
-      if (win_private->window_type == GDK_WINDOW_PIXMAP)
-       {
-         SelectObject (hdc, oldbitmap1);
-         DeleteDC (hdc);
-       }
-      else
-       {
-         ReleaseDC (win_private->xwindow, hdc);
-       }
-      g_free (image);
-      return NULL;
-    }
+void
+_gdk_windowing_image_init (void)
+{
+  /* Nothing needed AFAIK */
+}
 
-  if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL)
-    {
-      g_warning ("gdk_image_get: SelectObject #2 failed");
-      DeleteObject (private->ximage);
-      DeleteDC (memdc);
-      if (win_private->window_type == GDK_WINDOW_PIXMAP)
-       {
-         SelectObject (hdc, oldbitmap1);
-         DeleteDC (hdc);
-       }
-      else
-       {
-         ReleaseDC (win_private->xwindow, hdc);
-       }
-      g_free (image);
-      return NULL;
-    }
+GdkImage*
+_gdk_image_new_for_depth (GdkScreen    *screen,
+                         GdkImageType  type,
+                         GdkVisual    *visual,
+                         gint          width,
+                         gint          height,
+                         gint          depth)
+{
+  GdkPixmap *pixmap;
 
-  if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
-    {
-      g_warning ("gdk_image_get: BitBlt failed");
-      SelectObject (memdc, oldbitmap2);
-      DeleteObject (private->ximage);
-      DeleteDC (memdc);
-      if (win_private->window_type == GDK_WINDOW_PIXMAP)
-       {
-         SelectObject (hdc, oldbitmap1);
-         DeleteDC (hdc);
-       }
-      else
-       {
-         ReleaseDC (win_private->xwindow, hdc);
-       }
-      g_free (image);
-      return NULL;
-    }
+  g_return_val_if_fail (!visual || GDK_IS_VISUAL (visual), NULL);
+  g_return_val_if_fail (visual || depth != -1, NULL);
+  g_return_val_if_fail (screen == gdk_screen_get_default (), NULL);
+  if (visual)
+    depth = visual->depth;
 
-  if (SelectObject (memdc, oldbitmap2) == NULL)
-    g_warning ("gdk_image_get: SelectObject #3 failed");
+  pixmap = gdk_pixmap_new (NULL, width, height, depth);
 
-  if (!DeleteDC (memdc))
-    g_warning ("gdk_image_get: DeleteDC failed");
+  if (pixmap == NULL)
+    return NULL;
 
-  if (win_private->window_type == GDK_WINDOW_PIXMAP)
-    {
-      SelectObject (hdc, oldbitmap1);
-      DeleteDC (hdc);
-    }
-  else
-    {
-      ReleaseDC (win_private->xwindow, hdc);
-    }
+  GDK_NOTE (IMAGE, g_print ("_gdk_image_new_for_depth: %dx%dx%d=%p\n",
+                           width, height, depth, GDK_PIXMAP_HBITMAP (pixmap)));
+  
+  return GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl)->image;
+}
 
-  switch (image->depth)
-    {
-    case 1:
-    case 8:
-      image->bpp = 1;
-      break;
-    case 15:
-    case 16:
-      image->bpp = 2;
-      break;
-    case 24:
-      image->bpp = 3;
-      break;
-    case 32:
-      image->bpp = 4;
-      break;
-    default:
-      g_warning ("gdk_image_get: image->depth = %d", image->depth);
-      g_assert_not_reached ();
-    }
-  image->byte_order = GDK_LSB_FIRST;
-  if (image->depth == 1)
-    image->bpl = (width - 1)/8 + 1;
-  else
-    image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
+GdkImage*
+_gdk_win32_copy_to_image (GdkDrawable    *drawable,
+                         GdkImage       *image,
+                         gint            src_x,
+                         gint            src_y,
+                         gint            dest_x,
+                         gint            dest_y,
+                         gint            width,
+                         gint            height)
+{
+  GdkGC *gc;
+  GdkScreen *screen = gdk_drawable_get_screen (drawable);
+  
+  g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable), NULL);
+  g_return_val_if_fail (image != NULL || (dest_x == 0 && dest_y == 0), NULL);
 
-  GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
-                          private->ximage, image->mem, image->bpl));
+  GDK_NOTE (IMAGE, g_print ("_gdk_win32_copy_to_image: %p\n",
+                           GDK_DRAWABLE_HANDLE (drawable)));
+
+  if (!image)
+    image = _gdk_image_new_for_depth (screen, GDK_IMAGE_FASTEST, NULL, width, height,
+                                     gdk_drawable_get_depth (drawable));
+
+  gc = gdk_gc_new ((GdkDrawable *) image->windowing_data);
+  _gdk_win32_blit
+    (FALSE,
+     GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (image->windowing_data)->impl),
+     gc, drawable, src_x, src_y, dest_x, dest_y, width, height);
+  gdk_gc_unref (gc);
 
   return image;
 }
 
 guint32
 gdk_image_get_pixel (GdkImage *image,
-                    gint x,
-                    gint y)
+                    gint      x,
+                    gint      y)
 {
-  guint32 pixel;
-  GdkImagePrivate *private;
+  guchar *pixelp;
 
   g_return_val_if_fail (image != NULL, 0);
+  g_return_val_if_fail (x >= 0 && x < image->width, 0);
+  g_return_val_if_fail (y >= 0 && y < image->height, 0);
 
-  private = (GdkImagePrivate *) image;
-
-  g_return_val_if_fail (x >= 0 && x < image->width
-                       && y >= 0 && y < image->height, 0);
+  if (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
+      return 0;
 
   if (image->depth == 1)
-    pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
-  else
-    {
-      guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
-      
-      switch (image->bpp)
-       {
-       case 1:
-         pixel = *pixelp;
-         break;
-
-       /* Windows is always LSB, no need to check image->byte_order. */
-       case 2:
-         pixel = pixelp[0] | (pixelp[1] << 8);
-         break;
+    return (((guchar *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
 
-       case 3:
-         pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
-         break;
+  if (image->depth == 4)
+    {
+      pixelp = (guchar *) image->mem + y * image->bpl + (x >> 1);
+      if (x&1)
+       return (*pixelp) & 0x0F;
 
-       case 4:
-         pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
-         break;
-       }
+      return (*pixelp) >> 4;
     }
+    
+  pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
+      
+  switch (image->bpp)
+    {
+    case 1:
+      return *pixelp;
+      
+      /* Windows is always LSB, no need to check image->byte_order. */
+    case 2:
+      return pixelp[0] | (pixelp[1] << 8);
+      
+    case 3:
+      return pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
 
-  return pixel;
+    case 4:
+      return pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
+    }
+  g_assert_not_reached ();
+  return 0;
 }
 
 void
 gdk_image_put_pixel (GdkImage *image,
-                    gint x,
-                    gint y,
-                    guint32 pixel)
+                    gint       x,
+                    gint       y,
+                    guint32    pixel)
 {
-  GdkImagePrivate *private;
+  guchar *pixelp;
 
   g_return_if_fail (image != NULL);
+  g_return_if_fail (x >= 0 && x < image->width);
+  g_return_if_fail (y >= 0 && y < image->height);
 
-  private = (GdkImagePrivate *) image;
-
-  g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height);
+  if  (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
+    return;
 
+  GdiFlush ();
   if (image->depth == 1)
     if (pixel & 1)
       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
     else
       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
+  else if (image->depth == 4)
+    {
+      pixelp = (guchar *) image->mem + y * image->bpl + (x >> 1);
+
+      if (x&1)
+       {
+         *pixelp &= 0xF0;
+         *pixelp |= (pixel & 0x0F);
+       }
+      else
+       {
+         *pixelp &= 0x0F;
+         *pixelp |= (pixel << 4);
+       }
+    }
   else
     {
-      guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
+      pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
       
       /* Windows is always LSB, no need to check image->byte_order. */
       switch (image->bpp)
@@ -615,143 +359,61 @@ gdk_image_put_pixel (GdkImage *image,
     }
 }
 
-void
-gdk_image_destroy (GdkImage *image)
+static void
+gdk_win32_image_destroy (GdkImage *image)
 {
-  GdkImagePrivate *private;
+  GdkPixmap *pixmap;
 
-  g_return_if_fail (image != NULL);
+  g_return_if_fail (GDK_IS_IMAGE (image));
 
-  private = (GdkImagePrivate*) image;
+  pixmap = image->windowing_data;
 
-  GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n",
-                          private->ximage,
-                          (image->type == GDK_IMAGE_SHARED_PIXMAP ?
-                           " (shared pixmap)" : "")));
-  
-  switch (image->type)
-    {
-    case GDK_IMAGE_SHARED_PIXMAP:
-      break;                   /* The Windows bitmap has already been
-                                * (or will be) deleted when freeing
-                                * the corresponding pixmap.
+  if (pixmap == NULL)          /* This means that _gdk_image_exit()
+                                * destroyed the image already, and
+                                * now we're called a second time from
+                                * _finalize()
                                 */
+    return;
+  
+  GDK_NOTE (IMAGE, g_print ("gdk_win32_image_destroy: %p\n",
+                           GDK_PIXMAP_HBITMAP (pixmap)));
 
-    case GDK_IMAGE_SHARED:
-      if (!DeleteObject (private->ximage))
-       g_warning ("gdk_image_destroy: DeleteObject failed");
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-
-  g_free (image);
+  gdk_pixmap_unref (pixmap);
+  image->windowing_data = NULL;
 }
 
-static void
-gdk_image_put_normal (GdkDrawable *drawable,
-                     GdkGC       *gc,
-                     GdkImage    *image,
-                     gint         xsrc,
-                     gint         ysrc,
-                     gint         xdest,
-                     gint         ydest,
-                     gint         width,
-                     gint         height)
+gint
+_gdk_windowing_get_bits_for_depth (GdkDisplay *display,
+                                   gint        depth)
 {
-  GdkWindowPrivate *drawable_private;
-  GdkImagePrivate *image_private;
-  GdkGCPrivate *gc_private;
-  HDC hdc;
-  GdkColormapPrivate *colormap_private;
+  g_return_val_if_fail (display == gdk_display_get_default (), 0);
 
-  g_return_if_fail (drawable != NULL);
-  g_return_if_fail (image != NULL);
-  g_return_if_fail (gc != NULL);
-
-  drawable_private = (GdkWindowPrivate*) drawable;
-  if (drawable_private->destroyed)
-    return;
-  image_private = (GdkImagePrivate*) image;
-  gc_private = (GdkGCPrivate*) gc;
-
-  /* The image can in fact be "shared", so don't test */
-
-  hdc = gdk_gc_predraw (drawable_private, gc_private);
-  colormap_private = (GdkColormapPrivate *) drawable_private->colormap;
-  if (colormap_private && colormap_private->xcolormap->rc_palette)
+  switch (depth)
     {
-      DIBSECTION ds;
-      static struct {
-       BITMAPINFOHEADER bmiHeader;
-       WORD bmiIndices[256];
-      } bmi;
-      static gboolean bmi_inited = FALSE;
-      int i;
-
-      if (!bmi_inited)
-       {
-         for (i = 0; i < 256; i++)
-           bmi.bmiIndices[i] = i;
-         bmi_inited = TRUE;
-       }
+    case 1:
+      return 1;
 
-      if (GetObject (image_private->ximage, sizeof (DIBSECTION),
-                    &ds) != sizeof (DIBSECTION))
-       {
-         g_warning ("gdk_image_put_normal: GetObject failed");
-       }
-#if 0
-      g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
-             xdest, ydest, xsrc, ysrc, width, height);
-      g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
-             ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
-      g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
-             ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
-#endif
-      bmi.bmiHeader = ds.dsBmih;
-      /* I have spent hours on getting the parameters to
-       * SetDIBitsToDevice right. I wonder what drugs the guys in
-       * Redmond were on when they designed this API.
-       */
-      if (SetDIBitsToDevice (hdc,
-                            xdest, ydest,
-                            width, height,
-                            xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
-                            0, -ds.dsBmih.biHeight,
-                            ds.dsBm.bmBits,
-                            (CONST BITMAPINFO *) &bmi,
-                            DIB_PAL_COLORS) == 0)
-       g_warning ("SetDIBitsToDevice failed");
-    }
-  else
-    {
-      HDC memdc;
-      HGDIOBJ oldbitmap;
+    case 2:
+    case 3:
+    case 4:
+      return 4;
 
-      if ((memdc = CreateCompatibleDC (hdc)) == NULL)
-       {
-         g_warning ("gdk_image_put_normal: CreateCompatibleDC failed");
-         gdk_gc_postdraw (drawable_private, gc_private);
-         return;
-       }
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+      return 8;
 
-      if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL)
-       {
-         g_warning ("gdk_image_put_normal: SelectObject #1 failed");
-         gdk_gc_postdraw (drawable_private, gc_private);
-         return;
-       }
-      if (!BitBlt (hdc, xdest, ydest, width, height,
-                  memdc, xsrc, ysrc, SRCCOPY))
-       g_warning ("gdk_image_put_normal: BitBlt failed");
+    case 15:
+    case 16:
+      return 16;
 
-      if (SelectObject (memdc, oldbitmap) == NULL)
-       g_warning ("gdk_image_put_normal: SelectObject #2 failed");
+    case 24:
+      return 24;
 
-      if (!DeleteDC (memdc))
-       g_warning ("gdk_image_put_normal: DeleteDC failed");
+    case 32:
+      return 32;
     }
-  gdk_gc_postdraw (drawable_private, gc_private);
+  g_assert_not_reached ();
+  return 0;
 }