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