1 /*
2 * Copyright © 2016 Igalia S.L.
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Igalia Author(s): Frédéric Wang
25 */
26
27
28 #include "hb-test.h"
29
30 #include "hb-ft.h"
31 #include "hb-ot.h"
32
33 /* Unit tests for hb-ot-math.h - OpenType MATH table */
34
35 static FT_Library ft_library;
36 static FT_Face ft_face;
37 static hb_font_t *hb_font;
38 static hb_face_t *hb_face;
39
40 static inline void
initFreeType(void)41 initFreeType (void)
42 {
43 FT_Error ft_error;
44 if ((ft_error = FT_Init_FreeType (&ft_library)))
45 abort();
46 }
47
48 static inline void
cleanupFreeType(void)49 cleanupFreeType (void)
50 {
51 FT_Done_FreeType (ft_library);
52 }
53
54 static void
openFont(const char * fontFile)55 openFont(const char* fontFile)
56 {
57 #if GLIB_CHECK_VERSION(2,37,2)
58 gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL);
59 #else
60 gchar* path = g_strdup(fontFile);
61 #endif
62
63 FT_Error ft_error;
64 if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) {
65 g_free(path);
66 abort();
67 }
68 g_free(path);
69
70 if ((ft_error = FT_Set_Char_Size (ft_face, 2000, 1000, 0, 0)))
71 abort();
72 hb_font = hb_ft_font_create (ft_face, NULL);
73 hb_face = hb_face_reference (hb_font_get_face (hb_font));
74 }
75
76 static inline void
closeFont(void)77 closeFont (void)
78 {
79 hb_face_destroy (hb_face);
80 hb_font_destroy (hb_font);
81 FT_Done_Face (ft_face);
82 hb_face = NULL;
83 hb_font = NULL;
84 ft_face = NULL;
85 }
86
87 static void
test_has_data(void)88 test_has_data (void)
89 {
90 initFreeType();
91
92 openFont("fonts/MathTestFontNone.otf");
93 g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
94 closeFont();
95
96 openFont("fonts/MathTestFontEmpty.otf");
97 g_assert(hb_ot_math_has_data (hb_face)); // MATH table available
98 closeFont();
99
100 hb_face = hb_face_get_empty ();
101 hb_font = hb_font_create (hb_face);
102 g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
103
104 hb_font = hb_font_get_empty ();
105 hb_face = hb_font_get_face (hb_font);
106 g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
107
108 cleanupFreeType();
109 }
110
111 static void
test_get_constant(void)112 test_get_constant (void)
113 {
114 initFreeType();
115
116 openFont("fonts/MathTestFontEmpty.otf");
117 g_assert_cmpint(hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available
118 closeFont();
119
120 openFont("fonts/MathTestFontFull.otf");
121 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100);
122 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200);
123 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300);
124 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400);
125 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500);
126 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600);
127 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700);
128 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800);
129 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900);
130 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100);
131 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200);
132 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300);
133 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400);
134 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500);
135 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600);
136 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 3400);
137 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800);
138 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900);
139 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200);
140 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300);
141 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400);
142 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500);
143 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600);
144 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700);
145 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800);
146 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900);
147 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000);
148 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100);
149 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200);
150 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300);
151 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400);
152 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500);
153 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600);
154 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700);
155 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800);
156 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900);
157 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000);
158 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100);
159 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200);
160 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 8600);
161 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400);
162 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500);
163 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600);
164 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700);
165 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800);
166 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900);
167 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000);
168 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100);
169 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200);
170 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300);
171 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400);
172 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 11000);
173 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 11200);
174 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87);
175 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76);
176 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65);
177 closeFont();
178
179 cleanupFreeType();
180 }
181
182 static void
test_get_glyph_italics_correction(void)183 test_get_glyph_italics_correction (void)
184 {
185 hb_codepoint_t glyph;
186 initFreeType();
187
188 openFont("fonts/MathTestFontEmpty.otf");
189 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
190 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
191 closeFont();
192
193 openFont("fonts/MathTestFontPartial1.otf");
194 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
195 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
196 closeFont();
197
198 openFont("fonts/MathTestFontPartial2.otf");
199 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
200 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
201 closeFont();
202
203 openFont("fonts/MathTestFontFull.otf");
204 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
205 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
206 g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
207 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 394);
208 g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
209 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 300);
210 g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
211 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 904);
212 closeFont();
213
214 cleanupFreeType();
215 }
216
217 static void
test_get_glyph_top_accent_attachment(void)218 test_get_glyph_top_accent_attachment (void)
219 {
220 hb_codepoint_t glyph;
221 initFreeType();
222
223 openFont("fonts/MathTestFontEmpty.otf");
224 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
225 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo not available
226 closeFont();
227
228 openFont("fonts/MathTestFontPartial1.otf");
229 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
230 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo empty
231 closeFont();
232
233 openFont("fonts/MathTestFontPartial2.otf");
234 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
235 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathTopAccentAttachment empty
236 closeFont();
237
238 openFont("fonts/MathTestFontFull.otf");
239 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
240 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // Glyph without top accent attachment.
241 g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
242 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 748);
243 g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
244 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 692);
245 g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph));
246 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 636);
247 closeFont();
248
249 cleanupFreeType();
250 }
251
252 static void
test_is_glyph_extended_shape(void)253 test_is_glyph_extended_shape (void)
254 {
255 hb_codepoint_t glyph;
256 initFreeType();
257
258 openFont("fonts/MathTestFontEmpty.otf");
259 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
260 g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo not available
261 closeFont();
262
263 openFont("fonts/MathTestFontPartial1.otf");
264 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
265 g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo empty
266 closeFont();
267
268 openFont("fonts/MathTestFontFull.otf");
269 g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph));
270 g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
271 g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph));
272 g_assert(hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
273 closeFont();
274
275 cleanupFreeType();
276 }
277
278 static void
test_get_glyph_kerning(void)279 test_get_glyph_kerning (void)
280 {
281 hb_codepoint_t glyph;
282 initFreeType();
283
284 openFont("fonts/MathTestFontEmpty.otf");
285 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
286 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available
287 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available
288 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available
289 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available
290 closeFont();
291
292 openFont("fonts/MathTestFontPartial2.otf");
293 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
294 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty
295 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty
296 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty
297 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty
298 closeFont();
299
300 openFont("fonts/MathTestFontPartial3.otf");
301 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
302 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
303 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty
304 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
305 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty
306 closeFont();
307
308 openFont("fonts/MathTestFontFull.otf");
309 g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph));
310
311 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min heigth
312 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height
313 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104);
314 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104);
315 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146);
316 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146);
317 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height
318 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height
319 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height
320
321 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 188); // top right
322 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 110); // top left
323 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 44); // bottom right
324 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 100); // bottom left
325
326 closeFont();
327
328 cleanupFreeType();
329 }
330
331
332 static hb_position_t
get_glyph_assembly_italics_correction(hb_font_t * font,hb_codepoint_t glyph,hb_bool_t horizontal)333 get_glyph_assembly_italics_correction (hb_font_t *font,
334 hb_codepoint_t glyph,
335 hb_bool_t horizontal)
336 {
337 hb_position_t corr;
338 hb_ot_math_get_glyph_assembly (font, glyph,
339 horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB,
340 0, NULL, NULL,
341 &corr);
342 return corr;
343 }
344
345 static void
test_get_glyph_assembly_italics_correction(void)346 test_get_glyph_assembly_italics_correction (void)
347 {
348 hb_codepoint_t glyph;
349 initFreeType();
350
351 openFont("fonts/MathTestFontEmpty.otf");
352 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
353 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
354 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
355 closeFont();
356
357 openFont("fonts/MathTestFontPartial1.otf");
358 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
359 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
360 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
361 closeFont();
362
363 openFont("fonts/MathTestFontPartial2.otf");
364 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
365 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
366 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
367 closeFont();
368
369 openFont("fonts/MathTestFontPartial3.otf");
370 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
371 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
372 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
373 closeFont();
374
375 openFont("fonts/MathTestFontPartial4.otf");
376 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
377 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
378 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
379 closeFont();
380
381 openFont("fonts/MathTestFontFull.otf");
382 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
383 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 248);
384 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
385 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
386 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
387 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 662);
388 closeFont();
389
390 cleanupFreeType();
391 }
392
393 static void
test_get_min_connector_overlap(void)394 test_get_min_connector_overlap (void)
395 {
396 initFreeType();
397
398 openFont("fonts/MathTestFontEmpty.otf");
399 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available
400 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available
401 closeFont();
402
403 openFont("fonts/MathTestFontPartial1.otf");
404 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 108);
405 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 54);
406 closeFont();
407
408 cleanupFreeType();
409 }
410
411 static void
test_get_glyph_variants(void)412 test_get_glyph_variants (void)
413 {
414 hb_codepoint_t glyph;
415 hb_ot_math_glyph_variant_t variants[20];
416 unsigned variantsSize = sizeof (variants) / sizeof (variants[0]);
417 unsigned int count;
418 unsigned int offset = 0;
419
420 initFreeType();
421
422 openFont("fonts/MathTestFontEmpty.otf");
423 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
424 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
425 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
426 closeFont();
427
428 openFont("fonts/MathTestFontPartial1.otf");
429 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
430 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
431 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
432 closeFont();
433
434 openFont("fonts/MathTestFontPartial2.otf");
435 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
436 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
437 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
438 closeFont();
439
440 openFont("fonts/MathTestFontPartial3.otf");
441 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
442 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
443 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
444 closeFont();
445
446 openFont("fonts/MathTestFontPartial4.otf");
447 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
448 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
449 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
450 closeFont();
451
452 openFont("fonts/MathTestFontFull.otf");
453
454 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
455 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
456 glyph,
457 HB_DIRECTION_BTT,
458 0,
459 NULL,
460 NULL), ==, 0);
461 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
462 glyph,
463 HB_DIRECTION_RTL,
464 0,
465 NULL,
466 NULL), ==, 3);
467
468 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
469 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
470 glyph,
471 HB_DIRECTION_BTT,
472 0,
473 NULL,
474 NULL), ==, 4);
475 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
476 glyph,
477 HB_DIRECTION_RTL,
478 0,
479 NULL,
480 NULL), ==, 0);
481
482 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
483 do {
484 count = variantsSize;
485 hb_ot_math_get_glyph_variants (hb_font,
486 glyph,
487 HB_DIRECTION_RTL,
488 offset,
489 &count,
490 variants);
491 offset += count;
492 } while (count == variantsSize);
493 g_assert_cmpint(offset, ==, 3);
494 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size2", -1, &glyph));
495 g_assert_cmpint(variants[0].glyph, ==, glyph);
496 g_assert_cmpint(variants[0].advance, ==, 4302);
497 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size3", -1, &glyph));
498 g_assert_cmpint(variants[1].glyph, ==, glyph);
499 g_assert_cmpint(variants[1].advance, ==, 4802);
500 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size4", -1, &glyph));
501 g_assert_cmpint(variants[2].glyph, ==, glyph);
502 g_assert_cmpint(variants[2].advance, ==, 5802);
503
504 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
505 offset = 0;
506 do {
507 count = variantsSize;
508 hb_ot_math_get_glyph_variants (hb_font,
509 glyph,
510 HB_DIRECTION_BTT,
511 offset,
512 &count,
513 variants);
514 offset += count;
515 } while (count == variantsSize);
516 g_assert_cmpint(offset, ==, 4);
517 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size2", -1, &glyph));
518 g_assert_cmpint(variants[0].glyph, ==, glyph);
519 g_assert_cmpint(variants[0].advance, ==, 2251);
520 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size3", -1, &glyph));
521 g_assert_cmpint(variants[1].glyph, ==, glyph);
522 g_assert_cmpint(variants[1].advance, ==, 2501);
523 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size4", -1, &glyph));
524 g_assert_cmpint(variants[2].glyph, ==, glyph);
525 g_assert_cmpint(variants[2].advance, ==, 3001);
526 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size5", -1, &glyph));
527 g_assert_cmpint(variants[3].glyph, ==, glyph);
528 g_assert_cmpint(variants[3].advance, ==, 3751);
529
530 closeFont();
531
532 cleanupFreeType();
533 }
534
535 static void
test_get_glyph_assembly(void)536 test_get_glyph_assembly (void)
537 {
538 hb_codepoint_t glyph;
539 hb_ot_math_glyph_part_t parts[20];
540 unsigned partsSize = sizeof (parts) / sizeof (parts[0]);
541 unsigned int count;
542 unsigned int offset = 0;
543
544 initFreeType();
545
546 openFont("fonts/MathTestFontEmpty.otf");
547 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
548 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
549 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
550 closeFont();
551
552 openFont("fonts/MathTestFontPartial1.otf");
553 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
554 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
555 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
556 closeFont();
557
558 openFont("fonts/MathTestFontPartial2.otf");
559 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
560 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
561 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
562 closeFont();
563
564 openFont("fonts/MathTestFontPartial3.otf");
565 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
566 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
567 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
568 closeFont();
569
570 openFont("fonts/MathTestFontPartial4.otf");
571 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
572 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
573 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
574 closeFont();
575
576 openFont("fonts/MathTestFontFull.otf");
577
578 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
579 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
580 glyph,
581 HB_DIRECTION_BTT,
582 0,
583 NULL,
584 NULL,
585 NULL), ==, 0);
586 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
587 glyph,
588 HB_DIRECTION_RTL,
589 0,
590 NULL,
591 NULL,
592 NULL), ==, 3);
593
594 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
595 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
596 glyph,
597 HB_DIRECTION_BTT,
598 0,
599 NULL,
600 NULL,
601 NULL), ==, 5);
602 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
603 glyph,
604 HB_DIRECTION_RTL,
605 0,
606 NULL,
607 NULL,
608 NULL), ==, 0);
609
610 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
611 do {
612 count = partsSize;
613 hb_ot_math_get_glyph_assembly (hb_font,
614 glyph,
615 HB_DIRECTION_RTL,
616 offset,
617 &count,
618 parts,
619 NULL);
620 offset += count;
621 } while (count == partsSize);
622 g_assert_cmpint(offset, ==, 3);
623 g_assert(hb_font_get_glyph_from_name (hb_font, "left", -1, &glyph));
624 g_assert_cmpint(parts[0].glyph, ==, glyph);
625 g_assert_cmpint(parts[0].start_connector_length, ==, 800);
626 g_assert_cmpint(parts[0].end_connector_length, ==, 384);
627 g_assert_cmpint(parts[0].full_advance, ==, 2000);
628 g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
629 g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph));
630 g_assert_cmpint(parts[1].glyph, ==, glyph);
631 g_assert_cmpint(parts[1].start_connector_length, ==, 524);
632 g_assert_cmpint(parts[1].end_connector_length, ==, 800);
633 g_assert_cmpint(parts[1].full_advance, ==, 2000);
634 g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
635 g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph));
636 g_assert_cmpint(parts[2].glyph, ==, glyph);
637 g_assert_cmpint(parts[2].start_connector_length, ==, 316);
638 g_assert_cmpint(parts[2].end_connector_length, ==, 454);
639 g_assert_cmpint(parts[2].full_advance, ==, 2000);
640 g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
641
642 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
643 offset = 0;
644 do {
645 count = partsSize;
646 hb_ot_math_get_glyph_assembly (hb_font,
647 glyph,
648 HB_DIRECTION_BTT,
649 offset,
650 &count,
651 parts,
652 NULL);
653 offset += count;
654 } while (count == partsSize);
655 g_assert_cmpint(offset, ==, 5);
656 g_assert(hb_font_get_glyph_from_name (hb_font, "bottom", -1, &glyph));
657 g_assert_cmpint(parts[0].glyph, ==, glyph);
658 g_assert_cmpint(parts[0].start_connector_length, ==, 365);
659 g_assert_cmpint(parts[0].end_connector_length, ==, 158);
660 g_assert_cmpint(parts[0].full_advance, ==, 1000);
661 g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
662 g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
663 g_assert_cmpint(parts[1].glyph, ==, glyph);
664 g_assert_cmpint(parts[1].glyph, ==, glyph);
665 g_assert_cmpint(parts[1].start_connector_length, ==, 227);
666 g_assert_cmpint(parts[1].end_connector_length, ==, 365);
667 g_assert_cmpint(parts[1].full_advance, ==, 1000);
668 g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
669 g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph));
670 g_assert_cmpint(parts[2].glyph, ==, glyph);
671 g_assert_cmpint(parts[2].start_connector_length, ==, 54);
672 g_assert_cmpint(parts[2].end_connector_length, ==, 158);
673 g_assert_cmpint(parts[2].full_advance, ==, 1000);
674 g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
675 g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
676 g_assert_cmpint(parts[3].glyph, ==, glyph);
677 g_assert_cmpint(parts[3].glyph, ==, glyph);
678 g_assert_cmpint(parts[3].glyph, ==, glyph);
679 g_assert_cmpint(parts[3].start_connector_length, ==, 400);
680 g_assert_cmpint(parts[3].end_connector_length, ==, 296);
681 g_assert_cmpint(parts[3].full_advance, ==, 1000);
682 g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
683 g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph));
684 g_assert_cmpint(parts[4].glyph, ==, glyph);
685 g_assert_cmpint(parts[4].start_connector_length, ==, 123);
686 g_assert_cmpint(parts[4].end_connector_length, ==, 192);
687 g_assert_cmpint(parts[4].full_advance, ==, 1000);
688 g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
689
690 closeFont();
691
692 cleanupFreeType();
693 }
694
695 int
main(int argc,char ** argv)696 main (int argc, char **argv)
697 {
698 hb_test_init (&argc, &argv);
699
700 hb_test_add (test_has_data);
701 hb_test_add (test_get_constant);
702 hb_test_add (test_get_glyph_italics_correction);
703 hb_test_add (test_get_glyph_top_accent_attachment);
704 hb_test_add (test_is_glyph_extended_shape);
705 hb_test_add (test_get_glyph_kerning);
706 hb_test_add (test_get_glyph_assembly_italics_correction);
707 hb_test_add (test_get_min_connector_overlap);
708 hb_test_add (test_get_glyph_variants);
709 hb_test_add (test_get_glyph_assembly);
710
711 return hb_test_run();
712 }
713