• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2011,2014  Google, Inc.
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  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
25  */
26 
27 #include "hb.hh"
28 
29 #ifndef HB_NO_OT_FONT
30 
31 #include "hb-ot.h"
32 
33 #include "hb-cache.hh"
34 #include "hb-font.hh"
35 #include "hb-machinery.hh"
36 #include "hb-ot-face.hh"
37 
38 #include "hb-ot-cmap-table.hh"
39 #include "hb-ot-glyf-table.hh"
40 #include "hb-ot-cff1-table.hh"
41 #include "hb-ot-cff2-table.hh"
42 #include "hb-ot-hmtx-table.hh"
43 #include "hb-ot-post-table.hh"
44 #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
45 #include "hb-ot-vorg-table.hh"
46 #include "hb-ot-color-cbdt-table.hh"
47 #include "hb-ot-color-sbix-table.hh"
48 #include "hb-ot-color-colr-table.hh"
49 
50 
51 /**
52  * SECTION:hb-ot-font
53  * @title: hb-ot-font
54  * @short_description: OpenType font implementation
55  * @include: hb-ot.h
56  *
57  * Functions for using OpenType fonts with hb_shape().  Note that fonts returned
58  * by hb_font_create() default to using these functions, so most clients would
59  * never need to call these functions directly.
60  **/
61 
62 using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>;
63 
64 struct hb_ot_font_t
65 {
66   const hb_ot_face_t *ot_face;
67 
68   /* h_advance caching */
69   mutable hb_atomic_int_t cached_coords_serial;
70   mutable hb_atomic_ptr_t<hb_ot_font_advance_cache_t> advance_cache;
71 };
72 
73 static hb_ot_font_t *
_hb_ot_font_create(hb_font_t * font)74 _hb_ot_font_create (hb_font_t *font)
75 {
76   hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
77   if (unlikely (!ot_font))
78     return nullptr;
79 
80   ot_font->ot_face = &font->face->table;
81 
82   return ot_font;
83 }
84 
85 static void
_hb_ot_font_destroy(void * font_data)86 _hb_ot_font_destroy (void *font_data)
87 {
88   hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
89 
90   auto *cache = ot_font->advance_cache.get_relaxed ();
91   if (cache)
92   {
93     cache->fini ();
94     hb_free (cache);
95   }
96 
97   hb_free (ot_font);
98 }
99 
100 static hb_bool_t
hb_ot_get_nominal_glyph(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t unicode,hb_codepoint_t * glyph,void * user_data HB_UNUSED)101 hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
102 			 void *font_data,
103 			 hb_codepoint_t unicode,
104 			 hb_codepoint_t *glyph,
105 			 void *user_data HB_UNUSED)
106 {
107   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
108   const hb_ot_face_t *ot_face = ot_font->ot_face;
109   return ot_face->cmap->get_nominal_glyph (unicode, glyph);
110 }
111 
112 static unsigned int
hb_ot_get_nominal_glyphs(hb_font_t * font HB_UNUSED,void * font_data,unsigned int count,const hb_codepoint_t * first_unicode,unsigned int unicode_stride,hb_codepoint_t * first_glyph,unsigned int glyph_stride,void * user_data HB_UNUSED)113 hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
114 			  void *font_data,
115 			  unsigned int count,
116 			  const hb_codepoint_t *first_unicode,
117 			  unsigned int unicode_stride,
118 			  hb_codepoint_t *first_glyph,
119 			  unsigned int glyph_stride,
120 			  void *user_data HB_UNUSED)
121 {
122   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
123   const hb_ot_face_t *ot_face = ot_font->ot_face;
124   return ot_face->cmap->get_nominal_glyphs (count,
125 					    first_unicode, unicode_stride,
126 					    first_glyph, glyph_stride);
127 }
128 
129 static hb_bool_t
hb_ot_get_variation_glyph(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t unicode,hb_codepoint_t variation_selector,hb_codepoint_t * glyph,void * user_data HB_UNUSED)130 hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
131 			   void *font_data,
132 			   hb_codepoint_t unicode,
133 			   hb_codepoint_t variation_selector,
134 			   hb_codepoint_t *glyph,
135 			   void *user_data HB_UNUSED)
136 {
137   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
138   const hb_ot_face_t *ot_face = ot_font->ot_face;
139   return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
140 }
141 
142 static void
hb_ot_get_glyph_h_advances(hb_font_t * font,void * font_data,unsigned count,const hb_codepoint_t * first_glyph,unsigned glyph_stride,hb_position_t * first_advance,unsigned advance_stride,void * user_data HB_UNUSED)143 hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
144 			    unsigned count,
145 			    const hb_codepoint_t *first_glyph,
146 			    unsigned glyph_stride,
147 			    hb_position_t *first_advance,
148 			    unsigned advance_stride,
149 			    void *user_data HB_UNUSED)
150 {
151   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
152   const hb_ot_face_t *ot_face = ot_font->ot_face;
153   const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
154 
155 #ifndef HB_NO_VAR
156   const OT::HVAR &HVAR = *hmtx.var_table;
157   const OT::VariationStore &varStore = &HVAR + HVAR.varStore;
158   OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
159 
160   bool use_cache = font->num_coords;
161 #else
162   OT::VariationStore::cache_t *varStore_cache = nullptr;
163   bool use_cache = false;
164 #endif
165 
166   hb_ot_font_advance_cache_t *cache = nullptr;
167   if (use_cache)
168   {
169   retry:
170     cache = ot_font->advance_cache.get_acquire ();
171     if (unlikely (!cache))
172     {
173       cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
174       if (unlikely (!cache))
175       {
176 	use_cache = false;
177 	goto out;
178       }
179 
180       cache->init ();
181       if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
182       {
183 	hb_free (cache);
184 	goto retry;
185       }
186       ot_font->cached_coords_serial.set_release (font->serial_coords);
187     }
188   }
189   out:
190 
191   if (!use_cache)
192   {
193     for (unsigned int i = 0; i < count; i++)
194     {
195       *first_advance = font->em_scale_x (hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
196       first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
197       first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
198     }
199   }
200   else
201   { /* Use cache. */
202     if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords)
203     {
204       ot_font->advance_cache->init ();
205       ot_font->cached_coords_serial.set_release (font->serial_coords);
206     }
207 
208     for (unsigned int i = 0; i < count; i++)
209     {
210       hb_position_t v;
211       unsigned cv;
212       if (ot_font->advance_cache->get (*first_glyph, &cv))
213 	v = cv;
214       else
215       {
216         v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
217 	ot_font->advance_cache->set (*first_glyph, v);
218       }
219       *first_advance = font->em_scale_x (v);
220       first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
221       first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
222     }
223   }
224 
225 #ifndef HB_NO_VAR
226   OT::VariationStore::destroy_cache (varStore_cache);
227 #endif
228 }
229 
230 #ifndef HB_NO_VERTICAL
231 static void
hb_ot_get_glyph_v_advances(hb_font_t * font,void * font_data,unsigned count,const hb_codepoint_t * first_glyph,unsigned glyph_stride,hb_position_t * first_advance,unsigned advance_stride,void * user_data HB_UNUSED)232 hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
233 			    unsigned count,
234 			    const hb_codepoint_t *first_glyph,
235 			    unsigned glyph_stride,
236 			    hb_position_t *first_advance,
237 			    unsigned advance_stride,
238 			    void *user_data HB_UNUSED)
239 {
240   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
241   const hb_ot_face_t *ot_face = ot_font->ot_face;
242   const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
243 
244   if (vmtx.has_data ())
245   {
246 #ifndef HB_NO_VAR
247     const OT::VVAR &VVAR = *vmtx.var_table;
248     const OT::VariationStore &varStore = &VVAR + VVAR.varStore;
249     OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
250 #else
251     OT::VariationStore::cache_t *varStore_cache = nullptr;
252 #endif
253 
254     for (unsigned int i = 0; i < count; i++)
255     {
256       *first_advance = font->em_scale_y (-(int) vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
257       first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
258       first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
259     }
260 
261 #ifndef HB_NO_VAR
262     OT::VariationStore::destroy_cache (varStore_cache);
263 #endif
264   }
265   else
266   {
267     hb_font_extents_t font_extents;
268     font->get_h_extents_with_fallback (&font_extents);
269     hb_position_t advance = -(font_extents.ascender - font_extents.descender);
270 
271     for (unsigned int i = 0; i < count; i++)
272     {
273       *first_advance = advance;
274       first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
275       first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
276     }
277   }
278 }
279 #endif
280 
281 #ifndef HB_NO_VERTICAL
282 static hb_bool_t
hb_ot_get_glyph_v_origin(hb_font_t * font,void * font_data,hb_codepoint_t glyph,hb_position_t * x,hb_position_t * y,void * user_data HB_UNUSED)283 hb_ot_get_glyph_v_origin (hb_font_t *font,
284 			  void *font_data,
285 			  hb_codepoint_t glyph,
286 			  hb_position_t *x,
287 			  hb_position_t *y,
288 			  void *user_data HB_UNUSED)
289 {
290   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
291   const hb_ot_face_t *ot_face = ot_font->ot_face;
292 
293   *x = font->get_glyph_h_advance (glyph) / 2;
294 
295   const OT::VORG &VORG = *ot_face->VORG;
296   if (VORG.has_data ())
297   {
298     float delta = 0;
299 
300 #ifndef HB_NO_VAR
301     const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
302     const OT::VVAR &VVAR = *vmtx.var_table;
303     if (font->num_coords)
304       VVAR.get_vorg_delta_unscaled (glyph,
305 				    font->coords, font->num_coords,
306 				    &delta);
307 #endif
308 
309     *y = font->em_scalef_y (VORG.get_y_origin (glyph) + delta);
310     return true;
311   }
312 
313   hb_glyph_extents_t extents = {0};
314   if (ot_face->glyf->get_extents (font, glyph, &extents))
315   {
316     const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
317     int tsb = 0;
318     if (vmtx.get_leading_bearing_with_var_unscaled (font, glyph, &tsb))
319     {
320       *y = extents.y_bearing + font->em_scale_y (tsb);
321       return true;
322     }
323 
324     hb_font_extents_t font_extents;
325     font->get_h_extents_with_fallback (&font_extents);
326     hb_position_t advance = font_extents.ascender - font_extents.descender;
327     int diff = advance - -extents.height;
328     *y = extents.y_bearing + (diff >> 1);
329     return true;
330   }
331 
332   hb_font_extents_t font_extents;
333   font->get_h_extents_with_fallback (&font_extents);
334   *y = font_extents.ascender;
335 
336   return true;
337 }
338 #endif
339 
340 static hb_bool_t
hb_ot_get_glyph_extents(hb_font_t * font,void * font_data,hb_codepoint_t glyph,hb_glyph_extents_t * extents,void * user_data HB_UNUSED)341 hb_ot_get_glyph_extents (hb_font_t *font,
342 			 void *font_data,
343 			 hb_codepoint_t glyph,
344 			 hb_glyph_extents_t *extents,
345 			 void *user_data HB_UNUSED)
346 {
347   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
348   const hb_ot_face_t *ot_face = ot_font->ot_face;
349 
350 #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
351   if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
352   if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
353 #endif
354 #if !defined(HB_NO_COLOR)
355   if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
356 #endif
357   if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
358 #ifndef HB_NO_OT_FONT_CFF
359   if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
360   if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
361 #endif
362 
363   return false;
364 }
365 
366 #ifndef HB_NO_OT_FONT_GLYPH_NAMES
367 static hb_bool_t
hb_ot_get_glyph_name(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t glyph,char * name,unsigned int size,void * user_data HB_UNUSED)368 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
369 		      void *font_data,
370 		      hb_codepoint_t glyph,
371 		      char *name, unsigned int size,
372 		      void *user_data HB_UNUSED)
373 {
374   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
375   const hb_ot_face_t *ot_face = ot_font->ot_face;
376 
377   if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
378 #ifndef HB_NO_OT_FONT_CFF
379   if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
380 #endif
381   return false;
382 }
383 static hb_bool_t
hb_ot_get_glyph_from_name(hb_font_t * font HB_UNUSED,void * font_data,const char * name,int len,hb_codepoint_t * glyph,void * user_data HB_UNUSED)384 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
385 			   void *font_data,
386 			   const char *name, int len,
387 			   hb_codepoint_t *glyph,
388 			   void *user_data HB_UNUSED)
389 {
390   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
391   const hb_ot_face_t *ot_face = ot_font->ot_face;
392 
393   if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
394 #ifndef HB_NO_OT_FONT_CFF
395     if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
396 #endif
397   return false;
398 }
399 #endif
400 
401 static hb_bool_t
hb_ot_get_font_h_extents(hb_font_t * font,void * font_data HB_UNUSED,hb_font_extents_t * metrics,void * user_data HB_UNUSED)402 hb_ot_get_font_h_extents (hb_font_t *font,
403 			  void *font_data HB_UNUSED,
404 			  hb_font_extents_t *metrics,
405 			  void *user_data HB_UNUSED)
406 {
407   return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
408 	 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
409 	 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
410 }
411 
412 #ifndef HB_NO_VERTICAL
413 static hb_bool_t
hb_ot_get_font_v_extents(hb_font_t * font,void * font_data HB_UNUSED,hb_font_extents_t * metrics,void * user_data HB_UNUSED)414 hb_ot_get_font_v_extents (hb_font_t *font,
415 			  void *font_data HB_UNUSED,
416 			  hb_font_extents_t *metrics,
417 			  void *user_data HB_UNUSED)
418 {
419   return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_ASCENDER, &metrics->ascender) &&
420 	 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
421 	 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
422 }
423 #endif
424 
425 #ifndef HB_NO_DRAW
426 static void
hb_ot_get_glyph_shape(hb_font_t * font,void * font_data HB_UNUSED,hb_codepoint_t glyph,hb_draw_funcs_t * draw_funcs,void * draw_data,void * user_data)427 hb_ot_get_glyph_shape (hb_font_t *font,
428 		       void *font_data HB_UNUSED,
429 		       hb_codepoint_t glyph,
430 		       hb_draw_funcs_t *draw_funcs, void *draw_data,
431 		       void *user_data)
432 {
433   hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
434   if (font->face->table.glyf->get_path (font, glyph, draw_session)) return;
435 #ifndef HB_NO_CFF
436   if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
437   if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
438 #endif
439 }
440 #endif
441 
442 static inline void free_static_ot_funcs ();
443 
444 static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
445 {
createhb_ot_font_funcs_lazy_loader_t446   static hb_font_funcs_t *create ()
447   {
448     hb_font_funcs_t *funcs = hb_font_funcs_create ();
449 
450     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
451     hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
452     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
453 
454     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
455     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
456     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
457 
458 #ifndef HB_NO_VERTICAL
459     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
460     hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
461     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
462 #endif
463 
464 #ifndef HB_NO_DRAW
465     hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr);
466 #endif
467 
468     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
469     //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
470 
471 #ifndef HB_NO_OT_FONT_GLYPH_NAMES
472     hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
473     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
474 #endif
475 
476     hb_font_funcs_make_immutable (funcs);
477 
478     hb_atexit (free_static_ot_funcs);
479 
480     return funcs;
481   }
482 } static_ot_funcs;
483 
484 static inline
free_static_ot_funcs()485 void free_static_ot_funcs ()
486 {
487   static_ot_funcs.free_instance ();
488 }
489 
490 static hb_font_funcs_t *
_hb_ot_get_font_funcs()491 _hb_ot_get_font_funcs ()
492 {
493   return static_ot_funcs.get_unconst ();
494 }
495 
496 
497 /**
498  * hb_ot_font_set_funcs:
499  * @font: #hb_font_t to work upon
500  *
501  * Sets the font functions to use when working with @font.
502  *
503  * Since: 0.9.28
504  **/
505 void
hb_ot_font_set_funcs(hb_font_t * font)506 hb_ot_font_set_funcs (hb_font_t *font)
507 {
508   hb_ot_font_t *ot_font = _hb_ot_font_create (font);
509   if (unlikely (!ot_font))
510     return;
511 
512   hb_font_set_funcs (font,
513 		     _hb_ot_get_font_funcs (),
514 		     ot_font,
515 		     _hb_ot_font_destroy);
516 }
517 
518 #ifndef HB_NO_VAR
519 bool
_glyf_get_leading_bearing_with_var_unscaled(hb_font_t * font,hb_codepoint_t glyph,bool is_vertical,int * lsb)520 _glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
521 					     int *lsb)
522 {
523   return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
524 }
525 
526 unsigned
_glyf_get_advance_with_var_unscaled(hb_font_t * font,hb_codepoint_t glyph,bool is_vertical)527 _glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
528 {
529   return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
530 }
531 #endif
532 
533 
534 #endif
535