summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-08-31 14:34:52 -0400
committerMatthias Clasen <mclasen@redhat.com>2017-09-01 12:06:05 -0400
commit3dc257dedd0b65fd59b2b4fe67e0fcd82e7b89e3 (patch)
treeb8b96c95fbd78283d6d98ddf0556c43f9a676275
parent5040e1064173a8291d187b6e4647c33fb12070f7 (diff)
downloadgtk+-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.h9
-rw-r--r--gsk/gskrendernodeimpl.c140
-rw-r--r--gtk/gskpango.c122
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