• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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