Supercedes https://github.com/behdad/harfbuzz/pull/326 Fixes https://github.com/behdad/harfbuzz/pull/331pull/335/head
commit
6d3e6abf0c
18 changed files with 1944 additions and 6 deletions
@ -0,0 +1,722 @@ |
||||
/*
|
||||
* Copyright © 2016 Igalia S.L. |
||||
* |
||||
* This is part of HarfBuzz, a text shaping library. |
||||
* |
||||
* Permission is hereby granted, without written agreement and without |
||||
* license or royalty fees, to use, copy, modify, and distribute this |
||||
* software and its documentation for any purpose, provided that the |
||||
* above copyright notice and the following two paragraphs appear in |
||||
* all copies of this software. |
||||
* |
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
||||
* DAMAGE. |
||||
* |
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||
* |
||||
* Igalia Author(s): Frédéric Wang |
||||
*/ |
||||
|
||||
#ifndef HB_OT_LAYOUT_MATH_TABLE_HH |
||||
#define HB_OT_LAYOUT_MATH_TABLE_HH |
||||
|
||||
#include "hb-open-type-private.hh" |
||||
#include "hb-ot-layout-common-private.hh" |
||||
#include "hb-ot-math.h" |
||||
|
||||
namespace OT { |
||||
|
||||
|
||||
struct MathValueRecord |
||||
{ |
||||
inline hb_position_t get_x_value (hb_font_t *font, const void *base) const |
||||
{ return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); } |
||||
inline hb_position_t get_y_value (hb_font_t *font, const void *base) const |
||||
{ return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); } |
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
||||
{ |
||||
TRACE_SANITIZE (this); |
||||
return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); |
||||
} |
||||
|
||||
protected: |
||||
SHORT value; /* The X or Y value in design units */ |
||||
OffsetTo<Device> deviceTable; /* Offset to the device table - from the
|
||||
* beginning of parent table. May be NULL. |
||||
* Suggested format for device table is 1. */ |
||||
|
||||
public: |
||||
DEFINE_SIZE_STATIC (4); |
||||
}; |
||||
|
||||
struct MathConstants |
||||
{ |
||||
inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const |
||||
{ |
||||
TRACE_SANITIZE (this); |
||||
|
||||
unsigned int count = ARRAY_LENGTH (mathValueRecords); |
||||
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) && sanitize_math_value_records(c)); |
||||
} |
||||
|
||||
inline hb_position_t get_value (hb_ot_math_constant_t constant, |
||||
hb_font_t *font) const |
||||
{ |
||||
switch (constant) { |
||||
|
||||
case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: |
||||
case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: |
||||
return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; |
||||
|
||||
case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: |
||||
case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: |
||||
return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); |
||||
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: |
||||
case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: |
||||
case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: |
||||
case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: |
||||
return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this); |
||||
|
||||
case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: |
||||
case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: |
||||
case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: |
||||
case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: |
||||
case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_MATH_LEADING: |
||||
case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: |
||||
case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: |
||||
case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: |
||||
case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: |
||||
case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: |
||||
case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: |
||||
case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: |
||||
case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: |
||||
case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: |
||||
case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: |
||||
case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_STACK_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: |
||||
case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: |
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: |
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: |
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: |
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: |
||||
case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: |
||||
case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: |
||||
case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: |
||||
case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: |
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: |
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: |
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: |
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: |
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: |
||||
case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: |
||||
case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: |
||||
case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: |
||||
case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: |
||||
case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: |
||||
return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this); |
||||
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: |
||||
return radicalDegreeBottomRaisePercent; |
||||
|
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
protected: |
||||
SHORT percentScaleDown[2]; |
||||
USHORT minHeight[2]; |
||||
MathValueRecord mathValueRecords[51]; |
||||
SHORT radicalDegreeBottomRaisePercent; |
||||
|
||||
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 hb_position_t get_value (hb_codepoint_t glyph, |
||||
hb_font_t *font) const |
||||
{ |
||||
unsigned int index = (this+coverage).get_coverage (glyph); |
||||
return italicsCorrection[index].get_x_value (font, this); |
||||
} |
||||
|
||||
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 (4, 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 hb_position_t get_value (hb_codepoint_t glyph, |
||||
hb_font_t *font) const |
||||
{ |
||||
unsigned int index = (this+topAccentCoverage).get_coverage (glyph); |
||||
if (index == NOT_COVERED) |
||||
return font->get_glyph_h_advance (glyph) / 2; |
||||
return topAccentAttachment[index].get_x_value(font, this); |
||||
} |
||||
|
||||
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_position_t correction_height, hb_font_t *font) const |
||||
{ |
||||
const MathValueRecord* correctionHeight = mathValueRecords; |
||||
const MathValueRecord* kernValue = mathValueRecords + heightCount; |
||||
int sign = font->y_scale < 0 ? -1 : +1; |
||||
|
||||
/* 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 i = 0; |
||||
unsigned int count = heightCount; |
||||
while (count > 0) |
||||
{ |
||||
unsigned int half = count / 2; |
||||
hb_position_t height = correctionHeight[i + half].get_y_value(font, this); |
||||
if (sign * height < sign * 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 (heightCount entries), |
||||
* Followed by: |
||||
* Array of kern values corresponding |
||||
* to heights. (heightCount+1 entries). |
||||
*/ |
||||
|
||||
public: |
||||
DEFINE_SIZE_ARRAY (2, mathValueRecords); |
||||
}; |
||||
|
||||
struct MathKernInfoRecord |
||||
{ |
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
||||
{ |
||||
TRACE_SANITIZE (this); |
||||
|
||||
unsigned int count = ARRAY_LENGTH (mathKern); |
||||
for (unsigned int i = 0; i < count; i++) |
||||
if (unlikely (!mathKern[i].sanitize (c, base))) |
||||
return_trace (false); |
||||
|
||||
return_trace (true); |
||||
} |
||||
|
||||
inline hb_position_t get_kerning (hb_ot_math_kern_t kern, |
||||
hb_position_t correction_height, |
||||
hb_font_t *font, |
||||
const void *base) const |
||||
{ |
||||
unsigned int idx = kern; |
||||
if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0; |
||||
return (base+mathKern[idx]).get_value (correction_height, font); |
||||
} |
||||
|
||||
protected: |
||||
/* Offset to MathKern table for each corner -
|
||||
* from the beginning of MathKernInfo table. May be NULL. */ |
||||
OffsetTo<MathKern> mathKern[4]; |
||||
|
||||
public: |
||||
DEFINE_SIZE_STATIC (8); |
||||
}; |
||||
|
||||
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 hb_position_t get_kerning (hb_codepoint_t glyph, |
||||
hb_ot_math_kern_t kern, |
||||
hb_position_t correction_height, |
||||
hb_font_t *font) const |
||||
{ |
||||
unsigned int index = (this+mathKernCoverage).get_coverage (glyph); |
||||
return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); |
||||
} |
||||
|
||||
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 (4, 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 hb_position_t |
||||
get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const |
||||
{ return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } |
||||
|
||||
inline hb_position_t |
||||
get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const |
||||
{ return (this+mathTopAccentAttachment).get_value (glyph, font); } |
||||
|
||||
inline bool is_extended_shape (hb_codepoint_t glyph) const |
||||
{ return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } |
||||
|
||||
inline hb_position_t get_kerning (hb_codepoint_t glyph, |
||||
hb_ot_math_kern_t kern, |
||||
hb_position_t correction_height, |
||||
hb_font_t *font) const |
||||
{ return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } |
||||
|
||||
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 (8); |
||||
}; |
||||
|
||||
struct MathGlyphVariantRecord |
||||
{ |
||||
friend struct MathGlyphConstruction; |
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const |
||||
{ |
||||
TRACE_SANITIZE (this); |
||||
return_trace (c->check_struct (this)); |
||||
} |
||||
|
||||
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 (4); |
||||
}; |
||||
|
||||
struct PartFlags : USHORT |
||||
{ |
||||
enum Flags { |
||||
Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ |
||||
|
||||
Defined = 0x0001u, /* All defined flags. */ |
||||
}; |
||||
|
||||
public: |
||||
DEFINE_SIZE_STATIC (2); |
||||
}; |
||||
|
||||
struct MathGlyphPartRecord |
||||
{ |
||||
inline bool sanitize (hb_sanitize_context_t *c) const |
||||
{ |
||||
TRACE_SANITIZE (this); |
||||
return_trace (c->check_struct (this)); |
||||
} |
||||
|
||||
inline void extract (hb_ot_math_glyph_part_t &out, |
||||
int scale, |
||||
hb_font_t *font) const |
||||
{ |
||||
out.glyph = glyph; |
||||
|
||||
out.start_connector_length = font->em_scale (startConnectorLength, scale); |
||||
out.end_connector_length = font->em_scale (endConnectorLength, scale); |
||||
out.full_advance = font->em_scale (fullAdvance, scale); |
||||
|
||||
ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == |
||||
(unsigned int) PartFlags::Extender); |
||||
|
||||
out.flags = (hb_ot_math_glyph_part_flags_t) |
||||
(unsigned int) |
||||
(partFlags & PartFlags::Defined); |
||||
} |
||||
|
||||
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 (10); |
||||
}; |
||||
|
||||
struct MathGlyphAssembly |
||||
{ |
||||
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 unsigned int get_parts (hb_direction_t direction, |
||||
hb_font_t *font, |
||||
unsigned int start_offset, |
||||
unsigned int *parts_count, /* IN/OUT */ |
||||
hb_ot_math_glyph_part_t *parts /* OUT */, |
||||
hb_position_t *italics_correction /* OUT */) const |
||||
{ |
||||
if (parts_count) |
||||
{ |
||||
int scale = font->dir_scale (direction); |
||||
const MathGlyphPartRecord *arr = |
||||
partRecords.sub_array (start_offset, parts_count); |
||||
unsigned int count = *parts_count; |
||||
for (unsigned int i = 0; i < count; i++) |
||||
arr[i].extract (parts[i], scale, font); |
||||
} |
||||
|
||||
if (italics_correction) |
||||
*italics_correction = italicsCorrection.get_x_value (font, this); |
||||
|
||||
return partRecords.len; |
||||
} |
||||
|
||||
protected: |
||||
MathValueRecord italicsCorrection; /* Italics correction of this
|
||||
* MathGlyphAssembly. Should not |
||||
* depend on the assembly size. */ |
||||
ArrayOf<MathGlyphPartRecord> partRecords; /* Array of part records, from
|
||||
* left to right and bottom to |
||||
* top. */ |
||||
|
||||
public: |
||||
DEFINE_SIZE_ARRAY (6, 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 const MathGlyphAssembly &get_assembly (void) const |
||||
{ return this+glyphAssembly; } |
||||
|
||||
inline unsigned int get_variants (hb_direction_t direction, |
||||
hb_font_t *font, |
||||
unsigned int start_offset, |
||||
unsigned int *variants_count, /* IN/OUT */ |
||||
hb_ot_math_glyph_variant_t *variants /* OUT */) const |
||||
{ |
||||
if (variants_count) |
||||
{ |
||||
int scale = font->dir_scale (direction); |
||||
const MathGlyphVariantRecord *arr = |
||||
mathGlyphVariantRecord.sub_array (start_offset, variants_count); |
||||
unsigned int count = *variants_count; |
||||
for (unsigned int i = 0; i < count; i++) |
||||
{ |
||||
variants[i].glyph = arr[i].variantGlyph; |
||||
variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale); |
||||
} |
||||
} |
||||
return mathGlyphVariantRecord.len; |
||||
} |
||||
|
||||
protected: |
||||
/* Offset to MathGlyphAssembly table for this shape - from the beginning of
|
||||
MathGlyphConstruction table. May be NULL. */ |
||||
OffsetTo<MathGlyphAssembly> glyphAssembly; |
||||
|
||||
/* MathGlyphVariantRecords for alternative variants of the glyphs. */ |
||||
ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord; |
||||
|
||||
public: |
||||
DEFINE_SIZE_ARRAY (4, 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_direction_t direction, |
||||
hb_font_t *font) const |
||||
{ return font->em_scale_dir (minConnectorOverlap, direction); } |
||||
|
||||
inline unsigned int get_glyph_variants (hb_codepoint_t glyph, |
||||
hb_direction_t direction, |
||||
hb_font_t *font, |
||||
unsigned int start_offset, |
||||
unsigned int *variants_count, /* IN/OUT */ |
||||
hb_ot_math_glyph_variant_t *variants /* OUT */) const |
||||
{ return get_glyph_construction (glyph, direction, font) |
||||
.get_variants (direction, font, start_offset, variants_count, variants); } |
||||
|
||||
inline unsigned int get_glyph_parts (hb_codepoint_t glyph, |
||||
hb_direction_t direction, |
||||
hb_font_t *font, |
||||
unsigned int start_offset, |
||||
unsigned int *parts_count, /* IN/OUT */ |
||||
hb_ot_math_glyph_part_t *parts /* OUT */, |
||||
hb_position_t *italics_correction /* OUT */) const |
||||
{ return get_glyph_construction (glyph, direction, font) |
||||
.get_assembly () |
||||
.get_parts (direction, font, |
||||
start_offset, parts_count, parts, |
||||
italics_correction); } |
||||
|
||||
private: |
||||
inline const MathGlyphConstruction & |
||||
get_glyph_construction (hb_codepoint_t glyph, |
||||
hb_direction_t direction, |
||||
hb_font_t *font) const |
||||
{ |
||||
bool vertical = HB_DIRECTION_IS_VERTICAL (direction); |
||||
unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; |
||||
const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage |
||||
: horizGlyphCoverage; |
||||
|
||||
unsigned int index = (this+coverage).get_coverage (glyph); |
||||
if (unlikely (index >= count)) return Null(MathGlyphConstruction); |
||||
|
||||
if (!vertical) |
||||
index += vertGlyphCount; |
||||
|
||||
return this+glyphConstruction[index]; |
||||
} |
||||
|
||||
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 (10, glyphConstruction); |
||||
}; |
||||
|
||||
|
||||
/*
|
||||
* MATH -- The MATH Table |
||||
*/ |
||||
|
||||
struct MATH |
||||
{ |
||||
static const hb_tag_t tableTag = HB_OT_TAG_MATH; |
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const |
||||
{ |
||||
TRACE_SANITIZE (this); |
||||
return_trace (version.sanitize (c) && |
||||
likely (version.major == 1) && |
||||
mathConstants.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 |
||||
{ return (this+mathConstants).get_value (constant, font); } |
||||
|
||||
inline const MathGlyphInfo &get_math_glyph_info (void) const |
||||
{ return this+mathGlyphInfo; } |
||||
|
||||
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 (10); |
||||
}; |
||||
|
||||
} /* mathspace OT */ |
||||
|
||||
|
||||
#endif /* HB_OT_LAYOUT_MATH_TABLE_HH */ |
@ -0,0 +1,209 @@ |
||||
/*
|
||||
* Copyright © 2016 Igalia S.L. |
||||
* |
||||
* This is part of HarfBuzz, a text shaping library. |
||||
* |
||||
* Permission is hereby granted, without written agreement and without |
||||
* license or royalty fees, to use, copy, modify, and distribute this |
||||
* software and its documentation for any purpose, provided that the |
||||
* above copyright notice and the following two paragraphs appear in |
||||
* all copies of this software. |
||||
* |
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
||||
* DAMAGE. |
||||
* |
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||
* |
||||
* Igalia Author(s): Frédéric Wang |
||||
*/ |
||||
|
||||
#ifndef HB_OT_H_IN |
||||
#error "Include <hb-ot.h> instead." |
||||
#endif |
||||
|
||||
#ifndef HB_OT_MATH_H |
||||
#define HB_OT_MATH_H |
||||
|
||||
#include "hb.h" |
||||
|
||||
HB_BEGIN_DECLS |
||||
|
||||
|
||||
/*
|
||||
* MATH |
||||
*/ |
||||
|
||||
#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') |
||||
|
||||
/* Use with hb_buffer_set_script() for math shaping. */ |
||||
#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h') |
||||
|
||||
/* Types */ |
||||
|
||||
/**
|
||||
* hb_ot_math_constant_t: |
||||
* |
||||
* Since: 1.4.0 |
||||
*/ |
||||
typedef enum { |
||||
HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, |
||||
HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, |
||||
HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2, |
||||
HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3, |
||||
HB_OT_MATH_CONSTANT_MATH_LEADING = 4, |
||||
HB_OT_MATH_CONSTANT_AXIS_HEIGHT = 5, |
||||
HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT = 6, |
||||
HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT = 7, |
||||
HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN = 8, |
||||
HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX = 9, |
||||
HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN = 10, |
||||
HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP = 11, |
||||
HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED = 12, |
||||
HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN = 13, |
||||
HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX = 14, |
||||
HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN = 15, |
||||
HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT = 16, |
||||
HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT = 17, |
||||
HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN = 18, |
||||
HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN = 19, |
||||
HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN = 20, |
||||
HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN = 21, |
||||
HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP = 22, |
||||
HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP = 23, |
||||
HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN = 24, |
||||
HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN = 25, |
||||
HB_OT_MATH_CONSTANT_STACK_GAP_MIN = 26, |
||||
HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN = 27, |
||||
HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP = 28, |
||||
HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN = 29, |
||||
HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN = 30, |
||||
HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN = 31, |
||||
HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP = 32, |
||||
HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP = 33, |
||||
HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN = 34, |
||||
HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN = 35, |
||||
HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN = 36, |
||||
HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN = 37, |
||||
HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS = 38, |
||||
HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN = 39, |
||||
HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN = 40, |
||||
HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP = 41, |
||||
HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP = 42, |
||||
HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP = 43, |
||||
HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS = 44, |
||||
HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER = 45, |
||||
HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP = 46, |
||||
HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS = 47, |
||||
HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER = 48, |
||||
HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP = 49, |
||||
HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP = 50, |
||||
HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS = 51, |
||||
HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER = 52, |
||||
HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53, |
||||
HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54, |
||||
HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 |
||||
} hb_ot_math_constant_t; |
||||
|
||||
/**
|
||||
* hb_ot_math_kern_t: |
||||
* |
||||
* Since: 1.4.0 |
||||
*/ |
||||
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_ot_math_glyph_variant_t: |
||||
* |
||||
* Since: 1.4.0 |
||||
*/ |
||||
typedef struct hb_ot_math_glyph_variant_t { |
||||
hb_codepoint_t glyph; |
||||
hb_position_t advance; |
||||
} hb_ot_math_glyph_variant_t; |
||||
|
||||
/**
|
||||
* hb_ot_math_glyph_part_flags_t: |
||||
* |
||||
* Since: 1.4.0 |
||||
*/ |
||||
typedef enum { /*< flags >*/ |
||||
HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ |
||||
} hb_ot_math_glyph_part_flags_t; |
||||
|
||||
/**
|
||||
* hb_ot_math_glyph_part_t: |
||||
* |
||||
* Since: 1.4.0 |
||||
*/ |
||||
typedef struct hb_ot_math_glyph_part_t { |
||||
hb_codepoint_t glyph; |
||||
hb_position_t start_connector_length; |
||||
hb_position_t end_connector_length; |
||||
hb_position_t full_advance; |
||||
hb_ot_math_glyph_part_flags_t flags; |
||||
} hb_ot_math_glyph_part_t; |
||||
|
||||
/* Methods */ |
||||
|
||||
HB_EXTERN hb_bool_t |
||||
hb_ot_math_has_data (hb_face_t *face); |
||||
|
||||
HB_EXTERN hb_position_t |
||||
hb_ot_math_get_constant (hb_font_t *font, |
||||
hb_ot_math_constant_t constant); |
||||
|
||||
HB_EXTERN hb_position_t |
||||
hb_ot_math_get_glyph_italics_correction (hb_font_t *font, |
||||
hb_codepoint_t glyph); |
||||
|
||||
HB_EXTERN hb_position_t |
||||
hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, |
||||
hb_codepoint_t glyph); |
||||
|
||||
HB_EXTERN hb_bool_t |
||||
hb_ot_math_is_glyph_extended_shape (hb_face_t *face, |
||||
hb_codepoint_t glyph); |
||||
|
||||
HB_EXTERN hb_position_t |
||||
hb_ot_math_get_glyph_kerning (hb_font_t *font, |
||||
hb_codepoint_t glyph, |
||||
hb_ot_math_kern_t kern, |
||||
hb_position_t correction_height); |
||||
|
||||
HB_EXTERN unsigned int |
||||
hb_ot_math_get_glyph_variants (hb_font_t *font, |
||||
hb_codepoint_t glyph, |
||||
hb_direction_t direction, |
||||
unsigned int start_offset, |
||||
unsigned int *variants_count, /* IN/OUT */ |
||||
hb_ot_math_glyph_variant_t *variants /* OUT */); |
||||
|
||||
HB_EXTERN hb_position_t |
||||
hb_ot_math_get_min_connector_overlap (hb_font_t *font, |
||||
hb_direction_t direction); |
||||
|
||||
HB_EXTERN unsigned int |
||||
hb_ot_math_get_glyph_assembly (hb_font_t *font, |
||||
hb_codepoint_t glyph, |
||||
hb_direction_t direction, |
||||
unsigned int start_offset, |
||||
unsigned int *parts_count, /* IN/OUT */ |
||||
hb_ot_math_glyph_part_t *parts, /* OUT */ |
||||
hb_position_t *italics_correction /* OUT */); |
||||
|
||||
|
||||
HB_END_DECLS |
||||
|
||||
#endif /* HB_OT_MATH_H */ |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,694 @@ |
||||
/*
|
||||
* Copyright © 2016 Igalia S.L. |
||||
* |
||||
* This is part of HarfBuzz, a text shaping library. |
||||
* |
||||
* Permission is hereby granted, without written agreement and without |
||||
* license or royalty fees, to use, copy, modify, and distribute this |
||||
* software and its documentation for any purpose, provided that the |
||||
* above copyright notice and the following two paragraphs appear in |
||||
* all copies of this software. |
||||
* |
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
||||
* DAMAGE. |
||||
* |
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||
* |
||||
* Igalia Author(s): Frédéric Wang |
||||
*/ |
||||
|
||||
|
||||
#include "hb-test.h" |
||||
|
||||
#include "hb-ft.h" |
||||
#include "hb-ot.h" |
||||
|
||||
/* Unit tests for hb-ot-math.h - OpenType MATH table */ |
||||
|
||||
static FT_Library ft_library; |
||||
static FT_Face ft_face; |
||||
static hb_font_t *hb_font; |
||||
static hb_face_t *hb_face; |
||||
|
||||
static inline void |
||||
initFreeType (void) |
||||
{ |
||||
FT_Error ft_error; |
||||
if ((ft_error = FT_Init_FreeType (&ft_library))) |
||||
abort(); |
||||
} |
||||
|
||||
static inline void |
||||
cleanupFreeType (void) |
||||
{ |
||||
FT_Done_FreeType (ft_library); |
||||
} |
||||
|
||||
static void |
||||
openFont(const char* fontFile) |
||||
{ |
||||
gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); |
||||
|
||||
FT_Error ft_error; |
||||
if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { |
||||
g_free(path); |
||||
abort(); |
||||
} |
||||
g_free(path); |
||||
|
||||
if ((ft_error = FT_Set_Char_Size (ft_face, 2000, 1000, 0, 0))) |
||||
abort(); |
||||
hb_font = hb_ft_font_create (ft_face, NULL); |
||||
hb_face = hb_ft_face_create_cached(ft_face); |
||||
} |
||||
|
||||
static inline void |
||||
closeFont (void) |
||||
{ |
||||
hb_font_destroy (hb_font); |
||||
FT_Done_Face (ft_face); |
||||
} |
||||
|
||||
static void |
||||
test_has_data (void) |
||||
{ |
||||
initFreeType(); |
||||
|
||||
openFont("fonts/MathTestFontNone.otf"); |
||||
g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
|
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontEmpty.otf"); |
||||
g_assert(hb_ot_math_has_data (hb_face)); // MATH table available
|
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_get_constant (void) |
||||
{ |
||||
initFreeType(); |
||||
|
||||
openFont("fonts/MathTestFontEmpty.otf"); |
||||
g_assert_cmpint(hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available
|
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontFull.otf"); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 3400); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 8600); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 11000); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 11200); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76); |
||||
g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65); |
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_get_glyph_italics_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_math_get_glyph_italics_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_math_get_glyph_italics_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_math_get_glyph_italics_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_math_get_glyph_italics_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_math_get_glyph_italics_correction (hb_font, glyph), ==, 394); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 300); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 904); |
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_get_glyph_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_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // 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_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // 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_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // 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_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // Glyph without top accent attachment.
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 748); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 692); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 636); |
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_is_glyph_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_math_is_glyph_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_math_is_glyph_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_math_is_glyph_extended_shape (hb_face, glyph)); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); |
||||
g_assert(hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); |
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_get_glyph_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_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_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_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_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_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_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_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min heigth
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height
|
||||
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 188); // top right
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 110); // top left
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 44); // bottom right
|
||||
g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 100); // bottom left
|
||||
|
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
|
||||
static hb_position_t |
||||
get_glyph_assembly_italics_correction (hb_font_t *font, |
||||
hb_codepoint_t glyph, |
||||
hb_bool_t horizontal) |
||||
{ |
||||
hb_position_t corr; |
||||
hb_ot_math_get_glyph_assembly (font, glyph, |
||||
horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB, |
||||
0, NULL, NULL, |
||||
&corr); |
||||
return corr; |
||||
} |
||||
|
||||
static void |
||||
test_get_glyph_assembly_italics_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(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
|
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (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(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
|
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (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(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
|
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (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(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
|
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (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(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); |
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (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(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 248); |
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); |
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); |
||||
g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 662); |
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_get_min_connector_overlap (void) |
||||
{ |
||||
initFreeType(); |
||||
|
||||
openFont("fonts/MathTestFontEmpty.otf"); |
||||
g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available
|
||||
g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available
|
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontPartial1.otf"); |
||||
g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 108); |
||||
g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 54); |
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_get_glyph_variants (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_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); |
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontPartial1.otf"); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); |
||||
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_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); |
||||
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_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); |
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontPartial4.otf"); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); |
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontFull.otf"); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_BTT, |
||||
0, |
||||
NULL, |
||||
NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_RTL, |
||||
0, |
||||
NULL, |
||||
NULL), ==, 3); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_BTT, |
||||
0, |
||||
NULL, |
||||
NULL), ==, 4); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_RTL, |
||||
0, |
||||
NULL, |
||||
NULL), ==, 0); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); |
||||
hb_ot_math_glyph_variant_t variants[20]; |
||||
unsigned variantsSize = sizeof (variants) / sizeof (variants[0]); |
||||
unsigned int count; |
||||
unsigned int offset = 0; |
||||
do { |
||||
count = variantsSize; |
||||
hb_ot_math_get_glyph_variants (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_RTL, |
||||
offset, |
||||
&count, |
||||
variants); |
||||
offset += count; |
||||
} while (count == variantsSize); |
||||
g_assert_cmpint(offset, ==, 3); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size2", -1, &glyph)); |
||||
g_assert_cmpint(variants[0].glyph, ==, glyph); |
||||
g_assert_cmpint(variants[0].advance, ==, 4302); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size3", -1, &glyph)); |
||||
g_assert_cmpint(variants[1].glyph, ==, glyph); |
||||
g_assert_cmpint(variants[1].advance, ==, 4802); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size4", -1, &glyph)); |
||||
g_assert_cmpint(variants[2].glyph, ==, glyph); |
||||
g_assert_cmpint(variants[2].advance, ==, 5802); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); |
||||
offset = 0; |
||||
do { |
||||
count = variantsSize; |
||||
hb_ot_math_get_glyph_variants (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_BTT, |
||||
offset, |
||||
&count, |
||||
variants); |
||||
offset += count; |
||||
} while (count == variantsSize); |
||||
g_assert_cmpint(offset, ==, 4); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size2", -1, &glyph)); |
||||
g_assert_cmpint(variants[0].glyph, ==, glyph); |
||||
g_assert_cmpint(variants[0].advance, ==, 2251); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size3", -1, &glyph)); |
||||
g_assert_cmpint(variants[1].glyph, ==, glyph); |
||||
g_assert_cmpint(variants[1].advance, ==, 2501); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size4", -1, &glyph)); |
||||
g_assert_cmpint(variants[2].glyph, ==, glyph); |
||||
g_assert_cmpint(variants[2].advance, ==, 3001); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size5", -1, &glyph)); |
||||
g_assert_cmpint(variants[3].glyph, ==, glyph); |
||||
g_assert_cmpint(variants[3].advance, ==, 3751); |
||||
|
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
static void |
||||
test_get_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_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); |
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontPartial1.otf"); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); |
||||
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_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); |
||||
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_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); |
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontPartial4.otf"); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); |
||||
closeFont(); |
||||
|
||||
openFont("fonts/MathTestFontFull.otf"); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_BTT, |
||||
0, |
||||
NULL, |
||||
NULL, |
||||
NULL), ==, 0); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_RTL, |
||||
0, |
||||
NULL, |
||||
NULL, |
||||
NULL), ==, 3); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph)); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_BTT, |
||||
0, |
||||
NULL, |
||||
NULL, |
||||
NULL), ==, 5); |
||||
g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_RTL, |
||||
0, |
||||
NULL, |
||||
NULL, |
||||
NULL), ==, 0); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); |
||||
hb_ot_math_glyph_part_t parts[20]; |
||||
unsigned partsSize = sizeof (parts) / sizeof (parts[0]); |
||||
unsigned int count; |
||||
unsigned int offset = 0; |
||||
do { |
||||
count = partsSize; |
||||
hb_ot_math_get_glyph_assembly (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_RTL, |
||||
offset, |
||||
&count, |
||||
parts, |
||||
NULL); |
||||
offset += count; |
||||
} while (count == partsSize); |
||||
g_assert_cmpint(offset, ==, 3); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "left", -1, &glyph)); |
||||
g_assert_cmpint(parts[0].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[0].start_connector_length, ==, 800); |
||||
g_assert_cmpint(parts[0].end_connector_length, ==, 384); |
||||
g_assert_cmpint(parts[0].full_advance, ==, 2000); |
||||
g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph)); |
||||
g_assert_cmpint(parts[1].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[1].start_connector_length, ==, 524); |
||||
g_assert_cmpint(parts[1].end_connector_length, ==, 800); |
||||
g_assert_cmpint(parts[1].full_advance, ==, 2000); |
||||
g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph)); |
||||
g_assert_cmpint(parts[2].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[2].start_connector_length, ==, 316); |
||||
g_assert_cmpint(parts[2].end_connector_length, ==, 454); |
||||
g_assert_cmpint(parts[2].full_advance, ==, 2000); |
||||
g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); |
||||
|
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph)); |
||||
offset = 0; |
||||
do { |
||||
count = partsSize; |
||||
hb_ot_math_get_glyph_assembly (hb_font, |
||||
glyph, |
||||
HB_DIRECTION_BTT, |
||||
offset, |
||||
&count, |
||||
parts, |
||||
NULL); |
||||
offset += count; |
||||
} while (count == partsSize); |
||||
g_assert_cmpint(offset, ==, 5); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "bottom", -1, &glyph)); |
||||
g_assert_cmpint(parts[0].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[0].start_connector_length, ==, 365); |
||||
g_assert_cmpint(parts[0].end_connector_length, ==, 158); |
||||
g_assert_cmpint(parts[0].full_advance, ==, 1000); |
||||
g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); |
||||
g_assert_cmpint(parts[1].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[1].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[1].start_connector_length, ==, 227); |
||||
g_assert_cmpint(parts[1].end_connector_length, ==, 365); |
||||
g_assert_cmpint(parts[1].full_advance, ==, 1000); |
||||
g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph)); |
||||
g_assert_cmpint(parts[2].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[2].start_connector_length, ==, 54); |
||||
g_assert_cmpint(parts[2].end_connector_length, ==, 158); |
||||
g_assert_cmpint(parts[2].full_advance, ==, 1000); |
||||
g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); |
||||
g_assert_cmpint(parts[3].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[3].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[3].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[3].start_connector_length, ==, 400); |
||||
g_assert_cmpint(parts[3].end_connector_length, ==, 296); |
||||
g_assert_cmpint(parts[3].full_advance, ==, 1000); |
||||
g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); |
||||
g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph)); |
||||
g_assert_cmpint(parts[4].glyph, ==, glyph); |
||||
g_assert_cmpint(parts[4].start_connector_length, ==, 123); |
||||
g_assert_cmpint(parts[4].end_connector_length, ==, 192); |
||||
g_assert_cmpint(parts[4].full_advance, ==, 1000); |
||||
g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); |
||||
|
||||
closeFont(); |
||||
|
||||
cleanupFreeType(); |
||||
} |
||||
|
||||
int |
||||
main (int argc, char **argv) |
||||
{ |
||||
hb_test_init (&argc, &argv); |
||||
|
||||
hb_test_add (test_has_data); |
||||
hb_test_add (test_get_constant); |
||||
hb_test_add (test_get_glyph_italics_correction); |
||||
hb_test_add (test_get_glyph_top_accent_attachment); |
||||
hb_test_add (test_is_glyph_extended_shape); |
||||
hb_test_add (test_get_glyph_kerning); |
||||
hb_test_add (test_get_glyph_assembly_italics_correction); |
||||
hb_test_add (test_get_min_connector_overlap); |
||||
hb_test_add (test_get_glyph_variants); |
||||
hb_test_add (test_get_glyph_assembly); |
||||
|
||||
return hb_test_run(); |
||||
} |
Loading…
Reference in new issue