diff --git a/gsk/gl/gskglglyphylibrary.c b/gsk/gl/gskglglyphylibrary.c index b86561a9a3..0478e59bed 100644 --- a/gsk/gl/gskglglyphylibrary.c +++ b/gsk/gl/gskglglyphylibrary.c @@ -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 */ diff --git a/gsk/gl/gskglglyphylibraryprivate.h b/gsk/gl/gskglglyphylibraryprivate.h index 7bd83a5640..fece808bcd 100644 --- a/gsk/gl/gskglglyphylibraryprivate.h +++ b/gsk/gl/gskglglyphylibraryprivate.h @@ -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; } diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c index 5cbd3040d1..07c2acbdab 100644 --- a/gsk/gl/gskglrenderjob.c +++ b/gsk/gl/gskglrenderjob.c @@ -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);