forked from external/yambar
particle/string: re-use glyphs calculated in begin_expose()
In begin_expose(), we call cairo_scaled_font_text_to_glyphs() with (x,y) = (0,0), in order to calculate the glyph extents (needed for width calculation). Then, in expose(), we called it again, but with correct (x,y) offsets. Simplify this, by caching the glyphs from begin_expose(). Then, in expose(), simply adjust the glyph offsets before calling cairo_show_text_glyphs().
This commit is contained in:
parent
b1453fd65e
commit
5a0d192ec1
1 changed files with 40 additions and 34 deletions
|
@ -15,8 +15,16 @@ struct private {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct eprivate {
|
struct eprivate {
|
||||||
|
/* Set when instantiating */
|
||||||
char *text;
|
char *text;
|
||||||
|
|
||||||
|
/* Set in begin_expose() */
|
||||||
cairo_text_extents_t extents;
|
cairo_text_extents_t extents;
|
||||||
|
cairo_glyph_t *glyphs;
|
||||||
|
cairo_text_cluster_t *clusters;
|
||||||
|
cairo_text_cluster_flags_t cluster_flags;
|
||||||
|
int num_glyphs;
|
||||||
|
int num_clusters;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -34,21 +42,21 @@ 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_glyph_t *glyphs = NULL;
|
|
||||||
int num_glyphs;
|
|
||||||
cairo_status_t status = cairo_scaled_font_text_to_glyphs(
|
cairo_status_t status = cairo_scaled_font_text_to_glyphs(
|
||||||
scaled, 0, 0, e->text, -1, &glyphs, &num_glyphs, NULL, NULL, NULL);
|
scaled, 0, 0, e->text, -1, &e->glyphs, &e->num_glyphs,
|
||||||
|
&e->clusters, &e->num_clusters, &e->cluster_flags);
|
||||||
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS) {
|
if (status != CAIRO_STATUS_SUCCESS) {
|
||||||
LOG_WARN("failed to convert \"%s\" to glyphs: %s",
|
LOG_WARN("failed to convert \"%s\" to glyphs: %s",
|
||||||
e->text, cairo_status_to_string(status));
|
e->text, cairo_status_to_string(status));
|
||||||
|
|
||||||
|
e->num_glyphs = -1;
|
||||||
|
e->num_clusters = -1;
|
||||||
memset(&e->extents, 0, sizeof(e->extents));
|
memset(&e->extents, 0, sizeof(e->extents));
|
||||||
exposable->width = 0;
|
exposable->width = 0;
|
||||||
} else {
|
} else {
|
||||||
cairo_scaled_font_glyph_extents(scaled, glyphs, num_glyphs, &e->extents);
|
cairo_scaled_font_glyph_extents(
|
||||||
cairo_glyph_free(glyphs);
|
scaled, e->glyphs, e->num_glyphs, &e->extents);
|
||||||
|
|
||||||
exposable->width = (exposable->particle->left_margin +
|
exposable->width = (exposable->particle->left_margin +
|
||||||
e->extents.x_advance +
|
e->extents.x_advance +
|
||||||
|
@ -64,23 +72,18 @@ expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
|
||||||
exposable_render_deco(exposable, cr, x, y, height);
|
exposable_render_deco(exposable, cr, x, y, height);
|
||||||
|
|
||||||
const struct eprivate *e = exposable->private;
|
const struct eprivate *e = exposable->private;
|
||||||
const size_t text_len = strlen(e->text);
|
|
||||||
|
if (e->num_glyphs == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Adjust glyph offsets */
|
||||||
|
for (int i = 0; i < e->num_glyphs; i++) {
|
||||||
|
e->glyphs[i].x += x + exposable->particle->left_margin;
|
||||||
|
e->glyphs[i].y += (double)y +
|
||||||
|
((double)height - e->extents.height) / 2 - e->extents.y_bearing;
|
||||||
|
}
|
||||||
|
|
||||||
cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font);
|
cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font);
|
||||||
|
|
||||||
cairo_glyph_t *glyphs = NULL;
|
|
||||||
cairo_text_cluster_t *clusters = NULL;
|
|
||||||
cairo_text_cluster_flags_t cluster_flags;
|
|
||||||
int num_glyphs, num_clusters;
|
|
||||||
|
|
||||||
cairo_status_t status = cairo_scaled_font_text_to_glyphs(
|
|
||||||
scaled,
|
|
||||||
x + exposable->particle->left_margin,
|
|
||||||
(double)y + ((double)height - e->extents.height) / 2 - e->extents.y_bearing,
|
|
||||||
e->text, text_len, &glyphs, &num_glyphs,
|
|
||||||
&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,
|
||||||
|
@ -90,12 +93,11 @@ expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||||
|
|
||||||
cairo_show_text_glyphs(
|
cairo_show_text_glyphs(
|
||||||
cr, e->text, text_len, glyphs, num_glyphs,
|
cr, e->text, -1, e->glyphs, e->num_glyphs,
|
||||||
clusters, num_clusters, cluster_flags);
|
e->clusters, e->num_clusters, e->cluster_flags);
|
||||||
|
|
||||||
cairo_glyph_free(glyphs);
|
cairo_glyph_free(e->glyphs);
|
||||||
cairo_text_cluster_free(clusters);
|
cairo_text_cluster_free(e->clusters);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct exposable *
|
static struct exposable *
|
||||||
|
@ -106,6 +108,10 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
|
|
||||||
e->text = tags_expand_template(p->text, tags);
|
e->text = tags_expand_template(p->text, tags);
|
||||||
memset(&e->extents, 0, sizeof(e->extents));
|
memset(&e->extents, 0, sizeof(e->extents));
|
||||||
|
e->glyphs = NULL;
|
||||||
|
e->clusters = NULL;
|
||||||
|
e->num_glyphs = -1;
|
||||||
|
e->num_clusters = -1;
|
||||||
|
|
||||||
if (p->max_len > 0) {
|
if (p->max_len > 0) {
|
||||||
const size_t len = strlen(e->text);
|
const size_t len = strlen(e->text);
|
||||||
|
|
Loading…
Add table
Reference in a new issue