diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index e65680b5a..2eb0d9228 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -159,6 +159,267 @@ public: DEFINE_SIZE_STATIC (214); }; +struct MathItalicsCorrectionInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + coverage.sanitize (c, this) && + italicsCorrection.sanitize (c, this)); + } + + inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, + hb_position_t &value) const + { + unsigned int index = (this+coverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= italicsCorrection.len)) return false; + value = italicsCorrection[index].get_x_value(font, this); + return true; + } + +protected: + OffsetTo coverage; /* Offset to Coverage table - + from the beginning of + MathItalicsCorrectionInfo + table. */ + ArrayOf italicsCorrection; /* Array of MathValueRecords + defining italics correction + values for each + covered glyph. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, italicsCorrection); +}; + +struct MathTopAccentAttachment +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + topAccentCoverage.sanitize (c, this) && + topAccentAttachment.sanitize (c, this)); + } + + inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, + hb_position_t &value) const + { + unsigned int index = (this+topAccentCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= topAccentAttachment.len)) return false; + value = topAccentAttachment[index].get_x_value(font, this); + return true; + } + +protected: + OffsetTo topAccentCoverage; /* Offset to Coverage table - + from the beginning of + MathTopAccentAttachment + table. */ + ArrayOf topAccentAttachment; /* Array of MathValueRecords + defining top accent + attachment points for each + covered glyph. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); +}; + +struct MathKern +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = 2 * heightCount + 1; + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (mathValueRecords, + mathValueRecords[0].static_size, + 2 * heightCount + 1) && + sanitize_math_value_records (c)); + } + + inline hb_position_t get_value (hb_font_t *font, + hb_position_t &correction_height) const + { + const MathValueRecord* correctionHeight = mathValueRecords; + const MathValueRecord* kernValue = mathValueRecords + heightCount; + // 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: + unsigned int count = heightCount; + unsigned int i = 0; + while (count > 0) { + unsigned int half = count / 2; + hb_position_t height = + correctionHeight[i + half].get_y_value(font, this); + if (height < correction_height) { + i += half + 1; + count -= half + 1; + } else + count = half; + } + return kernValue[i].get_x_value(font, this); + } + +protected: + USHORT heightCount; + MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at + which the kern value changes. + Sorted by the height value in + design units. */ + /* Array of kern values corresponding + to heights. */ + +public: + DEFINE_SIZE_ARRAY (2, mathValueRecords); +}; + +struct MathKernInfoRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKern[HB_OT_MATH_KERN_TOP_RIGHT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_TOP_LEFT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_BOTTOM_RIGHT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT].sanitize (c, base)); + } + + inline bool has_math_kern (hb_ot_math_kern_t kern) const { + return mathKern[kern] != 0; + } + inline const MathKern &get_math_kern (hb_ot_math_kern_t kern, + const void *base) const { + return base+mathKern[kern]; + } + +protected: + /* Offset to MathKern table for each corner - + from the beginning of MathKernInfo table. May be NULL. */ + OffsetTo mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT - + HB_OT_MATH_KERN_TOP_RIGHT + 1]; + +public: + DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_KERN_BOTTOM_LEFT - + HB_OT_MATH_KERN_TOP_RIGHT + 1)); +}; + +struct MathKernInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKernCoverage.sanitize (c, this) && + mathKernInfoRecords.sanitize (c, this)); + } + + inline bool + get_math_kern_info_record (hb_codepoint_t glyph, + const MathKernInfoRecord *&record) const + { + unsigned int index = (this+mathKernCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= mathKernInfoRecords.len)) return false; + record = &mathKernInfoRecords[index]; + return true; + } + +protected: + OffsetTo mathKernCoverage; /* Offset to Coverage table - + from the beginning of the + MathKernInfo table. */ + ArrayOf mathKernInfoRecords; /* Array of + MathKernInfoRecords, + per-glyph information for + mathematical positioning + of subscripts and + superscripts. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, mathKernInfoRecords); +}; + +struct MathGlyphInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathItalicsCorrectionInfo.sanitize (c, this) && + mathTopAccentAttachment.sanitize (c, this) && + extendedShapeCoverage.sanitize (c, this) && + mathKernInfo.sanitize(c, this)); + } + + inline bool has_math_italics_correction_info (void) const { + return mathItalicsCorrectionInfo != 0; + } + inline const MathItalicsCorrectionInfo& + get_math_italics_correction_info (void) const { + return this+mathItalicsCorrectionInfo; + } + + inline bool has_math_top_accent_attachment (void) const { + return mathTopAccentAttachment != 0; + } + inline const MathTopAccentAttachment& + get_math_top_accent_attachment (void) const { + return this+mathTopAccentAttachment; + } + + inline bool is_extended_shape (hb_codepoint_t glyph) const + { + if (likely (extendedShapeCoverage == 0)) return false; + unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + return true; + } + + inline bool has_math_kern_info (void) const { return mathKernInfo != 0; } + inline const MathKernInfo &get_math_kern_info (void) const { + return this+mathKernInfo; + } + +protected: + /* Offset to MathItalicsCorrectionInfo table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathItalicsCorrectionInfo; + + /* Offset to MathTopAccentAttachment table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathTopAccentAttachment; + + /* Offset to coverage table for Extended Shape glyphs - + from the beginning of MathGlyphInfo table. When the left or right glyph of + a box is an extended shape variant, the (ink) box (and not the default + position defined by values in MathConstants table) should be used for + vertical positioning purposes. May be NULL.. */ + OffsetTo extendedShapeCoverage; + + /* Offset to MathKernInfo table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathKernInfo; + +public: + DEFINE_SIZE_STATIC (4 * 2); +}; + /* * MATH -- The MATH Table */ @@ -172,7 +433,8 @@ struct MATH TRACE_SANITIZE (this); return_trace (version.sanitize (c) && likely (version.major == 1) && - mathConstants.sanitize (c, this)); + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this)); } inline bool has_math_constants (void) const { return mathConstants != 0; } @@ -180,13 +442,18 @@ struct MATH return this+mathConstants; } + inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; } + inline const MathGlyphInfo &get_math_glyph_info (void) const { + return this+mathGlyphInfo; + } protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ OffsetTo mathConstants; /* MathConstants table */ + OffsetTo mathGlyphInfo; /* MathGlyphInfo table */ public: - DEFINE_SIZE_STATIC (6); + DEFINE_SIZE_STATIC (8); }; } /* mathspace OT */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 2ae138876..f14611b47 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1269,3 +1269,117 @@ hb_ot_layout_get_math_constant (hb_font_t *font, return math.has_math_constants() ? math.get_math_constants().get_value(font, constant) : 0; } + +/** + * hb_ot_layout_get_math_italic_correction: + * + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the italic correction of the glyph or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_italics_correction_info()) { + hb_position_t value; + if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, + value)) + return value; + } + } + return 0; +} + +/** + * hb_ot_layout_get_math_top_accent_attachment: + * + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the top accent attachment of the glyph or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_top_accent_attachment()) { + hb_position_t value; + if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, + value)) + return value; + } + } + return 0; +} + +/** + * hb_ot_layout_is_math_extended_shape: + * + * @font: a #hb_font_t to test + * @glyph: a glyph index to test + * + * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise + * + * Since: ???? + **/ +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (face); + return math.has_math_glyph_info() && + math.get_math_glyph_info().is_extended_shape(glyph); +} + +/** + * hb_ot_layout_get_math_kerning: + * + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * @kern: the #hb_ot_math_kern_t from which to retrieve the value + * @correction_height: the correction height to use to determine the kerning. + * + * This function tries to retrieve the MathKern table for the specified font, + * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the + * MathKern table to find one value that is greater or equal to specified + * correction_height. If one is found the corresponding value from the list of + * kerns is returned and otherwise the last kern value is returned. + * + * Return value: requested kerning or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_kern_info()) { + const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); + const OT::MathKernInfoRecord *kernInfoRecord; + if (kernInfo.get_math_kern_info_record(glyph, kernInfoRecord) && + kernInfoRecord->has_math_kern(kern)) { + return kernInfoRecord-> + get_math_kern(kern, &kernInfo).get_value(font, correction_height); + } + } + } + + return 0; +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 501082e28..ffb6321c7 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -310,6 +310,24 @@ HB_EXTERN hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, hb_ot_math_constant_t constant); +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); + HB_END_DECLS diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 7f0ec2713..a62b4b612 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -95,6 +95,13 @@ typedef enum { HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 } hb_ot_math_constant_t; +typedef enum { + HB_OT_MATH_KERN_TOP_RIGHT = 0, + HB_OT_MATH_KERN_TOP_LEFT = 1, + HB_OT_MATH_KERN_BOTTOM_RIGHT = 2, + HB_OT_MATH_KERN_BOTTOM_LEFT = 3 +} hb_ot_math_kern_t; + HB_END_DECLS #endif /* HB_OT_MATH_H */ diff --git a/test/api/fonts/MathTestFontPartial1.otf b/test/api/fonts/MathTestFontPartial1.otf new file mode 100644 index 000000000..b3bf36e33 Binary files /dev/null and b/test/api/fonts/MathTestFontPartial1.otf differ diff --git a/test/api/fonts/MathTestFontPartial2.otf b/test/api/fonts/MathTestFontPartial2.otf new file mode 100644 index 000000000..4607c1128 Binary files /dev/null and b/test/api/fonts/MathTestFontPartial2.otf differ diff --git a/test/api/fonts/MathTestFontPartial3.otf b/test/api/fonts/MathTestFontPartial3.otf new file mode 100644 index 000000000..ca18a9a22 Binary files /dev/null and b/test/api/fonts/MathTestFontPartial3.otf differ diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index 219959b65..5ba583f1b 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -160,6 +160,157 @@ test_get_math_constant (void) cleanupFreeType(); } +static void +test_get_math_italic_correction (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. + g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 197); + g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 150); + g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 452); + closeFont(); + + cleanupFreeType(); + +} + +static void +test_get_math_top_accent_attachment (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathTopAccentAttachment empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // Glyph without top accent attachment. + g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374); + g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 346); + g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 318); + closeFont(); + + cleanupFreeType(); +} + +static void +test_is_math_extended_shape (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); + g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); + g_assert(hb_ot_layout_is_math_extended_shape (hb_face, glyph)); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_math_kerning (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); + + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height + + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left + + closeFont(); + + cleanupFreeType(); +} + + int main (int argc, char **argv) { @@ -167,6 +318,10 @@ main (int argc, char **argv) hb_test_add (test_has_math_data); hb_test_add (test_get_math_constant); + hb_test_add (test_get_math_italic_correction); + hb_test_add (test_get_math_top_accent_attachment); + hb_test_add (test_is_math_extended_shape); + hb_test_add (test_get_math_kerning); return hb_test_run(); }