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-private.hh" 28 29 #include "hb-ot.h" 30 31 #include "hb-font-private.hh" 32 33 #include "hb-ot-cmap-table.hh" 34 #include "hb-ot-glyf-table.hh" 35 #include "hb-ot-hmtx-table.hh" 36 #include "hb-ot-kern-table.hh" 37 #include "hb-ot-post-table.hh" 38 39 #include "hb-ot-color-cbdt-table.hh" 40 41 42 struct hb_ot_font_t 43 { 44 OT::cmap::accelerator_t cmap; 45 OT::hmtx::accelerator_t h_metrics; 46 OT::vmtx::accelerator_t v_metrics; 47 OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf; 48 OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt; 49 OT::hb_lazy_loader_t<OT::post::accelerator_t> post; 50 OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern; 51 }; 52 53 54 static hb_ot_font_t * 55 _hb_ot_font_create (hb_face_t *face) 56 { 57 hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); 58 59 if (unlikely (!ot_font)) 60 return nullptr; 61 62 ot_font->cmap.init (face); 63 ot_font->h_metrics.init (face); 64 ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ 65 ot_font->glyf.init (face); 66 ot_font->cbdt.init (face); 67 ot_font->post.init (face); 68 ot_font->kern.init (face); 69 70 return ot_font; 71 } 72 73 static void 74 _hb_ot_font_destroy (void *data) 75 { 76 hb_ot_font_t *ot_font = (hb_ot_font_t *) data; 77 78 ot_font->cmap.fini (); 79 ot_font->h_metrics.fini (); 80 ot_font->v_metrics.fini (); 81 ot_font->glyf.fini (); 82 ot_font->cbdt.fini (); 83 ot_font->post.fini (); 84 ot_font->kern.fini (); 85 86 free (ot_font); 87 } 88 89 90 static hb_bool_t 91 hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, 92 void *font_data, 93 hb_codepoint_t unicode, 94 hb_codepoint_t *glyph, 95 void *user_data HB_UNUSED) 96 97 { 98 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 99 return ot_font->cmap.get_nominal_glyph (unicode, glyph); 100 } 101 102 static hb_bool_t 103 hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, 104 void *font_data, 105 hb_codepoint_t unicode, 106 hb_codepoint_t variation_selector, 107 hb_codepoint_t *glyph, 108 void *user_data HB_UNUSED) 109 { 110 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 111 return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph); 112 } 113 114 static hb_position_t 115 hb_ot_get_glyph_h_advance (hb_font_t *font, 116 void *font_data, 117 hb_codepoint_t glyph, 118 void *user_data HB_UNUSED) 119 { 120 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 121 return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font)); 122 } 123 124 static hb_position_t 125 hb_ot_get_glyph_v_advance (hb_font_t *font, 126 void *font_data, 127 hb_codepoint_t glyph, 128 void *user_data HB_UNUSED) 129 { 130 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 131 return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font)); 132 } 133 134 static hb_position_t 135 hb_ot_get_glyph_h_kerning (hb_font_t *font, 136 void *font_data, 137 hb_codepoint_t left_glyph, 138 hb_codepoint_t right_glyph, 139 void *user_data HB_UNUSED) 140 { 141 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 142 return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph)); 143 } 144 145 static hb_bool_t 146 hb_ot_get_glyph_extents (hb_font_t *font, 147 void *font_data, 148 hb_codepoint_t glyph, 149 hb_glyph_extents_t *extents, 150 void *user_data HB_UNUSED) 151 { 152 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 153 bool ret = ot_font->glyf->get_extents (glyph, extents); 154 if (!ret) 155 ret = ot_font->cbdt->get_extents (glyph, extents); 156 // TODO Hook up side-bearings variations. 157 extents->x_bearing = font->em_scale_x (extents->x_bearing); 158 extents->y_bearing = font->em_scale_y (extents->y_bearing); 159 extents->width = font->em_scale_x (extents->width); 160 extents->height = font->em_scale_y (extents->height); 161 return ret; 162 } 163 164 static hb_bool_t 165 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, 166 void *font_data, 167 hb_codepoint_t glyph, 168 char *name, unsigned int size, 169 void *user_data HB_UNUSED) 170 { 171 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 172 return ot_font->post->get_glyph_name (glyph, name, size); 173 } 174 175 static hb_bool_t 176 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, 177 void *font_data, 178 const char *name, int len, 179 hb_codepoint_t *glyph, 180 void *user_data HB_UNUSED) 181 { 182 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 183 return ot_font->post->get_glyph_from_name (name, len, glyph); 184 } 185 186 static hb_bool_t 187 hb_ot_get_font_h_extents (hb_font_t *font, 188 void *font_data, 189 hb_font_extents_t *metrics, 190 void *user_data HB_UNUSED) 191 { 192 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 193 metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); 194 metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); 195 metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); 196 // TODO Hook up variations. 197 return ot_font->h_metrics.has_font_extents; 198 } 199 200 static hb_bool_t 201 hb_ot_get_font_v_extents (hb_font_t *font, 202 void *font_data, 203 hb_font_extents_t *metrics, 204 void *user_data HB_UNUSED) 205 { 206 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 207 metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); 208 metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); 209 metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); 210 // TODO Hook up variations. 211 return ot_font->v_metrics.has_font_extents; 212 } 213 214 static hb_font_funcs_t *static_ot_funcs = nullptr; 215 216 #ifdef HB_USE_ATEXIT 217 static 218 void free_static_ot_funcs (void) 219 { 220 retry: 221 hb_font_funcs_t *ot_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); 222 if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, ot_funcs, nullptr)) 223 goto retry; 224 225 hb_font_funcs_destroy (ot_funcs); 226 } 227 #endif 228 229 static hb_font_funcs_t * 230 _hb_ot_get_font_funcs (void) 231 { 232 retry: 233 hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); 234 235 if (unlikely (!funcs)) 236 { 237 funcs = hb_font_funcs_create (); 238 239 hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); 240 hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); 241 hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); 242 hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); 243 hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr); 244 hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr); 245 //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr); 246 //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); 247 hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr); 248 //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr); 249 hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); 250 //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); 251 hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr); 252 hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr); 253 254 hb_font_funcs_make_immutable (funcs); 255 256 if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) { 257 hb_font_funcs_destroy (funcs); 258 goto retry; 259 } 260 261 #ifdef HB_USE_ATEXIT 262 atexit (free_static_ot_funcs); /* First person registers atexit() callback. */ 263 #endif 264 }; 265 266 return funcs; 267 } 268 269 270 /** 271 * hb_ot_font_set_funcs: 272 * 273 * Since: 0.9.28 274 **/ 275 void 276 hb_ot_font_set_funcs (hb_font_t *font) 277 { 278 hb_ot_font_t *ot_font = _hb_ot_font_create (font->face); 279 if (unlikely (!ot_font)) 280 return; 281 282 hb_font_set_funcs (font, 283 _hb_ot_get_font_funcs (), 284 ot_font, 285 _hb_ot_font_destroy); 286 } | 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 #include "hb-ot.h" 30 31 #include "hb-font.hh" 32 #include "hb-machinery.hh" 33 #include "hb-ot-face.hh" 34 35 #include "hb-ot-cmap-table.hh" 36 #include "hb-ot-glyf-table.hh" 37 #include "hb-ot-cff1-table.hh" 38 #include "hb-ot-cff2-table.hh" 39 #include "hb-ot-hmtx-table.hh" 40 #include "hb-ot-kern-table.hh" 41 #include "hb-ot-os2-table.hh" 42 #include "hb-ot-post-table.hh" 43 #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. 44 #include "hb-ot-vorg-table.hh" 45 #include "hb-ot-color-cbdt-table.hh" 46 #include "hb-ot-color-sbix-table.hh" 47 48 49 /** 50 * SECTION:hb-ot-font 51 * @title: hb-ot-font 52 * @short_description: OpenType font implementation 53 * @include: hb-ot.h 54 * 55 * Functions for using OpenType fonts with hb_shape(). Not that fonts returned 56 * by hb_font_create() default to using these functions, so most clients would 57 * never need to call these functions directly. 58 **/ 59 60 61 static hb_bool_t 62 hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, 63 void *font_data, 64 hb_codepoint_t unicode, 65 hb_codepoint_t *glyph, 66 void *user_data HB_UNUSED) 67 { 68 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 69 return ot_face->cmap->get_nominal_glyph (unicode, glyph); 70 } 71 72 static unsigned int 73 hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED, 74 void *font_data, 75 unsigned int count, 76 const hb_codepoint_t *first_unicode, 77 unsigned int unicode_stride, 78 hb_codepoint_t *first_glyph, 79 unsigned int glyph_stride, 80 void *user_data HB_UNUSED) 81 { 82 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 83 return ot_face->cmap->get_nominal_glyphs (count, 84 first_unicode, unicode_stride, 85 first_glyph, glyph_stride); 86 } 87 88 static hb_bool_t 89 hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, 90 void *font_data, 91 hb_codepoint_t unicode, 92 hb_codepoint_t variation_selector, 93 hb_codepoint_t *glyph, 94 void *user_data HB_UNUSED) 95 { 96 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 97 return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph); 98 } 99 100 static void 101 hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, 102 unsigned count, 103 const hb_codepoint_t *first_glyph, 104 unsigned glyph_stride, 105 hb_position_t *first_advance, 106 unsigned advance_stride, 107 void *user_data HB_UNUSED) 108 { 109 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 110 const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; 111 112 for (unsigned int i = 0; i < count; i++) 113 { 114 *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font)); 115 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 116 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 117 } 118 } 119 120 static void 121 hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, 122 unsigned count, 123 const hb_codepoint_t *first_glyph, 124 unsigned glyph_stride, 125 hb_position_t *first_advance, 126 unsigned advance_stride, 127 void *user_data HB_UNUSED) 128 { 129 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 130 const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; 131 132 for (unsigned int i = 0; i < count; i++) 133 { 134 *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font)); 135 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 136 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 137 } 138 } 139 140 static hb_bool_t 141 hb_ot_get_glyph_v_origin (hb_font_t *font, 142 void *font_data, 143 hb_codepoint_t glyph, 144 hb_position_t *x, 145 hb_position_t *y, 146 void *user_data HB_UNUSED) 147 { 148 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 149 150 *x = font->get_glyph_h_advance (glyph) / 2; 151 152 const OT::VORG &VORG = *ot_face->VORG; 153 if (VORG.has_data ()) 154 { 155 *y = font->em_scale_y (VORG.get_y_origin (glyph)); 156 return true; 157 } 158 159 hb_glyph_extents_t extents = {0}; 160 if (ot_face->glyf->get_extents (glyph, &extents)) 161 { 162 const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; 163 hb_position_t tsb = vmtx.get_side_bearing (glyph); 164 *y = font->em_scale_y (extents.y_bearing + tsb); 165 return true; 166 } 167 168 hb_font_extents_t font_extents; 169 font->get_h_extents_with_fallback (&font_extents); 170 *y = font_extents.ascender; 171 172 return true; 173 } 174 175 static hb_bool_t 176 hb_ot_get_glyph_extents (hb_font_t *font, 177 void *font_data, 178 hb_codepoint_t glyph, 179 hb_glyph_extents_t *extents, 180 void *user_data HB_UNUSED) 181 { 182 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 183 bool ret = ot_face->sbix->get_extents (font, glyph, extents); 184 if (!ret) 185 ret = ot_face->glyf->get_extents (glyph, extents); 186 if (!ret) 187 ret = ot_face->cff1->get_extents (glyph, extents); 188 if (!ret) 189 ret = ot_face->cff2->get_extents (font, glyph, extents); 190 if (!ret) 191 ret = ot_face->CBDT->get_extents (font, glyph, extents); 192 // TODO Hook up side-bearings variations. 193 extents->x_bearing = font->em_scale_x (extents->x_bearing); 194 extents->y_bearing = font->em_scale_y (extents->y_bearing); 195 extents->width = font->em_scale_x (extents->width); 196 extents->height = font->em_scale_y (extents->height); 197 return ret; 198 } 199 200 static hb_bool_t 201 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, 202 void *font_data, 203 hb_codepoint_t glyph, 204 char *name, unsigned int size, 205 void *user_data HB_UNUSED) 206 { 207 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 208 return ot_face->post->get_glyph_name (glyph, name, size); 209 } 210 211 static hb_bool_t 212 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, 213 void *font_data, 214 const char *name, int len, 215 hb_codepoint_t *glyph, 216 void *user_data HB_UNUSED) 217 { 218 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 219 return ot_face->post->get_glyph_from_name (name, len, glyph); 220 } 221 222 static hb_bool_t 223 hb_ot_get_font_h_extents (hb_font_t *font, 224 void *font_data, 225 hb_font_extents_t *metrics, 226 void *user_data HB_UNUSED) 227 { 228 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 229 const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; 230 metrics->ascender = font->em_scale_y (hmtx.ascender); 231 metrics->descender = font->em_scale_y (hmtx.descender); 232 metrics->line_gap = font->em_scale_y (hmtx.line_gap); 233 // TODO Hook up variations. 234 return hmtx.has_font_extents; 235 } 236 237 static hb_bool_t 238 hb_ot_get_font_v_extents (hb_font_t *font, 239 void *font_data, 240 hb_font_extents_t *metrics, 241 void *user_data HB_UNUSED) 242 { 243 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; 244 const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; 245 metrics->ascender = font->em_scale_x (vmtx.ascender); 246 metrics->descender = font->em_scale_x (vmtx.descender); 247 metrics->line_gap = font->em_scale_x (vmtx.line_gap); 248 // TODO Hook up variations. 249 return vmtx.has_font_extents; 250 } 251 252 #if HB_USE_ATEXIT 253 static void free_static_ot_funcs (); 254 #endif 255 256 static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t> 257 { 258 static hb_font_funcs_t *create () 259 { 260 hb_font_funcs_t *funcs = hb_font_funcs_create (); 261 262 hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); 263 hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); 264 hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); 265 hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr); 266 hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); 267 hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr); 268 hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); 269 //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr); 270 hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); 271 hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); 272 //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); 273 hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr); 274 hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr); 275 276 hb_font_funcs_make_immutable (funcs); 277 278 #if HB_USE_ATEXIT 279 atexit (free_static_ot_funcs); 280 #endif 281 282 return funcs; 283 } 284 } static_ot_funcs; 285 286 #if HB_USE_ATEXIT 287 static 288 void free_static_ot_funcs () 289 { 290 static_ot_funcs.free_instance (); 291 } 292 #endif 293 294 static hb_font_funcs_t * 295 _hb_ot_get_font_funcs () 296 { 297 return static_ot_funcs.get_unconst (); 298 } 299 300 301 /** 302 * hb_ot_font_set_funcs: 303 * 304 * Since: 0.9.28 305 **/ 306 void 307 hb_ot_font_set_funcs (hb_font_t *font) 308 { 309 hb_font_set_funcs (font, 310 _hb_ot_get_font_funcs (), 311 &font->face->table, 312 nullptr); 313 } |