diff options
author | Matthias Clasen <mclasen@redhat.com> | 2017-08-31 14:34:52 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2017-09-01 12:06:05 -0400 |
commit | 3dc257dedd0b65fd59b2b4fe67e0fcd82e7b89e3 (patch) | |
tree | b8b96c95fbd78283d6d98ddf0556c43f9a676275 | |
parent | 5040e1064173a8291d187b6e4647c33fb12070f7 (diff) | |
download | gtk+-3dc257dedd0b65fd59b2b4fe67e0fcd82e7b89e3.tar.gz |
Make the text node do the rendering
For now, this is just the fallback implementation
using cairo.
-rw-r--r-- | gsk/gskrendernode.h | 9 | ||||
-rw-r--r-- | gsk/gskrendernodeimpl.c | 140 | ||||
-rw-r--r-- | gtk/gskpango.c | 122 |
3 files changed, 160 insertions, 111 deletions
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h index a55027255f..4c94f8d94b 100644 --- a/gsk/gskrendernode.h +++ b/gsk/gskrendernode.h @@ -176,9 +176,12 @@ GskRenderNode * gsk_cross_fade_node_new (GskRenderNode GDK_AVAILABLE_IN_3_92 GskRenderNode * gsk_text_node_new (PangoFont *font, - int x, - int y, - PangoGlyphString *glyphs); + PangoGlyphString *glyphs, + const GdkRGBA *color, + int x_offset, + int y_offset, + double base_x, + double base_y); GDK_AVAILABLE_IN_3_90 void gsk_render_node_set_scaling_filters (GskRenderNode *node, diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 29db76b1de..2d04bb3a64 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -3811,8 +3811,11 @@ struct _GskTextNode PangoFont *font; PangoGlyphString *glyphs; - int x; - int y; + GdkRGBA color; + int x_offset; + int y_offset; + double base_x; + double base_y; }; static void @@ -3824,35 +3827,80 @@ gsk_text_node_finalize (GskRenderNode *node) pango_glyph_string_free (self->glyphs); } +static gboolean +_pango_cairo_font_install (PangoFont *font, + cairo_t *cr) +{ + cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font); + + if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)) + return FALSE; + + cairo_set_scaled_font (cr, scaled_font); + + return TRUE; +} + +#ifndef STACK_BUFFER_SIZE +#define STACK_BUFFER_SIZE (512 * sizeof (int)) +#endif + +#define STACK_ARRAY_LENGTH(T) (STACK_BUFFER_SIZE / sizeof(T)) + static void gsk_text_node_draw (GskRenderNode *node, cairo_t *cr) { GskTextNode *self = (GskTextNode *) node; - int i; - PangoFontDescription *desc; - char *s; + int i, count; + int x_position = 0; + cairo_glyph_t *cairo_glyphs; + cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)]; - desc = pango_font_describe (self->font); - s = pango_font_description_to_string (desc); - g_print ("draw gyphs: font %s, x %d y %d\n", s, self->x, self->y); - g_free (s); - pango_font_description_free (desc); + cairo_save (cr); + cairo_translate (cr, self->x_offset, self->y_offset); + + gdk_cairo_set_source_rgba (cr, &self->color); + if (!_pango_cairo_font_install (self->font, cr)) + goto done; + + if (self->glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs)) + cairo_glyphs = g_new (cairo_glyph_t, self->glyphs->num_glyphs); + else + cairo_glyphs = stack_glyphs; + + count = 0; for (i = 0; i < self->glyphs->num_glyphs; i++) { - PangoGlyphInfo *glyph = &self->glyphs->glyphs[i]; - g_print (" glyph %u width %d x %d y %d cs %d\n", - glyph->glyph, - glyph->geometry.width, - glyph->geometry.x_offset, - glyph->geometry.y_offset, - glyph->attr.is_cluster_start); + PangoGlyphInfo *gi = &self->glyphs->glyphs[i]; + + if (gi->glyph != PANGO_GLYPH_EMPTY) + { + double cx = self->base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset == 0 ? self->base_y : self->base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE; + + if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) + { + cairo_glyphs[count].index = gi->glyph; + cairo_glyphs[count].x = cx; + cairo_glyphs[count].y = cy; + count++; + } + } + x_position += gi->geometry.width; } - g_print ("\n"); + + cairo_show_glyphs (cr, cairo_glyphs, count); + + if (cairo_glyphs != stack_glyphs) + g_free (cairo_glyphs); + +done: + cairo_restore (cr); } -#define GSK_TEXT_NODE_VARIANT_TYPE "(siia(uiiii))" +#define GSK_TEXT_NODE_VARIANT_TYPE "(sddddiidda(uiiii))" static GVariant * gsk_text_node_serialize (GskRenderNode *node) @@ -3878,7 +3926,17 @@ gsk_text_node_serialize (GskRenderNode *node) } g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(uiiii)")); - v = g_variant_new (GSK_TEXT_NODE_VARIANT_TYPE, s, self->x, self->y, &builder); + v = g_variant_new (GSK_TEXT_NODE_VARIANT_TYPE, + s, + self->color.red, + self->color.green, + self->color.blue, + self->color.alpha, + self->x_offset, + self->y_offset, + self->base_x, + self->base_y, + &builder); g_free (s); pango_font_description_free (desc); @@ -3891,7 +3949,6 @@ gsk_text_node_deserialize (GVariant *variant, GError **error) { PangoFont *font; - int x, y; PangoGlyphString *glyphs; GVariantIter iter; GskRenderNode *result; @@ -3901,12 +3958,19 @@ gsk_text_node_deserialize (GVariant *variant, PangoContext *context; int cluster_start; char *s; + GdkRGBA color; + int x_offset, y_offset; + double base_x, base_y; int i; if (!check_variant_type (variant, GSK_TEXT_NODE_VARIANT_TYPE, error)) return NULL; - g_variant_get (variant, "(&siia(uiiii))", &s, &x, &y, &iter); + g_variant_get (variant, "(&sddddiidda(uiiii))", + &color.red, &color.green, &color.blue, &color.alpha, + &x_offset, &y_offset, + &base_x, &base_y, + &s, &iter); desc = pango_font_description_from_string (s); fontmap = pango_cairo_font_map_get_default (); @@ -3923,7 +3987,9 @@ gsk_text_node_deserialize (GVariant *variant, i++; } - result = gsk_text_node_new (font, x, y, glyphs); + result = gsk_text_node_new (font, glyphs, &color, /* FIXME: Avoid copying glyphs */ + x_offset, y_offset, + base_x, base_y); pango_glyph_string_free (glyphs); pango_font_description_free (desc); @@ -3945,18 +4011,34 @@ static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = { GskRenderNode * gsk_text_node_new (PangoFont *font, - int x, - int y, - PangoGlyphString *glyphs) + PangoGlyphString *glyphs, + const GdkRGBA *color, + int x_offset, + int y_offset, + double base_x, + double base_y) { GskTextNode *self; + PangoRectangle ink_rect; self = (GskTextNode *) gsk_render_node_new (&GSK_TEXT_NODE_CLASS, 0); - self->font = font ? g_object_ref (font) : NULL; - self->x = x; - self->y = y; + self->font = g_object_ref (font); self->glyphs = pango_glyph_string_copy (glyphs); + self->color = *color; + self->x_offset = x_offset; + self->y_offset = y_offset; + self->base_x = base_x; + self->base_y = base_y; + + pango_glyph_string_extents (glyphs, font, &ink_rect, NULL); + pango_extents_to_pixels (&ink_rect, NULL); + + graphene_rect_init (&self->render_node.bounds, + x_offset + base_x + ink_rect.x, + y_offset + base_y + ink_rect.y, + ink_rect.width, + ink_rect.height); return &self->render_node; } diff --git a/gtk/gskpango.c b/gtk/gskpango.c index f63179fa54..83376e4e66 100644 --- a/gtk/gskpango.c +++ b/gtk/gskpango.c @@ -97,20 +97,6 @@ set_color (GskPangoRenderer *crenderer, gdk_cairo_set_source_rgba (cr, crenderer->fg_color); } -static gboolean -_pango_cairo_font_install (PangoFont *font, - cairo_t *cr) -{ - cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font); - - if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)) - return FALSE; - - cairo_set_scaled_font (cr, scaled_font); - - return TRUE; -} - static void gsk_pango_renderer_draw_unknown_glyph (GskPangoRenderer *crenderer, PangoFont *font, @@ -136,12 +122,6 @@ gsk_pango_renderer_draw_unknown_glyph (GskPangoRenderer *crenderer, cairo_destroy (cr); } -#ifndef STACK_BUFFER_SIZE -#define STACK_BUFFER_SIZE (512 * sizeof (int)) -#endif - -#define STACK_ARRAY_LENGTH(T) (STACK_BUFFER_SIZE / sizeof(T)) - static void gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer, const char *text, @@ -155,84 +135,68 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer, int y) { GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer); - - cairo_t *cr; - int i, count; - int x_position = 0; - cairo_glyph_t *cairo_glyphs; - cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)]; double base_x = crenderer->x_offset + (double)x / PANGO_SCALE; double base_y = crenderer->y_offset + (double)y / PANGO_SCALE; + int x_offset, y_offset; + cairo_scaled_font_t *scaled_font; + gboolean font_failed = FALSE; + int x_position; + int num_glyphs; + int i; - cr = gtk_snapshot_append_cairo (crenderer->snapshot, &crenderer->bounds, "Text<%dglyphs>", glyphs->num_glyphs); - - set_color (crenderer, PANGO_RENDER_PART_FOREGROUND, cr); - - if (!_pango_cairo_font_install (font, cr)) - { - for (i = 0; i < glyphs->num_glyphs; i++) - { - PangoGlyphInfo *gi = &glyphs->glyphs[i]; - - if (gi->glyph != PANGO_GLYPH_EMPTY) - { - double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - double cy = gi->geometry.y_offset == 0 ? - base_y : - base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE; - - gsk_pango_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy); - } - x_position += gi->geometry.width; - } - - goto done; - } + gtk_snapshot_get_offset (crenderer->snapshot, &x_offset, &y_offset); - if (glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs)) - cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs); - else - cairo_glyphs = stack_glyphs; + scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font); + if (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS) + font_failed = TRUE; - count = 0; + x_position = 0; + num_glyphs = 0; for (i = 0; i < glyphs->num_glyphs; i++) { PangoGlyphInfo *gi = &glyphs->glyphs[i]; - if (gi->glyph != PANGO_GLYPH_EMPTY) + if (gi->glyph != PANGO_GLYPH_EMPTY && + (font_failed || gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) { double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - double cy = gi->geometry.y_offset == 0 ? - base_y : - base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset == 0 + ? base_y + : base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE; + + gsk_pango_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy); - if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG) - gsk_pango_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy); + if (num_glyphs == 0) + base_x += (gi->geometry.x_offset + gi->geometry.width) / PANGO_SCALE; else - { - cairo_glyphs[count].index = gi->glyph; - cairo_glyphs[count].x = cx; - cairo_glyphs[count].y = cy; - count++; - } + glyphs->glyphs[num_glyphs - 1].geometry.width += gi->geometry.x_offset + gi->geometry.width; + } + else + { + if (i != num_glyphs) + glyphs->glyphs[num_glyphs] = glyphs->glyphs[i]; + num_glyphs++; } x_position += gi->geometry.width; } - if (G_UNLIKELY (clusters)) - cairo_show_text_glyphs (cr, - text, text_len, - cairo_glyphs, count, - clusters, num_clusters, - backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : 0); - else - cairo_show_glyphs (cr, cairo_glyphs, count); + glyphs->num_glyphs = num_glyphs; + + if (glyphs->num_glyphs > 0) + { + GskRenderNode *node; + char name[64]; - if (cairo_glyphs != stack_glyphs) - g_free (cairo_glyphs); + gtk_snapshot_offset (crenderer->snapshot, base_x, base_y); -done: - cairo_destroy (cr); + node = gsk_text_node_new (font, glyphs, crenderer->fg_color, x_offset, y_offset, base_x, base_y); + snprintf (name, sizeof (name), "Glyphs<%d>", glyphs->num_glyphs); + gsk_render_node_set_name (node, name); + gtk_snapshot_append_node (crenderer->snapshot, node); + gsk_render_node_unref (node); + + gtk_snapshot_offset (crenderer->snapshot, -base_x, -base_y); + } } static void |