/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2004 Tor Lillqvist
- * Copyright (C) 2001-2004 Hans Breuer
+ * Copyright (C) 2001-2005 Hans Breuer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <glib.h>
#include <pango/pangowin32.h>
+#include <cairo-win32.h>
#include "gdkscreen.h" /* gdk_screen_get_default() */
#include "gdkregion-generic.h"
#define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \
GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE)
+#define MUST_RENDER_DASHES_MANUALLY(gcwin32) \
+ (gcwin32->line_style == GDK_LINE_DOUBLE_DASH || \
+ (gcwin32->line_style == GDK_LINE_ON_OFF_DASH && \
+ (gcwin32->pen_dash_offset || \
+ (!G_WIN32_IS_NT_BASED () && (gcwin32->pen_style & PS_STYLE_MASK) == PS_SOLID))))
+
static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
GdkGC *gc,
gboolean filled,
GdkGC *gc,
GdkPoint *points,
gint npoints);
-static void gdk_win32_draw_glyphs (GdkDrawable *drawable,
- GdkGC *gc,
- PangoFont *font,
- gint x,
- gint y,
- PangoGlyphString *glyphs);
-static void gdk_win32_draw_glyphs_transformed (GdkDrawable *drawable,
- GdkGC *gc,
- PangoMatrix *matrix,
- PangoFont *font,
- gint x,
- gint y,
- PangoGlyphString *glyphs);
static void gdk_win32_draw_image (GdkDrawable *drawable,
GdkGC *gc,
GdkImage *image,
gint width,
gint height);
+static cairo_surface_t *gdk_win32_ref_cairo_surface (GdkDrawable *drawable);
+
static void gdk_win32_set_colormap (GdkDrawable *drawable,
GdkColormap *colormap);
static void gdk_drawable_impl_win32_finalize (GObject *object);
static gpointer parent_class = NULL;
+static const cairo_user_data_key_t gdk_win32_cairo_key;
GType
gdk_drawable_impl_win32_get_type (void)
drawable_class->draw_points = gdk_win32_draw_points;
drawable_class->draw_segments = gdk_win32_draw_segments;
drawable_class->draw_lines = gdk_win32_draw_lines;
- drawable_class->draw_glyphs = gdk_win32_draw_glyphs;
- drawable_class->draw_glyphs_transformed = gdk_win32_draw_glyphs_transformed;
drawable_class->draw_image = gdk_win32_draw_image;
+ drawable_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
+
drawable_class->set_colormap = gdk_win32_set_colormap;
drawable_class->get_colormap = gdk_win32_get_colormap;
/* Drawing
*/
-/*
- * Render a dashed line 'by hand' cause the Win9x GDI is
- * too limited to do so
+static int
+rop2_to_rop3 (int rop2)
+{
+ switch (rop2)
+ {
+ /* Oh, Microsoft's silly names for binary and ternary rops. */
+#define CASE(rop2,rop3) case R2_##rop2: return rop3
+ CASE (BLACK, BLACKNESS);
+ CASE (NOTMERGEPEN, NOTSRCERASE);
+ CASE (MASKNOTPEN, 0x00220326);
+ CASE (NOTCOPYPEN, NOTSRCCOPY);
+ CASE (MASKPENNOT, SRCERASE);
+ CASE (NOT, DSTINVERT);
+ CASE (XORPEN, SRCINVERT);
+ CASE (NOTMASKPEN, 0x007700E6);
+ CASE (MASKPEN, SRCAND);
+ CASE (NOTXORPEN, 0x00990066);
+ CASE (NOP, 0x00AA0029);
+ CASE (MERGENOTPEN, MERGEPAINT);
+ CASE (COPYPEN, SRCCOPY);
+ CASE (MERGEPENNOT, 0x00DD0228);
+ CASE (MERGEPEN, SRCPAINT);
+ CASE (WHITE, WHITENESS);
+#undef CASE
+ default: return SRCCOPY;
+ }
+}
+
+static int
+rop2_to_patblt_rop (int rop2)
+{
+ switch (rop2)
+ {
+#define CASE(rop2,patblt_rop) case R2_##rop2: return patblt_rop
+ CASE (COPYPEN, PATCOPY);
+ CASE (XORPEN, PATINVERT);
+ CASE (NOT, DSTINVERT);
+ CASE (BLACK, BLACKNESS);
+ CASE (WHITE, WHITENESS);
+#undef CASE
+ default:
+ g_warning ("Unhandled rop2 in GC to be used in PatBlt: %#x", rop2);
+ return PATCOPY;
+ }
+}
+
+static inline int
+align_with_dash_offset (int a, DWORD *dashes, int num_dashes, GdkGCWin32 *gcwin32)
+{
+ int n = 0;
+ int len_sum = 0;
+ /*
+ * We can't simply add the dashoffset, it can be an arbitrary larger
+ * or smaller value not even between x1 and x2. It just says use the
+ * dash pattern aligned to the offset. So ensure x1 is smaller _x1
+ * and we start with the appropriate dash.
+ */
+ for (n = 0; n < num_dashes; n++)
+ len_sum += dashes[n];
+ if ( len_sum > 0 /* pathological api usage? */
+ && gcwin32->pen_dash_offset > a)
+ a -= (((gcwin32->pen_dash_offset/len_sum - a/len_sum) + 1) * len_sum);
+ else
+ a = gcwin32->pen_dash_offset;
+
+ return a;
+}
+
+/* Render a dashed line 'by hand'. Used for all dashes on Win9x (where
+ * GDI is way too limited), and for double dashes on all Windowses.
*/
static inline gboolean
-render_line_horizontal (HDC hdc,
- int x1,
- int x2,
- int y,
- int pen_width,
- DWORD *dashes,
- int num_dashes)
+render_line_horizontal (GdkGCWin32 *gcwin32,
+ int x1,
+ int x2,
+ int y)
{
- int n;
+ int n = 0;
+ const int pen_width = MAX (gcwin32->pen_width, 1);
+ const int _x1 = x1;
+
+ g_assert (gcwin32->pen_dashes);
+
+ x1 = align_with_dash_offset (x1, gcwin32->pen_dashes, gcwin32->pen_num_dashes, gcwin32);
for (n = 0; x1 < x2; n++)
{
- int len = dashes[n % num_dashes];
+ int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
if (x1 + len > x2)
len = x2 - x1;
- if (n % 2 == 0)
- if (!GDI_CALL (PatBlt, (hdc, x1, y - pen_width / 2,
+ if (n % 2 == 0 && x1 + len > _x1)
+ if (!GDI_CALL (PatBlt, (gcwin32->hdc,
+ x1 < _x1 ? _x1 : x1,
+ y - pen_width / 2,
len, pen_width,
- PATCOPY)))
+ rop2_to_patblt_rop (gcwin32->rop2))))
return FALSE;
- x1 += dashes[n % num_dashes];
+ x1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
+ }
+
+ if (gcwin32->line_style == GDK_LINE_DOUBLE_DASH)
+ {
+ HBRUSH hbr;
+
+ if ((hbr = SelectObject (gcwin32->hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR)
+ return FALSE;
+ x1 = _x1;
+ x1 += gcwin32->pen_dash_offset;
+ for (n = 0; x1 < x2; n++)
+ {
+ int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
+ if (x1 + len > x2)
+ len = x2 - x1;
+
+ if (n % 2)
+ if (!GDI_CALL (PatBlt, (gcwin32->hdc, x1, y - pen_width / 2,
+ len, pen_width,
+ rop2_to_patblt_rop (gcwin32->rop2))))
+ return FALSE;
+
+ x1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
+ }
+ if (SelectObject (gcwin32->hdc, hbr) == HGDI_ERROR)
+ return FALSE;
}
return TRUE;
}
static inline gboolean
-render_line_vertical (HDC hdc,
- int x,
- int y1,
- int y2,
- int pen_width,
- DWORD *dashes,
- int num_dashes)
+render_line_vertical (GdkGCWin32 *gcwin32,
+ int x,
+ int y1,
+ int y2)
{
int n;
+ const int pen_width = MAX (gcwin32->pen_width, 1);
+ const int _y1 = y1;
+
+ g_assert (gcwin32->pen_dashes);
+ y1 = align_with_dash_offset (y1, gcwin32->pen_dashes, gcwin32->pen_num_dashes, gcwin32);
for (n = 0; y1 < y2; n++)
{
- int len = dashes[n % num_dashes];
+ int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
if (y1 + len > y2)
len = y2 - y1;
- if (n % 2 == 0)
- if (!GDI_CALL (PatBlt, (hdc, x - pen_width / 2, y1,
+ if (n % 2 == 0 && y1 + len > _y1)
+ if (!GDI_CALL (PatBlt, (gcwin32->hdc, x - pen_width / 2,
+ y1 < _y1 ? _y1 : y1,
pen_width, len,
- PATCOPY)))
+ rop2_to_patblt_rop (gcwin32->rop2))))
return FALSE;
- y1 += dashes[n % num_dashes];
+ y1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
+ }
+
+ if (gcwin32->line_style == GDK_LINE_DOUBLE_DASH)
+ {
+ HBRUSH hbr;
+
+ if ((hbr = SelectObject (gcwin32->hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR)
+ return FALSE;
+ y1 = _y1;
+ y1 += gcwin32->pen_dash_offset;
+ for (n = 0; y1 < y2; n++)
+ {
+ int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
+ if (y1 + len > y2)
+ len = y2 - y1;
+ if (n % 2)
+ if (!GDI_CALL (PatBlt, (gcwin32->hdc, x - pen_width / 2, y1,
+ pen_width, len,
+ rop2_to_patblt_rop (gcwin32->rop2))))
+ return FALSE;
+
+ y1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
+ }
+ if (SelectObject (gcwin32->hdc, hbr) == HGDI_ERROR)
+ return FALSE;
}
return TRUE;
{
gint x, y;
- GDK_NOTE (MISC, g_print ("draw_tiles_lowlevel: %p +%d+%d tile=%p:%dx%d@+%d+%d %dx%d\n",
+ GDK_NOTE (MISC, g_print ("draw_tiles_lowlevel: %p %+d%+d tile=%p:%dx%d@%+d%+d %dx%d\n",
dest,
dest_x, dest_y,
tile, tile_width, tile_height,
gdk_gc_unref (gc_copy);
}
-static int
-rop2_to_rop3 (int rop2)
-{
- switch (rop2)
- {
- /* Oh, Microsoft's silly names for binary and ternary rops. */
-#define CASE(rop2,rop3) case R2_##rop2: return rop3
- CASE (BLACK, BLACKNESS);
- CASE (NOTMERGEPEN, NOTSRCERASE);
- CASE (MASKNOTPEN, 0x00220326);
- CASE (NOTCOPYPEN, NOTSRCCOPY);
- CASE (MASKPENNOT, SRCERASE);
- CASE (NOT, DSTINVERT);
- CASE (XORPEN, SRCINVERT);
- CASE (NOTMASKPEN, 0x007700E6);
- CASE (MASKPEN, SRCAND);
- CASE (NOTXORPEN, 0x00990066);
- CASE (NOP, 0x00AA0029);
- CASE (MERGENOTPEN, MERGEPAINT);
- CASE (COPYPEN, SRCCOPY);
- CASE (MERGEPENNOT, 0x00DD0228);
- CASE (MERGEPEN, SRCPAINT);
- CASE (WHITE, WHITENESS);
-#undef CASE
- default: return SRCCOPY;
- }
-}
-
static void
generic_draw (GdkDrawable *drawable,
GdkGC *gc,
GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc);
HDC hdc;
va_list args;
+ GdkFill fill_style = _gdk_gc_get_fill (gc);
va_start (args, region);
*/
if (gcwin32->values_mask & GDK_GC_FILL &&
- ((gcwin32->fill_style == GDK_TILED &&
+ ((fill_style == GDK_TILED &&
gcwin32->values_mask & GDK_GC_TILE &&
- gcwin32->tile != NULL)
+ _gdk_gc_get_tile (gc) != NULL)
||
- ((gcwin32->fill_style == GDK_OPAQUE_STIPPLED ||
- gcwin32->fill_style == GDK_STIPPLED) &&
+ ((fill_style == GDK_OPAQUE_STIPPLED ||
+ fill_style == GDK_STIPPLED) &&
gcwin32->values_mask & GDK_GC_STIPPLE &&
- gcwin32->stipple != NULL)))
+ _gdk_gc_get_stipple (gc) != NULL)))
{
const GdkGCValuesMask blitting_mask = 0;
GdkGCValuesMask drawing_mask = GDK_GC_FOREGROUND;
region->extents.x1, region->extents.y1, args);
gdk_win32_hdc_release (mask_pixmap, mask_gc, drawing_mask);
- if (gcwin32->fill_style == GDK_TILED)
+ if (fill_style == GDK_TILED)
{
/* Tile pixmap with tile */
draw_tiles (tile_pixmap, tile_gc, SRCCOPY,
- gcwin32->tile,
+ _gdk_gc_get_tile (gc),
0, 0, ts_x_origin, ts_y_origin,
width, height);
}
/* Tile stipple bitmap */
draw_tiles (stipple_bitmap, stipple_gc, SRCCOPY,
- gcwin32->stipple,
+ _gdk_gc_get_stipple (gc),
0, 0, ts_x_origin, ts_y_origin,
width, height);
- if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
+ if (fill_style == GDK_OPAQUE_STIPPLED)
{
/* Fill tile pixmap with background */
- fg.pixel = gcwin32->background;
+ fg.pixel = _gdk_gc_get_bg_pixel (gc);
gdk_gc_set_foreground (tile_gc, &fg);
gdk_draw_rectangle (tile_pixmap, tile_gc, TRUE,
0, 0, width, height);
if ((old_tile_hbm = SelectObject (tile_hdc, GDK_PIXMAP_HBITMAP (tile_pixmap))) == NULL)
WIN32_GDI_FAILED ("SelectObject");
- if (gcwin32->fill_style == GDK_STIPPLED ||
- gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
+ if (fill_style == GDK_STIPPLED ||
+ fill_style == GDK_OPAQUE_STIPPLED)
{
HDC stipple_hdc;
HGDIOBJ old_stipple_hbm;
if ((fg_brush = CreateSolidBrush
(_gdk_win32_colormap_color (impl->colormap,
- gcwin32->foreground))) == NULL)
+ _gdk_gc_get_fg_pixel (gc)))) == NULL)
WIN32_GDI_FAILED ("CreateSolidBrush");
if ((old_tile_brush = SelectObject (tile_hdc, fg_brush)) == NULL)
GDI_CALL (BitBlt, (tile_hdc, 0, 0, width, height,
stipple_hdc, 0, 0, ROP3_DSPDxax));
- if (gcwin32->fill_style == GDK_STIPPLED)
+ if (fill_style == GDK_STIPPLED)
{
/* Punch holes in mask where stipple is zero */
GDI_CALL (BitBlt, (mask_hdc, 0, 0, width, height,
x -= x_offset;
y -= y_offset;
- if (!filled && gcwin32->pen_dashes && !G_WIN32_IS_NT_BASED ())
+ if (!filled && MUST_RENDER_DASHES_MANUALLY (gcwin32))
{
- render_line_vertical (hdc, x, y, y+height+1,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes) &&
- render_line_horizontal (hdc, x, x+width+1, y,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes) &&
- render_line_vertical (hdc, x+width+1, y, y+height+1,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes) &&
- render_line_horizontal (hdc, x, x+width+1, y+height+1,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes);
+ render_line_vertical (gcwin32, x, y, y+height+1) &&
+ render_line_horizontal (gcwin32, x, x+width+1, y) &&
+ render_line_vertical (gcwin32, x+width+1, y, y+height+1) &&
+ render_line_horizontal (gcwin32, x, x+width+1, y+height+1);
}
else
{
GdkRectangle bounds;
GdkRegion *region;
- GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %s (%p) %s%dx%d@+%d+%d\n",
+ GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %s (%p) %s%dx%d@%+d%+d\n",
_gdk_win32_drawable_description (drawable),
gc,
(filled ? "fill " : ""),
region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
generic_draw (drawable, gc,
- GDK_GC_FOREGROUND | (filled ? 0 : LINE_ATTRIBUTES),
+ GDK_GC_FOREGROUND | GDK_GC_BACKGROUND |
+ (filled ? 0 : LINE_ATTRIBUTES),
draw_rectangle, region, filled, x, y, width, height);
gdk_region_destroy (region);
if (filled)
{
old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
- GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
- x, y, x+width, y+height,
- nXStartArc, nYStartArc,
- nXEndArc, nYEndArc));
+ GDK_NOTE (MISC, g_print ("... Pie(%p,%d,%d,%d,%d,%d,%d,%d,%d)\n",
+ hdc, x, y, x+width, y+height,
+ nXStartArc, nYStartArc, nXEndArc, nYEndArc));
GDI_CALL (Pie, (hdc, x, y, x+width, y+height,
nXStartArc, nYStartArc, nXEndArc, nYEndArc));
GDI_CALL (SelectObject, (hdc, old_pen));
}
else
{
- GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
- x, y, x+width, y+height,
- nXStartArc, nYStartArc,
- nXEndArc, nYEndArc));
+ GDK_NOTE (MISC, g_print ("... Arc(%p,%d,%d,%d,%d,%d,%d,%d,%d)\n",
+ hdc, x, y, x+width, y+height,
+ nXStartArc, nYStartArc, nXEndArc, nYEndArc));
GDI_CALL (Arc, (hdc, x, y, x+width, y+height,
nXStartArc, nYStartArc, nXEndArc, nYEndArc));
}
}
}
- if (gcwin32->pen_dashes && !G_WIN32_IS_NT_BASED ())
+ if (MUST_RENDER_DASHES_MANUALLY (gcwin32))
{
for (i = 0; i < nsegs; i++)
{
else
y1 = segs[i].y2, y2 = segs[i].y1;
- render_line_vertical (hdc,
- segs[i].x1, y1, y2,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes);
+ render_line_vertical (gcwin32, segs[i].x1, y1, y2);
}
else if (segs[i].y1 == segs[i].y2)
{
else
x1 = segs[i].x2, x2 = segs[i].x1;
- render_line_horizontal (hdc,
- x1, x2, segs[i].y1,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes);
+ render_line_horizontal (gcwin32, x1, x2, segs[i].y1);
}
else
GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2));
-
}
}
else
{
for (i = 0; i < nsegs; i++)
- GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
- GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2));
-
- /* not drawing the end pixel does produce a crippled mask, look
- * e.g. at xpm icons produced with gdk_pixbuf_new_from_xpm_data trough
- * gdk_pixbuf_render_threshold_alpha (testgtk folder icon or
- * Dia's toolbox icons) but only on win9x ... --hb
- *
- * Update : see bug #81895 and bug #126710 why this is finally
- * needed on any win32 platform ;-)
- */
- if (gcwin32->pen_width <= 1)
- {
- GdkSegment *ps = &segs[nsegs-1];
- int xc = 0, yc = 0;
-
- if (ps->y2 == ps->y1 && ps->x2 == ps->x1)
- xc = 1; /* just a point */
- else if (ps->y2 == ps->y1)
- xc = (ps->x1 < ps->x2) ? 1 : -1; /* advance x only */
- else if (ps->x2 == ps->x1)
- yc = (ps->y1 < ps->y2) ? 1 : -1; /* advance y only */
- else
- {
- xc = (ps->x1 < ps->x2) ? 1 : -1;
- yc = (ps->y1 < ps->y2) ? 1 : -1;
- }
-
- GDI_CALL (LineTo, (hdc, ps->x2 + xc, ps->y2 + yc));
- }
+ {
+ const GdkSegment *ps = &segs[i];
+ const int x1 = ps->x1, y1 = ps->y1;
+ int x2 = ps->x2, y2 = ps->y2;
+
+ GDK_NOTE (MISC, g_print (" +%d+%d..+%d+%d", x1, y1, x2, y2));
+ GDI_CALL (MoveToEx, (hdc, x1, y1, NULL)) &&
+ GDI_CALL (LineTo, (hdc, x2, y2));
+ }
+
+ GDK_NOTE (MISC, g_print ("\n"));
}
if (x_offset != 0 || y_offset != 0)
g_free (segs);
region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
- generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
+ generic_draw (drawable, gc, GDK_GC_FOREGROUND | LINE_ATTRIBUTES,
draw_segments, region, segs, nsegs);
gdk_region_destroy (region);
pts[i].y -= y_offset;
}
- if (gcwin32->pen_dashes && !G_WIN32_IS_NT_BASED ())
+ if (MUST_RENDER_DASHES_MANUALLY (gcwin32))
{
for (i = 0; i < npoints - 1; i++)
{
else
y1 = pts[i].y, y2 = pts[i+1].y;
- render_line_vertical (hdc, pts[i].x, y1, y2,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes);
+ render_line_vertical (gcwin32, pts[i].x, y1, y2);
}
else if (pts[i].y == pts[i+1].y)
{
else
x1 = pts[i].x, x2 = pts[i+1].x;
- render_line_horizontal (hdc, x1, x2, pts[i].y,
- gcwin32->pen_width,
- gcwin32->pen_dashes,
- gcwin32->pen_num_dashes);
+ render_line_horizontal (gcwin32, x1, x2, pts[i].y);
}
else
GDI_CALL (MoveToEx, (hdc, pts[i].x, pts[i].y, NULL)) &&
region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
- generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
+ generic_draw (drawable, gc, GDK_GC_FOREGROUND | GDK_GC_BACKGROUND |
+ LINE_ATTRIBUTES,
draw_lines, region, pts, npoints);
gdk_region_destroy (region);
g_free (pts);
}
-static void
-draw_glyphs (GdkGCWin32 *gcwin32,
- HDC hdc,
- gint x_offset,
- gint y_offset,
- va_list args)
-{
- PangoFont *font;
- gint x;
- gint y;
- PangoGlyphString *glyphs;
-
- font = va_arg (args, PangoFont *);
- x = va_arg (args, gint);
- y = va_arg (args, gint);
- glyphs = va_arg (args, PangoGlyphString *);
-
- x -= x_offset;
- y -= y_offset;
-
- pango_win32_render (hdc, font, glyphs, x, y);
-}
-
-static void
-draw_glyphs_transformed (GdkGCWin32 *gcwin32,
- HDC hdc,
- gint x_offset,
- gint y_offset,
- va_list args)
-{
- PangoFont *font;
- gint x;
- gint y;
- PangoGlyphString *glyphs;
- PangoMatrix *matrix;
-
- matrix = va_arg(args, PangoMatrix *);
- font = va_arg (args, PangoFont *);
- x = va_arg (args, gint);
- y = va_arg (args, gint);
- glyphs = va_arg (args, PangoGlyphString *);
-
- x -= x_offset;
- y -= y_offset;
-
- pango_win32_render_transformed (hdc, matrix, font, glyphs, x, y);
-}
-
-static void
-gdk_win32_draw_glyphs (GdkDrawable *drawable,
- GdkGC *gc,
- PangoFont *font,
- gint x,
- gint y,
- PangoGlyphString *glyphs)
-{
- GdkRectangle bounds;
- GdkRegion *region;
- PangoRectangle ink_rect;
-
- pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
-
- bounds.x = x + PANGO_PIXELS (ink_rect.x) - 1;
- bounds.y = y + PANGO_PIXELS (ink_rect.y) - 1;
- bounds.width = PANGO_PIXELS (ink_rect.width) + 2;
- bounds.height = PANGO_PIXELS (ink_rect.height) + 2;
- region = gdk_region_rectangle (&bounds);
-
- generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_FONT,
- draw_glyphs, region, font, x, y, glyphs);
-
- gdk_region_destroy (region);
-}
-
-static void
-gdk_win32_draw_glyphs_transformed (GdkDrawable *drawable,
- GdkGC *gc,
- PangoMatrix *matrix,
- PangoFont *font,
- gint x,
- gint y,
- PangoGlyphString *glyphs)
-{
- GdkRectangle bounds;
- GdkRegion *region;
- PangoRectangle ink_rect;
-
- pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
-
- bounds.x = x + PANGO_PIXELS (ink_rect.x) - 1;
- bounds.y = y + PANGO_PIXELS (ink_rect.y) - 1;
- bounds.width = PANGO_PIXELS (ink_rect.width) + 2;
- bounds.height = PANGO_PIXELS (ink_rect.height) + 2;
- region = gdk_region_rectangle (&bounds);
-
- if (matrix)
- {
- /* transform region */
- bounds.x = bounds.x * matrix->xx + bounds.y * matrix->xy + matrix->x0;
- bounds.y = bounds.x * matrix->yx + bounds.y * matrix->yy + matrix->x0;
- bounds.width = bounds.width * matrix->xx + bounds.height * matrix->xy;
- bounds.height = bounds.height * matrix->yx + bounds.width * matrix->xy;
-
- generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_FONT,
- draw_glyphs_transformed, region, matrix, font, x, y, glyphs);
- }
- else
- {
- generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_FONT,
- draw_glyphs, region, font, x/PANGO_SCALE, y/PANGO_SCALE, glyphs);
- }
-
- gdk_region_destroy (region);
-}
-
static void
blit_from_pixmap (gboolean use_fg_bg,
GdkDrawableImplWin32 *dest,
HDC hdc,
GdkPixmapImplWin32 *src,
- GdkGCWin32 *gcwin32,
+ GdkGC *gc,
gint xsrc,
gint ysrc,
gint xdest,
gint width,
gint height)
{
+ GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc);
HDC srcdc;
HBITMAP holdbitmap;
RGBQUAD oldtable[256], newtable[256];
GDK_NOTE (MISC, g_print ("blit_from_pixmap\n"));
- if (!(srcdc = CreateCompatibleDC (NULL)))
- {
- WIN32_GDI_FAILED ("CreateCompatibleDC");
- return;
- }
-
+ srcdc = _gdk_win32_drawable_acquire_dc (GDK_DRAWABLE (src));
+ if (!srcdc)
+ return;
+
if (!(holdbitmap = SelectObject (srcdc, ((GdkDrawableImplWin32 *) src)->handle)))
WIN32_GDI_FAILED ("SelectObject");
else
if (use_fg_bg)
{
- bgix = gcwin32->background;
- fgix = gcwin32->foreground;
+ bgix = _gdk_gc_get_bg_pixel (gc);
+ fgix = _gdk_gc_get_fg_pixel (gc);
}
else
{
GDI_CALL (SelectObject, (srcdc, holdbitmap));
}
- GDI_CALL (DeleteDC, (srcdc));
+
+ _gdk_win32_drawable_release_dc (GDK_DRAWABLE (src));
}
static void
-blit_inside_window (HDC hdc,
- GdkGCWin32 *gcwin32,
- gint xsrc,
- gint ysrc,
- gint xdest,
- gint ydest,
- gint width,
- gint height)
+blit_inside_drawable (HDC hdc,
+ GdkGCWin32 *gcwin32,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
{
- GDK_NOTE (MISC, g_print ("blit_inside_window\n"));
+ GDK_NOTE (MISC, g_print ("blit_inside_drawable\n"));
GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
void
_gdk_win32_blit (gboolean use_fg_bg,
- GdkDrawableImplWin32 *drawable,
+ GdkDrawableImplWin32 *draw_impl,
GdkGC *gc,
GdkDrawable *src,
gint xsrc,
HDC hdc;
HRGN src_rgn, draw_rgn, outside_rgn;
RECT r;
- GdkDrawableImplWin32 *draw_impl;
GdkDrawableImplWin32 *src_impl = NULL;
gint src_width, src_height;
- GDK_NOTE (MISC, g_print ("_gdk_win32_blit: src:%s %dx%d@+%d+%d\n"
- " dst:%s @+%d+%d use_fg_bg=%d\n",
+ GDK_NOTE (MISC, g_print ("_gdk_win32_blit: src:%s %dx%d@%+d%+d\n"
+ " dst:%s @%+d%+d use_fg_bg=%d\n",
_gdk_win32_drawable_description (src),
width, height, xsrc, ysrc,
- _gdk_win32_drawable_description ((GdkDrawable *) drawable),
+ _gdk_win32_drawable_description (&draw_impl->parent_instance),
xdest, ydest,
use_fg_bg));
- draw_impl = (GdkDrawableImplWin32 *) drawable;
+ /* If blitting from the root window, take the multi-monitor offset
+ * into account.
+ */
+ if (src == ((GdkWindowObject *)_gdk_root)->impl)
+ {
+ GDK_NOTE (MISC, g_print ("... offsetting src coords\n"));
+ xsrc -= _gdk_offset_x;
+ ysrc -= _gdk_offset_y;
+ }
if (GDK_IS_DRAWABLE_IMPL_WIN32 (src))
src_impl = (GdkDrawableImplWin32 *) src;
else
g_assert_not_reached ();
- hdc = gdk_win32_hdc_get ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
+ hdc = gdk_win32_hdc_get (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND);
gdk_drawable_get_size (src, &src_width, &src_height);
{
OffsetRgn (outside_rgn, xdest, ydest);
GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
- g_print ("...calling InvalidateRgn, "
- "bbox: %ldx%ld@+%ld+%ld\n",
+ g_print ("... InvalidateRgn "
+ "bbox: %ldx%ld@%+ld%+ld\n",
r.right - r.left - 1, r.bottom - r.top - 1,
r.left, r.top)));
InvalidateRgn (draw_impl->handle, outside_rgn, TRUE);
width = r.right - xsrc - 1;
height = r.bottom - ysrc - 1;
- GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
- "dest: @+%d+%d\n",
+ GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@%+d%+d, "
+ "dest: @%+d%+d\n",
width, height, xsrc, ysrc,
xdest, ydest));
}
GDI_CALL (DeleteObject, (draw_rgn));
}
- if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
+ if (draw_impl->handle == src_impl->handle)
+ blit_inside_drawable (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
+ else if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
blit_from_pixmap (use_fg_bg, draw_impl, hdc,
- (GdkPixmapImplWin32 *) src_impl, GDK_GC_WIN32 (gc),
+ (GdkPixmapImplWin32 *) src_impl, gc,
xsrc, ysrc, xdest, ydest, width, height);
- else if (draw_impl->handle == src_impl->handle)
- blit_inside_window (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
else
blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
- gdk_win32_hdc_release ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
+ gdk_win32_hdc_release (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND);
}
static void
xsrc, ysrc, xdest, ydest, width, height);
}
+/**
+ * _gdk_win32_drawable_acquire_dc
+ * @drawable: a Win32 #GdkDrawable implementation
+ *
+ * Gets a DC with the given drawable selected into
+ * it.
+ *
+ * Return value: The DC, on success. Otherwise
+ * %NULL. If this function succeeded
+ * _gdk_win32_drawable_release_dc() must be called
+ * release the DC when you are done using it.
+ **/
+HDC
+_gdk_win32_drawable_acquire_dc (GdkDrawable *drawable)
+{
+ GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
+
+ if (GDK_IS_WINDOW_IMPL_WIN32 (drawable) &&
+ GDK_WINDOW_DESTROYED (impl->wrapper))
+ return NULL;
+
+ if (!impl->hdc)
+ {
+ if (GDK_IS_PIXMAP_IMPL_WIN32 (impl))
+ {
+ impl->hdc = CreateCompatibleDC (NULL);
+ if (!impl->hdc)
+ WIN32_GDI_FAILED ("CreateCompatibleDC");
+
+ if (impl->hdc)
+ {
+ impl->saved_dc_bitmap = SelectObject (impl->hdc,
+ impl->handle);
+ if (!impl->saved_dc_bitmap)
+ {
+ WIN32_GDI_FAILED ("CreateCompatibleDC");
+ DeleteDC (impl->hdc);
+ impl->hdc = NULL;
+ }
+ }
+ }
+ else
+ {
+ impl->hdc = GetDC (impl->handle);
+ if (!impl->hdc)
+ WIN32_GDI_FAILED ("GetDC");
+ }
+ }
+
+ if (impl->hdc)
+ {
+ impl->hdc_count++;
+ return impl->hdc;
+ }
+ else
+ return NULL;
+}
+
+/**
+ * _gdk_win32_drawable_release_dc
+ * @drawable: a Win32 #GdkDrawable implementation
+ *
+ * Releases the reference count for the DC
+ * from _gdk_win32_drawable_acquire_dc()
+ **/
+void
+_gdk_win32_drawable_release_dc (GdkDrawable *drawable)
+{
+ GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
+
+ g_return_if_fail (impl->hdc_count > 0);
+
+ impl->hdc_count--;
+ if (impl->hdc_count == 0)
+ {
+ if (impl->saved_dc_bitmap)
+ {
+ GDI_CALL (SelectObject, (impl->hdc, impl->saved_dc_bitmap));
+ impl->saved_dc_bitmap = NULL;
+ }
+
+ if (impl->hdc)
+ {
+ GDI_CALL (DeleteDC, (impl->hdc));
+ impl->hdc = NULL;
+ }
+ }
+}
+
+static void
+gdk_win32_cairo_surface_destroy (void *data)
+{
+ GdkDrawableImplWin32 *impl = data;
+
+ _gdk_win32_drawable_release_dc (GDK_DRAWABLE (impl));
+ impl->cairo_surface = NULL;
+}
+
+static cairo_surface_t *
+gdk_win32_ref_cairo_surface (GdkDrawable *drawable)
+{
+ GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
+
+ if (GDK_IS_WINDOW_IMPL_WIN32 (drawable) &&
+ GDK_WINDOW_DESTROYED (impl->wrapper))
+ return NULL;
+
+ if (!impl->cairo_surface)
+ {
+ HDC hdc = _gdk_win32_drawable_acquire_dc (drawable);
+ if (!hdc)
+ return NULL;
+
+ impl->cairo_surface = cairo_win32_surface_create (hdc);
+
+ cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
+ drawable, gdk_win32_cairo_surface_destroy);
+ }
+ else
+ cairo_surface_reference (impl->cairo_surface);
+
+ return impl->cairo_surface;
+}
+
static gint
gdk_win32_get_depth (GdkDrawable *drawable)
{
return GDK_DRAWABLE_HANDLE (drawable);
}
-gboolean
-gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable,
- gint x,
- gint y,
- gint width,
- gint height,
- GdkColor *color,
- guint16 alpha)
+/**
+ * _gdk_win32_drawable_finish
+ * @drawable: a Win32 #GdkDrawable implementation
+ *
+ * Releases any resources allocated internally for the drawable.
+ * This is called when the drawable becomes unusable
+ * (gdk_window_destroy() for a window, or the refcount going to
+ * zero for a pixmap.)
+ **/
+void
+_gdk_win32_drawable_finish (GdkDrawable *drawable)
{
- return FALSE;
+ GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
+
+ if (impl->cairo_surface)
+ {
+ cairo_surface_finish (impl->cairo_surface);
+ cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
+ NULL, NULL);
+ }
+
+ g_assert (impl->hdc_count == 0);
}
+