From 51d40ca02372bcf242ed62f84a59d3b9152c4d8d Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 14 Jul 2018 20:21:15 +0200 Subject: render: Make gtk_render_layout() use the snapshot API This removes a lot of duplicated code. --- gtk/gtkcssshadowsvalue.c | 15 --- gtk/gtkcssshadowsvalueprivate.h | 4 - gtk/gtkcssshadowvalue.c | 137 -------------------------- gtk/gtkcssshadowvalueprivate.h | 4 - gtk/gtkpango.c | 206 ---------------------------------------- gtk/gtkpango.h | 4 - gtk/gtkrender.c | 63 +++--------- 7 files changed, 14 insertions(+), 419 deletions(-) diff --git a/gtk/gtkcssshadowsvalue.c b/gtk/gtkcssshadowsvalue.c index 729b879991..6aa4c50a93 100644 --- a/gtk/gtkcssshadowsvalue.c +++ b/gtk/gtkcssshadowsvalue.c @@ -287,21 +287,6 @@ gtk_css_shadows_value_get_shadows (const GtkCssValue *shadows, gtk_css_shadow_value_get_shadow (shadows->values[i], &out_shadows[i]); } -void -_gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows, - cairo_t *cr, - PangoLayout *layout) -{ - guint i; - - g_return_if_fail (shadows->class == >K_CSS_VALUE_SHADOWS); - - for (i = 0; i < shadows->len; i++) - { - _gtk_css_shadow_value_paint_layout (shadows->values[i], cr, layout); - } -} - void _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows, cairo_t *cr) diff --git a/gtk/gtkcssshadowsvalueprivate.h b/gtk/gtkcssshadowsvalueprivate.h index 5bd78615f4..30eb4eebd9 100644 --- a/gtk/gtkcssshadowsvalueprivate.h +++ b/gtk/gtkcssshadowsvalueprivate.h @@ -41,10 +41,6 @@ gsize gtk_css_shadows_value_get_n_shadows (const GtkCssValue void gtk_css_shadows_value_get_shadows (const GtkCssValue *shadows, GskShadow *out_shadows); -void _gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows, - cairo_t *cr, - PangoLayout *layout); - void _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows, cairo_t *cr); diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c index 62e0db7340..b57d6aa9f0 100644 --- a/gtk/gtkcssshadowvalue.c +++ b/gtk/gtkcssshadowvalue.c @@ -430,143 +430,6 @@ gtk_css_shadow_value_finish_drawing (const GtkCssValue *shadow, return original_cr; } -static const cairo_user_data_key_t radius_key; -static const cairo_user_data_key_t layout_serial_key; - -GQuark pango_cached_blurred_surface_quark (void); - -G_DEFINE_QUARK (GtkCssShadowValue pango_cached_blurred_surface, pango_cached_blurred_surface) - -static cairo_surface_t * -get_cached_pango_surface (PangoLayout *layout, - const GtkCssValue *shadow) -{ - cairo_surface_t *cached_surface = g_object_get_qdata (G_OBJECT (layout), pango_cached_blurred_surface_quark ()); - guint cached_radius, cached_serial; - guint radius, serial; - - if (!cached_surface) - return NULL; - - radius = _gtk_css_number_value_get (shadow->radius, 0); - cached_radius = GPOINTER_TO_UINT (cairo_surface_get_user_data (cached_surface, &radius_key)); - if (radius != cached_radius) - return NULL; - - serial = pango_layout_get_serial (layout); - cached_serial = GPOINTER_TO_UINT (cairo_surface_get_user_data (cached_surface, &layout_serial_key)); - if (serial != cached_serial) - return NULL; - - return cached_surface; -} - -static cairo_surface_t * -make_blurred_pango_surface (cairo_t *existing_cr, - PangoLayout *layout, - const GtkCssValue *shadow) -{ - cairo_surface_t *surface; - cairo_t *cr; - gdouble radius, clip_radius; - gdouble x_scale, y_scale; - PangoRectangle ink_rect; - - radius = _gtk_css_number_value_get (shadow->radius, 0); - - pango_layout_get_pixel_extents (layout, &ink_rect, NULL); - clip_radius = gsk_cairo_blur_compute_pixels (radius); - x_scale = y_scale = 1; - cairo_surface_get_device_scale (cairo_get_target (existing_cr), &x_scale, &y_scale); - - surface = cairo_surface_create_similar_image (cairo_get_target (existing_cr), - CAIRO_FORMAT_A8, - x_scale * (ink_rect.width + 2 * clip_radius), - y_scale * (ink_rect.height + 2 * clip_radius)); - cairo_surface_set_device_scale (surface, x_scale, y_scale); - cairo_surface_set_device_offset (surface, -ink_rect.x + clip_radius, -ink_rect.y + clip_radius); - cr = cairo_create (surface); - cairo_move_to (cr, 0, 0); - _gtk_pango_fill_layout (cr, layout); - gsk_cairo_blur_surface (surface, radius * x_scale, GSK_BLUR_X | GSK_BLUR_Y); - - cairo_destroy (cr); - - return surface; -} - -static cairo_surface_t * -get_blurred_pango_surface (cairo_t *cr, - PangoLayout *layout, - const GtkCssValue *shadow) -{ - cairo_surface_t *surface; - guint radius, serial; - - surface = get_cached_pango_surface (layout, shadow); - if (!surface) - { - surface = make_blurred_pango_surface (cr, layout, shadow); - - /* Cache the surface on the PangoLayout */ - radius = _gtk_css_number_value_get (shadow->radius, 0); - cairo_surface_set_user_data (surface, &radius_key, GUINT_TO_POINTER (radius), NULL); - - serial = pango_layout_get_serial (layout); - cairo_surface_set_user_data (surface, &layout_serial_key, GUINT_TO_POINTER (serial), NULL); - - g_object_set_qdata_full (G_OBJECT (layout), pango_cached_blurred_surface_quark (), - surface, (GDestroyNotify) cairo_surface_destroy); - } - - return surface; -} - -void -_gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow, - cairo_t *cr, - PangoLayout *layout) -{ - g_return_if_fail (shadow->class == >K_CSS_VALUE_SHADOW); - - /* We don't need to draw invisible shadows */ - if (gdk_rgba_is_clear (_gtk_css_rgba_value_get_rgba (shadow->color))) - return; - - if (!cairo_has_current_point (cr)) - cairo_move_to (cr, 0, 0); - - cairo_save (cr); - - if (needs_blur (shadow)) - { - cairo_surface_t *blurred_surface = get_blurred_pango_surface (cr, layout, shadow); - double x, y; - cairo_get_current_point (cr, &x, &y); - cairo_translate (cr, x, y); - cairo_translate (cr, - _gtk_css_number_value_get (shadow->hoffset, 0), - _gtk_css_number_value_get (shadow->voffset, 0)); - - gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color)); - cairo_mask_surface (cr, blurred_surface, 0, 0); - } - else - { - /* The no blur case -- just paint directly. */ - cairo_rel_move_to (cr, - _gtk_css_number_value_get (shadow->hoffset, 0), - _gtk_css_number_value_get (shadow->voffset, 0)); - gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color)); - _gtk_pango_fill_layout (cr, layout); - cairo_rel_move_to (cr, - - _gtk_css_number_value_get (shadow->hoffset, 0), - - _gtk_css_number_value_get (shadow->voffset, 0)); - } - - cairo_restore (cr); -} - void _gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow, cairo_t *cr) diff --git a/gtk/gtkcssshadowvalueprivate.h b/gtk/gtkcssshadowvalueprivate.h index e3113d106a..b04beea986 100644 --- a/gtk/gtkcssshadowvalueprivate.h +++ b/gtk/gtkcssshadowvalueprivate.h @@ -42,10 +42,6 @@ void gtk_css_shadow_value_get_extents (const GtkCssValue void gtk_css_shadow_value_get_shadow (const GtkCssValue *value, GskShadow *shadow); -void _gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow, - cairo_t *cr, - PangoLayout *layout); - void _gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow, cairo_t *cr); void _gtk_css_shadow_value_paint_box (const GtkCssValue *shadow, diff --git a/gtk/gtkpango.c b/gtk/gtkpango.c index 2c87e8cb65..1f6e70954a 100644 --- a/gtk/gtkpango.c +++ b/gtk/gtkpango.c @@ -27,212 +27,6 @@ #include #include "gtkintl.h" -#define GTK_TYPE_FILL_LAYOUT_RENDERER (_gtk_fill_layout_renderer_get_type()) -#define GTK_FILL_LAYOUT_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRenderer)) -#define GTK_IS_FILL_LAYOUT_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_FILL_LAYOUT_RENDERER)) -#define GTK_FILL_LAYOUT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRendererClass)) -#define GTK_IS_FILL_LAYOUT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILL_LAYOUT_RENDERER)) -#define GTK_FILL_LAYOUT_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRendererClass)) - -typedef struct _GtkFillLayoutRenderer GtkFillLayoutRenderer; -typedef struct _GtkFillLayoutRendererClass GtkFillLayoutRendererClass; - -struct _GtkFillLayoutRenderer -{ - PangoRenderer parent_instance; - - cairo_t *cr; -}; - -struct _GtkFillLayoutRendererClass -{ - PangoRendererClass parent_class; -}; - -GType _gtk_fill_layout_renderer_get_type (void); - -G_DEFINE_TYPE (GtkFillLayoutRenderer, _gtk_fill_layout_renderer, PANGO_TYPE_RENDERER) - -static void -gtk_fill_layout_renderer_draw_glyphs (PangoRenderer *renderer, - PangoFont *font, - PangoGlyphString *glyphs, - int x, - int y) -{ - GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer); - - cairo_move_to (text_renderer->cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE); - pango_cairo_show_glyph_string (text_renderer->cr, font, glyphs); -} - -static void -gtk_fill_layout_renderer_draw_glyph_item (PangoRenderer *renderer, - const char *text, - PangoGlyphItem *glyph_item, - int x, - int y) -{ - GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer); - - cairo_move_to (text_renderer->cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE); - pango_cairo_show_glyph_item (text_renderer->cr, text, glyph_item); -} - -static void -gtk_fill_layout_renderer_draw_rectangle (PangoRenderer *renderer, - PangoRenderPart part, - int x, - int y, - int width, - int height) -{ - GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer); - - if (part == PANGO_RENDER_PART_BACKGROUND) - return; - - cairo_rectangle (text_renderer->cr, - (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, - (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); - cairo_fill (text_renderer->cr); -} - -static void -gtk_fill_layout_renderer_draw_trapezoid (PangoRenderer *renderer, - PangoRenderPart part, - double y1_, - double x11, - double x21, - double y2, - double x12, - double x22) -{ - GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer); - cairo_matrix_t matrix; - cairo_t *cr; - - cr = text_renderer->cr; - - cairo_save (cr); - - /* use identity scale, but keep translation */ - cairo_get_matrix (cr, &matrix); - matrix.xx = matrix.yy = 1; - matrix.xy = matrix.yx = 0; - cairo_set_matrix (cr, &matrix); - - cairo_move_to (cr, x11, y1_); - cairo_line_to (cr, x21, y1_); - cairo_line_to (cr, x22, y2); - cairo_line_to (cr, x12, y2); - cairo_close_path (cr); - - cairo_fill (cr); - - cairo_restore (cr); -} - -static void -gtk_fill_layout_renderer_draw_error_underline (PangoRenderer *renderer, - int x, - int y, - int width, - int height) -{ - GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer); - - pango_cairo_show_error_underline (text_renderer->cr, - (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, - (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); -} - -static void -gtk_fill_layout_renderer_draw_shape (PangoRenderer *renderer, - PangoAttrShape *attr, - int x, - int y) -{ - GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer); - cairo_t *cr = text_renderer->cr; - PangoLayout *layout; - PangoCairoShapeRendererFunc shape_renderer; - gpointer shape_renderer_data; - - layout = pango_renderer_get_layout (renderer); - - if (!layout) - return; - - shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout), - &shape_renderer_data); - - if (!shape_renderer) - return; - - cairo_save (cr); - - cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE); - - shape_renderer (cr, attr, FALSE, shape_renderer_data); - - cairo_restore (cr); -} - -static void -gtk_fill_layout_renderer_finalize (GObject *object) -{ - G_OBJECT_CLASS (_gtk_fill_layout_renderer_parent_class)->finalize (object); -} - -static void -_gtk_fill_layout_renderer_init (GtkFillLayoutRenderer *renderer) -{ -} - -static void -_gtk_fill_layout_renderer_class_init (GtkFillLayoutRendererClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); - - renderer_class->draw_glyphs = gtk_fill_layout_renderer_draw_glyphs; - renderer_class->draw_glyph_item = gtk_fill_layout_renderer_draw_glyph_item; - renderer_class->draw_rectangle = gtk_fill_layout_renderer_draw_rectangle; - renderer_class->draw_trapezoid = gtk_fill_layout_renderer_draw_trapezoid; - renderer_class->draw_error_underline = gtk_fill_layout_renderer_draw_error_underline; - renderer_class->draw_shape = gtk_fill_layout_renderer_draw_shape; - - object_class->finalize = gtk_fill_layout_renderer_finalize; -} - -void -_gtk_pango_fill_layout (cairo_t *cr, - PangoLayout *layout) -{ - static GtkFillLayoutRenderer *renderer = NULL; - gboolean has_current_point; - double current_x, current_y; - - has_current_point = cairo_has_current_point (cr); - cairo_get_current_point (cr, ¤t_x, ¤t_y); - - if (renderer == NULL) - renderer = g_object_new (GTK_TYPE_FILL_LAYOUT_RENDERER, NULL); - - cairo_save (cr); - cairo_translate (cr, current_x, current_y); - - renderer->cr = cr; - pango_renderer_draw_layout (PANGO_RENDERER (renderer), layout, 0, 0); - - cairo_restore (cr); - - if (has_current_point) - cairo_move_to (cr, current_x, current_y); -} - static AtkAttributeSet * add_attribute (AtkAttributeSet *attributes, AtkTextAttribute attr, diff --git a/gtk/gtkpango.h b/gtk/gtkpango.h index 216f928e8b..09c50b8731 100644 --- a/gtk/gtkpango.h +++ b/gtk/gtkpango.h @@ -31,10 +31,6 @@ G_BEGIN_DECLS -void _gtk_pango_fill_layout (cairo_t *cr, - PangoLayout *layout); - - AtkAttributeSet *_gtk_pango_get_default_attributes (AtkAttributeSet *attributes, PangoLayout *layout); diff --git a/gtk/gtkrender.c b/gtk/gtkrender.c index 3c90bb03d2..ae772a7f91 100644 --- a/gtk/gtkrender.c +++ b/gtk/gtkrender.c @@ -427,54 +427,6 @@ gtk_render_focus (GtkStyleContext *context, x, y, width, height); } -static void -prepare_context_for_layout (cairo_t *cr, - gdouble x, - gdouble y, - PangoLayout *layout) -{ - const PangoMatrix *matrix; - - matrix = pango_context_get_matrix (pango_layout_get_context (layout)); - - cairo_move_to (cr, x, y); - - if (matrix) - { - cairo_matrix_t cairo_matrix; - - cairo_matrix_init (&cairo_matrix, - matrix->xx, matrix->yx, - matrix->xy, matrix->yy, - matrix->x0, matrix->y0); - - cairo_transform (cr, &cairo_matrix); - } -} - -static void -gtk_do_render_layout (GtkStyleContext *context, - cairo_t *cr, - gdouble x, - gdouble y, - PangoLayout *layout) -{ - const GdkRGBA *fg_color; - - cairo_save (cr); - fg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)); - - prepare_context_for_layout (cr, x, y, layout); - - _gtk_css_shadows_value_paint_layout (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_TEXT_SHADOW), - cr, layout); - - gdk_cairo_set_source_rgba (cr, fg_color); - pango_cairo_show_layout (cr, layout); - - cairo_restore (cr); -} - /** * gtk_render_layout: * @context: a #GtkStyleContext @@ -492,11 +444,24 @@ gtk_render_layout (GtkStyleContext *context, gdouble y, PangoLayout *layout) { + GtkSnapshot *snapshot; + GskRenderNode *node; + g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); g_return_if_fail (PANGO_IS_LAYOUT (layout)); g_return_if_fail (cr != NULL); - gtk_do_render_layout (context, cr, x, y, layout); + snapshot = gtk_snapshot_new (); + gtk_snapshot_render_layout (snapshot, context, x, y, layout); + node = gtk_snapshot_free_to_node (snapshot); + if (node == NULL) + return; + + cairo_save (cr); + gsk_render_node_draw (node, cr); + cairo_restore (cr); + + gsk_render_node_unref (node); } static void -- cgit v1.2.1