diff options
author | Calvin Walton <calvin.walton@kepstin.ca> | 2023-02-28 18:34:05 +0100 |
---|---|---|
committer | Christian Persch <chpe@src.gnome.org> | 2023-02-28 18:34:05 +0100 |
commit | e343088f9d02be69c2ff377566b942553e6e21fd (patch) | |
tree | 549faf0fb5cdc3b3b817bfb717504bee23d0e1ff /src | |
parent | e8dcb5e0187f10dce9bdc67af66cff31f8dc630b (diff) | |
download | vte-e343088f9d02be69c2ff377566b942553e6e21fd.tar.gz |
widget: gtk4: Hint and quantize font metrics
With gtk4, the font metrics are unhinted by default. This causes
problems when measuring the font, since the width or height may
have fractional pixel values that get rounded up - resulting in
vte using integer cell sizes that are larger than would be
appropriate for the font - the usual side-effect is that horizontal
letter spacing looks too wide.
To fix this, set the cairo font option to hint vertical metrics,
which will result in the glyph ascent and descent values both being
integers.
Also make pango round glyph positions, so that the horizontal advance
of the glyphs will be integers appropirate for a renderer that doesn't
do sub-pixel glyph positioning.
Fixes: https://gitlab.gnome.org/GNOME/vte/-/issues/2573
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo-glue.hh | 1 | ||||
-rw-r--r-- | src/fonts-pangocairo.cc | 40 |
2 files changed, 33 insertions, 8 deletions
diff --git a/src/cairo-glue.hh b/src/cairo-glue.hh index 168356ab..6f10d9c0 100644 --- a/src/cairo-glue.hh +++ b/src/cairo-glue.hh @@ -23,6 +23,7 @@ namespace vte { +VTE_DECLARE_FREEABLE(cairo_font_options_t, cairo_font_options_destroy); VTE_DECLARE_FREEABLE(cairo_rectangle_list_t, cairo_rectangle_list_destroy); VTE_DECLARE_FREEABLE(cairo_region_t, cairo_region_destroy); VTE_DECLARE_FREEABLE(cairo_surface_t, cairo_surface_destroy); diff --git a/src/fonts-pangocairo.cc b/src/fonts-pangocairo.cc index 8d0cb2a3..98f1ab08 100644 --- a/src/fonts-pangocairo.cc +++ b/src/fonts-pangocairo.cc @@ -20,6 +20,7 @@ #include "fonts-pangocairo.hh" +#include "cairo-glue.hh" #include "debug.h" #include "vtedefines.hh" @@ -365,17 +366,40 @@ FontInfo::create_for_context(vte::glib::RefPtr<PangoContext> context, language != pango_context_get_language(context.get())) pango_context_set_language(context.get(), language); - /* Make sure our contexts have a font_options set. We use - * this invariant in our context hash and equal functions. - */ - if (!pango_cairo_context_get_font_options(context.get())) { - cairo_font_options_t *font_options; + // Ensure Pango and cairo are configured to quantize and hint font metrics. + // Terminal cells in vte have integer pixel sizes. If Pango is configured to do sub-pixel + // glyph advances, a small fractional part might get rounded up to a whole pixel - so the + // character spacing will appear too wide. Setting the cairo hint metrics option ensures + // that there are integer numbers of pixels both above and below the baseline. + { + auto font_options = vte::take_freeable(cairo_font_options_create()); +#if VTE_GTK == 4 + cairo_font_options_set_hint_metrics(font_options.get(), + CAIRO_HINT_METRICS_ON); +#endif /* VTE_GTK == 4 */ + + if (auto const ctx_font_options = + pango_cairo_context_get_font_options(context.get())) { + auto const merged_font_options = + vte::take_freeable(cairo_font_options_copy(ctx_font_options)); + cairo_font_options_merge(merged_font_options.get(), + font_options.get()); + pango_cairo_context_set_font_options(context.get(), + merged_font_options.get()); + } else { + // Make sure our contexts have a font_options set. We use + // this invariant in our context hash and equal functions. + pango_cairo_context_set_font_options(context.get(), + font_options.get()); + } - font_options = cairo_font_options_create (); - pango_cairo_context_set_font_options(context.get(), font_options); - cairo_font_options_destroy (font_options); +#if VTE_GTK == 4 + pango_context_set_round_glyph_positions (context.get(), true); +#endif /* VTE_GTK == 4 */ } + pango_context_changed (context.get()); + if (G_UNLIKELY(s_font_info_for_context == nullptr)) s_font_info_for_context = g_hash_table_new((GHashFunc) context_hash, (GEqualFunc) context_equal); |