From 78ff95ea4db5ba076311bd751941a885da18912d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 2 Nov 2021 16:37:36 +0100 Subject: [PATCH] WIP: Disable subpixel positioning when hinted Fully hinted doesn't really mesh well with subpixel positioning as it doesn't handle the glyph being moved around in non-integer steps. So do what others do and disable subpixel positioning for anything but the slightest hinting. --- src/cairo-ft-font.c | 4 +++- src/cairo-scaled-font.c | 10 ++++++++++ test/text-subpixel.c | 26 +++++++++++++++++--------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 683ee916d..984e99589 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2473,7 +2473,9 @@ _cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font, if (vertical_layout) _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, face->glyph); - if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { + if ((face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) && + ((scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) || + (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_SLIGHT))) { FT_Pos xshift, yshift; xshift = _cairo_scaled_glyph_xphase (scaled_glyph) << 4; diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index e0b586589..1badf30b7 100755 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -2183,9 +2183,14 @@ _cairo_scaled_font_single_glyph_device_extents (cairo_scaled_font_t *scaled_fon &scaled_glyph); if (likely (status == CAIRO_STATUS_SUCCESS)) { cairo_bool_t round_xy = _cairo_font_options_get_round_glyph_positions (&scaled_font->options) == CAIRO_ROUND_GLYPH_POS_ON; + cairo_hint_style_t hint_style = cairo_font_options_get_hint_style (&scaled_font->options); cairo_box_t box; cairo_fixed_t v; + if ((hint_style == CAIRO_HINT_STYLE_NONE) || + (hint_style == CAIRO_HINT_STYLE_SLIGHT)) + round_xy = TRUE; + if (round_xy) v = _cairo_fixed_from_int (_cairo_lround (glyph->x)); else @@ -2221,6 +2226,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, cairo_scaled_glyph_t *glyph_cache[64]; cairo_bool_t overlap = overlap_out ? FALSE : TRUE; cairo_round_glyph_positions_t round_glyph_positions = _cairo_font_options_get_round_glyph_positions (&scaled_font->options); + cairo_hint_style_t hint_style = cairo_font_options_get_hint_style (&scaled_font->options); int i; if (unlikely (scaled_font->status)) @@ -2234,6 +2240,10 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, extents); } + if ((hint_style == CAIRO_HINT_STYLE_NONE) || + (hint_style == CAIRO_HINT_STYLE_SLIGHT)) + round_glyph_positions = CAIRO_ROUND_GLYPH_POS_ON; + _cairo_scaled_font_freeze_cache (scaled_font); memset (glyph_cache, 0, sizeof (glyph_cache)); diff --git a/test/text-subpixel.c b/test/text-subpixel.c index 3ea63b950..f9fdf5f61 100644 --- a/test/text-subpixel.c +++ b/test/text-subpixel.c @@ -26,16 +26,13 @@ #include "cairo-test.h" #define WIDTH 300 -#define HEIGHT 200 +#define HEIGHT 300 * 4 -static cairo_test_status_t -draw (cairo_t *cr, int width, int height) +static void +do_subtest(cairo_t *cr, double y, cairo_hint_style_t hint_style) { cairo_font_options_t *font_options; - double size, y; - - cairo_set_source_rgb (cr, 1, 1, 1); - cairo_paint (cr); + double size; cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY "DejaVu Sans Mono", CAIRO_FONT_SLANT_NORMAL, @@ -44,11 +41,10 @@ draw (cairo_t *cr, int width, int height) font_options = cairo_font_options_create(); cairo_get_font_options (cr, font_options); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); - cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); + cairo_font_options_set_hint_style (font_options, hint_style); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); - y = 0.0; cairo_set_source_rgb (cr, 0, 0, 0); for (size = 10.0; size <= 40.0; size += 3.3) { cairo_set_font_size (cr, size); @@ -56,6 +52,18 @@ draw (cairo_t *cr, int width, int height) cairo_move_to (cr, 5, y); cairo_show_text (cr, "aaaaaaaaaa"); } +} + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + + do_subtest(cr, 0.0, CAIRO_HINT_STYLE_NONE); + do_subtest(cr, 300.0, CAIRO_HINT_STYLE_SLIGHT); + do_subtest(cr, 600.0, CAIRO_HINT_STYLE_MEDIUM); + do_subtest(cr, 900.0, CAIRO_HINT_STYLE_FULL); return CAIRO_TEST_SUCCESS; }