Merge branch 'matthiasc/for-main' into 'main'

gsk: Rework font reloading again

See merge request GNOME/gtk!7018
This commit is contained in:
Matthias Clasen 2024-03-12 11:47:20 +00:00
commit 91992111c3
4 changed files with 51 additions and 101 deletions

View File

@ -918,7 +918,13 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
return cache->image;
}
scaled_font = gsk_get_scaled_font (font, scale);
/* Note: we want to scale the font to the required size *and* ensure that
* metrics hinting is off. The latter is necessary since pango lets metrics
* hinting influence the rendering of hexboxes, and we get bad outcomes if
* that happens.
*/
scaled_font = gsk_reload_font (font, scale, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_STYLE_DEFAULT, CAIRO_ANTIALIAS_DEFAULT);
subpixel_x = (flags & 3) / 4.f;
subpixel_y = ((flags >> 2) & 3) / 4.f;
pango_font_get_glyph_extents (scaled_font, glyph, &ink_rect, NULL);

View File

@ -22,103 +22,27 @@ gsk_ensure_resources (void)
}
/*< private >
* gsk_get_scaled_font:
* @font: a `PangoFont`
* @scale: the scale
*
* Returns a font that is just like @font, at a size that
* is multiplied by @scale.
*
* Returns: (transfer full): a scaled version of @font
*/
PangoFont *
gsk_get_scaled_font (PangoFont *font,
float scale)
{
if (scale == 1.0)
return g_object_ref (font);
#if PANGO_VERSION_CHECK (1, 52, 0)
return pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, NULL, NULL);
#else
GHashTable *fonts;
int key;
PangoFont *font2;
PangoFontDescription *desc;
int size;
PangoFontMap *fontmap;
PangoContext *context;
cairo_scaled_font_t *sf;
cairo_font_options_t *options;
FcPattern *pattern;
double dpi;
key = (int) floor (scale * PANGO_SCALE + .5);
fonts = (GHashTable *) g_object_get_data (G_OBJECT (font), "gsk-scaled-fonts");
if (fonts)
{
font2 = g_hash_table_lookup (fonts, GINT_TO_POINTER (key));
if (font2)
return g_object_ref (font2);
}
else
{
fonts = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
g_object_set_data_full (G_OBJECT (font), "gsk-scaled-fonts",
fonts, (GDestroyNotify) g_hash_table_unref);
}
desc = pango_font_describe (font);
size = pango_font_description_get_size (desc);
if (pango_font_description_get_size_is_absolute (desc))
pango_font_description_set_absolute_size (desc, size * scale);
else
pango_font_description_set_size (desc, (int) floor (size * scale + .5));
fontmap = pango_font_get_font_map (font);
context = pango_font_map_create_context (fontmap);
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
options = cairo_font_options_create ();
cairo_scaled_font_get_font_options (sf, options);
pango_cairo_context_set_font_options (context, options);
cairo_font_options_destroy (options);
pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultMatch)
pango_cairo_context_set_resolution (context, dpi);
font2 = pango_font_map_load_font (fontmap, context, desc);
pango_font_description_free (desc);
g_object_unref (context);
g_hash_table_insert (fonts, GINT_TO_POINTER (key), font2);
return g_object_ref (font2);
#endif
}
/*< private >
* gsk_get_hinted_font:
* gsk_reload_font:
* @font: a `PangoFont`
* @scale: the scale to apply
* @hint_metris: hint metrics to use or `CAIRO_HINT_METRICS_DEFAILT` to keep the
* hint metrics of the font unchanged
* @hint_style: hint style to use or `CAIRO_HINT_STYLE_DEFAULT` to keep the
* hint style of @font unchanged
* @antialias: antialiasing to use, or `CAIRO_ANTIALIAS_DEFAULT` to keep the
* antialias option of @font unchanged
*
* Returns a font that is just like @font, but uses the
* given hinting options for its glyphs and metrics.
* given scale and hinting options for its glyphs and metrics.
*
* Returns: (transfer full): the modified `PangoFont`
*/
PangoFont *
gsk_get_hinted_font (PangoFont *font,
cairo_hint_style_t hint_style,
cairo_antialias_t antialias)
gsk_reload_font (PangoFont *font,
float scale,
cairo_hint_metrics_t hint_metrics,
cairo_hint_style_t hint_style,
cairo_antialias_t antialias)
{
cairo_font_options_t *options;
cairo_scaled_font_t *sf;
@ -127,24 +51,32 @@ gsk_get_hinted_font (PangoFont *font,
PangoFontDescription *desc;
FcPattern *pattern;
double dpi;
int size;
#endif
/* These requests often come in sequentially so keep the result
* around and re-use it if everything matches.
*/
static PangoFont *last_font;
static float last_scale;
static cairo_hint_metrics_t last_hint_metrics;
static cairo_hint_style_t last_hint_style;
static cairo_antialias_t last_antialias;
static PangoFont *last_result;
if (last_result != NULL &&
last_font == font &&
last_scale == scale &&
last_hint_metrics == hint_metrics &&
last_hint_style == hint_style &&
last_antialias == antialias)
return g_object_ref (last_result);
last_scale = scale;
last_hint_metrics = hint_metrics;
last_hint_style = hint_style;
last_antialias = antialias;
g_set_object (&last_font, font);
g_clear_object (&last_result);
@ -152,15 +84,19 @@ gsk_get_hinted_font (PangoFont *font,
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
cairo_scaled_font_get_font_options (sf, options);
if (hint_metrics == CAIRO_HINT_METRICS_DEFAULT)
hint_metrics = cairo_font_options_get_hint_metrics (options);
if (hint_style == CAIRO_HINT_STYLE_DEFAULT)
hint_style = cairo_font_options_get_hint_style (options);
if (antialias == CAIRO_ANTIALIAS_DEFAULT)
antialias = cairo_font_options_get_antialias (options);
if (cairo_font_options_get_hint_style (options) == hint_style &&
if (1.0 == scale &&
cairo_font_options_get_hint_metrics (options) == hint_metrics &&
cairo_font_options_get_hint_style (options) == hint_style &&
cairo_font_options_get_antialias (options) == antialias &&
cairo_font_options_get_hint_metrics (options) == CAIRO_HINT_METRICS_OFF &&
cairo_font_options_get_subpixel_order (options) == CAIRO_SUBPIXEL_ORDER_DEFAULT)
{
last_result = g_object_ref (font);
@ -168,9 +104,9 @@ gsk_get_hinted_font (PangoFont *font,
return g_object_ref (font);
}
cairo_font_options_set_hint_metrics (options, hint_metrics);
cairo_font_options_set_hint_style (options, hint_style);
cairo_font_options_set_antialias (options, antialias);
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_subpixel_order (options, CAIRO_SUBPIXEL_ORDER_DEFAULT);
if (!context)
@ -180,7 +116,7 @@ gsk_get_hinted_font (PangoFont *font,
cairo_font_options_destroy (options);
#if PANGO_VERSION_CHECK (1, 52, 0)
last_result = pango_font_map_reload_font (pango_font_get_font_map (font), font, 1.0, context, NULL);
last_result = pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, context, NULL);
#else
pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
@ -188,6 +124,13 @@ gsk_get_hinted_font (PangoFont *font,
pango_cairo_context_set_resolution (context, dpi);
desc = pango_font_describe (font);
size = pango_font_description_get_size (desc);
if (pango_font_description_get_size_is_absolute (desc))
pango_font_description_set_absolute_size (desc, size * scale);
else
pango_font_description_set_size (desc, (int) floor (size * scale + .5));
last_result = pango_font_map_load_font (pango_font_get_font_map (font), context, desc);
pango_font_description_free (desc);
#endif
@ -213,9 +156,11 @@ gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
{
PangoFont *unhinted;
unhinted = gsk_get_hinted_font (font,
CAIRO_HINT_STYLE_NONE,
CAIRO_ANTIALIAS_DEFAULT);
unhinted = gsk_reload_font (font,
1.0,
CAIRO_HINT_METRICS_OFF,
CAIRO_HINT_STYLE_NONE,
CAIRO_ANTIALIAS_DEFAULT);
pango_glyph_string_extents (glyphs, unhinted, ink_rect, NULL);

View File

@ -8,12 +8,11 @@ G_BEGIN_DECLS
void gsk_ensure_resources (void);
PangoFont *gsk_get_scaled_font (PangoFont *font,
float scale);
PangoFont *gsk_get_hinted_font (PangoFont *font,
cairo_hint_style_t hint_style,
cairo_antialias_t antialias);
PangoFont *gsk_reload_font (PangoFont *font,
float scale,
cairo_hint_metrics_t hint_metrics,
cairo_hint_style_t hint_style,
cairo_antialias_t antialias);
void gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
PangoFont *font,

View File

@ -2345,7 +2345,7 @@ parse_text_node (GtkCssParser *parser,
g_assert (font);
}
hinted = gsk_get_hinted_font (font, hint_style, antialias);
hinted = gsk_reload_font (font, 1.0, CAIRO_HINT_METRICS_OFF, hint_style, antialias);
g_object_unref (font);
font = hinted;