MATH table: Add API to access math variants.
This commit is contained in:
parent
722e620f20
commit
51da7a1cd6
|
@ -279,7 +279,7 @@ struct MathKern
|
|||
}
|
||||
|
||||
protected:
|
||||
USHORT heightCount;
|
||||
USHORT heightCount;
|
||||
MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
|
||||
* which the kern value changes.
|
||||
* Sorted by the height value in
|
||||
|
@ -413,6 +413,243 @@ public:
|
|||
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
|
||||
|
@ -428,24 +665,32 @@ struct MATH
|
|||
return_trace (version.sanitize (c) &&
|
||||
likely (version.major == 1) &&
|
||||
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,
|
||||
hb_font_t *font) const
|
||||
hb_font_t *font) const
|
||||
{ return (this+mathConstants).get_value (constant, font); }
|
||||
|
||||
inline const MathGlyphInfo &get_math_glyph_info (void) const {
|
||||
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:
|
||||
FixedVersion<>version; /* Version of the MATH table
|
||||
* initially set to 0x00010000u */
|
||||
OffsetTo<MathConstants> mathConstants;/* MathConstants table */
|
||||
OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
|
||||
OffsetTo<MathVariants> mathVariants; /* MathVariants table */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
};
|
||||
|
||||
} /* mathspace OT */
|
||||
|
|
|
@ -617,5 +617,15 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
|
|||
#undef lig_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 */
|
||||
|
|
|
@ -1350,3 +1350,57 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
|
|||
const OT::MATH &math = _get_math (font->face);
|
||||
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.
|
@ -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
|
||||
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_is_math_extended_shape);
|
||||
hb_test_add (test_get_math_kerning);
|
||||
//hb_test_add (test_get_math_italic_correction_for_glyph_assembly);
|
||||
|
||||
return hb_test_run();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue