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 hb_font_destroy (hb_font);
104 hb_face_destroy (hb_face);
105
106 hb_font = hb_font_get_empty ();
107 hb_face = hb_font_get_face (hb_font);
108 g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
109 hb_font_destroy (hb_font);
110 hb_face_destroy (hb_face);
111
112 cleanupFreeType();
113 }
114
115 static void
test_get_constant(void)116 test_get_constant (void)
117 {
118 initFreeType();
119
120 openFont("fonts/MathTestFontEmpty.otf");
121 g_assert_cmpint(hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available
122 closeFont();
123
124 openFont("fonts/MathTestFontFull.otf");
125 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100);
126 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200);
127 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300);
128 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400);
129 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500);
130 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600);
131 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700);
132 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800);
133 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900);
134 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100);
135 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200);
136 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300);
137 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400);
138 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500);
139 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600);
140 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 3400);
141 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800);
142 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900);
143 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200);
144 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300);
145 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400);
146 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500);
147 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600);
148 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700);
149 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800);
150 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900);
151 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000);
152 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100);
153 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200);
154 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300);
155 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400);
156 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500);
157 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600);
158 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700);
159 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800);
160 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900);
161 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000);
162 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100);
163 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200);
164 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 8600);
165 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400);
166 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500);
167 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600);
168 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700);
169 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800);
170 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900);
171 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000);
172 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100);
173 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200);
174 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300);
175 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400);
176 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 11000);
177 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 11200);
178 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87);
179 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76);
180 g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65);
181 closeFont();
182
183 cleanupFreeType();
184 }
185
186 static void
test_get_glyph_italics_correction(void)187 test_get_glyph_italics_correction (void)
188 {
189 hb_codepoint_t glyph;
190 initFreeType();
191
192 openFont("fonts/MathTestFontEmpty.otf");
193 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
194 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
195 closeFont();
196
197 openFont("fonts/MathTestFontPartial1.otf");
198 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
199 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
200 closeFont();
201
202 openFont("fonts/MathTestFontPartial2.otf");
203 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
204 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
205 closeFont();
206
207 openFont("fonts/MathTestFontFull.otf");
208 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
209 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
210 g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
211 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 394);
212 g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
213 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 300);
214 g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
215 g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 904);
216 closeFont();
217
218 cleanupFreeType();
219 }
220
221 static void
test_get_glyph_top_accent_attachment(void)222 test_get_glyph_top_accent_attachment (void)
223 {
224 hb_codepoint_t glyph;
225 initFreeType();
226
227 openFont("fonts/MathTestFontEmpty.otf");
228 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
229 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo not available
230 closeFont();
231
232 openFont("fonts/MathTestFontPartial1.otf");
233 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
234 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo empty
235 closeFont();
236
237 openFont("fonts/MathTestFontPartial2.otf");
238 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
239 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathTopAccentAttachment empty
240 closeFont();
241
242 openFont("fonts/MathTestFontFull.otf");
243 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
244 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // Glyph without top accent attachment.
245 g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
246 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 748);
247 g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
248 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 692);
249 g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph));
250 g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 636);
251 closeFont();
252
253 cleanupFreeType();
254 }
255
256 static void
test_is_glyph_extended_shape(void)257 test_is_glyph_extended_shape (void)
258 {
259 hb_codepoint_t glyph;
260 initFreeType();
261
262 openFont("fonts/MathTestFontEmpty.otf");
263 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
264 g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo not available
265 closeFont();
266
267 openFont("fonts/MathTestFontPartial1.otf");
268 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
269 g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo empty
270 closeFont();
271
272 openFont("fonts/MathTestFontFull.otf");
273 g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph));
274 g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
275 g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph));
276 g_assert(hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
277 closeFont();
278
279 cleanupFreeType();
280 }
281
282 static void
test_get_glyph_kerning(void)283 test_get_glyph_kerning (void)
284 {
285 hb_codepoint_t glyph;
286 initFreeType();
287
288 openFont("fonts/MathTestFontEmpty.otf");
289 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
290 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available
291 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available
292 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available
293 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available
294 closeFont();
295
296 openFont("fonts/MathTestFontPartial2.otf");
297 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
298 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty
299 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty
300 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty
301 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty
302 closeFont();
303
304 openFont("fonts/MathTestFontPartial3.otf");
305 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
306 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
307 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty
308 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
309 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty
310 closeFont();
311
312 openFont("fonts/MathTestFontFull.otf");
313 g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph));
314
315 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min heigth
316 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height
317 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104);
318 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104);
319 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146);
320 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146);
321 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height
322 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height
323 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height
324
325 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 188); // top right
326 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 110); // top left
327 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 44); // bottom right
328 g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 100); // bottom left
329
330 closeFont();
331
332 cleanupFreeType();
333 }
334
335
336 static hb_position_t
get_glyph_assembly_italics_correction(hb_font_t * font,hb_codepoint_t glyph,hb_bool_t horizontal)337 get_glyph_assembly_italics_correction (hb_font_t *font,
338 hb_codepoint_t glyph,
339 hb_bool_t horizontal)
340 {
341 hb_position_t corr;
342 hb_ot_math_get_glyph_assembly (font, glyph,
343 horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB,
344 0, NULL, NULL,
345 &corr);
346 return corr;
347 }
348
349 static void
test_get_glyph_assembly_italics_correction(void)350 test_get_glyph_assembly_italics_correction (void)
351 {
352 hb_codepoint_t glyph;
353 initFreeType();
354
355 openFont("fonts/MathTestFontEmpty.otf");
356 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
357 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
358 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
359 closeFont();
360
361 openFont("fonts/MathTestFontPartial1.otf");
362 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
363 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
364 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
365 closeFont();
366
367 openFont("fonts/MathTestFontPartial2.otf");
368 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
369 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
370 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
371 closeFont();
372
373 openFont("fonts/MathTestFontPartial3.otf");
374 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
375 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
376 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
377 closeFont();
378
379 openFont("fonts/MathTestFontPartial4.otf");
380 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
381 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
382 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
383 closeFont();
384
385 openFont("fonts/MathTestFontFull.otf");
386 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
387 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 248);
388 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
389 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
390 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
391 g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 662);
392 closeFont();
393
394 cleanupFreeType();
395 }
396
397 static void
test_get_min_connector_overlap(void)398 test_get_min_connector_overlap (void)
399 {
400 initFreeType();
401
402 openFont("fonts/MathTestFontEmpty.otf");
403 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 0); // MathVariants not available
404 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 0); // MathVariants not available
405 closeFont();
406
407 openFont("fonts/MathTestFontPartial1.otf");
408 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 108);
409 g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 54);
410 closeFont();
411
412 cleanupFreeType();
413 }
414
415 static void
test_get_glyph_variants(void)416 test_get_glyph_variants (void)
417 {
418 hb_codepoint_t glyph;
419 hb_ot_math_glyph_variant_t variants[20];
420 unsigned variantsSize = sizeof (variants) / sizeof (variants[0]);
421 unsigned int count;
422 unsigned int offset = 0;
423
424 initFreeType();
425
426 openFont("fonts/MathTestFontEmpty.otf");
427 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
428 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
429 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
430 closeFont();
431
432 openFont("fonts/MathTestFontPartial1.otf");
433 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
434 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
435 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
436 closeFont();
437
438 openFont("fonts/MathTestFontPartial2.otf");
439 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
440 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
441 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
442 closeFont();
443
444 openFont("fonts/MathTestFontPartial3.otf");
445 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
446 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
447 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
448 closeFont();
449
450 openFont("fonts/MathTestFontPartial4.otf");
451 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
452 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
453 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
454 closeFont();
455
456 openFont("fonts/MathTestFontFull.otf");
457
458 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
459 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
460 glyph,
461 HB_DIRECTION_BTT,
462 0,
463 NULL,
464 NULL), ==, 0);
465 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
466 glyph,
467 HB_DIRECTION_RTL,
468 0,
469 NULL,
470 NULL), ==, 3);
471
472 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
473 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
474 glyph,
475 HB_DIRECTION_BTT,
476 0,
477 NULL,
478 NULL), ==, 4);
479 g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
480 glyph,
481 HB_DIRECTION_RTL,
482 0,
483 NULL,
484 NULL), ==, 0);
485
486 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
487 do {
488 count = variantsSize;
489 hb_ot_math_get_glyph_variants (hb_font,
490 glyph,
491 HB_DIRECTION_RTL,
492 offset,
493 &count,
494 variants);
495 offset += count;
496 } while (count == variantsSize);
497 g_assert_cmpint(offset, ==, 3);
498 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size2", -1, &glyph));
499 g_assert_cmpint(variants[0].glyph, ==, glyph);
500 g_assert_cmpint(variants[0].advance, ==, 4302);
501 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size3", -1, &glyph));
502 g_assert_cmpint(variants[1].glyph, ==, glyph);
503 g_assert_cmpint(variants[1].advance, ==, 4802);
504 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size4", -1, &glyph));
505 g_assert_cmpint(variants[2].glyph, ==, glyph);
506 g_assert_cmpint(variants[2].advance, ==, 5802);
507
508 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
509 offset = 0;
510 do {
511 count = variantsSize;
512 hb_ot_math_get_glyph_variants (hb_font,
513 glyph,
514 HB_DIRECTION_BTT,
515 offset,
516 &count,
517 variants);
518 offset += count;
519 } while (count == variantsSize);
520 g_assert_cmpint(offset, ==, 4);
521 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size2", -1, &glyph));
522 g_assert_cmpint(variants[0].glyph, ==, glyph);
523 g_assert_cmpint(variants[0].advance, ==, 2251);
524 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size3", -1, &glyph));
525 g_assert_cmpint(variants[1].glyph, ==, glyph);
526 g_assert_cmpint(variants[1].advance, ==, 2501);
527 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size4", -1, &glyph));
528 g_assert_cmpint(variants[2].glyph, ==, glyph);
529 g_assert_cmpint(variants[2].advance, ==, 3001);
530 g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size5", -1, &glyph));
531 g_assert_cmpint(variants[3].glyph, ==, glyph);
532 g_assert_cmpint(variants[3].advance, ==, 3751);
533
534 closeFont();
535
536 cleanupFreeType();
537 }
538
539 static void
test_get_glyph_assembly(void)540 test_get_glyph_assembly (void)
541 {
542 hb_codepoint_t glyph;
543 hb_ot_math_glyph_part_t parts[20];
544 unsigned partsSize = sizeof (parts) / sizeof (parts[0]);
545 unsigned int count;
546 unsigned int offset = 0;
547
548 initFreeType();
549
550 openFont("fonts/MathTestFontEmpty.otf");
551 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
552 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
553 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
554 closeFont();
555
556 openFont("fonts/MathTestFontPartial1.otf");
557 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
558 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
559 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
560 closeFont();
561
562 openFont("fonts/MathTestFontPartial2.otf");
563 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
564 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
565 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
566 closeFont();
567
568 openFont("fonts/MathTestFontPartial3.otf");
569 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
570 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
571 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
572 closeFont();
573
574 openFont("fonts/MathTestFontPartial4.otf");
575 g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
576 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
577 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
578 closeFont();
579
580 openFont("fonts/MathTestFontFull.otf");
581
582 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
583 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
584 glyph,
585 HB_DIRECTION_BTT,
586 0,
587 NULL,
588 NULL,
589 NULL), ==, 0);
590 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
591 glyph,
592 HB_DIRECTION_RTL,
593 0,
594 NULL,
595 NULL,
596 NULL), ==, 3);
597
598 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
599 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
600 glyph,
601 HB_DIRECTION_BTT,
602 0,
603 NULL,
604 NULL,
605 NULL), ==, 5);
606 g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
607 glyph,
608 HB_DIRECTION_RTL,
609 0,
610 NULL,
611 NULL,
612 NULL), ==, 0);
613
614 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
615 do {
616 count = partsSize;
617 hb_ot_math_get_glyph_assembly (hb_font,
618 glyph,
619 HB_DIRECTION_RTL,
620 offset,
621 &count,
622 parts,
623 NULL);
624 offset += count;
625 } while (count == partsSize);
626 g_assert_cmpint(offset, ==, 3);
627 g_assert(hb_font_get_glyph_from_name (hb_font, "left", -1, &glyph));
628 g_assert_cmpint(parts[0].glyph, ==, glyph);
629 g_assert_cmpint(parts[0].start_connector_length, ==, 800);
630 g_assert_cmpint(parts[0].end_connector_length, ==, 384);
631 g_assert_cmpint(parts[0].full_advance, ==, 2000);
632 g_assert(!(parts[0].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
633 g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph));
634 g_assert_cmpint(parts[1].glyph, ==, glyph);
635 g_assert_cmpint(parts[1].start_connector_length, ==, 524);
636 g_assert_cmpint(parts[1].end_connector_length, ==, 800);
637 g_assert_cmpint(parts[1].full_advance, ==, 2000);
638 g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER);
639 g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph));
640 g_assert_cmpint(parts[2].glyph, ==, glyph);
641 g_assert_cmpint(parts[2].start_connector_length, ==, 316);
642 g_assert_cmpint(parts[2].end_connector_length, ==, 454);
643 g_assert_cmpint(parts[2].full_advance, ==, 2000);
644 g_assert(!(parts[2].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
645
646 g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
647 offset = 0;
648 do {
649 count = partsSize;
650 hb_ot_math_get_glyph_assembly (hb_font,
651 glyph,
652 HB_DIRECTION_BTT,
653 offset,
654 &count,
655 parts,
656 NULL);
657 offset += count;
658 } while (count == partsSize);
659 g_assert_cmpint(offset, ==, 5);
660 g_assert(hb_font_get_glyph_from_name (hb_font, "bottom", -1, &glyph));
661 g_assert_cmpint(parts[0].glyph, ==, glyph);
662 g_assert_cmpint(parts[0].start_connector_length, ==, 365);
663 g_assert_cmpint(parts[0].end_connector_length, ==, 158);
664 g_assert_cmpint(parts[0].full_advance, ==, 1000);
665 g_assert(!(parts[0].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
666 g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
667 g_assert_cmpint(parts[1].glyph, ==, glyph);
668 g_assert_cmpint(parts[1].glyph, ==, glyph);
669 g_assert_cmpint(parts[1].start_connector_length, ==, 227);
670 g_assert_cmpint(parts[1].end_connector_length, ==, 365);
671 g_assert_cmpint(parts[1].full_advance, ==, 1000);
672 g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER);
673 g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph));
674 g_assert_cmpint(parts[2].glyph, ==, glyph);
675 g_assert_cmpint(parts[2].start_connector_length, ==, 54);
676 g_assert_cmpint(parts[2].end_connector_length, ==, 158);
677 g_assert_cmpint(parts[2].full_advance, ==, 1000);
678 g_assert(!(parts[2].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
679 g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
680 g_assert_cmpint(parts[3].glyph, ==, glyph);
681 g_assert_cmpint(parts[3].glyph, ==, glyph);
682 g_assert_cmpint(parts[3].glyph, ==, glyph);
683 g_assert_cmpint(parts[3].start_connector_length, ==, 400);
684 g_assert_cmpint(parts[3].end_connector_length, ==, 296);
685 g_assert_cmpint(parts[3].full_advance, ==, 1000);
686 g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER);
687 g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph));
688 g_assert_cmpint(parts[4].glyph, ==, glyph);
689 g_assert_cmpint(parts[4].start_connector_length, ==, 123);
690 g_assert_cmpint(parts[4].end_connector_length, ==, 192);
691 g_assert_cmpint(parts[4].full_advance, ==, 1000);
692 g_assert(!(parts[4].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
693
694 closeFont();
695
696 cleanupFreeType();
697 }
698
699 int
main(int argc,char ** argv)700 main (int argc, char **argv)
701 {
702 hb_test_init (&argc, &argv);
703
704 hb_test_add (test_has_data);
705 hb_test_add (test_get_constant);
706 hb_test_add (test_get_glyph_italics_correction);
707 hb_test_add (test_get_glyph_top_accent_attachment);
708 hb_test_add (test_is_glyph_extended_shape);
709 hb_test_add (test_get_glyph_kerning);
710 hb_test_add (test_get_glyph_assembly_italics_correction);
711 hb_test_add (test_get_min_connector_overlap);
712 hb_test_add (test_get_glyph_variants);
713 hb_test_add (test_get_glyph_assembly);
714
715 return hb_test_run();
716 }
717