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