particle/string: handle conversion failures in cairo_scaled_font_text_to_glyphs()

In particular, use cairo_scaled_font_text_to_glyphs() to calculate the
extents, since the cairo_scaled_font_text_extents() will leave the
scaled font in an error state, which is impossible to recuperate from.
This commit is contained in:
Daniel Eklöf 2019-01-17 20:18:46 +01:00
parent 1bbdaf145f
commit 09270c4670

View file

@ -34,11 +34,26 @@ begin_expose(struct exposable *exposable)
struct eprivate *e = exposable->private; struct eprivate *e = exposable->private;
cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font); cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font);
cairo_scaled_font_text_extents(scaled, e->text, &e->extents);
cairo_glyph_t *glyphs = NULL;
int num_glyphs;
cairo_status_t status = cairo_scaled_font_text_to_glyphs(
scaled, 0, 0, e->text, -1, &glyphs, &num_glyphs, NULL, NULL, NULL);
if (status != CAIRO_STATUS_SUCCESS) {
LOG_WARN("failed to convert \"%s\" to glyphs: %s",
e->text, cairo_status_to_string(status));
memset(&e->extents, 0, sizeof(e->extents));
exposable->width = 0;
} else {
cairo_scaled_font_glyph_extents(scaled, glyphs, num_glyphs, &e->extents);
cairo_glyph_free(glyphs);
exposable->width = (exposable->particle->left_margin + exposable->width = (exposable->particle->left_margin +
e->extents.x_advance + e->extents.x_advance +
exposable->particle->right_margin); exposable->particle->right_margin);
}
return exposable->width; return exposable->width;
} }
@ -57,13 +72,15 @@ expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
cairo_text_cluster_t *clusters = NULL; cairo_text_cluster_t *clusters = NULL;
cairo_text_cluster_flags_t cluster_flags; cairo_text_cluster_flags_t cluster_flags;
int num_glyphs, num_clusters; int num_glyphs, num_clusters;
cairo_scaled_font_text_to_glyphs(
cairo_status_t status = cairo_scaled_font_text_to_glyphs(
scaled, scaled,
x + exposable->particle->left_margin, x + exposable->particle->left_margin,
(double)y + ((double)height - e->extents.height) / 2 - e->extents.y_bearing, (double)y + ((double)height - e->extents.height) / 2 - e->extents.y_bearing,
e->text, text_len, &glyphs, &num_glyphs, e->text, text_len, &glyphs, &num_glyphs,
&clusters, &num_clusters, &cluster_flags); &clusters, &num_clusters, &cluster_flags);
if (status == CAIRO_STATUS_SUCCESS) {
cairo_set_scaled_font(cr, scaled); cairo_set_scaled_font(cr, scaled);
cairo_set_source_rgba(cr, cairo_set_source_rgba(cr,
exposable->particle->foreground.red, exposable->particle->foreground.red,
@ -79,6 +96,7 @@ expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
cairo_glyph_free(glyphs); cairo_glyph_free(glyphs);
cairo_text_cluster_free(clusters); cairo_text_cluster_free(clusters);
} }
}
static struct exposable * static struct exposable *
instantiate(const struct particle *particle, const struct tag_set *tags) instantiate(const struct particle *particle, const struct tag_set *tags)