From c17d67467f86fa491835cc50b9f454d825648407 Mon Sep 17 00:00:00 2001 From: Lie Yan Date: Sun, 7 Jan 2024 22:10:10 +0800 Subject: [PATCH] [ot-math] Fix a bug in MathKern::get_value() Fixes https://github.com/harfbuzz/harfbuzz/issues/4542 --- src/hb-ot-math-table.hh | 14 ++++++-------- test/api/test-ot-math.c | 8 ++++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh index 32e497aef..7abb44980 100644 --- a/src/hb-ot-math-table.hh +++ b/src/hb-ot-math-table.hh @@ -344,13 +344,11 @@ struct MathKern const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount; int sign = font->y_scale < 0 ? -1 : +1; - /* The description of the MathKern table is a ambiguous, but interpreting - * "between the two heights found at those indexes" for 0 < i < len as - * - * correctionHeight[i-1] < correction_height <= correctionHeight[i] - * - * makes the result consistent with the limit cases and we can just use the - * binary search algorithm of std::upper_bound: + /* According to OpenType spec (v1.9), except for the boundary cases, the index + * chosen for kern value should be i such that + * correctionHeight[i-1] <= correction_height < correctionHeight[i] + * We can just use the binary search algorithm of std::upper_bound(), which + * matches the spec, including for the boundary cases. */ unsigned int i = 0; unsigned int count = heightCount; @@ -358,7 +356,7 @@ struct MathKern { unsigned int half = count / 2; hb_position_t height = correctionHeight[i + half].get_y_value (font, this); - if (sign * height < sign * correction_height) + if (sign * height <= sign * correction_height) { i += half + 1; count -= half + 1; diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 6d87396e1..0f539f39b 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -313,12 +313,12 @@ test_get_glyph_kerning (void) g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 104); // equal to min height g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 146); g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 188); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 440); // equal to max height g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height