• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2009  Red Hat, Inc.
3  * Copyright © 2012  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28 
29 #include "hb-private.hh"
30 
31 #include "hb-ot-layout-private.hh"
32 
33 #include "hb-font-private.hh"
34 #include "hb-blob.h"
35 #include "hb-open-file-private.hh"
36 #include "hb-ot-head-table.hh"
37 #include "hb-ot-maxp-table.hh"
38 
39 #include "hb-cache-private.hh"
40 
41 #include <string.h>
42 
43 
44 
45 /*
46  * hb_font_funcs_t
47  */
48 
49 static hb_bool_t
hb_font_get_glyph_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t unicode,hb_codepoint_t variation_selector,hb_codepoint_t * glyph,void * user_data HB_UNUSED)50 hb_font_get_glyph_nil (hb_font_t *font,
51 		       void *font_data HB_UNUSED,
52 		       hb_codepoint_t unicode,
53 		       hb_codepoint_t variation_selector,
54 		       hb_codepoint_t *glyph,
55 		       void *user_data HB_UNUSED)
56 {
57   if (font->parent)
58     return font->parent->get_glyph (unicode, variation_selector, glyph);
59 
60   *glyph = 0;
61   return false;
62 }
63 
64 static hb_position_t
hb_font_get_glyph_h_advance_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,void * user_data HB_UNUSED)65 hb_font_get_glyph_h_advance_nil (hb_font_t *font,
66 				 void *font_data HB_UNUSED,
67 				 hb_codepoint_t glyph,
68 				 void *user_data HB_UNUSED)
69 {
70   if (font->parent)
71     return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
72 
73   return font->x_scale;
74 }
75 
76 static hb_position_t
hb_font_get_glyph_v_advance_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,void * user_data HB_UNUSED)77 hb_font_get_glyph_v_advance_nil (hb_font_t *font,
78 				 void *font_data HB_UNUSED,
79 				 hb_codepoint_t glyph,
80 				 void *user_data HB_UNUSED)
81 {
82   if (font->parent)
83     return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
84 
85   return font->y_scale;
86 }
87 
88 static hb_bool_t
hb_font_get_glyph_h_origin_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,hb_position_t * x,hb_position_t * y,void * user_data HB_UNUSED)89 hb_font_get_glyph_h_origin_nil (hb_font_t *font,
90 				void *font_data HB_UNUSED,
91 				hb_codepoint_t glyph,
92 				hb_position_t *x,
93 				hb_position_t *y,
94 				void *user_data HB_UNUSED)
95 {
96   if (font->parent) {
97     hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
98     if (ret)
99       font->parent_scale_position (x, y);
100     return ret;
101   }
102 
103   *x = *y = 0;
104   return false;
105 }
106 
107 static hb_bool_t
hb_font_get_glyph_v_origin_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,hb_position_t * x,hb_position_t * y,void * user_data HB_UNUSED)108 hb_font_get_glyph_v_origin_nil (hb_font_t *font,
109 				void *font_data HB_UNUSED,
110 				hb_codepoint_t glyph,
111 				hb_position_t *x,
112 				hb_position_t *y,
113 				void *user_data HB_UNUSED)
114 {
115   if (font->parent) {
116     hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
117     if (ret)
118       font->parent_scale_position (x, y);
119     return ret;
120   }
121 
122   *x = *y = 0;
123   return false;
124 }
125 
126 static hb_position_t
hb_font_get_glyph_h_kerning_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t left_glyph,hb_codepoint_t right_glyph,void * user_data HB_UNUSED)127 hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
128 				 void *font_data HB_UNUSED,
129 				 hb_codepoint_t left_glyph,
130 				 hb_codepoint_t right_glyph,
131 				 void *user_data HB_UNUSED)
132 {
133   if (font->parent)
134     return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
135 
136   return 0;
137 }
138 
139 static hb_position_t
hb_font_get_glyph_v_kerning_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t top_glyph,hb_codepoint_t bottom_glyph,void * user_data HB_UNUSED)140 hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
141 				 void *font_data HB_UNUSED,
142 				 hb_codepoint_t top_glyph,
143 				 hb_codepoint_t bottom_glyph,
144 				 void *user_data HB_UNUSED)
145 {
146   if (font->parent)
147     return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
148 
149   return 0;
150 }
151 
152 static hb_bool_t
hb_font_get_glyph_extents_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,hb_glyph_extents_t * extents,void * user_data HB_UNUSED)153 hb_font_get_glyph_extents_nil (hb_font_t *font,
154 			       void *font_data HB_UNUSED,
155 			       hb_codepoint_t glyph,
156 			       hb_glyph_extents_t *extents,
157 			       void *user_data HB_UNUSED)
158 {
159   if (font->parent) {
160     hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
161     if (ret) {
162       font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
163       font->parent_scale_distance (&extents->width, &extents->height);
164     }
165     return ret;
166   }
167 
168   memset (extents, 0, sizeof (*extents));
169   return false;
170 }
171 
172 static hb_bool_t
hb_font_get_glyph_contour_point_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,unsigned int point_index,hb_position_t * x,hb_position_t * y,void * user_data HB_UNUSED)173 hb_font_get_glyph_contour_point_nil (hb_font_t *font,
174 				     void *font_data HB_UNUSED,
175 				     hb_codepoint_t glyph,
176 				     unsigned int point_index,
177 				     hb_position_t *x,
178 				     hb_position_t *y,
179 				     void *user_data HB_UNUSED)
180 {
181   if (font->parent) {
182     hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
183     if (ret)
184       font->parent_scale_position (x, y);
185     return ret;
186   }
187 
188   *x = *y = 0;
189   return false;
190 }
191 
192 static hb_bool_t
hb_font_get_glyph_name_nil(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,char * name,unsigned int size,void * user_data HB_UNUSED)193 hb_font_get_glyph_name_nil (hb_font_t *font,
194 			    void *font_data HB_UNUSED,
195 			    hb_codepoint_t glyph,
196 			    char *name, unsigned int size,
197 			    void *user_data HB_UNUSED)
198 {
199   if (font->parent)
200     return font->parent->get_glyph_name (glyph, name, size);
201 
202   if (size) *name = '\0';
203   return false;
204 }
205 
206 static hb_bool_t
hb_font_get_glyph_from_name_nil(hb_font_t * font,void * font_data HB_UNUSED,const char * name,int len,hb_codepoint_t * glyph,void * user_data HB_UNUSED)207 hb_font_get_glyph_from_name_nil (hb_font_t *font,
208 				 void *font_data HB_UNUSED,
209 				 const char *name, int len, /* -1 means nul-terminated */
210 				 hb_codepoint_t *glyph,
211 				 void *user_data HB_UNUSED)
212 {
213   if (font->parent)
214     return font->parent->get_glyph_from_name (name, len, glyph);
215 
216   *glyph = 0;
217   return false;
218 }
219 
220 
221 static const hb_font_funcs_t _hb_font_funcs_nil = {
222   HB_OBJECT_HEADER_STATIC,
223 
224   true, /* immutable */
225 
226   {
227 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
228     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
229 #undef HB_FONT_FUNC_IMPLEMENT
230   }
231 };
232 
233 
234 hb_font_funcs_t *
hb_font_funcs_create(void)235 hb_font_funcs_create (void)
236 {
237   hb_font_funcs_t *ffuncs;
238 
239   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
240     return hb_font_funcs_get_empty ();
241 
242   ffuncs->get = _hb_font_funcs_nil.get;
243 
244   return ffuncs;
245 }
246 
247 hb_font_funcs_t *
hb_font_funcs_get_empty(void)248 hb_font_funcs_get_empty (void)
249 {
250   return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
251 }
252 
253 hb_font_funcs_t *
hb_font_funcs_reference(hb_font_funcs_t * ffuncs)254 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
255 {
256   return hb_object_reference (ffuncs);
257 }
258 
259 void
hb_font_funcs_destroy(hb_font_funcs_t * ffuncs)260 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
261 {
262   if (!hb_object_destroy (ffuncs)) return;
263 
264 #define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
265   ffuncs->destroy.name (ffuncs->user_data.name);
266   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
267 #undef HB_FONT_FUNC_IMPLEMENT
268 
269   free (ffuncs);
270 }
271 
272 hb_bool_t
hb_font_funcs_set_user_data(hb_font_funcs_t * ffuncs,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)273 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
274 			     hb_user_data_key_t *key,
275 			     void *              data,
276 			     hb_destroy_func_t   destroy,
277 			     hb_bool_t           replace)
278 {
279   return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
280 }
281 
282 void *
hb_font_funcs_get_user_data(hb_font_funcs_t * ffuncs,hb_user_data_key_t * key)283 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
284 			     hb_user_data_key_t *key)
285 {
286   return hb_object_get_user_data (ffuncs, key);
287 }
288 
289 
290 void
hb_font_funcs_make_immutable(hb_font_funcs_t * ffuncs)291 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
292 {
293   if (hb_object_is_inert (ffuncs))
294     return;
295 
296   ffuncs->immutable = true;
297 }
298 
299 hb_bool_t
hb_font_funcs_is_immutable(hb_font_funcs_t * ffuncs)300 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
301 {
302   return ffuncs->immutable;
303 }
304 
305 
306 #define HB_FONT_FUNC_IMPLEMENT(name) \
307                                                                          \
308 void                                                                     \
309 hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
310                                  hb_font_get_##name##_func_t  func,      \
311                                  void                        *user_data, \
312                                  hb_destroy_func_t            destroy)   \
313 {                                                                        \
314   if (ffuncs->immutable) {                                               \
315     if (destroy)                                                         \
316       destroy (user_data);                                               \
317     return;                                                              \
318   }                                                                      \
319                                                                          \
320   if (ffuncs->destroy.name)                                              \
321     ffuncs->destroy.name (ffuncs->user_data.name);                       \
322                                                                          \
323   if (func) {                                                            \
324     ffuncs->get.name = func;                                             \
325     ffuncs->user_data.name = user_data;                                  \
326     ffuncs->destroy.name = destroy;                                      \
327   } else {                                                               \
328     ffuncs->get.name = hb_font_get_##name##_nil;                         \
329     ffuncs->user_data.name = NULL;                                       \
330     ffuncs->destroy.name = NULL;                                         \
331   }                                                                      \
332 }
333 
334 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
335 #undef HB_FONT_FUNC_IMPLEMENT
336 
337 
338 /* Public getters */
339 
340 hb_bool_t
hb_font_get_glyph(hb_font_t * font,hb_codepoint_t unicode,hb_codepoint_t variation_selector,hb_codepoint_t * glyph)341 hb_font_get_glyph (hb_font_t *font,
342 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
343 		   hb_codepoint_t *glyph)
344 {
345   return font->get_glyph (unicode, variation_selector, glyph);
346 }
347 
348 hb_position_t
hb_font_get_glyph_h_advance(hb_font_t * font,hb_codepoint_t glyph)349 hb_font_get_glyph_h_advance (hb_font_t *font,
350 			     hb_codepoint_t glyph)
351 {
352   return font->get_glyph_h_advance (glyph);
353 }
354 
355 hb_position_t
hb_font_get_glyph_v_advance(hb_font_t * font,hb_codepoint_t glyph)356 hb_font_get_glyph_v_advance (hb_font_t *font,
357 			     hb_codepoint_t glyph)
358 {
359   return font->get_glyph_v_advance (glyph);
360 }
361 
362 hb_bool_t
hb_font_get_glyph_h_origin(hb_font_t * font,hb_codepoint_t glyph,hb_position_t * x,hb_position_t * y)363 hb_font_get_glyph_h_origin (hb_font_t *font,
364 			    hb_codepoint_t glyph,
365 			    hb_position_t *x, hb_position_t *y)
366 {
367   return font->get_glyph_h_origin (glyph, x, y);
368 }
369 
370 hb_bool_t
hb_font_get_glyph_v_origin(hb_font_t * font,hb_codepoint_t glyph,hb_position_t * x,hb_position_t * y)371 hb_font_get_glyph_v_origin (hb_font_t *font,
372 			    hb_codepoint_t glyph,
373 			    hb_position_t *x, hb_position_t *y)
374 {
375   return font->get_glyph_v_origin (glyph, x, y);
376 }
377 
378 hb_position_t
hb_font_get_glyph_h_kerning(hb_font_t * font,hb_codepoint_t left_glyph,hb_codepoint_t right_glyph)379 hb_font_get_glyph_h_kerning (hb_font_t *font,
380 			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
381 {
382   return font->get_glyph_h_kerning (left_glyph, right_glyph);
383 }
384 
385 hb_position_t
hb_font_get_glyph_v_kerning(hb_font_t * font,hb_codepoint_t left_glyph,hb_codepoint_t right_glyph)386 hb_font_get_glyph_v_kerning (hb_font_t *font,
387 			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
388 {
389   return font->get_glyph_v_kerning (left_glyph, right_glyph);
390 }
391 
392 hb_bool_t
hb_font_get_glyph_extents(hb_font_t * font,hb_codepoint_t glyph,hb_glyph_extents_t * extents)393 hb_font_get_glyph_extents (hb_font_t *font,
394 			   hb_codepoint_t glyph,
395 			   hb_glyph_extents_t *extents)
396 {
397   return font->get_glyph_extents (glyph, extents);
398 }
399 
400 hb_bool_t
hb_font_get_glyph_contour_point(hb_font_t * font,hb_codepoint_t glyph,unsigned int point_index,hb_position_t * x,hb_position_t * y)401 hb_font_get_glyph_contour_point (hb_font_t *font,
402 				 hb_codepoint_t glyph, unsigned int point_index,
403 				 hb_position_t *x, hb_position_t *y)
404 {
405   return font->get_glyph_contour_point (glyph, point_index, x, y);
406 }
407 
408 hb_bool_t
hb_font_get_glyph_name(hb_font_t * font,hb_codepoint_t glyph,char * name,unsigned int size)409 hb_font_get_glyph_name (hb_font_t *font,
410 			hb_codepoint_t glyph,
411 			char *name, unsigned int size)
412 {
413   return font->get_glyph_name (glyph, name, size);
414 }
415 
416 hb_bool_t
hb_font_get_glyph_from_name(hb_font_t * font,const char * name,int len,hb_codepoint_t * glyph)417 hb_font_get_glyph_from_name (hb_font_t *font,
418 			     const char *name, int len, /* -1 means nul-terminated */
419 			     hb_codepoint_t *glyph)
420 {
421   return font->get_glyph_from_name (name, len, glyph);
422 }
423 
424 
425 /* A bit higher-level, and with fallback */
426 
427 void
hb_font_get_glyph_advance_for_direction(hb_font_t * font,hb_codepoint_t glyph,hb_direction_t direction,hb_position_t * x,hb_position_t * y)428 hb_font_get_glyph_advance_for_direction (hb_font_t *font,
429 					 hb_codepoint_t glyph,
430 					 hb_direction_t direction,
431 					 hb_position_t *x, hb_position_t *y)
432 {
433   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
434 }
435 
436 void
hb_font_get_glyph_origin_for_direction(hb_font_t * font,hb_codepoint_t glyph,hb_direction_t direction,hb_position_t * x,hb_position_t * y)437 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
438 					hb_codepoint_t glyph,
439 					hb_direction_t direction,
440 					hb_position_t *x, hb_position_t *y)
441 {
442   return font->get_glyph_origin_for_direction (glyph, direction, x, y);
443 }
444 
445 void
hb_font_add_glyph_origin_for_direction(hb_font_t * font,hb_codepoint_t glyph,hb_direction_t direction,hb_position_t * x,hb_position_t * y)446 hb_font_add_glyph_origin_for_direction (hb_font_t *font,
447 					hb_codepoint_t glyph,
448 					hb_direction_t direction,
449 					hb_position_t *x, hb_position_t *y)
450 {
451   return font->add_glyph_origin_for_direction (glyph, direction, x, y);
452 }
453 
454 void
hb_font_subtract_glyph_origin_for_direction(hb_font_t * font,hb_codepoint_t glyph,hb_direction_t direction,hb_position_t * x,hb_position_t * y)455 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
456 					     hb_codepoint_t glyph,
457 					     hb_direction_t direction,
458 					     hb_position_t *x, hb_position_t *y)
459 {
460   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
461 }
462 
463 void
hb_font_get_glyph_kerning_for_direction(hb_font_t * font,hb_codepoint_t first_glyph,hb_codepoint_t second_glyph,hb_direction_t direction,hb_position_t * x,hb_position_t * y)464 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
465 					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
466 					 hb_direction_t direction,
467 					 hb_position_t *x, hb_position_t *y)
468 {
469   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
470 }
471 
472 hb_bool_t
hb_font_get_glyph_extents_for_origin(hb_font_t * font,hb_codepoint_t glyph,hb_direction_t direction,hb_glyph_extents_t * extents)473 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
474 				      hb_codepoint_t glyph,
475 				      hb_direction_t direction,
476 				      hb_glyph_extents_t *extents)
477 {
478   return font->get_glyph_extents_for_origin (glyph, direction, extents);
479 }
480 
481 hb_bool_t
hb_font_get_glyph_contour_point_for_origin(hb_font_t * font,hb_codepoint_t glyph,unsigned int point_index,hb_direction_t direction,hb_position_t * x,hb_position_t * y)482 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
483 					    hb_codepoint_t glyph, unsigned int point_index,
484 					    hb_direction_t direction,
485 					    hb_position_t *x, hb_position_t *y)
486 {
487   return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
488 }
489 
490 /* Generates gidDDD if glyph has no name. */
491 void
hb_font_glyph_to_string(hb_font_t * font,hb_codepoint_t glyph,char * s,unsigned int size)492 hb_font_glyph_to_string (hb_font_t *font,
493 			 hb_codepoint_t glyph,
494 			 char *s, unsigned int size)
495 {
496   font->glyph_to_string (glyph, s, size);
497 }
498 
499 /* Parses gidDDD and uniUUUU strings automatically. */
500 hb_bool_t
hb_font_glyph_from_string(hb_font_t * font,const char * s,int len,hb_codepoint_t * glyph)501 hb_font_glyph_from_string (hb_font_t *font,
502 			   const char *s, int len, /* -1 means nul-terminated */
503 			   hb_codepoint_t *glyph)
504 {
505   return font->glyph_from_string (s, len, glyph);
506 }
507 
508 
509 /*
510  * hb_face_t
511  */
512 
513 static const hb_face_t _hb_face_nil = {
514   HB_OBJECT_HEADER_STATIC,
515 
516   true, /* immutable */
517 
518   NULL, /* reference_table_func */
519   NULL, /* user_data */
520   NULL, /* destroy */
521 
522   0,    /* index */
523   1000, /* upem */
524   0,    /* num_glyphs */
525 
526   {
527 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
528 #include "hb-shaper-list.hh"
529 #undef HB_SHAPER_IMPLEMENT
530   },
531 
532   NULL, /* shape_plans */
533 };
534 
535 
536 hb_face_t *
hb_face_create_for_tables(hb_reference_table_func_t reference_table_func,void * user_data,hb_destroy_func_t destroy)537 hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
538 			   void                      *user_data,
539 			   hb_destroy_func_t          destroy)
540 {
541   hb_face_t *face;
542 
543   if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
544     if (destroy)
545       destroy (user_data);
546     return hb_face_get_empty ();
547   }
548 
549   face->reference_table_func = reference_table_func;
550   face->user_data = user_data;
551   face->destroy = destroy;
552 
553   face->upem = 0;
554   face->num_glyphs = (unsigned int) -1;
555 
556   return face;
557 }
558 
559 
560 typedef struct hb_face_for_data_closure_t {
561   hb_blob_t *blob;
562   unsigned int  index;
563 } hb_face_for_data_closure_t;
564 
565 static hb_face_for_data_closure_t *
_hb_face_for_data_closure_create(hb_blob_t * blob,unsigned int index)566 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
567 {
568   hb_face_for_data_closure_t *closure;
569 
570   closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
571   if (unlikely (!closure))
572     return NULL;
573 
574   closure->blob = blob;
575   closure->index = index;
576 
577   return closure;
578 }
579 
580 static void
_hb_face_for_data_closure_destroy(hb_face_for_data_closure_t * closure)581 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
582 {
583   hb_blob_destroy (closure->blob);
584   free (closure);
585 }
586 
587 static hb_blob_t *
_hb_face_for_data_reference_table(hb_face_t * face HB_UNUSED,hb_tag_t tag,void * user_data)588 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
589 {
590   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
591 
592   if (tag == HB_TAG_NONE)
593     return hb_blob_reference (data->blob);
594 
595   const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
596   const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
597 
598   const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
599 
600   hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
601 
602   return blob;
603 }
604 
605 hb_face_t *
hb_face_create(hb_blob_t * blob,unsigned int index)606 hb_face_create (hb_blob_t    *blob,
607 		unsigned int  index)
608 {
609   hb_face_t *face;
610 
611   if (unlikely (!blob || !hb_blob_get_length (blob)))
612     return hb_face_get_empty ();
613 
614   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
615 
616   if (unlikely (!closure))
617     return hb_face_get_empty ();
618 
619   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
620 				    closure,
621 				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
622 
623   hb_face_set_index (face, index);
624 
625   return face;
626 }
627 
628 hb_face_t *
hb_face_get_empty(void)629 hb_face_get_empty (void)
630 {
631   return const_cast<hb_face_t *> (&_hb_face_nil);
632 }
633 
634 
635 hb_face_t *
hb_face_reference(hb_face_t * face)636 hb_face_reference (hb_face_t *face)
637 {
638   return hb_object_reference (face);
639 }
640 
641 void
hb_face_destroy(hb_face_t * face)642 hb_face_destroy (hb_face_t *face)
643 {
644   if (!hb_object_destroy (face)) return;
645 
646   for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
647   {
648     hb_face_t::plan_node_t *next = node->next;
649     hb_shape_plan_destroy (node->shape_plan);
650     free (node);
651     node = next;
652   }
653 
654 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
655 #include "hb-shaper-list.hh"
656 #undef HB_SHAPER_IMPLEMENT
657 
658   if (face->destroy)
659     face->destroy (face->user_data);
660 
661   free (face);
662 }
663 
664 hb_bool_t
hb_face_set_user_data(hb_face_t * face,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)665 hb_face_set_user_data (hb_face_t          *face,
666 		       hb_user_data_key_t *key,
667 		       void *              data,
668 		       hb_destroy_func_t   destroy,
669 		       hb_bool_t           replace)
670 {
671   return hb_object_set_user_data (face, key, data, destroy, replace);
672 }
673 
674 void *
hb_face_get_user_data(hb_face_t * face,hb_user_data_key_t * key)675 hb_face_get_user_data (hb_face_t          *face,
676 		       hb_user_data_key_t *key)
677 {
678   return hb_object_get_user_data (face, key);
679 }
680 
681 void
hb_face_make_immutable(hb_face_t * face)682 hb_face_make_immutable (hb_face_t *face)
683 {
684   if (hb_object_is_inert (face))
685     return;
686 
687   face->immutable = true;
688 }
689 
690 hb_bool_t
hb_face_is_immutable(hb_face_t * face)691 hb_face_is_immutable (hb_face_t *face)
692 {
693   return face->immutable;
694 }
695 
696 
697 hb_blob_t *
hb_face_reference_table(hb_face_t * face,hb_tag_t tag)698 hb_face_reference_table (hb_face_t *face,
699 			 hb_tag_t   tag)
700 {
701   return face->reference_table (tag);
702 }
703 
704 hb_blob_t *
hb_face_reference_blob(hb_face_t * face)705 hb_face_reference_blob (hb_face_t *face)
706 {
707   return face->reference_table (HB_TAG_NONE);
708 }
709 
710 void
hb_face_set_index(hb_face_t * face,unsigned int index)711 hb_face_set_index (hb_face_t    *face,
712 		   unsigned int  index)
713 {
714   if (hb_object_is_inert (face))
715     return;
716 
717   face->index = index;
718 }
719 
720 unsigned int
hb_face_get_index(hb_face_t * face)721 hb_face_get_index (hb_face_t    *face)
722 {
723   return face->index;
724 }
725 
726 void
hb_face_set_upem(hb_face_t * face,unsigned int upem)727 hb_face_set_upem (hb_face_t    *face,
728 		  unsigned int  upem)
729 {
730   if (hb_object_is_inert (face))
731     return;
732 
733   face->upem = upem;
734 }
735 
736 unsigned int
hb_face_get_upem(hb_face_t * face)737 hb_face_get_upem (hb_face_t *face)
738 {
739   return face->get_upem ();
740 }
741 
742 void
load_upem(void) const743 hb_face_t::load_upem (void) const
744 {
745   hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head));
746   const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
747   upem = head_table->get_upem ();
748   hb_blob_destroy (head_blob);
749 }
750 
751 void
hb_face_set_glyph_count(hb_face_t * face,unsigned int glyph_count)752 hb_face_set_glyph_count (hb_face_t    *face,
753 			 unsigned int  glyph_count)
754 {
755   if (hb_object_is_inert (face))
756     return;
757 
758   face->num_glyphs = glyph_count;
759 }
760 
761 unsigned int
hb_face_get_glyph_count(hb_face_t * face)762 hb_face_get_glyph_count (hb_face_t *face)
763 {
764   return face->get_num_glyphs ();
765 }
766 
767 void
load_num_glyphs(void) const768 hb_face_t::load_num_glyphs (void) const
769 {
770   hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp));
771   const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
772   num_glyphs = maxp_table->get_num_glyphs ();
773   hb_blob_destroy (maxp_blob);
774 }
775 
776 
777 /*
778  * hb_font_t
779  */
780 
781 hb_font_t *
hb_font_create(hb_face_t * face)782 hb_font_create (hb_face_t *face)
783 {
784   hb_font_t *font;
785 
786   if (unlikely (!face))
787     face = hb_face_get_empty ();
788   if (unlikely (hb_object_is_inert (face)))
789     return hb_font_get_empty ();
790   if (!(font = hb_object_create<hb_font_t> ()))
791     return hb_font_get_empty ();
792 
793   hb_face_make_immutable (face);
794   font->face = hb_face_reference (face);
795   font->klass = hb_font_funcs_get_empty ();
796 
797   return font;
798 }
799 
800 hb_font_t *
hb_font_create_sub_font(hb_font_t * parent)801 hb_font_create_sub_font (hb_font_t *parent)
802 {
803   if (unlikely (!parent))
804     return hb_font_get_empty ();
805 
806   hb_font_t *font = hb_font_create (parent->face);
807 
808   if (unlikely (hb_object_is_inert (font)))
809     return font;
810 
811   hb_font_make_immutable (parent);
812   font->parent = hb_font_reference (parent);
813 
814   font->x_scale = parent->x_scale;
815   font->y_scale = parent->y_scale;
816   font->x_ppem = parent->x_ppem;
817   font->y_ppem = parent->y_ppem;
818 
819   return font;
820 }
821 
822 hb_font_t *
hb_font_get_empty(void)823 hb_font_get_empty (void)
824 {
825   static const hb_font_t _hb_font_nil = {
826     HB_OBJECT_HEADER_STATIC,
827 
828     true, /* immutable */
829 
830     NULL, /* parent */
831     const_cast<hb_face_t *> (&_hb_face_nil),
832 
833     0, /* x_scale */
834     0, /* y_scale */
835 
836     0, /* x_ppem */
837     0, /* y_ppem */
838 
839     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
840     NULL, /* user_data */
841     NULL, /* destroy */
842 
843     {
844 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
845 #include "hb-shaper-list.hh"
846 #undef HB_SHAPER_IMPLEMENT
847     }
848   };
849 
850   return const_cast<hb_font_t *> (&_hb_font_nil);
851 }
852 
853 hb_font_t *
hb_font_reference(hb_font_t * font)854 hb_font_reference (hb_font_t *font)
855 {
856   return hb_object_reference (font);
857 }
858 
859 void
hb_font_destroy(hb_font_t * font)860 hb_font_destroy (hb_font_t *font)
861 {
862   if (!hb_object_destroy (font)) return;
863 
864 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
865 #include "hb-shaper-list.hh"
866 #undef HB_SHAPER_IMPLEMENT
867 
868   if (font->destroy)
869     font->destroy (font->user_data);
870 
871   hb_font_destroy (font->parent);
872   hb_face_destroy (font->face);
873   hb_font_funcs_destroy (font->klass);
874 
875   free (font);
876 }
877 
878 hb_bool_t
hb_font_set_user_data(hb_font_t * font,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)879 hb_font_set_user_data (hb_font_t          *font,
880 		       hb_user_data_key_t *key,
881 		       void *              data,
882 		       hb_destroy_func_t   destroy,
883 		       hb_bool_t           replace)
884 {
885   return hb_object_set_user_data (font, key, data, destroy, replace);
886 }
887 
888 void *
hb_font_get_user_data(hb_font_t * font,hb_user_data_key_t * key)889 hb_font_get_user_data (hb_font_t          *font,
890 		       hb_user_data_key_t *key)
891 {
892   return hb_object_get_user_data (font, key);
893 }
894 
895 void
hb_font_make_immutable(hb_font_t * font)896 hb_font_make_immutable (hb_font_t *font)
897 {
898   if (hb_object_is_inert (font))
899     return;
900 
901   font->immutable = true;
902 }
903 
904 hb_bool_t
hb_font_is_immutable(hb_font_t * font)905 hb_font_is_immutable (hb_font_t *font)
906 {
907   return font->immutable;
908 }
909 
910 hb_font_t *
hb_font_get_parent(hb_font_t * font)911 hb_font_get_parent (hb_font_t *font)
912 {
913   return font->parent;
914 }
915 
916 hb_face_t *
hb_font_get_face(hb_font_t * font)917 hb_font_get_face (hb_font_t *font)
918 {
919   return font->face;
920 }
921 
922 
923 void
hb_font_set_funcs(hb_font_t * font,hb_font_funcs_t * klass,void * user_data,hb_destroy_func_t destroy)924 hb_font_set_funcs (hb_font_t         *font,
925 		   hb_font_funcs_t   *klass,
926 		   void              *user_data,
927 		   hb_destroy_func_t  destroy)
928 {
929   if (font->immutable) {
930     if (destroy)
931       destroy (user_data);
932     return;
933   }
934 
935   if (font->destroy)
936     font->destroy (font->user_data);
937 
938   if (!klass)
939     klass = hb_font_funcs_get_empty ();
940 
941   hb_font_funcs_reference (klass);
942   hb_font_funcs_destroy (font->klass);
943   font->klass = klass;
944   font->user_data = user_data;
945   font->destroy = destroy;
946 }
947 
948 void
hb_font_set_funcs_data(hb_font_t * font,void * user_data,hb_destroy_func_t destroy)949 hb_font_set_funcs_data (hb_font_t         *font,
950 		        void              *user_data,
951 		        hb_destroy_func_t  destroy)
952 {
953   /* Destroy user_data? */
954   if (font->immutable) {
955     if (destroy)
956       destroy (user_data);
957     return;
958   }
959 
960   if (font->destroy)
961     font->destroy (font->user_data);
962 
963   font->user_data = user_data;
964   font->destroy = destroy;
965 }
966 
967 
968 void
hb_font_set_scale(hb_font_t * font,int x_scale,int y_scale)969 hb_font_set_scale (hb_font_t *font,
970 		   int x_scale,
971 		   int y_scale)
972 {
973   if (font->immutable)
974     return;
975 
976   font->x_scale = x_scale;
977   font->y_scale = y_scale;
978 }
979 
980 void
hb_font_get_scale(hb_font_t * font,int * x_scale,int * y_scale)981 hb_font_get_scale (hb_font_t *font,
982 		   int *x_scale,
983 		   int *y_scale)
984 {
985   if (x_scale) *x_scale = font->x_scale;
986   if (y_scale) *y_scale = font->y_scale;
987 }
988 
989 void
hb_font_set_ppem(hb_font_t * font,unsigned int x_ppem,unsigned int y_ppem)990 hb_font_set_ppem (hb_font_t *font,
991 		  unsigned int x_ppem,
992 		  unsigned int y_ppem)
993 {
994   if (font->immutable)
995     return;
996 
997   font->x_ppem = x_ppem;
998   font->y_ppem = y_ppem;
999 }
1000 
1001 void
hb_font_get_ppem(hb_font_t * font,unsigned int * x_ppem,unsigned int * y_ppem)1002 hb_font_get_ppem (hb_font_t *font,
1003 		  unsigned int *x_ppem,
1004 		  unsigned int *y_ppem)
1005 {
1006   if (x_ppem) *x_ppem = font->x_ppem;
1007   if (y_ppem) *y_ppem = font->y_ppem;
1008 }
1009