summaryrefslogtreecommitdiff
path: root/gdk/gdkpango.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/gdkpango.c')
-rw-r--r--gdk/gdkpango.c193
1 files changed, 67 insertions, 126 deletions
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;
@@ -80,10 +82,6 @@ gdk_pango_renderer_finalize (GObject *object)
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;
-
- pattern = cairo_pattern_create_for_surface (surface);
- cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+ const PangoMatrix *matrix;
+
+ priv->cr = gdk_drawable_create_cairo_context (priv->drawable);
- 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);
}
-
- cairo_set_source (cr, pattern);
- cairo_pattern_destroy (pattern);
}
- else
- {
- set_part_color (gdk_renderer, cr, part);
- }
-
- matrix = pango_renderer_get_matrix (renderer);
- if (matrix)
+
+ priv->last_part = (PangoRenderPart)-1;
+ if (part != priv->last_part)
{
- cairo_matrix_t *cairo_matrix;
+ 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_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);
+ _gdk_gc_update_context (priv->base_gc,
+ priv->cr,
+ color,
+ priv->stipple[part]);
+ priv->last_part = part;
}
- 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,19 +353,17 @@ 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");
@@ -447,6 +371,20 @@ gdk_pango_renderer_begin (PangoRenderer *renderer)
}
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;