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
35static FT_Library ft_library;
36static FT_Face ft_face;
37static hb_font_t *hb_font;
38static hb_face_t *hb_face;
39
40static inline void
41initFreeType (void)
42{
43  FT_Error ft_error;
44  if ((ft_error = FT_Init_FreeType (&ft_library)))
45    abort();
46}
47
48static inline void
49cleanupFreeType (void)
50{
51  FT_Done_FreeType (ft_library);
52}
53
54static void
55openFont(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
76static inline void
77closeFont (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
87static void
88test_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
111static void
112test_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
182static void
183test_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
217static void
218test_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
252static void
253test_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
278static void
279test_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
332static hb_position_t
333get_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
345static void
346test_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
393static void
394test_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
411static void
412test_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
535static void
536test_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
695int
696main (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