[gtk+/gtk-2-24] win32: Let cairo create DIBs for GdkPixmap
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-2-24] win32: Let cairo create DIBs for GdkPixmap
- Date: Wed, 9 Nov 2011 12:34:15 +0000 (UTC)
commit 2ae574ab6dd1f9810c4667920f9984ed1e95d0f7
Author: Alexander Larsson <alexl redhat com>
Date: Wed Nov 9 13:25:02 2011 +0100
win32: Let cairo create DIBs for GdkPixmap
The win32 code for GdkPixmap dib creation workes as such, but
when creating a cairo surface for it with cairo_win32_surface_create
from the HDC it fails for any bitmap format than RGB24, due to
assumptions in cairo.
In order to create a cairo surface for e.g. A1 formats we need
to let cairo create the surface via cairo_win32_surface_create_with_dib.
Additionally, we must then make sure to use this surface in
gdk_drawable_ref_cairo_surface, and to not create a new HDC for
it but reuse the cairo one (as only one HDC can write to a bitmap).
Even with this fixed there are some issues with current cairo, as
cairo A1 format isn't quite the same as win32 monochrome bitmaps.
Fixes for cairo will be submitted.
gdk/win32/gdkpixmap-win32.c | 166 +++++++++++-------------------------------
1 files changed, 44 insertions(+), 122 deletions(-)
---
diff --git a/gdk/win32/gdkpixmap-win32.c b/gdk/win32/gdkpixmap-win32.c
index c8b33b4..30b9c8a 100644
--- a/gdk/win32/gdkpixmap-win32.c
+++ b/gdk/win32/gdkpixmap-win32.c
@@ -35,6 +35,7 @@
#include "gdkscreen.h"
#include "gdkprivate-win32.h"
+#include <cairo-win32.h>
static void gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable,
gint *width,
@@ -109,9 +110,10 @@ gdk_pixmap_impl_win32_finalize (GObject *object)
GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_impl_win32_finalize: %p\n",
GDK_PIXMAP_HBITMAP (wrapper)));
- _gdk_win32_drawable_finish (GDK_DRAWABLE (object));
+ if (!impl->is_foreign)
+ GDK_DRAWABLE_IMPL_WIN32 (impl)->hdc_count--;
- GDI_CALL (DeleteObject, (GDK_PIXMAP_HBITMAP (wrapper)));
+ _gdk_win32_drawable_finish (GDK_DRAWABLE (object));
gdk_win32_handle_table_remove (GDK_PIXMAP_HBITMAP (wrapper));
@@ -135,26 +137,16 @@ _gdk_pixmap_new (GdkDrawable *drawable,
gint height,
gint depth)
{
- struct {
- BITMAPINFOHEADER bmiHeader;
- union {
- WORD bmiIndices[256];
- DWORD bmiMasks[3];
- RGBQUAD bmiColors[256];
- } u;
- } bmi;
- UINT iUsage;
HDC hdc;
- HWND hwnd;
HPALETTE holdpal = NULL;
HBITMAP hbitmap;
GdkPixmap *pixmap;
GdkDrawableImplWin32 *drawable_impl;
GdkPixmapImplWin32 *pixmap_impl;
GdkColormap *cmap;
- guchar *bits;
- gint i;
gint window_depth;
+ cairo_surface_t *dib_surface, *image_surface;
+ cairo_format_t format;
g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
@@ -173,6 +165,27 @@ _gdk_pixmap_new (GdkDrawable *drawable,
GDK_NOTE (PIXMAP, g_print ("gdk_pixmap_new: %dx%dx%d drawable=%p\n",
width, height, depth, drawable));
+ switch (depth)
+ {
+ case 1:
+ format = CAIRO_FORMAT_A1;
+ break;
+
+ case 8:
+ format = CAIRO_FORMAT_A8;
+ break;
+
+ case 24:
+ case 32:
+ format = CAIRO_FORMAT_RGB24;
+ break;
+
+ default:
+ g_warning ("gdk_win32_pixmap_new: depth = %d not supported", depth);
+ return NULL;
+ break;
+ }
+
pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
drawable_impl = GDK_DRAWABLE_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
@@ -189,123 +202,32 @@ _gdk_pixmap_new (GdkDrawable *drawable,
if (cmap)
gdk_drawable_set_colormap (pixmap, cmap);
}
-
- if (GDK_IS_WINDOW (drawable))
- hwnd = GDK_WINDOW_HWND (drawable);
- else
- hwnd = GetDesktopWindow ();
- if ((hdc = GetDC (hwnd)) == NULL)
+
+ dib_surface = cairo_win32_surface_create_with_dib (format, width, height);
+ if (dib_surface == 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;
- switch (depth)
- {
- case 1:
- case 24:
- case 32:
- bmi.bmiHeader.biBitCount = _gdk_windowing_get_bits_for_depth (gdk_display_get_default (), depth);
- break;
-
- case 4:
- bmi.bmiHeader.biBitCount = 4;
- break;
-
- case 5:
- case 6:
- case 7:
- case 8:
- bmi.bmiHeader.biBitCount = 8;
- break;
-
- case 15:
- case 16:
- bmi.bmiHeader.biBitCount = 16;
- break;
-
- default:
- g_warning ("gdk_win32_pixmap_new: depth = %d", depth);
- g_assert_not_reached ();
- }
-
- if (bmi.bmiHeader.biBitCount == 16)
- bmi.bmiHeader.biCompression = BI_BITFIELDS;
- else
- bmi.bmiHeader.biCompression = BI_RGB;
+ /* 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);
- bmi.bmiHeader.biSizeImage = 0;
- bmi.bmiHeader.biXPelsPerMeter =
- bmi.bmiHeader.biYPelsPerMeter = 0;
- bmi.bmiHeader.biClrUsed = 0;
- bmi.bmiHeader.biClrImportant = 0;
+ /* We need to use the same hdc, because only one hdc
+ can render to the same bitmap */
+ drawable_impl->hdc = hdc;
+ drawable_impl->hdc_count = 1; /* Ensure we never free the cairo surface HDC */
- iUsage = DIB_RGB_COLORS;
- 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;
- }
- else
- {
- if (depth <= 8 && drawable_impl->colormap != NULL)
- {
- GdkColormapPrivateWin32 *cmapp =
- GDK_WIN32_COLORMAP_DATA (drawable_impl->colormap);
- gint k;
-
- if ((holdpal = SelectPalette (hdc, cmapp->hpal, FALSE)) == NULL)
- WIN32_GDI_FAILED ("SelectPalette");
- else if ((k = RealizePalette (hdc)) == GDI_ERROR)
- WIN32_GDI_FAILED ("RealizePalette");
- else if (k > 0)
- GDK_NOTE (PIXMAP_OR_COLORMAP, g_print ("_gdk_win32_pixmap_new: realized %p: %d colors\n",
- cmapp->hpal, k));
-
- iUsage = DIB_PAL_COLORS;
- for (i = 0; i < 256; i++)
- bmi.u.bmiIndices[i] = i;
- }
- else if (bmi.bmiHeader.biBitCount == 16)
- {
- GdkVisual *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);
- if (holdpal != NULL)
- SelectPalette (hdc, holdpal, FALSE);
-
- GDI_CALL (ReleaseDC, (hwnd, hdc));
-
- GDK_NOTE (PIXMAP, g_print ("... =%p bits=%p pixmap=%p\n", hbitmap, bits, pixmap));
-
- if (hbitmap == NULL)
- {
- WIN32_GDI_FAILED ("CreateDIBSection");
- g_object_unref ((GObject *) pixmap);
- return NULL;
- }
+ /* 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;
- pixmap_impl->bits = bits;
+
+ image_surface = cairo_win32_surface_get_image (dib_surface);
+ pixmap_impl->bits = cairo_image_surface_get_data (image_surface);
gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]