font: use font-config to load font

This allows us to a) move away from cairo's "toy" API, and b) let the
user specify font options in a single font "name" string:

  Serif:size=10:weight=bold:slant=italic

This also allows us to simplify the font code significantly (except
for the fontconfig parts...); the font no longer sets itself in a
cairo surface - font users do that; the font simply returns a
cairo_scaled_font_t.

Furthermore, font_clone() has now been simplified to basically just
refcount the scaled font. I.e. there's no need to run the full
constructor and lookup and instantiate the cairo scaled font again.
This commit is contained in:
Daniel Eklöf 2019-01-09 18:30:35 +01:00
parent b52bdf14b2
commit f6977417e0
7 changed files with 167 additions and 111 deletions

View file

@ -4,33 +4,46 @@
#include <string.h>
#include <assert.h>
#define LOG_MODULE "string"
#define LOG_ENABLE_DBG 1
#include "../log.h"
struct private {
char *text;
size_t max_len;
struct font *font;
struct rgba foreground;
};
struct eprivate {
char *text;
const struct font *font;
struct rgba foreground;
cairo_text_extents_t extents;
};
static void
exposable_destroy(struct exposable *exposable)
{
struct private *e = exposable->private;
struct eprivate *e = exposable->private;
free(e->text);
free(e);
exposable_default_destroy(exposable);
}
static int
begin_expose(struct exposable *exposable, cairo_t *cr)
begin_expose(struct exposable *exposable)
{
const struct private *e = exposable->private;
struct eprivate *e = exposable->private;
cairo_scaled_font_t *scaled = font_use_in_cairo(e->font, cr);
cairo_text_extents_t extents;
cairo_scaled_font_text_extents(scaled, e->text, &extents);
cairo_scaled_font_t *scaled = font_scaled_font(e->font);
cairo_scaled_font_text_extents(scaled, e->text, &e->extents);
exposable->width = (exposable->particle->left_margin +
extents.x_advance +
e->extents.x_advance +
exposable->particle->right_margin);
return exposable->width;
@ -39,12 +52,12 @@ begin_expose(struct exposable *exposable, cairo_t *cr)
static void
expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
{
const struct private *e = exposable->private;
exposable_render_deco(exposable, cr, x, y, height);
cairo_scaled_font_t *scaled = font_use_in_cairo(e->font, cr);
const struct eprivate *e = exposable->private;
const size_t text_len = strlen(e->text);
cairo_text_extents_t extents;
cairo_scaled_font_text_extents(scaled, e->text, &extents);
cairo_scaled_font_t *scaled = font_scaled_font(e->font);
cairo_glyph_t *glyphs = NULL;
cairo_text_cluster_t *clusters = NULL;
@ -53,37 +66,47 @@ expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
cairo_scaled_font_text_to_glyphs(
scaled,
x + exposable->particle->left_margin,
(double)y + ((double)height - extents.y_bearing) / 2 + font_y_offset(e->font),
e->text, strlen(e->text), &glyphs, &num_glyphs,
(double)y + ((double)height - e->extents.height) / 2 - e->extents.y_bearing,
e->text, text_len, &glyphs, &num_glyphs,
&clusters, &num_clusters, &cluster_flags);
exposable_render_deco(exposable, cr, x, y, height);
cairo_set_scaled_font(cr, scaled);
cairo_set_source_rgba(cr,
e->foreground.red,
e->foreground.green,
e->foreground.blue,
e->foreground.alpha);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_show_text_glyphs(cr, e->text, strlen(e->text),
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags);
cairo_show_text_glyphs(
cr, e->text, text_len, glyphs, num_glyphs,
clusters, num_clusters, cluster_flags);
cairo_glyph_free(glyphs);
cairo_text_cluster_free(clusters);
/*cairo_scaled_font_destroy(scaled);*/
}
static struct exposable *
instantiate(const struct particle *particle, const struct tag_set *tags)
{
const struct private *p = particle->private;
struct private *e = malloc(sizeof(*e));
struct eprivate *e = malloc(sizeof(*e));
e->text = tags_expand_template(p->text, tags);
e->font = p->font;
e->foreground = p->foreground;
memset(&e->extents, 0, sizeof(e->extents));
if (p->max_len > 0) {
size_t len = strlen(e->text);
if (len > p->max_len) {
if (p->max_len >= 3) {
for (size_t i = 0; i < 3; i++)
e->text[p->max_len - 3 + i] = '.';
}
e->text[p->max_len] = '\0';
}
}
char *on_click = tags_expand_template(particle->on_click_template, tags);
@ -108,12 +131,13 @@ particle_destroy(struct particle *particle)
}
struct particle *
particle_string_new(const char *text, struct font *font,
particle_string_new(const char *text, size_t max_len, struct font *font,
struct rgba foreground, int left_margin, int right_margin,
const char *on_click_template)
{
struct private *p = malloc(sizeof(*p));
p->text = strdup(text);
p->max_len = max_len;
p->font = font;
p->foreground = foreground;

View file

@ -2,5 +2,5 @@
#include "../particle.h"
struct particle *particle_string_new(
const char *text, struct font *font, struct rgba foreground,
const char *text, size_t max_len, struct font *font, struct rgba foreground,
int left_margin, int right_margin, const char *on_click_template);