glyphy: Make glyphy cache size-independent

Use a hb font at nominal size when generating sdf
contours, and use a cache key that is independent
of the size.
This commit is contained in:
Matthias Clasen
2022-03-19 14:32:03 -04:00
parent ad9d916dfd
commit a3d82174e6
3 changed files with 84 additions and 23 deletions

View File

@@ -89,11 +89,7 @@ gsk_gl_glyphy_key_hash (gconstpointer data)
* for us.
*/
#if GLIB_SIZEOF_VOID_P == 4
return (guint)(GPOINTER_TO_SIZE (key->font) << 6) ^ key->glyph;
#else
return (guint)(GPOINTER_TO_SIZE (key->font) << 5) ^ key->glyph;
#endif
return (key->font << 8) ^ key->glyph;
}
static gboolean
@@ -108,7 +104,6 @@ gsk_gl_glyphy_key_free (gpointer data)
{
GskGLGlyphyKey *key = data;
g_clear_object (&key->font);
g_slice_free (GskGLGlyphyKey, key);
}
@@ -197,12 +192,16 @@ gsk_gl_glyphy_library_finalize (GObject *object)
G_OBJECT_CLASS (gsk_gl_glyphy_library_parent_class)->finalize (object);
}
GQuark quark_glyphy_font_key;
static void
gsk_gl_glyphy_library_class_init (GskGLGlyphyLibraryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GskGLTextureLibraryClass *library_class = GSK_GL_TEXTURE_LIBRARY_CLASS (klass);
quark_glyphy_font_key = g_quark_from_static_string ("glyphy-font-key");
object_class->finalize = gsk_gl_glyphy_library_finalize;
library_class->allocate = gsk_gl_glyphy_library_allocate;
@@ -294,16 +293,39 @@ encode_glyph (GskGLGlyphyLibrary *self,
return TRUE;
}
static inline hb_font_t *
get_nominal_size_hb_font (PangoFont *font)
{
hb_font_t *hbfont;
const float *coords;
unsigned int length;
hbfont = (hb_font_t *) g_object_get_data ((GObject *)font, "glyph-nominal-size-font");
if (hbfont == NULL)
{
hbfont = hb_font_create (hb_font_get_face (pango_font_get_hb_font (font)));
coords = hb_font_get_var_coords_design (pango_font_get_hb_font (font), &length);
if (length > 0)
hb_font_set_var_coords_design (hbfont, coords, length);
g_object_set_data_full ((GObject *)font, "glyphy-nominal-size-font",
hbfont, (GDestroyNotify)hb_font_destroy);
}
return hbfont;
}
gboolean
gsk_gl_glyphy_library_add (GskGLGlyphyLibrary *self,
GskGLGlyphyKey *key,
PangoFont *font,
const GskGLGlyphyValue **out_value)
{
static glyphy_rgba_t buffer[4096 * 16];
GskGLTextureLibrary *tl = (GskGLTextureLibrary *)self;
GskGLGlyphyValue *value;
glyphy_extents_t extents;
hb_font_t *font;
hb_font_t *hbfont;
guint packed_x;
guint packed_y;
guint nominal_w, nominal_h;
@@ -313,15 +335,15 @@ gsk_gl_glyphy_library_add (GskGLGlyphyLibrary *self,
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (self));
g_assert (key != NULL);
g_assert (key->font != NULL);
g_assert (font != NULL);
g_assert (out_value != NULL);
hbfont = get_nominal_size_hb_font (font);
/* Convert the glyph to a list of arcs */
font = pango_font_get_hb_font (key->font);
if (!encode_glyph (self, font, key->glyph, TOLERANCE,
if (!encode_glyph (self, hbfont, key->glyph, TOLERANCE,
buffer, sizeof buffer, &output_len,
&nominal_w, &nominal_h,
&extents))
&nominal_w, &nominal_h, &extents))
return FALSE;
/* Allocate space for list within atlas */

View File

@@ -30,9 +30,44 @@ G_BEGIN_DECLS
#define GSK_TYPE_GL_GLYPHY_LIBRARY (gsk_gl_glyphy_library_get_type())
typedef guint FontKey;
extern GQuark quark_glyphy_font_key;
static inline FontKey
gsk_gl_glyphy_library_get_font_key (PangoFont *font)
{
FontKey key;
key = (FontKey) GPOINTER_TO_UINT (g_object_get_qdata ((GObject *)font, quark_glyphy_font_key));
if (key == 0)
{
PangoFontDescription *desc = pango_font_describe (font);
pango_font_description_set_size (desc, 10 * PANGO_SCALE);
key = (FontKey) pango_font_description_hash (desc);
pango_font_description_free (desc);
g_object_set_qdata ((GObject *)font, quark_glyphy_font_key, GUINT_TO_POINTER (key));
}
return key;
}
static inline float
gsk_gl_glyphy_library_get_font_scale (PangoFont *font)
{
hb_font_t *hbfont;
int x_scale, y_scale;
hbfont = pango_font_get_hb_font (font);
hb_font_get_scale (hbfont, &x_scale, &y_scale);
return MAX (x_scale, y_scale) / 1000.0;
}
typedef struct _GskGLGlyphyKey
{
PangoFont *font;
FontKey font;
PangoGlyph glyph;
} GskGLGlyphyKey;
@@ -69,11 +104,13 @@ struct _GskGLGlyphyLibrary
GskGLGlyphyLibrary *gsk_gl_glyphy_library_new (GskGLDriver *driver);
gboolean gsk_gl_glyphy_library_add (GskGLGlyphyLibrary *self,
GskGLGlyphyKey *key,
PangoFont *font,
const GskGLGlyphyValue **out_value);
static inline guint
gsk_gl_glyphy_library_lookup_or_add (GskGLGlyphyLibrary *self,
const GskGLGlyphyKey *key,
PangoFont *font,
const GskGLGlyphyValue **out_value)
{
GskGLTextureAtlasEntry *entry;
@@ -92,8 +129,7 @@ gsk_gl_glyphy_library_lookup_or_add (GskGLGlyphyLibrary *self,
else
{
GskGLGlyphyKey *k = g_slice_copy (sizeof *key, key);
g_object_ref (k->font);
gsk_gl_glyphy_library_add (self, k, out_value);
gsk_gl_glyphy_library_add (self, k, font, out_value);
self->front[front_index].key = *key;
self->front[front_index].value = *out_value;
}

View File

@@ -3103,7 +3103,7 @@ typedef struct
float g16lo;
} EncodedGlyph;
static unsigned int
static inline unsigned int
glyph_encode (guint atlas_x , /* 7 bits */
guint atlas_y, /* 7 bits */
guint corner_x, /* 1 bit */
@@ -3126,7 +3126,7 @@ glyph_encode (guint atlas_x , /* 7 bits */
return (x << 16) | y;
}
static void
static inline void
encoded_glyph_init (EncodedGlyph *eg,
float x,
float y,
@@ -3160,7 +3160,7 @@ gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
const PangoGlyphInfo *gi;
GskGLGlyphyLibrary *library;
GskGLCommandBatch *batch;
const PangoFont *font;
PangoFont *font;
GskGLDrawVertex *vertices;
const guint16 *c;
GskGLGlyphyKey lookup;
@@ -3172,6 +3172,7 @@ gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
guint used = 0;
guint i;
int x_position = 0;
float font_scale;
g_assert (!gsk_text_node_has_color_glyphs (node));
@@ -3181,7 +3182,7 @@ gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
if (RGBA_IS_CLEAR (color))
return;
font = gsk_text_node_get_font (node);
font = (PangoFont *)gsk_text_node_get_font (node);
glyphs = gsk_text_node_get_glyphs (node, NULL);
library = job->driver->glyphy_library;
offset = gsk_text_node_get_offset (node);
@@ -3196,7 +3197,8 @@ gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
batch = gsk_gl_command_queue_get_batch (job->command_queue);
vertices = gsk_gl_command_queue_add_n_vertices (job->command_queue, num_glyphs);
lookup.font = (PangoFont *)font;
lookup.font = gsk_gl_glyphy_library_get_font_key (font);
font_scale = gsk_gl_glyphy_library_get_font_scale (font);
for (i = 0, gi = glyphs; i < num_glyphs; i++, gi++)
{
@@ -3205,7 +3207,8 @@ gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
guint texture_id;
lookup.glyph = gi->glyph;
texture_id = gsk_gl_glyphy_library_lookup_or_add (library, &lookup, &glyph);
texture_id = gsk_gl_glyphy_library_lookup_or_add (library, &lookup, font, &glyph);
if G_UNLIKELY (texture_id == 0)
continue;
@@ -3255,8 +3258,8 @@ gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
EncodedGlyph encoded[4];
#define ENCODE_CORNER(_cx, _cy) \
G_STMT_START { \
float _vx = x + cx + ((1-_cx) * glyph->extents.min_x + _cx * glyph->extents.max_x); \
float _vy = y + cy - ((1-_cy) * glyph->extents.min_y + _cy * glyph->extents.max_y); \
float _vx = x + cx + font_scale * ((1-_cx) * glyph->extents.min_x + _cx * glyph->extents.max_x); \
float _vy = y + cy - font_scale * ((1-_cy) * glyph->extents.min_y + _cy * glyph->extents.max_y); \
encoded_glyph_init (&encoded[_cx * 2 + _cy], _vx, _vy, _cx, _cy, glyph); \
} G_STMT_END
ENCODE_CORNER (0, 0);