MATH Table: Add API to access glyph info.

This commit is contained in:
Frédéric Wang 2016-08-25 11:15:31 +02:00 committed by Behdad Esfahbod
parent 6fd2fe418d
commit d7182d1296
8 changed files with 563 additions and 2 deletions

View File

@ -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> coverage; /* Offset to Coverage table -
from the beginning of
MathItalicsCorrectionInfo
table. */
ArrayOf<MathValueRecord> 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<Coverage> topAccentCoverage; /* Offset to Coverage table -
from the beginning of
MathTopAccentAttachment
table. */
ArrayOf<MathValueRecord> 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> 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<Coverage> mathKernCoverage; /* Offset to Coverage table -
from the beginning of the
MathKernInfo table. */
ArrayOf<MathKernInfoRecord> 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> mathItalicsCorrectionInfo;
/* Offset to MathTopAccentAttachment table -
from the beginning of MathGlyphInfo table. */
OffsetTo<MathTopAccentAttachment> 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<Coverage> extendedShapeCoverage;
/* Offset to MathKernInfo table -
from the beginning of MathGlyphInfo table. */
OffsetTo<MathKernInfo> 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; /* MathConstants table */
OffsetTo<MathGlyphInfo> mathGlyphInfo; /* MathGlyphInfo table */
public:
DEFINE_SIZE_STATIC (6);
DEFINE_SIZE_STATIC (8);
};
} /* mathspace OT */

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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();
}