[gtk+/gtk-2-24] win32: Fix 16bit pixmaps



commit ba8c4bb049b36b3707c2c8f22c5c66b497e2d2cf
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Dec 6 11:27:53 2011 +0100

    win32: Fix 16bit pixmaps
    
    This reverts to the old dibsection creation code for 16bit depth.
    This makes the non-cairo stuff work, we then access the bits as
    a cairo image surface, which isn't 100% right, but might be good
    enough.
    
    Fixes bug 665013

 gdk/win32/gdkpixmap-win32.c |  107 +++++++++++++++++++++++++++++++++++++------
 1 files changed, 92 insertions(+), 15 deletions(-)
---
diff --git a/gdk/win32/gdkpixmap-win32.c b/gdk/win32/gdkpixmap-win32.c
index 30b9c8a..e803877 100644
--- a/gdk/win32/gdkpixmap-win32.c
+++ b/gdk/win32/gdkpixmap-win32.c
@@ -138,7 +138,6 @@ _gdk_pixmap_new (GdkDrawable *drawable,
 		gint         depth)
 {
   HDC hdc;
-  HPALETTE holdpal = NULL;
   HBITMAP hbitmap;
   GdkPixmap *pixmap;
   GdkDrawableImplWin32 *drawable_impl;
@@ -147,6 +146,7 @@ _gdk_pixmap_new (GdkDrawable *drawable,
   gint window_depth;
   cairo_surface_t *dib_surface, *image_surface;
   cairo_format_t format;
+  guchar *bits;
 
   g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
   g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
@@ -175,6 +175,11 @@ _gdk_pixmap_new (GdkDrawable *drawable,
       format = CAIRO_FORMAT_A8;
       break;
 
+    case 15:
+    case 16:
+      format = CAIRO_FORMAT_RGB16_565;
+      break;
+
     case 24:
     case 32:
       format = CAIRO_FORMAT_RGB24;
@@ -203,16 +208,93 @@ _gdk_pixmap_new (GdkDrawable *drawable,
         gdk_drawable_set_colormap (pixmap, cmap);
     }
 
-  dib_surface = cairo_win32_surface_create_with_dib (format, width, height);
-  if (dib_surface == NULL)
+  if (depth != 15 && depth != 16)
     {
-      g_object_unref ((GObject *) pixmap);
-      return NULL;
+      dib_surface = cairo_win32_surface_create_with_dib (format, width, height);
+      if (dib_surface == NULL)
+	{
+	  g_object_unref ((GObject *) pixmap);
+	  return NULL;
+	}
+
+      /* We need to have cairo create the dibsection for us, because
+	 creating a cairo surface from a hdc only works for rgb24 format */
+      hdc = cairo_win32_surface_get_dc (dib_surface);
+
+      /* Get the bitmap from the cairo hdc */
+      hbitmap = GetCurrentObject (hdc, OBJ_BITMAP);
+
+      image_surface = cairo_win32_surface_get_image (dib_surface);
+      bits = cairo_image_surface_get_data (image_surface);
+    }
+  else
+    {
+      /* 16 bpp not supported by win32 cairo surface */
+      struct {
+	BITMAPINFOHEADER bmiHeader;
+	union {
+	  WORD bmiIndices[256];
+	  DWORD bmiMasks[3];
+	  RGBQUAD bmiColors[256];
+	} u;
+      } bmi;
+      UINT iUsage;
+      HWND hwnd;
+      GdkVisual *visual;
+
+      if (GDK_IS_WINDOW (drawable))
+	hwnd = GDK_WINDOW_HWND (drawable);
+      else
+	hwnd = GetDesktopWindow ();
+      if ((hdc = GetDC (hwnd)) == NULL)
+	{
+	  WIN32_GDI_FAILED ("GetDC");
+	  g_object_unref ((GObject *) pixmap);
+	  return NULL;
+	}
+
+      bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+      bmi.bmiHeader.biWidth = width;
+      bmi.bmiHeader.biHeight = -height;
+      bmi.bmiHeader.biPlanes = 1;
+      bmi.bmiHeader.biBitCount = 16;
+      bmi.bmiHeader.biCompression = BI_BITFIELDS;
+      bmi.bmiHeader.biSizeImage = 0;
+      bmi.bmiHeader.biXPelsPerMeter =
+	bmi.bmiHeader.biYPelsPerMeter = 0;
+      bmi.bmiHeader.biClrUsed = 0;
+      bmi.bmiHeader.biClrImportant = 0;
+
+      iUsage = DIB_RGB_COLORS;
+      visual = gdk_visual_get_system ();
+      bmi.u.bmiMasks[0] = visual->red_mask;
+      bmi.u.bmiMasks[1] = visual->green_mask;
+      bmi.u.bmiMasks[2] = visual->blue_mask;
+
+      hbitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bmi,
+				  iUsage, (PVOID *) &bits, NULL, 0);
+      GDI_CALL (ReleaseDC, (hwnd, hdc));
+      if (hbitmap == NULL)
+	{
+	  WIN32_GDI_FAILED ("CreateDIBSection");
+	  g_object_unref ((GObject *) pixmap);
+	  return NULL;
+	}
+
+      dib_surface = cairo_image_surface_create_for_data (bits,
+							 format, width, height,
+							 (width * 2 + 3) & ~3);
+
+      hdc = CreateCompatibleDC (NULL);
+      if (!hdc)
+	{
+	  WIN32_GDI_FAILED ("CreateCompatibleDC");
+	  g_object_unref ((GObject *) pixmap);
+	  return NULL;
+	}
+
+      SelectObject (hdc, hbitmap);
     }
-
-  /* We need to have cairo create the dibsection for us, because
-     creating a cairo surface from a hdc only works for rgb24 format */
-  hdc = cairo_win32_surface_get_dc (dib_surface);
 
   /* We need to use the same hdc, because only one hdc
      can render to the same bitmap */
@@ -221,13 +303,8 @@ _gdk_pixmap_new (GdkDrawable *drawable,
 
   /* No need to create a new surface when needed, as we have one already */
   drawable_impl->cairo_surface = dib_surface;
-
-  /* Get the bitmap from the cairo hdc */
-  hbitmap = GetCurrentObject (hdc, OBJ_BITMAP);
   drawable_impl->handle = hbitmap;
-
-  image_surface = cairo_win32_surface_get_image (dib_surface);
-  pixmap_impl->bits = cairo_image_surface_get_data (image_surface);
+  pixmap_impl->bits = bits;
 
   gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]