diff --git a/ChangeLog b/ChangeLog index 95bf48c129..730c7586e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +2005-04-28 Owen Taylor + + * gtk/gtkwidget.c: Add a draw-border style property to allow + themes to draw outside the widget's allocation. + + * gdk/gdkwindow.c gtk/gtkstyle.c: Remove some save/restore pairs + that were working around the clip-leakage bug in Cairo. + + * gtk/gtkstyle.c: Use cairo_fill_preserve() rathe than + save/fill/restore. + + * gdk/gdkgc.c gdk/gdkinternals.h: Add _gdk_gc_update_context() + That updates a Cairo context to match a GC. + + * gdk/gdkdraw.c: Use _gdk_gc_update_context() to add support + for tiles/stipples/clipping to gdk_draw_glyphs(), + gdk_draw_trapezoids(). + + * gdk/gdkpango.c: Use _gdk_gc_update_context() instead of internal + implementation of stipples. Use one cairo_t across the entire + drawing operation. Replace cairo_matrix_create() with + stack-allocated matrices. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c: Save various aspects of the + GC state (fill, tile, stipple, foreground, background, clip region) + in instance-private-data for future use. Add getters. + Get rid of _gdk_windowing_gc_get_foreground() function implemented + by the backends. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Add + _gdk_gc_init() to do initial setup of the GC from values; + fixes some problems from drawable redirection. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Move + gdk_gc_copy() and gdk_gc_set_clip_{region,rectangle}() into + the generic code, add _gdk_windowing_gc_copy(), + _gdk_windowing_gc_set_clip_region() to do backend specific + stuff. + + * gdk/x11/{gdkprivate-x11.h,gdkgc-x11.c.c,gdkdrawable-x11.c} + gdk/win32/{gdkprivate-win32.h,gdkgc-x11.c.c,gdkdrawable-x11.c} + gdk/linux-fb/{gdkprivate-fb.h,gdkgc-fb.c.c,gdkdrawable-fb.c}: + Don't duplicate state that now is stored by the generic code. + + * gdk/gdk.symbols Update + 2005-05-02 Matthias Clasen * tests/testiconview.c: Test cell renderers. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 95bf48c129..730c7586e6 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,52 @@ +2005-04-28 Owen Taylor + + * gtk/gtkwidget.c: Add a draw-border style property to allow + themes to draw outside the widget's allocation. + + * gdk/gdkwindow.c gtk/gtkstyle.c: Remove some save/restore pairs + that were working around the clip-leakage bug in Cairo. + + * gtk/gtkstyle.c: Use cairo_fill_preserve() rathe than + save/fill/restore. + + * gdk/gdkgc.c gdk/gdkinternals.h: Add _gdk_gc_update_context() + That updates a Cairo context to match a GC. + + * gdk/gdkdraw.c: Use _gdk_gc_update_context() to add support + for tiles/stipples/clipping to gdk_draw_glyphs(), + gdk_draw_trapezoids(). + + * gdk/gdkpango.c: Use _gdk_gc_update_context() instead of internal + implementation of stipples. Use one cairo_t across the entire + drawing operation. Replace cairo_matrix_create() with + stack-allocated matrices. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c: Save various aspects of the + GC state (fill, tile, stipple, foreground, background, clip region) + in instance-private-data for future use. Add getters. + Get rid of _gdk_windowing_gc_get_foreground() function implemented + by the backends. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Add + _gdk_gc_init() to do initial setup of the GC from values; + fixes some problems from drawable redirection. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Move + gdk_gc_copy() and gdk_gc_set_clip_{region,rectangle}() into + the generic code, add _gdk_windowing_gc_copy(), + _gdk_windowing_gc_set_clip_region() to do backend specific + stuff. + + * gdk/x11/{gdkprivate-x11.h,gdkgc-x11.c.c,gdkdrawable-x11.c} + gdk/win32/{gdkprivate-win32.h,gdkgc-x11.c.c,gdkdrawable-x11.c} + gdk/linux-fb/{gdkprivate-fb.h,gdkgc-fb.c.c,gdkdrawable-fb.c}: + Don't duplicate state that now is stored by the generic code. + + * gdk/gdk.symbols Update + 2005-05-02 Matthias Clasen * tests/testiconview.c: Test cell renderers. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 95bf48c129..730c7586e6 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,52 @@ +2005-04-28 Owen Taylor + + * gtk/gtkwidget.c: Add a draw-border style property to allow + themes to draw outside the widget's allocation. + + * gdk/gdkwindow.c gtk/gtkstyle.c: Remove some save/restore pairs + that were working around the clip-leakage bug in Cairo. + + * gtk/gtkstyle.c: Use cairo_fill_preserve() rathe than + save/fill/restore. + + * gdk/gdkgc.c gdk/gdkinternals.h: Add _gdk_gc_update_context() + That updates a Cairo context to match a GC. + + * gdk/gdkdraw.c: Use _gdk_gc_update_context() to add support + for tiles/stipples/clipping to gdk_draw_glyphs(), + gdk_draw_trapezoids(). + + * gdk/gdkpango.c: Use _gdk_gc_update_context() instead of internal + implementation of stipples. Use one cairo_t across the entire + drawing operation. Replace cairo_matrix_create() with + stack-allocated matrices. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c: Save various aspects of the + GC state (fill, tile, stipple, foreground, background, clip region) + in instance-private-data for future use. Add getters. + Get rid of _gdk_windowing_gc_get_foreground() function implemented + by the backends. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Add + _gdk_gc_init() to do initial setup of the GC from values; + fixes some problems from drawable redirection. + + * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c + gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Move + gdk_gc_copy() and gdk_gc_set_clip_{region,rectangle}() into + the generic code, add _gdk_windowing_gc_copy(), + _gdk_windowing_gc_set_clip_region() to do backend specific + stuff. + + * gdk/x11/{gdkprivate-x11.h,gdkgc-x11.c.c,gdkdrawable-x11.c} + gdk/win32/{gdkprivate-win32.h,gdkgc-x11.c.c,gdkdrawable-x11.c} + gdk/linux-fb/{gdkprivate-fb.h,gdkgc-fb.c.c,gdkdrawable-fb.c}: + Don't duplicate state that now is stored by the generic code. + + * gdk/gdk.symbols Update + 2005-05-02 Matthias Clasen * tests/testiconview.c: Test cell renderers. diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index b5904f0960..a7883569be 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -579,11 +579,14 @@ gdk_gc_set_stipple gdk_gc_set_ts_origin gdk_gc_set_clip_origin gdk_gc_set_clip_mask +gdk_gc_set_clip_rectangle +gdk_gc_set_clip_region gdk_gc_set_subwindow gdk_gc_set_exposures gdk_gc_set_line_attributes gdk_gc_set_dashes gdk_gc_offset +gdk_gc_copy gdk_gc_get_colormap gdk_gc_set_colormap gdk_gc_set_rgb_bg_color @@ -593,10 +596,7 @@ gdk_gc_set_rgb_fg_color #if IN_HEADER(__GDK_GC_H__) #if IN_FILE(__GDK_GC_X11_C__) -gdk_gc_copy gdk_gc_get_screen -gdk_gc_set_clip_rectangle -gdk_gc_set_clip_region #endif #endif diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c index c5bd2d8b62..ca0950d2c4 100644 --- a/gdk/gdkdraw.c +++ b/gdk/gdkdraw.c @@ -877,13 +877,10 @@ real_draw_glyphs (GdkDrawable *drawable, gdouble y, PangoGlyphString *glyphs) { - GdkColor color; cairo_t *cr; cr = gdk_drawable_create_cairo_context (drawable); - - _gdk_windowing_gc_get_foreground (gc, &color); - gdk_cairo_set_source_color (cr, &color); + _gdk_gc_update_context (gc, cr, NULL, NULL); if (matrix) { @@ -999,7 +996,6 @@ gdk_draw_trapezoids (GdkDrawable *drawable, GdkTrapezoid *trapezoids, gint n_trapezoids) { - GdkColor color; cairo_t *cr; int i; @@ -1008,10 +1004,8 @@ gdk_draw_trapezoids (GdkDrawable *drawable, g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL); cr = gdk_drawable_create_cairo_context (drawable); + _gdk_gc_update_context (gc, cr, NULL, NULL); - _gdk_windowing_gc_get_foreground (gc, &color); - gdk_cairo_set_source_color (cr, &color); - for (i = 0; i < n_trapezoids; i++) { cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1); diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c index c51b433383..50179d4110 100644 --- a/gdk/gdkgc.c +++ b/gdk/gdkgc.c @@ -28,52 +28,56 @@ #include #include "gdkgc.h" +#include "gdkinternals.h" +#include "gdkpixmap.h" +#include "gdkregion-generic.h" #include "gdkrgb.h" #include "gdkprivate.h" #include "gdkalias.h" -static void gdk_gc_class_init (GObjectClass *class); static void gdk_gc_finalize (GObject *object); -static GObjectClass *parent_class; +typedef struct _GdkGCPrivate GdkGCPrivate; -GType -gdk_gc_get_type (void) +struct _GdkGCPrivate { - static GType object_type = 0; + GdkRegion *clip_region; - if (!object_type) - { - static const GTypeInfo object_info = - { - sizeof (GdkGCClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gdk_gc_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GdkGC), - 0, /* n_preallocs */ - (GInstanceInitFunc) NULL, - }; - - object_type = g_type_register_static (G_TYPE_OBJECT, - "GdkGC", - &object_info, - G_TYPE_FLAG_ABSTRACT); - } + GdkFill fill; + GdkBitmap *stipple; + GdkPixmap *tile; - return object_type; + guint32 fg_pixel; + guint32 bg_pixel; +}; + +#define GDK_GC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_GC, GdkGCPrivate)) + +G_DEFINE_TYPE (GdkGC, gdk_gc, G_TYPE_OBJECT); + +static void +gdk_gc_class_init (GdkGCClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = gdk_gc_finalize; + + g_type_class_add_private (object_class, sizeof (GdkGCPrivate)); } static void -gdk_gc_class_init (GObjectClass *class) +gdk_gc_init (GdkGC *gc) { - parent_class = g_type_class_peek_parent (class); - - class->finalize = gdk_gc_finalize; -} + GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); + priv->fill = GDK_SOLID; + + /* These are the default X11 value, which we match. They are clearly + * wrong for TrueColor displays, so apps have to change them. + */ + priv->fg_pixel = 0; + priv->bg_pixel = 1; +} /** * gdk_gc_new: @@ -109,17 +113,39 @@ gdk_gc_new_with_values (GdkDrawable *drawable, GdkGCValues *values, GdkGCValuesMask values_mask) { - GdkGC *gc; - g_return_val_if_fail (drawable != NULL, NULL); - gc = GDK_DRAWABLE_GET_CLASS (drawable)->create_gc (drawable, - values, - values_mask); + return GDK_DRAWABLE_GET_CLASS (drawable)->create_gc (drawable, + values, + values_mask); +} + +/** + * _gdk_gc_init: + * @gc: a #GdkGC + * @drawable: a #GdkDrawable. + * @values: a structure containing initial values for the GC. + * @values_mask: a bit mask indicating which fields in @values + * are set. + * + * Does initialization of the generic portions of a #GdkGC + * created with the specified values and values_mask. This + * should be called out of the implementation of + * GdkDrawable.create_gc() immediately after creating the + * #GdkGC object. + **/ +void +_gdk_gc_init (GdkGC *gc, + GdkDrawable *drawable, + GdkGCValues *values, + GdkGCValuesMask values_mask) +{ + GdkGCPrivate *priv; + + g_return_if_fail (GDK_IS_GC (gc)); + + priv = GDK_GC_GET_PRIVATE (gc); - if (gc == NULL) /* This would mean the drawable was destroyed. */ - return NULL; - if (values_mask & GDK_GC_CLIP_X_ORIGIN) gc->clip_x_origin = values->clip_x_origin; if (values_mask & GDK_GC_CLIP_Y_ORIGIN) @@ -128,29 +154,42 @@ gdk_gc_new_with_values (GdkDrawable *drawable, gc->ts_x_origin = values->ts_x_origin; if (values_mask & GDK_GC_TS_Y_ORIGIN) gc->ts_y_origin = values->ts_y_origin; - - /* gc->colormap will already be set if gdk_gc_new_with_values() - * recurses - as in GdkPixmap => impl object. - */ - if (!gc->colormap) + if (values_mask & GDK_GC_FILL) + priv->fill = values->fill; + if (values_mask & GDK_GC_STIPPLE) { - gc->colormap = gdk_drawable_get_colormap (drawable); - if (gc->colormap) - g_object_ref (gc->colormap); + priv->stipple = values->stipple; + if (priv->stipple) + g_object_ref (priv->stipple); } - - return gc; + if (values_mask & GDK_GC_TILE) + { + priv->tile = values->tile; + if (priv->tile) + g_object_ref (priv->tile); + } + if (values_mask & GDK_GC_FOREGROUND) + priv->fg_pixel = values->foreground.pixel; + if (values_mask & GDK_GC_BACKGROUND) + priv->bg_pixel = values->background.pixel; + + gc->colormap = gdk_drawable_get_colormap (drawable); + if (gc->colormap) + g_object_ref (gc->colormap); } static void gdk_gc_finalize (GObject *object) { GdkGC *gc = GDK_GC (object); + GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); + if (priv->clip_region) + gdk_region_destroy (priv->clip_region); if (gc->colormap) g_object_unref (gc->colormap); - parent_class->finalize (object); + G_OBJECT_CLASS (gdk_gc_parent_class)->finalize (object); } /** @@ -219,9 +258,13 @@ gdk_gc_set_values (GdkGC *gc, GdkGCValues *values, GdkGCValuesMask values_mask) { + GdkGCPrivate *priv; + g_return_if_fail (GDK_IS_GC (gc)); g_return_if_fail (values != NULL); + priv = GDK_GC_GET_PRIVATE (gc); + if (values_mask & GDK_GC_CLIP_X_ORIGIN) gc->clip_x_origin = values->clip_x_origin; if (values_mask & GDK_GC_CLIP_Y_ORIGIN) @@ -230,6 +273,43 @@ gdk_gc_set_values (GdkGC *gc, gc->ts_x_origin = values->ts_x_origin; if (values_mask & GDK_GC_TS_Y_ORIGIN) gc->ts_y_origin = values->ts_y_origin; + if (values_mask & GDK_GC_CLIP_MASK) + { + GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); + if (priv->clip_region) + { + gdk_region_destroy (priv->clip_region); + priv->clip_region = NULL; + } + } + if (values_mask & GDK_GC_FILL) + priv->fill = values->fill; + if (values_mask & GDK_GC_STIPPLE) + { + if (priv->stipple != values->stipple) + { + if (priv->stipple) + g_object_unref (priv->stipple); + priv->stipple = values->stipple; + if (priv->stipple) + g_object_ref (priv->stipple); + } + } + if (values_mask & GDK_GC_TILE) + { + if (priv->tile != values->tile) + { + if (priv->tile) + g_object_unref (priv->tile); + priv->tile = values->tile; + if (priv->tile) + g_object_ref (priv->tile); + } + } + if (values_mask & GDK_GC_FOREGROUND) + priv->fg_pixel = values->foreground.pixel; + if (values_mask & GDK_GC_BACKGROUND) + priv->bg_pixel = values->background.pixel; GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask); } @@ -459,6 +539,169 @@ gdk_gc_set_clip_mask (GdkGC *gc, gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK); } +static void +_gdk_gc_set_clip_region_internal (GdkGC *gc, + GdkRegion *region) +{ + GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); + + if (priv->clip_region) + gdk_region_destroy (priv->clip_region); + + priv->clip_region = region; + + _gdk_windowing_gc_set_clip_region (gc, region); +} + +/** + * gdk_gc_set_clip_rectangle: + * @gc: a #GdkGC. + * @rectangle: the rectangle to clip to. + * + * Sets the clip mask for a graphics context from a + * rectangle. The clip mask is interpreted relative to the clip + * origin. (See gdk_gc_set_clip_origin()). + **/ +void +gdk_gc_set_clip_rectangle (GdkGC *gc, + GdkRectangle *rectangle) +{ + GdkRegion *region; + + g_return_if_fail (GDK_IS_GC (gc)); + + if (rectangle) + region = gdk_region_rectangle (rectangle); + else + region = NULL; + + _gdk_gc_set_clip_region_internal (gc, region); +} + +/** + * gdk_gc_set_clip_region: + * @gc: a #GdkGC. + * @region: the #GdkRegion. + * + * Sets the clip mask for a graphics context from a region structure. + * The clip mask is interpreted relative to the clip origin. (See + * gdk_gc_set_clip_origin()). + **/ +void +gdk_gc_set_clip_region (GdkGC *gc, + GdkRegion *region) +{ + g_return_if_fail (GDK_IS_GC (gc)); + + if (region) + region = gdk_region_copy (region); + + _gdk_gc_set_clip_region_internal (gc, region); +} + +/** + * _gdk_gc_get_clip_region: + * @gc: a #GdkGC + * + * Gets the current clip region for @gc, if any. + * + * Return value: the clip region for the GC, or %NULL. + * (if a clip mask is set, the return will be %NULL) + * This value is owned by the GC and must not be freed. + **/ +GdkRegion * +_gdk_gc_get_clip_region (GdkGC *gc) +{ + g_return_val_if_fail (GDK_IS_GC (gc), NULL); + + return GDK_GC_GET_PRIVATE (gc)->clip_region; +} + +/** + * _gdk_gc_get_fill: + * @gc: a #GdkGC + * + * Gets the current file style for the GC + * + * Return value: the file style for the GC + **/ +GdkFill +_gdk_gc_get_fill (GdkGC *gc) +{ + g_return_val_if_fail (GDK_IS_GC (gc), GDK_SOLID); + + return GDK_GC_GET_PRIVATE (gc)->fill; +} + +/** + * _gdk_gc_get_tile: + * @gc: a #GdkGC + * + * Gets the tile pixmap for @gc, if any + * + * Return value: the tile set on the GC, or %NULL. The + * value is owned by the GC and must not be freed. + **/ +GdkPixmap * +_gdk_gc_get_tile (GdkGC *gc) +{ + g_return_val_if_fail (GDK_IS_GC (gc), NULL); + + return GDK_GC_GET_PRIVATE (gc)->tile; +} + +/** + * _gdk_gc_get_stipple: + * @gc: a #GdkGC + * + * Gets the stipple pixmap for @gc, if any + * + * Return value: the stipple set on the GC, or %NULL. The + * value is owned by the GC and must not be freed. + **/ +GdkBitmap * +_gdk_gc_get_stipple (GdkGC *gc) +{ + g_return_val_if_fail (GDK_IS_GC (gc), NULL); + + return GDK_GC_GET_PRIVATE (gc)->stipple; +} + +/** + * _gdk_gc_get_fg_pixel: + * @gc: a #GdkGC + * + * Gets the foreground pixel value for @gc. If the + * foreground pixel has never been set, returns the + * default value 0. + * + * Return value: the foreground pixel value of the GC + **/ +guint32 +_gdk_gc_get_fg_pixel (GdkGC *gc) +{ + g_return_val_if_fail (GDK_IS_GC (gc), 0); + + return GDK_GC_GET_PRIVATE (gc)->fg_pixel; +} + +/** + * _gdk_gc_get_bg_pixel: + * @gc: a #GdkGC + * + * Gets the background pixel value for @gc.If the + * foreground pixel has never been set, returns the + * default value 1. + * + * Return value: the foreground pixel value of the GC + **/ +guint32 +_gdk_gc_get_bg_pixel (GdkGC *gc) +{ + g_return_val_if_fail (GDK_IS_GC (gc), 0); + + return GDK_GC_GET_PRIVATE (gc)->bg_pixel; +} /** * gdk_gc_set_subwindow: @@ -598,6 +841,67 @@ gdk_gc_offset (GdkGC *gc, } } +/** + * gdk_gc_copy: + * @dst_gc: the destination graphics context. + * @src_gc: the source graphics context. + * + * Copy the set of values from one graphics context + * onto another graphics context. + **/ +void +gdk_gc_copy (GdkGC *dst_gc, + GdkGC *src_gc) +{ + GdkGCPrivate *dst_priv, *src_priv; + + g_return_if_fail (GDK_IS_GC (dst_gc)); + g_return_if_fail (GDK_IS_GC (src_gc)); + + dst_priv = GDK_GC_GET_PRIVATE (dst_gc); + src_priv = GDK_GC_GET_PRIVATE (src_gc); + + _gdk_windowing_gc_copy (dst_gc, src_gc); + + dst_gc->clip_x_origin = src_gc->clip_x_origin; + dst_gc->clip_y_origin = src_gc->clip_y_origin; + dst_gc->ts_x_origin = src_gc->ts_x_origin; + dst_gc->ts_y_origin = src_gc->ts_y_origin; + + if (src_gc->colormap) + g_object_ref (src_gc->colormap); + + if (dst_gc->colormap) + g_object_unref (dst_gc->colormap); + + dst_gc->colormap = src_gc->colormap; + + if (dst_priv->clip_region) + gdk_region_destroy (dst_priv->clip_region); + + if (src_priv->clip_region) + dst_priv->clip_region = gdk_region_copy (src_priv->clip_region); + else + dst_priv->clip_region = NULL; + + dst_priv->fill = src_priv->fill; + + if (dst_priv->stipple) + g_object_unref (dst_priv->stipple); + dst_priv->stipple = src_priv->stipple; + if (dst_priv->stipple) + g_object_ref (dst_priv->stipple); + + if (dst_priv->tile) + g_object_unref (dst_priv->tile); + dst_priv->tile = src_priv->tile; + if (dst_priv->tile) + g_object_ref (dst_priv->tile); + + dst_priv->fg_pixel = src_priv->fg_pixel; + dst_priv->bg_pixel = src_priv->bg_pixel; +} + /** * gdk_gc_set_colormap: * @gc: a #GdkGC @@ -724,5 +1028,225 @@ gdk_gc_set_rgb_bg_color (GdkGC *gc, gdk_gc_set_background (gc, &tmp_color); } +static cairo_surface_t * +make_stipple_tile_surface (cairo_t *cr, + GdkBitmap *stipple, + GdkColor *foreground, + GdkColor *background) +{ + cairo_t *tmp_cr; + cairo_surface_t *surface; + cairo_surface_t *alpha_surface; + gint width, height; + + gdk_drawable_get_size (stipple, + &width, &height); + + alpha_surface = _gdk_drawable_ref_cairo_surface (stipple); + + surface = cairo_surface_create_similar (cairo_get_target_surface (cr), + CAIRO_FORMAT_ARGB32, + width, height); + + tmp_cr = cairo_create (); + cairo_set_target_surface (tmp_cr, surface); + + cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SRC); + + if (background) + gdk_cairo_set_source_color (tmp_cr, background); + else + cairo_set_source_rgba (tmp_cr, 0, 0, 0 ,0); + + cairo_paint (tmp_cr); + + cairo_set_operator (tmp_cr, CAIRO_OPERATOR_OVER); + + gdk_cairo_set_source_color (tmp_cr, foreground); + cairo_mask_surface (tmp_cr, alpha_surface, 0, 0); + + cairo_destroy (tmp_cr); + cairo_surface_destroy (alpha_surface); + + return surface; +} + +static void +gc_get_foreground (GdkGC *gc, + GdkColor *color) +{ + GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); + + color->pixel = priv->bg_pixel; + + if (gc->colormap) + gdk_colormap_query_color (gc->colormap, priv->bg_pixel, color); + else + g_warning ("No colormap in gc_get_background"); +} + +static void +gc_get_background (GdkGC *gc, + GdkColor *color) +{ + GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); + + color->pixel = priv->bg_pixel; + + if (gc->colormap) + gdk_colormap_query_color (gc->colormap, priv->bg_pixel, color); + else + g_warning ("No colormap in gc_get_background"); +} + +/** + * _gdk_gc_update_context: + * @gc: a #GdkGC + * @cr: a #cairo_t + * @override_foreground: a foreground color to use to override the + * foreground color of the GC + * @override_stipple: a stipple pattern to use to override the + * stipple from the GC. If this is present and the fill mode + * of the GC isn't %GDK_STIPPLED or %GDK_OPAQUE_STIPPLED + * the fill mode will be forced to %GDK_STIPPLED + * + * Set the attributes of a cairo context to match those of a #GdkGC + * as far as possible. Some aspects of a #GdkGC, such as clip masks + * and functions other than %GDK_COPY are not currently handled. + **/ +void +_gdk_gc_update_context (GdkGC *gc, + cairo_t *cr, + GdkColor *override_foreground, + GdkBitmap *override_stipple) +{ + GdkGCPrivate *priv; + GdkFill fill; + GdkColor foreground; + GdkColor background; + cairo_surface_t *tile_surface = NULL; + GdkBitmap *stipple = NULL; + + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (cr != NULL); + g_return_if_fail (override_stipple == NULL || GDK_IS_PIXMAP (override_stipple)); + + priv = GDK_GC_GET_PRIVATE (gc); + + fill = priv->fill; + if (override_stipple && fill != GDK_OPAQUE_STIPPLED) + fill = GDK_STIPPLED; + + if (fill != GDK_TILED) + { + if (override_foreground) + foreground = *override_foreground; + else + gc_get_foreground (gc, &foreground); + } + + if (fill == GDK_OPAQUE_STIPPLED) + { + if (override_foreground) + foreground = *override_foreground; + else + gc_get_background (gc, &background); + } + + switch (fill) + { + case GDK_SOLID: + break; + case GDK_TILED: + if (!priv->tile) + fill = GDK_SOLID; + break; + case GDK_STIPPLED: + case GDK_OPAQUE_STIPPLED: + if (override_stipple) + stipple = override_stipple; + else + stipple = priv->stipple; + + if (!stipple) + fill = GDK_SOLID; + break; + } + + switch (fill) + { + case GDK_SOLID: + gdk_cairo_set_source_color (cr, &foreground); + break; + case GDK_TILED: + tile_surface = _gdk_drawable_ref_cairo_surface (priv->tile); + break; + case GDK_STIPPLED: + tile_surface = make_stipple_tile_surface (cr, stipple, &foreground, NULL); + break; + case GDK_OPAQUE_STIPPLED: + tile_surface = make_stipple_tile_surface (cr, stipple, &foreground, &background); + break; + } + + /* Tiles, stipples, and clip regions are all specified in device space, + * not user space. For the clip region, we can simply change the matrix, + * clip, then clip back, but for the source pattern, we need to + * compute the right matrix. + * + * What we want is: + * + * CTM_inverse * Pattern_matrix = Translate(- ts_x, - ts_y) + * + * (So that ts_x, ts_y in device space is taken to 0,0 in pattern + * space). So, pattern_matrix = CTM * Translate(- ts_x, - tx_y); + */ + + if (tile_surface) + { + cairo_pattern_t *pattern = cairo_pattern_create_for_surface (tile_surface); + cairo_matrix_t user_to_device; + cairo_matrix_t user_to_pattern; + cairo_matrix_t device_to_pattern; + + cairo_get_matrix (cr, &user_to_device); + cairo_matrix_init_translate (&device_to_pattern, + - gc->ts_x_origin, - gc->ts_y_origin); + cairo_matrix_multiply (&user_to_pattern, + &user_to_device, &device_to_pattern); + + cairo_pattern_set_matrix (pattern, &user_to_pattern); + cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); + cairo_set_source (cr, pattern); + + cairo_surface_destroy (tile_surface); + cairo_pattern_destroy (pattern); + } + + cairo_reset_clip (cr); + if (priv->clip_region) + { + GdkRegionBox *boxes = priv->clip_region->rects; + gint n_boxes = priv->clip_region->numRects; + int i; + + cairo_save (cr); + + cairo_identity_matrix (cr); + + cairo_new_path (cr); + for (i=0; i < n_boxes; i++) + cairo_rectangle (cr, + boxes[i].x1 + gc->clip_x_origin, + boxes[i].y1 + gc->clip_y_origin, + boxes[i].x2 - boxes[i].x1, + boxes[i].y2 - boxes[i].y1); + + cairo_restore (cr); + + cairo_clip (cr); + } +} + #define __GDK_GC_C__ #include "gdkaliasdef.c" diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index ffe770017f..c5aaca8aaf 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -216,6 +216,11 @@ cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable); GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable, gboolean graphics_exposures); +void _gdk_gc_update_context (GdkGC *gc, + cairo_t *cr, + GdkColor *override_foreground, + GdkBitmap *override_stipple); + /************************************* * Interfaces used by windowing code * *************************************/ @@ -228,6 +233,18 @@ void _gdk_screen_close (GdkScreen *screen); const char *_gdk_get_sm_client_id (void); +void _gdk_gc_init (GdkGC *gc, + GdkDrawable *drawable, + GdkGCValues *values, + GdkGCValuesMask values_mask); + +GdkRegion *_gdk_gc_get_clip_region (GdkGC *gc); +GdkFill _gdk_gc_get_fill (GdkGC *gc); +GdkPixmap *_gdk_gc_get_tile (GdkGC *gc); +GdkBitmap *_gdk_gc_get_stipple (GdkGC *gc); +guint32 _gdk_gc_get_fg_pixel (GdkGC *gc); +guint32 _gdk_gc_get_bg_pixel (GdkGC *gc); + /***************************************** * Interfaces provided by windowing code * *****************************************/ @@ -323,9 +340,41 @@ GType _gdk_window_impl_get_type (void) G_GNUC_CONST; GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST; +/** + * _gdk_windowing_gc_set_clip_region: + * @gc: a #GdkGC + * @region: the new clip region + * + * Do any window-system specific processing necessary + * for a change in clip region. Since the clip origin + * will likely change before the GC is used with the + * new clip, frequently this function will only set a flag and + * do the real processing later. + * + * When this function is called, _gdk_gc_get_clip_region + * will already return the new region. + **/ +void _gdk_windowing_gc_set_clip_region (GdkGC *gc, + GdkRegion *region); + +/** + * _gdk_windowing_gc_copy: + * @dst_gc: a #GdkGC from the GDK backend + * @src_gc: a #GdkGC from the GDK backend + * + * Copies backend specific state from @src_gc to @dst_gc. + * This is called before the generic state is copied, so + * the old generic state is still available from @dst_gc + **/ +void _gdk_windowing_gc_copy (GdkGC *dst_gc, + GdkGC *src_gc); + /* Queries the current foreground color of a GdkGC */ void _gdk_windowing_gc_get_foreground (GdkGC *gc, GdkColor *color); +/* Queries the current background color of a GdkGC */ +void _gdk_windowing_gc_get_background (GdkGC *gc, + GdkColor *color); /************************************ * Initialization and exit routines * diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c index bf5b517cf2..a5801fcbfe 100644 --- a/gdk/gdkpango.c +++ b/gdk/gdkpango.c @@ -49,9 +49,11 @@ struct _GdkPangoRendererPrivate gboolean override_color_set[MAX_RENDER_PART + 1]; GdkBitmap *stipple[MAX_RENDER_PART + 1]; - cairo_surface_t *stipple_surface[MAX_RENDER_PART + 1]; gboolean embossed; + cairo_t *cr; + PangoRenderPart last_part; + /* Current target */ GdkDrawable *drawable; GdkGC *base_gc; @@ -79,10 +81,6 @@ gdk_pango_renderer_finalize (GObject *object) if (priv->drawable) g_object_unref (priv->drawable); - for (i = 0; i <= MAX_RENDER_PART; i++) - if (priv->stipple_surface[i]) - cairo_surface_destroy (priv->stipple_surface[i]); - for (i = 0; i <= MAX_RENDER_PART; i++) if (priv->stipple[i]) g_object_unref (priv->stipple[i]); @@ -132,122 +130,56 @@ emboss_context (cairo_t *cr) cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); } -static void -set_part_color (GdkPangoRenderer *gdk_renderer, - cairo_t *cr, - PangoRenderPart part) -{ - PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (gdk_renderer), - part); - if (color) - { - cairo_set_source_rgb (cr, - color->red / 65535., - color->green / 65535., - color->blue / 65535.); - } - else - { - GdkColor gc_color; - - _gdk_windowing_gc_get_foreground (gdk_renderer->priv->base_gc, &gc_color); - gdk_cairo_set_source_color (cr, &gc_color); - } -} - -static cairo_surface_t * -get_stipple_surface (GdkPangoRenderer *gdk_renderer, - cairo_t *cr, - PangoRenderPart part) -{ - if (!gdk_renderer->priv->stipple_surface[part]) - { - cairo_t *tmp_cr; - cairo_surface_t *surface; - cairo_surface_t *alpha_surface; - gint width, height; - - gdk_drawable_get_size (gdk_renderer->priv->stipple[part], - &width, &height); - - alpha_surface = _gdk_drawable_ref_cairo_surface (gdk_renderer->priv->stipple[part]); - - surface = cairo_surface_create_similar (cairo_get_target_surface (cr), - CAIRO_FORMAT_ARGB32, - width, height); - - tmp_cr = cairo_create (); - cairo_set_target_surface (tmp_cr, surface); - - cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SRC); - cairo_show_surface (tmp_cr, alpha_surface, width, height); - - set_part_color (gdk_renderer, tmp_cr, part); - cairo_set_operator (tmp_cr, CAIRO_OPERATOR_ATOP); - - cairo_rectangle (tmp_cr, 0, 0, width, height); - cairo_fill (tmp_cr); - - cairo_destroy (tmp_cr); - cairo_surface_destroy (alpha_surface); - - gdk_renderer->priv->stipple_surface[part] = surface; - } - - return gdk_renderer->priv->stipple_surface[part]; -} - static cairo_t * -create_cairo_context (GdkPangoRenderer *gdk_renderer, - PangoRenderPart part) +get_cairo_context (GdkPangoRenderer *gdk_renderer, + PangoRenderPart part) { PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer); - const PangoMatrix *matrix; - cairo_t *cr = gdk_drawable_create_cairo_context (gdk_renderer->priv->drawable); + GdkPangoRendererPrivate *priv = gdk_renderer->priv; - if (gdk_renderer->priv->stipple[part]) + if (!priv->cr) { - cairo_surface_t *surface = get_stipple_surface (gdk_renderer, cr, part); - cairo_pattern_t *pattern; + const PangoMatrix *matrix; + + priv->cr = gdk_drawable_create_cairo_context (priv->drawable); - pattern = cairo_pattern_create_for_surface (surface); - cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); - - if (gdk_renderer->priv->base_gc->ts_x_origin != 0 || - gdk_renderer->priv->base_gc->ts_y_origin != 0) + matrix = pango_renderer_get_matrix (renderer); + if (matrix) { - cairo_matrix_t *matrix = cairo_matrix_create (); - cairo_matrix_translate (matrix, - - gdk_renderer->priv->base_gc->ts_x_origin, - - gdk_renderer->priv->base_gc->ts_y_origin); - cairo_pattern_set_matrix (pattern, matrix); - cairo_matrix_destroy (matrix); + cairo_matrix_t cairo_matrix; + + cairo_matrix_init (&cairo_matrix, + matrix->xx, matrix->yx, + matrix->xy, matrix->yy, + matrix->x0, matrix->y0); + cairo_set_matrix (priv->cr, &cairo_matrix); + } + } + + priv->last_part = (PangoRenderPart)-1; + if (part != priv->last_part) + { + PangoColor *pango_color = pango_renderer_get_color (renderer, + part); + GdkColor *color = NULL; + GdkColor tmp_color; + if (pango_color) + { + tmp_color.red = pango_color->red; + tmp_color.green = pango_color->green; + tmp_color.blue = pango_color->blue; + + color = &tmp_color; } - cairo_set_source (cr, pattern); - cairo_pattern_destroy (pattern); - } - else - { - set_part_color (gdk_renderer, cr, part); + _gdk_gc_update_context (priv->base_gc, + priv->cr, + color, + priv->stipple[part]); + priv->last_part = part; } - matrix = pango_renderer_get_matrix (renderer); - if (matrix) - { - cairo_matrix_t *cairo_matrix; - - cairo_matrix = cairo_matrix_create (); - cairo_matrix_set_affine (cairo_matrix, - matrix->xx, matrix->yx, - matrix->xy, matrix->yy, - matrix->x0, matrix->y0); - - cairo_set_matrix (cr, cairo_matrix); - cairo_matrix_destroy (cairo_matrix); - } - - return cr; + return priv->cr; } static void @@ -261,8 +193,8 @@ gdk_pango_renderer_draw_glyphs (PangoRenderer *renderer, GdkPangoRendererPrivate *priv = gdk_renderer->priv; cairo_t *cr; - cr = create_cairo_context (gdk_renderer, - PANGO_RENDER_PART_FOREGROUND); + cr = get_cairo_context (gdk_renderer, + PANGO_RENDER_PART_FOREGROUND); if (priv->embossed) { @@ -275,8 +207,6 @@ gdk_pango_renderer_draw_glyphs (PangoRenderer *renderer, cairo_move_to (cr, x / PANGO_SCALE, y / PANGO_SCALE); pango_cairo_show_glyph_string (cr, font, glyphs); - - cairo_destroy (cr); } /* Draws an error underline that looks like one of: @@ -369,7 +299,7 @@ gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, GdkPangoRendererPrivate *priv = gdk_renderer->priv; cairo_t *cr; - cr = create_cairo_context (gdk_renderer, part); + cr = get_cairo_context (gdk_renderer, part); if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) { @@ -387,8 +317,6 @@ gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); cairo_fill (cr); - - cairo_destroy (cr); } static void @@ -402,7 +330,7 @@ gdk_pango_renderer_draw_error_underline (PangoRenderer *renderer, GdkPangoRendererPrivate *priv = gdk_renderer->priv; cairo_t *cr; - cr = create_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE); + cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE); if (priv->embossed) { @@ -417,8 +345,6 @@ gdk_pango_renderer_draw_error_underline (PangoRenderer *renderer, draw_error_underline (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); - - cairo_destroy (cr); } static void @@ -427,25 +353,37 @@ gdk_pango_renderer_part_changed (PangoRenderer *renderer, { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - if (gdk_renderer->priv->stipple_surface[part]) - { - cairo_surface_destroy (gdk_renderer->priv->stipple_surface[part]); - gdk_renderer->priv->stipple_surface[part] = NULL; - } + if (gdk_renderer->priv->last_part == part) + gdk_renderer->priv->last_part = (PangoRenderPart)-1; } -void +static void gdk_pango_renderer_begin (PangoRenderer *renderer) { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - - if (!gdk_renderer->priv->drawable || !gdk_renderer->priv->base_gc) + GdkPangoRendererPrivate *priv = gdk_renderer->priv; + + if (!priv->drawable || !priv->base_gc) { g_warning ("gdk_pango_renderer_set_drawable() and gdk_pango_renderer_set_drawable()" "must be used to set the target drawable and GC before using the renderer\n"); } } +static void +gdk_pango_renderer_end (PangoRenderer *renderer) +{ + GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); + GdkPangoRendererPrivate *priv = gdk_renderer->priv; + + if (priv->cr) + { + cairo_destroy (priv->cr); + priv->cr = NULL; + } + priv->last_part = (PangoRenderPart)-1; +} + static void gdk_pango_renderer_prepare_run (PangoRenderer *renderer, PangoLayoutRun *run) @@ -541,6 +479,8 @@ gdk_pango_renderer_init (GdkPangoRenderer *renderer) renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer, GDK_TYPE_PANGO_RENDERER, GdkPangoRendererPrivate); + + renderer->priv->last_part = (PangoRenderPart)-1; } static void @@ -555,6 +495,7 @@ gdk_pango_renderer_class_init (GdkPangoRendererClass *klass) renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline; renderer_class->part_changed = gdk_pango_renderer_part_changed; renderer_class->begin = gdk_pango_renderer_begin; + renderer_class->end = gdk_pango_renderer_end; renderer_class->prepare_run = gdk_pango_renderer_prepare_run; object_class->finalize = gdk_pango_renderer_finalize; diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 03829181bc..145e275194 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -1800,16 +1800,12 @@ gdk_window_clear_backing_rect (GdkWindow *window, gdk_window_set_bg_pattern (window, cr, 0, 0); - cairo_save (cr); - cairo_rectangle (cr, x, y, width, height); cairo_clip (cr); region_path (cr, paint->region); cairo_fill (cr); - cairo_restore (cr); - cairo_destroy (cr); } diff --git a/gdk/linux-fb/gdkdrawable-fb2.c b/gdk/linux-fb/gdkdrawable-fb2.c index 20d1105304..adbb79cee5 100644 --- a/gdk/linux-fb/gdkdrawable-fb2.c +++ b/gdk/linux-fb/gdkdrawable-fb2.c @@ -433,9 +433,11 @@ gdk_fb_clip_region (GdkDrawable *drawable, if (gc) { - if (GDK_GC_FBDATA (gc)->clip_region) + GdkRegion *gc = _gdk_gc_get_clip_region (gc); + + if (clip_region) { - tmpreg = gdk_region_copy (GDK_GC_FBDATA (gc)->clip_region); + tmpreg = gdk_region_copy (clip_region); gdk_region_offset (tmpreg, private->abs_x + GDK_GC_P (gc)->clip_x_origin, private->abs_y + GDK_GC_P (gc)->clip_y_origin); gdk_region_intersect (real_clip_region, tmpreg); diff --git a/gdk/linux-fb/gdkgc-fb.c b/gdk/linux-fb/gdkgc-fb.c index 8b8a4c702d..a27b9ea962 100644 --- a/gdk/linux-fb/gdkgc-fb.c +++ b/gdk/linux-fb/gdkgc-fb.c @@ -79,6 +79,8 @@ _gdk_fb_gc_new (GdkDrawable *drawable, gc = g_object_new (gdk_gc_fb_get_type (), NULL); + _gdk_gc_init (gc, drawable, values, values_mask); + private = (GdkGCFBData *)gc; private->depth = GDK_DRAWABLE_FBDATA (drawable)->depth; @@ -103,14 +105,8 @@ gdk_fb_gc_finalize (GObject *obj) private = GDK_GC_FBDATA (gc); - if (private->clip_region) - gdk_region_destroy (private->clip_region); if (private->values.clip_mask) gdk_pixmap_unref (private->values.clip_mask); - if (private->values.stipple) - gdk_pixmap_unref (private->values.stipple); - if (private->values.tile) - gdk_pixmap_unref (private->values.tile); g_free (private->dash_list); @@ -175,7 +171,7 @@ gdk_fb_gc_set_values (GdkGC *gc, if (values->tile) g_assert (GDK_DRAWABLE_IMPL_FBDATA (values->tile)->depth >= 8); - private->values.tile = values->tile ? gdk_pixmap_ref (values->tile) : NULL; + private->values.tile = values->tile; private->values_mask |= GDK_GC_TILE; if (oldpm) gdk_pixmap_unref (oldpm); @@ -186,7 +182,7 @@ gdk_fb_gc_set_values (GdkGC *gc, oldpm = private->values.stipple; if (values->stipple) g_assert (GDK_DRAWABLE_IMPL_FBDATA (values->stipple)->depth == 1); - private->values.stipple = values->stipple ? gdk_pixmap_ref (values->stipple) : NULL; + private->values.stipple = values->stipple; private->values_mask |= GDK_GC_STIPPLE; if (oldpm) gdk_pixmap_unref (oldpm); @@ -200,12 +196,6 @@ gdk_fb_gc_set_values (GdkGC *gc, private->values_mask |= GDK_GC_CLIP_MASK; if (oldpm) gdk_pixmap_unref (oldpm); - - if (private->clip_region) - { - gdk_region_destroy (private->clip_region); - private->clip_region = NULL; - } } if (values_mask & GDK_GC_SUBWINDOW) @@ -313,60 +303,13 @@ gc_unset_cmask(GdkGC *gc) } void -gdk_gc_set_clip_rectangle (GdkGC *gc, - GdkRectangle *rectangle) +_gdk_windowing_gc_set_clip_region (GdkGC *gc, + GdkRegion *region) { - GdkGC *private = (GdkGC *)gc; - GdkGCFBData *data; + GdkGCFBData *data = GDK_GC_FBDATA (gc); - g_return_if_fail (gc != NULL); - - data = GDK_GC_FBDATA (gc); - - if (data->clip_region) - { - gdk_region_destroy (data->clip_region); - data->clip_region = NULL; - } - - if (rectangle) - data->clip_region = gdk_region_rectangle (rectangle); - - private->clip_x_origin = 0; - private->clip_y_origin = 0; - data->values.clip_x_origin = 0; - data->values.clip_y_origin = 0; - - gc_unset_cmask (gc); - - _gdk_fb_gc_calc_state (gc, GDK_GC_CLIP_X_ORIGIN|GDK_GC_CLIP_Y_ORIGIN); -} - -void -gdk_gc_set_clip_region (GdkGC *gc, - GdkRegion *region) -{ - GdkGC *private = (GdkGC *)gc; - GdkGCFBData *data; - - g_return_if_fail (gc != NULL); - - data = GDK_GC_FBDATA (gc); - - if (region == data->clip_region) - return; - - if (data->clip_region) - { - gdk_region_destroy (data->clip_region); - data->clip_region = NULL; - } - - if (region) - data->clip_region = gdk_region_copy (region); - - private->clip_x_origin = 0; - private->clip_y_origin = 0; + gc->clip_x_origin = 0; + gc->clip_y_origin = 0; data->values.clip_x_origin = 0; data->values.clip_y_origin = 0; @@ -377,49 +320,35 @@ gdk_gc_set_clip_region (GdkGC *gc, void -gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc) +_gdk_windowing_gc_copy (GdkGC *dst_gc, + GdkGC *src_gc) { - GdkGCFBData *dst_private; - GdkGCFBData *src_private; - - src_private = GDK_GC_FBDATA (dst_gc); - dst_private = GDK_GC_FBDATA (dst_gc); - - g_return_if_fail (dst_gc != NULL); - g_return_if_fail (src_gc != NULL); - - if (dst_private->clip_region) - gdk_region_destroy (dst_private->clip_region); + GdkGCFBData *dst_private = GDK_GC_FBDATA (dst_gc); + GdkGCFBData *src_private = GDK_GC_FBDATA (src_gc); + GdkGCValuesMask old_mask = dst_private->values_mask; if (dst_private->values_mask & GDK_GC_FONT) gdk_font_unref (dst_private->values.font); - if (dst_private->values_mask & GDK_GC_TILE) - gdk_pixmap_unref (dst_private->values.tile); - if (dst_private->values_mask & GDK_GC_STIPPLE) - gdk_pixmap_unref (dst_private->values.stipple); if (dst_private->values_mask & GDK_GC_CLIP_MASK) - gdk_pixmap_unref (dst_private->values.clip_mask); + g_object_unref (dst_private->values.clip_mask); g_free (dst_private->dash_list); - *dst_private = *src_private; + if (src_private->dash_list) + dst_private->dash_list = g_memdup (src_private->dash_list, + src_private->dash_list_len); + + dst_private->values_mask = src_private->values_mask; + dst_private->values = src_private->values; if (dst_private->values_mask & GDK_GC_FONT) gdk_font_ref (dst_private->values.font); - if (dst_private->values_mask & GDK_GC_TILE) - gdk_pixmap_ref (dst_private->values.tile); - if (dst_private->values_mask & GDK_GC_STIPPLE) - gdk_pixmap_ref (dst_private->values.stipple); if (dst_private->values_mask & GDK_GC_CLIP_MASK) - gdk_pixmap_ref (dst_private->values.clip_mask); - - if (dst_private->clip_region) - dst_private->clip_region = gdk_region_copy (dst_private->clip_region); - - if (dst_private->dash_list) - { - dst_private->dash_list = g_malloc (dst_private->dash_list_len); - memcpy (dst_private->dash_list, - src_private->dash_list, - dst_private->dash_list_len); - } + g_object_ref (dst_private->values.clip_mask); + + dst_private->dash_offset = src_private->dash_offset; + dst_private->alu = src_private->alu; + + dst_private->set_pixel = src_private->set_pixel; + + _gdk_fb_gc_calc_state (gc, old_mask | dst_private->values_mask); } diff --git a/gdk/linux-fb/gdkprivate-fb.h b/gdk/linux-fb/gdkprivate-fb.h index a64d06edfa..4466ffcb72 100644 --- a/gdk/linux-fb/gdkprivate-fb.h +++ b/gdk/linux-fb/gdkprivate-fb.h @@ -229,7 +229,6 @@ typedef void gdk_fb_draw_drawable_func (GdkDrawable *drawable, typedef struct { GdkGC parent_instance; - GdkRegion *clip_region; gchar *dash_list; GdkGCValuesMask values_mask; GdkGCValues values; diff --git a/gdk/win32/gdkdrawable-win32.c b/gdk/win32/gdkdrawable-win32.c index cf4412ccd6..58576ffc2f 100644 --- a/gdk/win32/gdkdrawable-win32.c +++ b/gdk/win32/gdkdrawable-win32.c @@ -525,6 +525,7 @@ generic_draw (GdkDrawable *drawable, GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc); HDC hdc; va_list args; + GdkFillStyle *fill_style = _gdk_gc_get_fill (gc); va_start (args, region); @@ -532,14 +533,14 @@ generic_draw (GdkDrawable *drawable, */ 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; @@ -614,11 +615,11 @@ generic_draw (GdkDrawable *drawable, 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); } @@ -632,14 +633,14 @@ generic_draw (GdkDrawable *drawable, /* 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); @@ -658,8 +659,8 @@ generic_draw (GdkDrawable *drawable, 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; @@ -676,7 +677,7 @@ generic_draw (GdkDrawable *drawable, 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) @@ -701,7 +702,7 @@ generic_draw (GdkDrawable *drawable, 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, @@ -1549,8 +1550,8 @@ blit_from_pixmap (gboolean use_fg_bg, 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 { diff --git a/gdk/win32/gdkgc-win32.c b/gdk/win32/gdkgc-win32.c index 787a013546..0be44dd7f3 100644 --- a/gdk/win32/gdkgc-win32.c +++ b/gdk/win32/gdkgc-win32.c @@ -107,12 +107,6 @@ gdk_gc_win32_finalize (GObject *object) if (win32_gc->values_mask & GDK_GC_FONT) gdk_font_unref (win32_gc->font); - if (win32_gc->values_mask & GDK_GC_TILE) - g_object_unref (win32_gc->tile); - - if (win32_gc->values_mask & GDK_GC_STIPPLE) - g_object_unref (win32_gc->stipple); - if (win32_gc->pen_dashes) g_free (win32_gc->pen_dashes); @@ -125,21 +119,18 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values, GdkGCWin32 *win32_gc) { char *s = ""; - gint sw, sh; GDK_NOTE (GC, g_print ("{")); if (mask & GDK_GC_FOREGROUND) { - win32_gc->foreground = values->foreground.pixel; win32_gc->values_mask |= GDK_GC_FOREGROUND; - GDK_NOTE (GC, (g_print ("fg=%.06lx", win32_gc->foreground), + GDK_NOTE (GC, (g_print ("fg=%.06lx", values->, s = ",")); } if (mask & GDK_GC_BACKGROUND) { - win32_gc->background = values->background.pixel; win32_gc->values_mask |= GDK_GC_BACKGROUND; GDK_NOTE (GC, (g_print ("%sbg=%.06lx", s, win32_gc->background), s = ",")); @@ -196,25 +187,20 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values, if (mask & GDK_GC_FILL) { - win32_gc->fill_style = values->fill; win32_gc->values_mask |= GDK_GC_FILL; GDK_NOTE (GC, (g_print ("%sfill=%s", s, - _gdk_win32_fill_style_to_string (win32_gc->fill_style)), + _gdk_win32_fill_style_to_string (values->fill)), s = ",")); } if (mask & GDK_GC_TILE) { - if (win32_gc->tile != NULL) - g_object_unref (win32_gc->tile); - win32_gc->tile = values->tile; - if (win32_gc->tile != NULL) + if (values->tile != NULL) { - g_object_ref (win32_gc->tile); win32_gc->values_mask |= GDK_GC_TILE; GDK_NOTE (GC, (g_print ("%stile=%p", s, - GDK_PIXMAP_HBITMAP (win32_gc->tile)), + GDK_PIXMAP_HBITMAP (values->tile)), s = ",")); } else @@ -227,17 +213,19 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values, if (mask & GDK_GC_STIPPLE) { - if (win32_gc->stipple != NULL) - g_object_unref (win32_gc->stipple); - win32_gc->stipple = values->stipple; - if (win32_gc->stipple != NULL) + if (values->stipple != NULL) { - gdk_drawable_get_size (win32_gc->stipple, &sw, &sh); - #if 0 /* HB: this size limitation is disabled to make radio and check * buttons work. I got the impression from the API docs, that * it shouldn't be necessary at all, but win9x would do the clipping + * + * This code will need some work if reenabled since the stipple is + * now stored in the backend-independent code. */ + gint sw, sh; + + gdk_drawable_get_size (values->stipple, &sw, &sh); + if ( (sw != 8 || sh != 8) && !G_WIN32_IS_NT_BASED ()) /* HB: the MSDN says it's a Win95 limitation */ { @@ -257,7 +245,7 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values, j = 0; while (j < 8) { - gdk_draw_drawable (bm, gc, win32_gc->stipple, 0, 0, i, j, sw, sh); + gdk_draw_drawable (bm, gc, values->stipple, 0, 0, i, j, sw, sh); j += sh; } i += sw; @@ -265,13 +253,11 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values, win32_gc->stipple = bm; gdk_gc_unref (gc); } - else #endif - g_object_ref (win32_gc->stipple); win32_gc->values_mask |= GDK_GC_STIPPLE; GDK_NOTE (GC, (g_print ("%sstipple=%p", s, - GDK_PIXMAP_HBITMAP (win32_gc->stipple)), + GDK_PIXMAP_HBITMAP (values->stipple)), s = ",")); } else @@ -446,18 +432,12 @@ _gdk_win32_gc_new (GdkDrawable *drawable, gc = g_object_new (_gdk_gc_win32_get_type (), NULL); win32_gc = GDK_GC_WIN32 (gc); + _gdk_gc_init (gc, drawable, values, values_mask); + win32_gc->hcliprgn = NULL; - /* Use the same default values as X11 does, even if they don't make - * sense per se. But apps always set fg and bg anyway. - */ - win32_gc->foreground = 0; - win32_gc->background = 1; win32_gc->font = NULL; win32_gc->rop2 = R2_COPYPEN; - win32_gc->fill_style = GDK_SOLID; - win32_gc->tile = NULL; - win32_gc->stipple = NULL; win32_gc->subwindow_mode = GDK_CLIP_BY_CHILDREN; win32_gc->graphics_exposures = TRUE; win32_gc->pen_width = 0; @@ -485,8 +465,8 @@ gdk_win32_gc_get_values (GdkGC *gc, { GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc); - values->foreground.pixel = win32_gc->foreground; - values->background.pixel = win32_gc->background; + values->foreground.pixel = _gdk_gc_get_fg_pixel (gc); + values->background.pixel = _gdk_gc_get_bg_pixel (gc); values->font = win32_gc->font; switch (win32_gc->rop2) @@ -525,10 +505,9 @@ gdk_win32_gc_get_values (GdkGC *gc, values->function = GDK_SET; break; } - values->fill = win32_gc->fill_style; - - values->tile = win32_gc->tile; - values->stipple = win32_gc->stipple; + values->fill = _gdk_gc_get_fill (gc); + values->tile = _gdk_gc_get_tile (gc); + values->stipple = _gdk_gc_get_stipple (gc); /* Also the X11 backend always returns a NULL clip_mask */ values->clip_mask = NULL; @@ -608,51 +587,10 @@ gdk_win32_gc_set_dashes (GdkGC *gc, } void -gdk_gc_set_clip_rectangle (GdkGC *gc, - GdkRectangle *rectangle) +_gdk_windowing_set_clip_region (GdkGC *gc, + GdkRegion *region) { - GdkGCWin32 *win32_gc; - - g_return_if_fail (GDK_IS_GC (gc)); - - win32_gc = GDK_GC_WIN32 (gc); - - if (win32_gc->hcliprgn) - DeleteObject (win32_gc->hcliprgn); - - if (rectangle) - { - GDK_NOTE (GC, g_print ("gdk_gc_set_clip_rectangle: %p: %s\n", - win32_gc, - _gdk_win32_gdkrectangle_to_string (rectangle))); - win32_gc->hcliprgn = CreateRectRgn (rectangle->x, rectangle->y, - rectangle->x + rectangle->width, - rectangle->y + rectangle->height); - win32_gc->values_mask |= GDK_GC_CLIP_MASK; - } - else - { - GDK_NOTE (GC, g_print ("gdk_gc_set_clip_rectangle: NULL\n")); - - win32_gc->hcliprgn = NULL; - win32_gc->values_mask &= ~GDK_GC_CLIP_MASK; - } - - gc->clip_x_origin = 0; - gc->clip_y_origin = 0; - - win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN); -} - -void -gdk_gc_set_clip_region (GdkGC *gc, - GdkRegion *region) -{ - GdkGCWin32 *win32_gc; - - g_return_if_fail (GDK_IS_GC (gc)); - - win32_gc = GDK_GC_WIN32 (gc); + GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc); if (win32_gc->hcliprgn) DeleteObject (win32_gc->hcliprgn); @@ -681,46 +619,23 @@ gdk_gc_set_clip_region (GdkGC *gc, } void -gdk_gc_copy (GdkGC *dst_gc, - GdkGC *src_gc) +_gdk_windowing_gc_copy (GdkGC *dst_gc, + GdkGC *src_gc) { - GdkGCWin32 *dst_win32_gc; - GdkGCWin32 *src_win32_gc; - - g_return_if_fail (GDK_IS_GC_WIN32 (dst_gc)); - g_return_if_fail (GDK_IS_GC_WIN32 (src_gc)); - - dst_win32_gc = GDK_GC_WIN32 (dst_gc); - src_win32_gc = GDK_GC_WIN32 (src_gc); + GdkGCWin32 *dst_win32_gc = GDK_GC_WIN32 (dst_gc); + GdkGCWin32 *src_win32_gc = GDK_GC_WIN32 (src_gc); GDK_NOTE (GC, g_print ("gdk_gc_copy: %p := %p\n", dst_win32_gc, src_win32_gc)); - if (dst_gc->colormap) - g_object_unref (dst_gc->colormap); - if (dst_win32_gc->hcliprgn != NULL) DeleteObject (dst_win32_gc->hcliprgn); if (dst_win32_gc->font != NULL) gdk_font_unref (dst_win32_gc->font); - if (dst_win32_gc->tile != NULL) - g_object_unref (dst_win32_gc->tile); - - if (dst_win32_gc->stipple != NULL) - g_object_unref (dst_win32_gc->stipple); - if (dst_win32_gc->pen_dashes) g_free (dst_win32_gc->pen_dashes); - dst_gc->clip_x_origin = src_gc->clip_x_origin; - dst_gc->clip_y_origin = src_gc->clip_y_origin; - dst_gc->ts_x_origin = src_gc->ts_x_origin; - dst_gc->ts_y_origin = src_gc->ts_y_origin; - dst_gc->colormap = src_gc->colormap; - if (dst_gc->colormap) - g_object_ref (dst_gc->colormap); - dst_win32_gc->hcliprgn = src_win32_gc->hcliprgn; if (dst_win32_gc->hcliprgn) { @@ -732,21 +647,11 @@ gdk_gc_copy (GdkGC *dst_gc, } dst_win32_gc->values_mask = src_win32_gc->values_mask; - dst_win32_gc->foreground = src_win32_gc->foreground; - dst_win32_gc->background = src_win32_gc->background; dst_win32_gc->font = src_win32_gc->font; if (dst_win32_gc->font != NULL) gdk_font_ref (dst_win32_gc->font); dst_win32_gc->rop2 = src_win32_gc->rop2; - dst_win32_gc->fill_style = src_win32_gc->fill_style; - dst_win32_gc->tile = src_win32_gc->tile; - if (dst_win32_gc->tile != NULL) - g_object_ref (dst_win32_gc->tile); - - dst_win32_gc->stipple = src_win32_gc->stipple; - if (dst_win32_gc->stipple != NULL) - g_object_ref (dst_win32_gc->stipple); dst_win32_gc->subwindow_mode = src_win32_gc->subwindow_mode; dst_win32_gc->graphics_exposures = src_win32_gc->graphics_exposures; @@ -937,7 +842,7 @@ gdk_win32_hdc_get (GdkDrawable *drawable, if (ok && (usage & GDK_GC_FOREGROUND)) { - fg = _gdk_win32_colormap_color (impl->colormap, win32_gc->foreground); + fg = _gdk_win32_colormap_color (impl->colormap, _gdk_gc_get_fg_pixel (gc)); if ((hbr = CreateSolidBrush (fg)) == NULL) WIN32_GDI_FAILED ("CreateSolidBrush"), ok = FALSE; @@ -1259,23 +1164,3 @@ _gdk_win32_gdkregion_to_hrgn (GdkRegion *region, return (hrgn); } - -void -_gdk_windowing_gc_get_foreground (GdkGC *gc, - GdkColor *color) -{ - GdkGCWin32 *win32_gc; - GdkColormap *cmap; - - g_return_if_fail (GDK_IS_GC_WIN32 (gc)); - - win32_gc = GDK_GC_WIN32 (gc); - - color->pixel = win32_gc->foreground; - cmap = gdk_gc_get_colormap (gc); - - if (cmap) - gdk_colormap_query_color (cmap, win32_gc->foreground, color); - else - g_warning ("No colormap in _gdk_windowing_gc_get_foreground"); -} diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h index 0d1ab272de..d5786a086a 100644 --- a/gdk/win32/gdkprivate-win32.h +++ b/gdk/win32/gdkprivate-win32.h @@ -268,14 +268,8 @@ struct _GdkGCWin32 GdkGCValuesMask values_mask; - gulong foreground; /* Pixel values from GdkColor, */ - gulong background; /* not Win32 COLORREFs */ - GdkFont *font; gint rop2; - GdkFill fill_style; - GdkPixmap *tile; - GdkPixmap *stipple; GdkSubwindowMode subwindow_mode; gint graphics_exposures; gint pen_width; diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c index c502ffa56c..71e02909f5 100644 --- a/gdk/x11/gdkdrawable-x11.c +++ b/gdk/x11/gdkdrawable-x11.c @@ -346,13 +346,13 @@ gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable, { GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen); - GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL; Picture picture = gdk_x11_drawable_get_picture (drawable); + GdkRegion *clip_region = gc ? _gdk_gc_get_clip_region (gc) : NULL; - if (gc && gc_private->clip_region) + if (clip_region) { - GdkRegionBox *boxes = gc_private->clip_region->rects; - gint n_boxes = gc_private->clip_region->numRects; + GdkRegionBox *boxes = clip_region->rects; + gint n_boxes = clip_region->numRects; XRectangle *rects = g_new (XRectangle, n_boxes); int i; diff --git a/gdk/x11/gdkgc-x11.c b/gdk/x11/gdkgc-x11.c index 806e96fe76..2d0fe34a7b 100644 --- a/gdk/x11/gdkgc-x11.c +++ b/gdk/x11/gdkgc-x11.c @@ -107,14 +107,6 @@ gdk_gc_x11_finalize (GObject *object) { GdkGCX11 *x11_gc = GDK_GC_X11 (object); - if (x11_gc->clip_region) - gdk_region_destroy (x11_gc->clip_region); - - if (x11_gc->stipple) - g_object_unref (x11_gc->stipple); - if (x11_gc->tile) - g_object_unref (x11_gc->tile); - XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc)); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -140,9 +132,10 @@ _gdk_x11_gc_new (GdkDrawable *drawable, gc = g_object_new (_gdk_gc_x11_get_type (), NULL); private = GDK_GC_X11 (gc); + _gdk_gc_init (gc, drawable, values, values_mask); + private->dirty_mask = 0; private->have_clip_mask = FALSE; - private->clip_region = NULL; private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; @@ -160,29 +153,6 @@ _gdk_x11_gc_new (GdkDrawable *drawable, private->dirty_mask |= GDK_GC_DIRTY_TS; } - if (values_mask & GDK_GC_FOREGROUND) - private->fg_pixel = values->foreground.pixel; - - if (values_mask & GDK_GC_BACKGROUND) - private->bg_pixel = values->background.pixel; - - if (values_mask & GDK_GC_FILL) - private->fill = values->fill; - - if (values_mask & GDK_GC_STIPPLE) - { - private->stipple = values->stipple; - if (private->stipple) - g_object_ref (private->stipple); - } - - if (values_mask & GDK_GC_TILE) - { - private->tile = values->tile; - if (private->tile) - g_object_ref (private->tile); - } - if ((values_mask & GDK_GC_CLIP_MASK) && values->clip_mask) private->have_clip_mask = TRUE; @@ -211,7 +181,9 @@ _gdk_x11_gc_flush (GdkGC *gc) if (private->dirty_mask & GDK_GC_DIRTY_CLIP) { - if (!private->clip_region) + GdkRegion *clip_region = _gdk_gc_get_clip_region (gc); + + if (!clip_region) XSetClipOrigin (xdisplay, xgc, gc->clip_x_origin, gc->clip_y_origin); else @@ -219,7 +191,7 @@ _gdk_x11_gc_flush (GdkGC *gc) XRectangle *rectangles; gint n_rects; - _gdk_region_get_xrectangles (private->clip_region, + _gdk_region_get_xrectangles (clip_region, gc->clip_x_origin, gc->clip_y_origin, &rectangles, @@ -417,54 +389,10 @@ gdk_x11_gc_set_values (GdkGC *gc, if (values_mask & GDK_GC_CLIP_MASK) { - if (x11_gc->clip_region) - { - gdk_region_destroy (x11_gc->clip_region); - x11_gc->clip_region = NULL; - } - + x11_gc->have_clip_region = FALSE; x11_gc->have_clip_mask = values->clip_mask != NULL; } - if (values_mask & GDK_GC_FOREGROUND) - x11_gc->fg_pixel = values->foreground.pixel; - - if (values_mask & GDK_GC_BACKGROUND) - { - if (x11_gc->bg_pixel != values->background.pixel) - x11_gc->bg_pixel = values->background.pixel; - } - - if (values_mask & GDK_GC_FILL) - { - if (x11_gc->fill != values->fill) - x11_gc->fill = values->fill; - } - - if (values_mask & GDK_GC_STIPPLE) - { - if (x11_gc->stipple != values->stipple) - { - if (x11_gc->stipple) - g_object_unref (x11_gc->stipple); - x11_gc->stipple = values->stipple; - if (x11_gc->stipple) - g_object_ref (x11_gc->stipple); - } - } - - if (values_mask & GDK_GC_TILE) - { - if (x11_gc->tile != values->tile) - { - if (x11_gc->tile) - g_object_unref (x11_gc->tile); - x11_gc->tile = values->tile; - if (x11_gc->tile) - g_object_ref (x11_gc->tile); - } - } - gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask); XChangeGC (GDK_GC_XDISPLAY (gc), @@ -704,158 +632,42 @@ gdk_x11_gc_values_to_xvalues (GdkGCValues *values, } -/** - * gdk_gc_set_clip_rectangle: - * @gc: a #GdkGC. - * @rectangle: the rectangle to clip to. - * - * Sets the clip mask for a graphics context from a - * rectangle. The clip mask is interpreted relative to the clip - * origin. (See gdk_gc_set_clip_origin()). - **/ void -gdk_gc_set_clip_rectangle (GdkGC *gc, - GdkRectangle *rectangle) +_gdk_windowing_gc_set_clip_region (GdkGC *gc, + GdkRegion *region) { - GdkGCX11 *x11_gc; - gboolean had_region = FALSE; - - g_return_if_fail (GDK_IS_GC (gc)); - - x11_gc = GDK_GC_X11 (gc); - - if (x11_gc->clip_region) - { - had_region = TRUE; - gdk_region_destroy (x11_gc->clip_region); - } - - if (rectangle) - x11_gc->clip_region = gdk_region_rectangle (rectangle); - else - x11_gc->clip_region = NULL; + GdkGCX11 *x11_gc = GDK_GC_X11 (gc); /* Unset immediately, to make sure Xlib doesn't keep the * XID of an old clip mask cached */ - if ((had_region && !rectangle) || x11_gc->have_clip_mask) + if ((x11_gc->have_clip_region && !region) || x11_gc->have_clip_mask) { XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None); x11_gc->have_clip_mask = FALSE; } - gc->clip_x_origin = 0; - gc->clip_y_origin = 0; - - x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP; -} - -/** - * gdk_gc_set_clip_region: - * @gc: a #GdkGC. - * @region: the #GdkRegion. - * - * Sets the clip mask for a graphics context from a region structure. - * The clip mask is interpreted relative to the clip origin. (See - * gdk_gc_set_clip_origin()). - **/ -void -gdk_gc_set_clip_region (GdkGC *gc, - GdkRegion *region) -{ - GdkGCX11 *x11_gc; - gboolean had_region = FALSE; - - g_return_if_fail (GDK_IS_GC (gc)); - - x11_gc = GDK_GC_X11 (gc); - - if (x11_gc->clip_region) - { - had_region = TRUE; - gdk_region_destroy (x11_gc->clip_region); - } - - if (region) - x11_gc->clip_region = gdk_region_copy (region); - else - x11_gc->clip_region = NULL; - - /* Unset immediately, to make sure Xlib doesn't keep the - * XID of an old clip mask cached - */ - if ((had_region && !region) || x11_gc->have_clip_mask) - { - XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None); - x11_gc->have_clip_mask = FALSE; - } + x11_gc->have_clip_region = region != NULL; gc->clip_x_origin = 0; gc->clip_y_origin = 0; - + x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP; } - -/** - * gdk_gc_copy: - * @dst_gc: the destination graphics context. - * @src_gc: the source graphics context. - * - * Copy the set of values from one graphics context - * onto another graphics context. - **/ void -gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc) +_gdk_windowing_gc_copy (GdkGC *dst_gc, + GdkGC *src_gc) { - GdkGCX11 *x11_src_gc; - GdkGCX11 *x11_dst_gc; - - g_return_if_fail (GDK_IS_GC_X11 (dst_gc)); - g_return_if_fail (GDK_IS_GC_X11 (src_gc)); + GdkGCX11 *x11_src_gc = GDK_GC_X11 (src_gc); + GdkGCX11 *x11_dst_gc = GDK_GC_X11 (dst_gc); - x11_dst_gc = GDK_GC_X11 (dst_gc); - x11_src_gc = GDK_GC_X11 (src_gc); - XCopyGC (GDK_GC_XDISPLAY (src_gc), GDK_GC_XGC (src_gc), ~((~1) << GCLastBit), GDK_GC_XGC (dst_gc)); - dst_gc->clip_x_origin = src_gc->clip_x_origin; - dst_gc->clip_y_origin = src_gc->clip_y_origin; - dst_gc->ts_x_origin = src_gc->ts_x_origin; - dst_gc->ts_y_origin = src_gc->ts_y_origin; - - if (src_gc->colormap) - g_object_ref (src_gc->colormap); - - if (dst_gc->colormap) - g_object_unref (dst_gc->colormap); - - dst_gc->colormap = src_gc->colormap; - - if (x11_dst_gc->clip_region) - gdk_region_destroy (x11_dst_gc->clip_region); - - if (x11_src_gc->clip_region) - x11_dst_gc->clip_region = gdk_region_copy (x11_src_gc->clip_region); - else - x11_dst_gc->clip_region = NULL; - x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask; - x11_dst_gc->fg_pixel = x11_src_gc->fg_pixel; - x11_dst_gc->fill = x11_src_gc->fill; - - if (x11_dst_gc->stipple) - g_object_unref (x11_dst_gc->stipple); - x11_dst_gc->stipple = x11_src_gc->stipple; - if (x11_dst_gc->stipple) - g_object_ref (x11_dst_gc->stipple); - - if (x11_dst_gc->tile) - g_object_unref (x11_dst_gc->tile); - x11_dst_gc->tile = x11_src_gc->tile; - if (x11_dst_gc->tile) - g_object_ref (x11_dst_gc->tile); + x11_dst_gc->have_clip_region = x11_src_gc->have_clip_region; + x11_dst_gc->have_clip_mask = x11_src_gc->have_clip_mask; } /** @@ -915,26 +727,5 @@ gdk_x11_gc_get_xgc (GdkGC *gc) return gc_x11->xgc; } -void -_gdk_windowing_gc_get_foreground (GdkGC *gc, - GdkColor *color) -{ - GdkGCX11 *x11_gc; - GdkColormap *cmap; - - g_return_if_fail (GDK_IS_GC_X11 (gc)); - - x11_gc = GDK_GC_X11 (gc); - - color->pixel = x11_gc->fg_pixel; - - cmap = gdk_gc_get_colormap (gc); - - if (cmap) - gdk_colormap_query_color (cmap, x11_gc->fg_pixel, color); - else - g_warning ("No colormap in _gdk_windowing_gc_get_foreground"); -} - #define __GDK_GC_X11_C__ #include "gdkaliasdef.c" diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 8554beb762..cde9042f6f 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -59,17 +59,10 @@ struct _GdkGCX11 GC xgc; GdkScreen *screen; - GdkRegion *clip_region; guint16 dirty_mask; + guint have_clip_region : 1; guint have_clip_mask : 1; guint depth : 8; - - GdkFill fill; - GdkBitmap *stipple; - GdkPixmap *tile; - - gulong fg_pixel; - gulong bg_pixel; }; struct _GdkGCX11Class diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index 10fb2f7e26..7452c52e88 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -2905,7 +2905,6 @@ draw_arrow (GdkWindow *window, if (area) { - cairo_save (cr); cairo_rectangle (cr, area->x, area->y, area->width, area->height); cairo_clip (cr); cairo_new_path (cr); @@ -2939,9 +2938,6 @@ draw_arrow (GdkWindow *window, cairo_close_path (cr); cairo_fill (cr); - if (area) - cairo_restore (cr); - cairo_destroy (cr); } @@ -3631,7 +3627,6 @@ gtk_default_draw_check (GtkStyle *style, if (area) { - cairo_save (cr); cairo_rectangle (cr, area->x, area->y, area->width, area->height); cairo_clip (cr); cairo_new_path (cr); @@ -3726,9 +3721,6 @@ gtk_default_draw_check (GtkStyle *style, cairo_fill (cr); } - if (area) - cairo_restore (cr); - cairo_destroy (cr); } @@ -3759,7 +3751,6 @@ gtk_default_draw_option (GtkStyle *style, if (area) { - cairo_save (cr); cairo_rectangle (cr, area->x, area->y, area->width, area->height); cairo_clip (cr); cairo_new_path (cr); @@ -3784,9 +3775,7 @@ gtk_default_draw_option (GtkStyle *style, (exterior_size - 1) / 2., 0, 2 * G_PI); - cairo_save (cr); - cairo_fill (cr); - cairo_restore (cr); + cairo_fill_preserve (cr); if (type == BUTTON) gdk_cairo_set_source_color (cr, &style->fg[state_type]); @@ -3853,9 +3842,6 @@ gtk_default_draw_option (GtkStyle *style, cairo_fill (cr); } - if (area) - cairo_restore (cr); - cairo_destroy (cr); } @@ -4811,7 +4797,6 @@ gtk_default_draw_expander (GtkStyle *style, if (area) { - cairo_save (cr); cairo_rectangle (cr, area->x, area->y, area->width, area->height); cairo_clip (cr); cairo_new_path (cr); @@ -4888,7 +4873,6 @@ gtk_default_draw_expander (GtkStyle *style, cairo_set_line_width (cr, line_width); - cairo_save (cr); if (state_type == GTK_STATE_PRELIGHT) gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_PRELIGHT]); @@ -4899,15 +4883,11 @@ gtk_default_draw_expander (GtkStyle *style, gdk_cairo_set_source_color (cr, &style->base[GTK_STATE_NORMAL]); - cairo_fill (cr); - cairo_restore (cr); + cairo_fill_preserve (cr); gdk_cairo_set_source_color (cr, &style->fg[state_type]); cairo_stroke (cr); - if (area) - cairo_restore (cr); - cairo_destroy (cr); } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 44ecea206b..72b78f939c 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -227,6 +227,8 @@ static gboolean gtk_widget_real_can_activate_accel (GtkWidget *widg static void gtk_widget_set_usize_internal (GtkWidget *widget, gint width, gint height); +static void gtk_widget_get_draw_rectangle (GtkWidget *widget, + GdkRectangle *rect); /* --- variables --- */ @@ -1456,6 +1458,12 @@ gtk_widget_class_init (GtkWidgetClass *klass) P_("Aspect ratio with which to draw insertion cursor"), 0.0, 1.0, 0.04, GTK_PARAM_READABLE)); + gtk_widget_class_install_style_property (klass, + g_param_spec_boxed ("draw-border", + P_("Draw Border"), + P_("Size of areas outside the widget's allocation to draw"), + GTK_TYPE_BORDER, + GTK_PARAM_READABLE)); } static void @@ -2430,6 +2438,55 @@ gtk_widget_queue_draw_area (GtkWidget *widget, gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE); } +static void +widget_add_child_draw_rectangle (GtkWidget *widget, + GdkRectangle *rect) +{ + GdkRectangle child_rect; + + if (!GTK_WIDGET_REALIZED (widget) || + widget->window != widget->parent->window) + return; + + gtk_widget_get_draw_rectangle (widget, &child_rect); + gdk_rectangle_union (rect, &child_rect, rect); +} + +static void +gtk_widget_get_draw_rectangle (GtkWidget *widget, + GdkRectangle *rect) +{ + if (GTK_WIDGET_NO_WINDOW (widget)) + { + GtkBorder *draw_border = NULL; + + *rect = widget->allocation; + + gtk_widget_style_get (widget, + "draw-border", &draw_border, + NULL); + if (draw_border) + { + rect->x -= draw_border->top; + rect->y -= draw_border->left; + rect->width += draw_border->left + draw_border->right; + rect->height += draw_border->top + draw_border->bottom; + } + + if (GTK_IS_CONTAINER (widget)) + gtk_container_forall (GTK_CONTAINER (widget), + (GtkCallback)widget_add_child_draw_rectangle, + rect); + } + else + { + rect->x = 0; + rect->y = 0; + rect->width = widget->allocation.width; + rect->height = widget->allocation.height; + } +} + /** * gtk_widget_queue_draw: * @widget: a #GtkWidget @@ -2441,20 +2498,15 @@ gtk_widget_queue_draw_area (GtkWidget *widget, void gtk_widget_queue_draw (GtkWidget *widget) { + GdkRectangle rect; + g_return_if_fail (GTK_IS_WIDGET (widget)); - if (widget->allocation.width || widget->allocation.height) - { - if (GTK_WIDGET_NO_WINDOW (widget)) - gtk_widget_queue_draw_area (widget, widget->allocation.x, - widget->allocation.y, - widget->allocation.width, - widget->allocation.height); - else - gtk_widget_queue_draw_area (widget, 0, 0, - widget->allocation.width, - widget->allocation.height); - } + gtk_widget_get_draw_rectangle (widget, &rect); + + gtk_widget_queue_draw_area (widget, + rect.x, rect.y, + rect.width, rect.height); } /* Invalidates the given area (allocation-relative-coordinates) @@ -2687,11 +2739,13 @@ gtk_widget_invalidate_widget_windows (GtkWidget *widget, static void gtk_widget_queue_shallow_draw (GtkWidget *widget) { + GdkRectangle rect; GdkRegion *region; g_return_if_fail (GTK_IS_WIDGET (widget)); - - region = gdk_region_rectangle (&widget->allocation); + + gtk_widget_get_draw_rectangle (widget, &rect); + region = gdk_region_rectangle (&rect); gtk_widget_invalidate_widget_windows (widget, region); gdk_region_destroy (region); } @@ -3883,12 +3937,15 @@ GdkRegion * gtk_widget_region_intersect (GtkWidget *widget, GdkRegion *region) { + GdkRectangle rect; GdkRegion *dest; g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); g_return_val_if_fail (region != NULL, NULL); + + gtk_widget_get_draw_rectangle (widget, &rect); - dest = gdk_region_rectangle (&widget->allocation); + dest = gdk_region_rectangle (&rect); gdk_region_intersect (dest, region);