[ot-math] Add hb_ot_math_get_glyph_kernings

closes #3396
This commit is contained in:
Alexis King 2022-02-09 12:00:47 -06:00 committed by Behdad Esfahbod
parent 1bc4bad7a5
commit 81754a5a96
6 changed files with 230 additions and 0 deletions

View File

@ -546,6 +546,7 @@ HB_OT_TAG_MATH
HB_OT_TAG_MATH_SCRIPT HB_OT_TAG_MATH_SCRIPT
hb_ot_math_constant_t hb_ot_math_constant_t
hb_ot_math_kern_t hb_ot_math_kern_t
hb_ot_math_kern_entry_t
hb_ot_math_glyph_variant_t hb_ot_math_glyph_variant_t
hb_ot_math_glyph_part_flags_t hb_ot_math_glyph_part_flags_t
hb_ot_math_glyph_part_t hb_ot_math_glyph_part_t
@ -554,6 +555,7 @@ hb_ot_math_get_constant
hb_ot_math_get_glyph_italics_correction hb_ot_math_get_glyph_italics_correction
hb_ot_math_get_glyph_top_accent_attachment hb_ot_math_get_glyph_top_accent_attachment
hb_ot_math_get_glyph_kerning hb_ot_math_get_glyph_kerning
hb_ot_math_get_glyph_kernings
hb_ot_math_is_glyph_extended_shape hb_ot_math_is_glyph_extended_shape
hb_ot_math_get_glyph_variants hb_ot_math_get_glyph_variants
hb_ot_math_get_min_connector_overlap hb_ot_math_get_min_connector_overlap

View File

@ -369,6 +369,37 @@ struct MathKern
return kernValue[i].get_x_value (font, this); return kernValue[i].get_x_value (font, this);
} }
unsigned int get_entries (unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT */
hb_ot_math_kern_entry_t *kern_entries, /* OUT */
hb_font_t *font) const
{
const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
const unsigned int entriesCount = heightCount + 1;
if (entries_count)
{
unsigned int start = hb_min (start_offset, entriesCount);
unsigned int end = hb_min (start + *entries_count, entriesCount);
*entries_count = end - start;
for (unsigned int i = 0; i < *entries_count; i++) {
unsigned int j = start + i;
hb_position_t max_height;
if (j == heightCount) {
max_height = INT32_MAX;
} else {
max_height = correctionHeight[j].get_y_value (font, this);
}
kern_entries[i] = {max_height, kernValue[j].get_x_value (font, this)};
}
}
return entriesCount;
}
protected: protected:
HBUINT16 heightCount; HBUINT16 heightCount;
UnsizedArrayOf<MathValueRecord> UnsizedArrayOf<MathValueRecord>
@ -423,6 +454,24 @@ struct MathKernInfoRecord
return (base+mathKern[idx]).get_value (correction_height, font); return (base+mathKern[idx]).get_value (correction_height, font);
} }
unsigned int get_kernings (hb_ot_math_kern_t kern,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT */
hb_ot_math_kern_entry_t *kern_entries, /* OUT */
hb_font_t *font,
const void *base) const
{
unsigned int idx = kern;
if (unlikely (idx >= ARRAY_LENGTH (mathKern)) || !mathKern[idx]) {
if (entries_count) *entries_count = 0;
return 0;
}
return (base+mathKern[idx]).get_entries (start_offset,
entries_count,
kern_entries,
font);
}
protected: protected:
/* Offset to MathKern table for each corner - /* Offset to MathKern table for each corner -
* from the beginning of MathKernInfo table. May be NULL. */ * from the beginning of MathKernInfo table. May be NULL. */
@ -473,6 +522,22 @@ struct MathKernInfo
return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
} }
unsigned int get_kernings (hb_codepoint_t glyph,
hb_ot_math_kern_t kern,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT */
hb_ot_math_kern_entry_t *kern_entries, /* OUT */
hb_font_t *font) const
{
unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
return mathKernInfoRecords[index].get_kernings (kern,
start_offset,
entries_count,
kern_entries,
font,
this);
}
protected: protected:
Offset16To<Coverage> Offset16To<Coverage>
mathKernCoverage; mathKernCoverage;
@ -545,6 +610,19 @@ struct MathGlyphInfo
hb_font_t *font) const hb_font_t *font) const
{ return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
hb_position_t get_kernings (hb_codepoint_t glyph,
hb_ot_math_kern_t kern,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT */
hb_ot_math_kern_entry_t *kern_entries, /* OUT */
hb_font_t *font) const
{ return (this+mathKernInfo).get_kernings (glyph,
kern,
start_offset,
entries_count,
kern_entries,
font); }
protected: protected:
/* Offset to MathItalicsCorrectionInfo table - /* Offset to MathItalicsCorrectionInfo table -
* from the beginning of MathGlyphInfo table. */ * from the beginning of MathGlyphInfo table. */

View File

@ -184,6 +184,51 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
font); font);
} }
/**
* hb_ot_math_get_glyph_kernings:
* @font: #hb_font_t to work upon
* @glyph: The glyph index from which to retrieve the kernings
* @kern: The #hb_ot_math_kern_t from which to retrieve the kernings
* @start_offset: offset of the first kern entry to retrieve
* @entries_count: (inout) (optional): Input = the maximum number of kern entries to return;
* Output = the actual number of kern entries returned
* @kern_entries: (out caller-allocates) (array length=entries_count): array of kern entries returned
*
* Fetches the raw MathKern (cut-in) data for the specified font, glyph index,
* and @kern. The corresponding list of kern values and correction heights is
* returned as a list of #hb_ot_math_kern_entry_t structs.
*
* See also #hb_ot_math_get_glyph_kerning, which handles selecting the
* appropriate kern value for a given correction height.
*
* <note>For a glyph with @n defined kern values (where @n > 0), there are only
* @n1 defined correction heights, as each correction height defines a boundary
* past which the next kern value should be selected. Therefore, only the
* #hb_ot_math_kern_entry_t.kern_value of the uppermost #hb_ot_math_kern_entry_t
* actually comes from the font; its corresponding
* #hb_ot_math_kern_entry_t.max_correction_height is always set to
* <code>INT32_MAX</code>.</note>
*
* Return value: the total number of kern values available or zero
*
* Since: REPLACEME
**/
unsigned int
hb_ot_math_get_glyph_kernings (hb_font_t *font,
hb_codepoint_t glyph,
hb_ot_math_kern_t kern,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT */
hb_ot_math_kern_entry_t *kern_entries /* OUT */)
{
return font->face->table.MATH->get_glyph_info().get_kernings (glyph,
kern,
start_offset,
entries_count,
kern_entries,
font);
}
/** /**
* hb_ot_math_get_glyph_variants: * hb_ot_math_get_glyph_variants:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon

View File

@ -208,6 +208,20 @@ typedef enum {
HB_OT_MATH_KERN_BOTTOM_LEFT = 3 HB_OT_MATH_KERN_BOTTOM_LEFT = 3
} hb_ot_math_kern_t; } hb_ot_math_kern_t;
/**
* hb_ot_math_kern_entry_t:
* @max_correction_height: The maximum height at which this entry should be used
* @kern_value: The kern value of the entry
*
* Data type to hold math kerning (cut-in) information for a glyph.
*
* Since: REPLACEME
*/
typedef struct {
hb_position_t max_correction_height;
hb_position_t kern_value;
} hb_ot_math_kern_entry_t;
/** /**
* hb_ot_math_glyph_variant_t: * hb_ot_math_glyph_variant_t:
* @glyph: The glyph index of the variant * @glyph: The glyph index of the variant
@ -284,6 +298,14 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
hb_ot_math_kern_t kern, hb_ot_math_kern_t kern,
hb_position_t correction_height); hb_position_t correction_height);
HB_EXTERN unsigned int
hb_ot_math_get_glyph_kernings (hb_font_t *font,
hb_codepoint_t glyph,
hb_ot_math_kern_t kern,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT */
hb_ot_math_kern_entry_t *kern_entries /* OUT */);
HB_EXTERN unsigned int HB_EXTERN unsigned int
hb_ot_math_get_glyph_variants (hb_font_t *font, hb_ot_math_get_glyph_variants (hb_font_t *font,
hb_codepoint_t glyph, hb_codepoint_t glyph,

View File

@ -131,6 +131,7 @@ test_font (hb_font_t *font, hb_codepoint_t cp)
hb_ot_math_get_glyph_top_accent_attachment (font, cp); hb_ot_math_get_glyph_top_accent_attachment (font, cp);
hb_ot_math_is_glyph_extended_shape (face, cp); hb_ot_math_is_glyph_extended_shape (face, cp);
hb_ot_math_get_glyph_kerning (font, cp, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0); hb_ot_math_get_glyph_kerning (font, cp, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0);
hb_ot_math_get_glyph_kernings (font, cp, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0, NULL, NULL);
hb_ot_math_get_glyph_variants (font, cp, HB_DIRECTION_TTB, 0, NULL, NULL); hb_ot_math_get_glyph_variants (font, cp, HB_DIRECTION_TTB, 0, NULL, NULL);
hb_ot_math_get_min_connector_overlap (font, HB_DIRECTION_RTL); hb_ot_math_get_min_connector_overlap (font, HB_DIRECTION_RTL);
hb_ot_math_get_glyph_assembly (font, cp, HB_DIRECTION_BTT, 0, NULL, NULL, NULL); hb_ot_math_get_glyph_assembly (font, cp, HB_DIRECTION_BTT, 0, NULL, NULL, NULL);

View File

@ -332,6 +332,87 @@ test_get_glyph_kerning (void)
cleanupFreeType(); cleanupFreeType();
} }
static void
test_get_glyph_kernings (void)
{
hb_codepoint_t glyph;
hb_ot_math_kern_entry_t entries[20];
const unsigned entries_size = sizeof (entries) / sizeof (entries[0]);
unsigned int count;
initFreeType();
openFont("fonts/MathTestFontEmpty.otf");
g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0, NULL, NULL), ==, 0); // MathGlyphInfo not available
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0, NULL, NULL), ==, 0); // MathGlyphInfo not available
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0, NULL, NULL), ==, 0); // MathGlyphInfo not available
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0, NULL, NULL), ==, 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_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0, NULL, NULL), ==, 0); // MathKernInfo empty
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0, NULL, NULL), ==, 0); // MathKernInfo empty
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0, NULL, NULL), ==, 0); // MathKernInfo empty
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0, NULL, NULL), ==, 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_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0, NULL, NULL), ==, 0); // MathKernInfoRecords empty
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0, NULL, NULL), ==, 0); // MathKernInfoRecords empty
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0, NULL, NULL), ==, 0); // MathKernInfoRecords empty
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0, NULL, NULL), ==, 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_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0, NULL, NULL), ==, 10);
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0, NULL, NULL), ==, 3);
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0, NULL, NULL), ==, 9);
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0, NULL, NULL), ==, 7);
count = entries_size;
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0, &count, entries), ==, 10);
g_assert_cmpint(count, ==, 10);
g_assert_cmpint(entries[0].max_correction_height, ==, 14);
g_assert_cmpint(entries[0].kern_value, ==, 62);
g_assert_cmpint(entries[1].max_correction_height, ==, 23);
g_assert_cmpint(entries[1].kern_value, ==, 104);
g_assert_cmpint(entries[2].max_correction_height, ==, 32);
g_assert_cmpint(entries[2].kern_value, ==, 146);
g_assert_cmpint(entries[3].max_correction_height, ==, 41);
g_assert_cmpint(entries[3].kern_value, ==, 188);
g_assert_cmpint(entries[4].max_correction_height, ==, 50);
g_assert_cmpint(entries[4].kern_value, ==, 230);
g_assert_cmpint(entries[5].max_correction_height, ==, 59);
g_assert_cmpint(entries[5].kern_value, ==, 272);
g_assert_cmpint(entries[6].max_correction_height, ==, 68);
g_assert_cmpint(entries[6].kern_value, ==, 314);
g_assert_cmpint(entries[7].max_correction_height, ==, 77);
g_assert_cmpint(entries[7].kern_value, ==, 356);
g_assert_cmpint(entries[8].max_correction_height, ==, 86);
g_assert_cmpint(entries[8].kern_value, ==, 398);
g_assert_cmpint(entries[9].max_correction_height, ==, INT32_MAX);
g_assert_cmpint(entries[9].kern_value, ==, 440);
count = entries_size;
g_assert_cmpint(hb_ot_math_get_glyph_kernings (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0, &count, entries), ==, 3);
g_assert_cmpint(count, ==, 3);
g_assert_cmpint(entries[0].max_correction_height, ==, 20);
g_assert_cmpint(entries[0].kern_value, ==, 50);
g_assert_cmpint(entries[1].max_correction_height, ==, 35);
g_assert_cmpint(entries[1].kern_value, ==, 80);
g_assert_cmpint(entries[2].max_correction_height, ==, INT32_MAX);
g_assert_cmpint(entries[2].kern_value, ==, 110);
closeFont();
cleanupFreeType();
}
static hb_position_t static hb_position_t
get_glyph_assembly_italics_correction (hb_font_t *font, get_glyph_assembly_italics_correction (hb_font_t *font,
@ -707,6 +788,7 @@ main (int argc, char **argv)
hb_test_add (test_get_glyph_top_accent_attachment); hb_test_add (test_get_glyph_top_accent_attachment);
hb_test_add (test_is_glyph_extended_shape); hb_test_add (test_is_glyph_extended_shape);
hb_test_add (test_get_glyph_kerning); hb_test_add (test_get_glyph_kerning);
hb_test_add (test_get_glyph_kernings);
hb_test_add (test_get_glyph_assembly_italics_correction); hb_test_add (test_get_glyph_assembly_italics_correction);
hb_test_add (test_get_min_connector_overlap); hb_test_add (test_get_min_connector_overlap);
hb_test_add (test_get_glyph_variants); hb_test_add (test_get_glyph_variants);