MATH table: Add API to access math variants.

This commit is contained in:
Frédéric Wang 2016-08-25 11:17:50 +02:00 committed by Behdad Esfahbod
parent 722e620f20
commit 51da7a1cd6
5 changed files with 364 additions and 4 deletions

View File

@ -279,7 +279,7 @@ struct MathKern
} }
protected: protected:
USHORT heightCount; USHORT heightCount;
MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
* which the kern value changes. * which the kern value changes.
* Sorted by the height value in * Sorted by the height value in
@ -413,6 +413,243 @@ public:
DEFINE_SIZE_STATIC (8); DEFINE_SIZE_STATIC (8);
}; };
struct MathGlyphVariantRecord
{
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
hb_codepoint_t get_glyph() const { return variantGlyph; }
inline hb_position_t get_advance_measurement (hb_font_t *font,
bool horizontal) const
{
return horizontal ?
font->em_scale_x (advanceMeasurement) :
font->em_scale_y (advanceMeasurement);
}
protected:
GlyphID variantGlyph; /* Glyph ID for the variant. */
USHORT advanceMeasurement; /* Advance width/height, in design units, of the
* variant, in the direction of requested
* glyph extension. */
public:
DEFINE_SIZE_STATIC (2 + 2);
};
struct PartFlags : USHORT
{
enum Flags {
Extender = 0x0001u, /* If set, the part can be skipped or repeated. */
};
public:
DEFINE_SIZE_STATIC (2);
};
struct GlyphPartRecord
{
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
hb_codepoint_t get_glyph() const { return glyph; }
inline hb_position_t
get_start_connector_length (hb_font_t *font, bool horizontal) const
{
return horizontal ?
font->em_scale_x (startConnectorLength) :
font->em_scale_y (startConnectorLength);
}
inline hb_position_t
get_end_connector_length (hb_font_t *font, bool horizontal) const
{
return horizontal ?
font->em_scale_x (endConnectorLength) :
font->em_scale_y (endConnectorLength);
}
inline hb_position_t
get_full_advance (hb_font_t *font, bool horizontal) const
{
return horizontal ?
font->em_scale_x (fullAdvance) :
font->em_scale_y (fullAdvance);
}
inline bool is_extender() const {
return partFlags & PartFlags::Flags::Extender;
}
protected:
GlyphID glyph; /* Glyph ID for the part. */
USHORT startConnectorLength; /* Advance width/ height of the straight bar
* connector material, in design units, is at
* the beginning of the glyph, in the
* direction of the extension. */
USHORT endConnectorLength; /* Advance width/ height of the straight bar
* connector material, in design units, is at
* the end of the glyph, in the direction of
* the extension. */
USHORT fullAdvance; /* Full advance width/height for this part,
* in the direction of the extension.
* In design units. */
PartFlags partFlags; /* Part qualifiers. */
public:
DEFINE_SIZE_STATIC (5 * 2);
};
struct GlyphAssembly
{
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
italicsCorrection.sanitize(c, this) &&
partRecords.sanitize(c));
}
inline hb_position_t get_italic_correction (hb_font_t *font) const
{ return italicsCorrection.get_x_value(font, this); }
inline unsigned int part_record_count() const { return partRecords.len; }
inline const GlyphPartRecord &get_part_record(unsigned int i) const {
assert(i < partRecords.len);
return partRecords[i];
}
protected:
MathValueRecord italicsCorrection; /* Italics correction of this
* GlyphAssembly. Should not
* depend on the assembly size. */
ArrayOf<GlyphPartRecord> partRecords; /* Array of part records, from
* left to right and bottom to
* top. */
public:
DEFINE_SIZE_ARRAY (4 + 2, partRecords);
};
struct MathGlyphConstruction
{
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
glyphAssembly.sanitize(c, this) &&
mathGlyphVariantRecord.sanitize(c));
}
inline bool has_glyph_assembly (void) const { return glyphAssembly != 0; }
inline const GlyphAssembly &get_glyph_assembly (void) const {
return this+glyphAssembly;
}
inline unsigned int glyph_variant_count() const {
return mathGlyphVariantRecord.len;
}
inline const MathGlyphVariantRecord &get_glyph_variant(unsigned int i) const {
assert(i < mathGlyphVariantRecord.len);
return mathGlyphVariantRecord[i];
}
protected:
/* Offset to GlyphAssembly table for this shape - from the beginning of
MathGlyphConstruction table. May be NULL. */
OffsetTo<GlyphAssembly> glyphAssembly;
/* MathGlyphVariantRecords for alternative variants of the glyphs. */
ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
public:
DEFINE_SIZE_ARRAY (2 + 2, mathGlyphVariantRecord);
};
struct MathVariants
{
inline bool sanitize_offsets (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
unsigned int count = vertGlyphCount + horizGlyphCount;
for (unsigned int i = 0; i < count; i++)
if (!glyphConstruction[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) &&
vertGlyphCoverage.sanitize (c, this) &&
horizGlyphCoverage.sanitize (c, this) &&
c->check_array (glyphConstruction,
glyphConstruction[0].static_size,
vertGlyphCount + horizGlyphCount) &&
sanitize_offsets (c));
}
inline hb_position_t get_min_connector_overlap (hb_font_t *font,
bool horizontal) const
{
return horizontal ?
font->em_scale_x (minConnectorOverlap) :
font->em_scale_y (minConnectorOverlap);
}
inline bool
get_glyph_construction (hb_codepoint_t glyph,
hb_bool_t horizontal,
const MathGlyphConstruction *&glyph_construction) const {
unsigned int index =
horizontal ?
(this+horizGlyphCoverage).get_coverage (glyph) :
(this+vertGlyphCoverage).get_coverage (glyph);
if (likely (index == NOT_COVERED)) return false;
USHORT glyphCount = horizontal ? horizGlyphCount : vertGlyphCount;
if (unlikely (index >= glyphCount)) return false;
if (horizontal)
index += vertGlyphCount;
glyph_construction = &(this + glyphConstruction[index]);
return true;
}
protected:
USHORT minConnectorOverlap; /* Minimum overlap of connecting
* glyphs during glyph construction,
* in design units. */
OffsetTo<Coverage> vertGlyphCoverage; /* Offset to Coverage table -
* from the beginning of MathVariants
* table. */
OffsetTo<Coverage> horizGlyphCoverage; /* Offset to Coverage table -
* from the beginning of MathVariants
* table. */
USHORT vertGlyphCount; /* Number of glyphs for which
* information is provided for
* vertically growing variants. */
USHORT horizGlyphCount; /* Number of glyphs for which
* information is provided for
* horizontally growing variants. */
/* Array of offsets to MathGlyphConstruction tables - from the beginning of
the MathVariants table, for shapes growing in vertical/horizontal
direction. */
OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
public:
DEFINE_SIZE_ARRAY (5 * 2, glyphConstruction);
};
/* /*
* MATH -- The MATH Table * MATH -- The MATH Table
@ -428,24 +665,32 @@ struct MATH
return_trace (version.sanitize (c) && return_trace (version.sanitize (c) &&
likely (version.major == 1) && likely (version.major == 1) &&
mathConstants.sanitize (c, this) && mathConstants.sanitize (c, this) &&
mathGlyphInfo.sanitize (c, this)); mathGlyphInfo.sanitize (c, this) &&
mathVariants.sanitize (c, this));
} }
inline hb_position_t get_constant (hb_ot_math_constant_t constant, inline hb_position_t get_constant (hb_ot_math_constant_t constant,
hb_font_t *font) const hb_font_t *font) const
{ return (this+mathConstants).get_value (constant, font); } { return (this+mathConstants).get_value (constant, font); }
inline const MathGlyphInfo &get_math_glyph_info (void) const { inline const MathGlyphInfo &get_math_glyph_info (void) const {
return this+mathGlyphInfo; return this+mathGlyphInfo;
} }
inline bool has_math_variants (void) const { return mathVariants != 0; }
inline const MathVariants &get_math_variants (void) const {
return this+mathVariants;
}
protected: protected:
FixedVersion<>version; /* Version of the MATH table FixedVersion<>version; /* Version of the MATH table
* initially set to 0x00010000u */ * initially set to 0x00010000u */
OffsetTo<MathConstants> mathConstants;/* MathConstants table */ OffsetTo<MathConstants> mathConstants;/* MathConstants table */
OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */ OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
OffsetTo<MathVariants> mathVariants; /* MathVariants table */
public: public:
DEFINE_SIZE_STATIC (8); DEFINE_SIZE_STATIC (10);
}; };
} /* mathspace OT */ } /* mathspace OT */

View File

@ -617,5 +617,15 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
#undef lig_props #undef lig_props
#undef glyph_props #undef glyph_props
namespace OT {
struct MathGlyphConstruction;
};
HB_INTERNAL hb_bool_t
hb_ot_layout_get_math_glyph_construction (hb_font_t *font,
hb_codepoint_t glyph,
hb_bool_t horizontal,
hb_position_t &minConnectorOverlap,
const OT::MathGlyphConstruction *&glyph_construction);
#endif /* HB_OT_LAYOUT_PRIVATE_HH */ #endif /* HB_OT_LAYOUT_PRIVATE_HH */

View File

@ -1350,3 +1350,57 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
const OT::MATH &math = _get_math (font->face); const OT::MATH &math = _get_math (font->face);
return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
} }
#if 0
/**
* hb_ot_layout_get_math_italic_correction_for_glyph_assembly:
* @font: an #hb_font_t with an OpenType MATH table
* @base_glyph: index of the glyph to stretch
* @horizontal: direction of the stretching
*
* This function tries and get the italic correction associated to the glyph
* assembly used to stretch the base glyph in the specified direction.
*
* Return value: the italic correction of the glyph assembly or 0
*
* Since: ????
**/
HB_EXTERN hb_position_t
hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font_t *font,
hb_codepoint_t base_glyph,
hb_bool_t horizontal)
{
const OT::MATH &math = _get_math (font->face);
if (math.has_math_variants()) {
const OT::MathGlyphConstruction* glyph_construction;
if (math.get_math_variants().
get_glyph_construction(base_glyph, horizontal, glyph_construction) &&
glyph_construction->has_glyph_assembly())
return glyph_construction->
get_glyph_assembly().get_italic_correction(font);
}
return 0;
}
HB_INTERNAL hb_bool_t
hb_ot_layout_get_math_glyph_construction (hb_font_t *font,
hb_codepoint_t glyph,
hb_bool_t horizontal,
hb_position_t &minConnectorOverlap,
const OT::MathGlyphConstruction *&glyph_construction)
{
const OT::MATH &math = _get_math (font->face);
if (!math.has_math_variants()) return false;
const OT::MathVariants &mathVariants = math.get_math_variants();
if (!mathVariants.get_glyph_construction(glyph, horizontal,
glyph_construction)) return false;
minConnectorOverlap = mathVariants.get_min_connector_overlap(font, horizontal);
return true;
}
#endif

Binary file not shown.

View File

@ -315,6 +315,56 @@ test_get_math_kerning (void)
} }
#if 0
static void
test_get_math_italic_correction_for_glyph_assembly (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_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants 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_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
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_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage 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_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
closeFont();
openFont("fonts/MathTestFontPartial4.otf");
g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
closeFont();
openFont("fonts/MathTestFontFull.otf");
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124);
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331);
closeFont();
cleanupFreeType();
}
#endif
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -326,6 +376,7 @@ main (int argc, char **argv)
hb_test_add (test_get_math_top_accent_attachment); hb_test_add (test_get_math_top_accent_attachment);
hb_test_add (test_is_math_extended_shape); hb_test_add (test_is_math_extended_shape);
hb_test_add (test_get_math_kerning); hb_test_add (test_get_math_kerning);
//hb_test_add (test_get_math_italic_correction_for_glyph_assembly);
return hb_test_run(); return hb_test_run();
} }