1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2009 Red Hat, Inc.
3*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2009 Keith Stribley
4*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2015 Google, Inc.
5*2d1272b8SAndroid Build Coastguard Worker *
6*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library.
7*2d1272b8SAndroid Build Coastguard Worker *
8*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without
9*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this
10*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the
11*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in
12*2d1272b8SAndroid Build Coastguard Worker * all copies of this software.
13*2d1272b8SAndroid Build Coastguard Worker *
14*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18*2d1272b8SAndroid Build Coastguard Worker * DAMAGE.
19*2d1272b8SAndroid Build Coastguard Worker *
20*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25*2d1272b8SAndroid Build Coastguard Worker *
26*2d1272b8SAndroid Build Coastguard Worker * Red Hat Author(s): Behdad Esfahbod
27*2d1272b8SAndroid Build Coastguard Worker * Google Author(s): Behdad Esfahbod
28*2d1272b8SAndroid Build Coastguard Worker */
29*2d1272b8SAndroid Build Coastguard Worker
30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
31*2d1272b8SAndroid Build Coastguard Worker
32*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FREETYPE
33*2d1272b8SAndroid Build Coastguard Worker
34*2d1272b8SAndroid Build Coastguard Worker #include "hb-ft.h"
35*2d1272b8SAndroid Build Coastguard Worker
36*2d1272b8SAndroid Build Coastguard Worker #include "hb-cache.hh"
37*2d1272b8SAndroid Build Coastguard Worker #include "hb-draw.hh"
38*2d1272b8SAndroid Build Coastguard Worker #include "hb-font.hh"
39*2d1272b8SAndroid Build Coastguard Worker #include "hb-machinery.hh"
40*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-os2-table.hh"
41*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-shaper-arabic-pua.hh"
42*2d1272b8SAndroid Build Coastguard Worker #include "hb-paint.hh"
43*2d1272b8SAndroid Build Coastguard Worker
44*2d1272b8SAndroid Build Coastguard Worker #include FT_MODULE_H
45*2d1272b8SAndroid Build Coastguard Worker #include FT_ADVANCES_H
46*2d1272b8SAndroid Build Coastguard Worker #include FT_MULTIPLE_MASTERS_H
47*2d1272b8SAndroid Build Coastguard Worker #include FT_OUTLINE_H
48*2d1272b8SAndroid Build Coastguard Worker #include FT_TRUETYPE_TABLES_H
49*2d1272b8SAndroid Build Coastguard Worker #include FT_SYNTHESIS_H
50*2d1272b8SAndroid Build Coastguard Worker #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
51*2d1272b8SAndroid Build Coastguard Worker #include FT_COLOR_H
52*2d1272b8SAndroid Build Coastguard Worker #endif
53*2d1272b8SAndroid Build Coastguard Worker
54*2d1272b8SAndroid Build Coastguard Worker
55*2d1272b8SAndroid Build Coastguard Worker /**
56*2d1272b8SAndroid Build Coastguard Worker * SECTION:hb-ft
57*2d1272b8SAndroid Build Coastguard Worker * @title: hb-ft
58*2d1272b8SAndroid Build Coastguard Worker * @short_description: FreeType integration
59*2d1272b8SAndroid Build Coastguard Worker * @include: hb-ft.h
60*2d1272b8SAndroid Build Coastguard Worker *
61*2d1272b8SAndroid Build Coastguard Worker * Functions for using HarfBuzz with the FreeType library.
62*2d1272b8SAndroid Build Coastguard Worker *
63*2d1272b8SAndroid Build Coastguard Worker * HarfBuzz supports using FreeType to provide face and
64*2d1272b8SAndroid Build Coastguard Worker * font data.
65*2d1272b8SAndroid Build Coastguard Worker *
66*2d1272b8SAndroid Build Coastguard Worker * <note>Note that FreeType is not thread-safe, therefore these
67*2d1272b8SAndroid Build Coastguard Worker * functions are not thread-safe either.</note>
68*2d1272b8SAndroid Build Coastguard Worker **/
69*2d1272b8SAndroid Build Coastguard Worker
70*2d1272b8SAndroid Build Coastguard Worker
71*2d1272b8SAndroid Build Coastguard Worker /* TODO:
72*2d1272b8SAndroid Build Coastguard Worker *
73*2d1272b8SAndroid Build Coastguard Worker * In general, this file does a fine job of what it's supposed to do.
74*2d1272b8SAndroid Build Coastguard Worker * There are, however, things that need more work:
75*2d1272b8SAndroid Build Coastguard Worker *
76*2d1272b8SAndroid Build Coastguard Worker * - FreeType works in 26.6 mode. Clients can decide to use that mode, and everything
77*2d1272b8SAndroid Build Coastguard Worker * would work fine. However, we also abuse this API for performing in font-space,
78*2d1272b8SAndroid Build Coastguard Worker * but don't pass the correct flags to FreeType. We just abuse the no-hinting mode
79*2d1272b8SAndroid Build Coastguard Worker * for that, such that no rounding etc happens. As such, we don't set ppem, and
80*2d1272b8SAndroid Build Coastguard Worker * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and scale
81*2d1272b8SAndroid Build Coastguard Worker * ourselves.
82*2d1272b8SAndroid Build Coastguard Worker *
83*2d1272b8SAndroid Build Coastguard Worker * - We don't handle / allow for emboldening / obliqueing.
84*2d1272b8SAndroid Build Coastguard Worker *
85*2d1272b8SAndroid Build Coastguard Worker * - In the future, we should add constructors to create fonts in font space?
86*2d1272b8SAndroid Build Coastguard Worker */
87*2d1272b8SAndroid Build Coastguard Worker
88*2d1272b8SAndroid Build Coastguard Worker
89*2d1272b8SAndroid Build Coastguard Worker using hb_ft_advance_cache_t = hb_cache_t<16, 24, 8, false>;
90*2d1272b8SAndroid Build Coastguard Worker
91*2d1272b8SAndroid Build Coastguard Worker struct hb_ft_font_t
92*2d1272b8SAndroid Build Coastguard Worker {
93*2d1272b8SAndroid Build Coastguard Worker int load_flags;
94*2d1272b8SAndroid Build Coastguard Worker bool symbol; /* Whether selected cmap is symbol cmap. */
95*2d1272b8SAndroid Build Coastguard Worker bool unref; /* Whether to destroy ft_face when done. */
96*2d1272b8SAndroid Build Coastguard Worker bool transform; /* Whether to apply FT_Face's transform. */
97*2d1272b8SAndroid Build Coastguard Worker
98*2d1272b8SAndroid Build Coastguard Worker mutable hb_mutex_t lock; /* Protects members below. */
99*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face;
100*2d1272b8SAndroid Build Coastguard Worker mutable unsigned cached_serial;
101*2d1272b8SAndroid Build Coastguard Worker mutable hb_ft_advance_cache_t advance_cache;
102*2d1272b8SAndroid Build Coastguard Worker };
103*2d1272b8SAndroid Build Coastguard Worker
104*2d1272b8SAndroid Build Coastguard Worker static hb_ft_font_t *
_hb_ft_font_create(FT_Face ft_face,bool symbol,bool unref)105*2d1272b8SAndroid Build Coastguard Worker _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
106*2d1272b8SAndroid Build Coastguard Worker {
107*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_t *ft_font = (hb_ft_font_t *) hb_calloc (1, sizeof (hb_ft_font_t));
108*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!ft_font)) return nullptr;
109*2d1272b8SAndroid Build Coastguard Worker
110*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.init ();
111*2d1272b8SAndroid Build Coastguard Worker ft_font->ft_face = ft_face;
112*2d1272b8SAndroid Build Coastguard Worker ft_font->symbol = symbol;
113*2d1272b8SAndroid Build Coastguard Worker ft_font->unref = unref;
114*2d1272b8SAndroid Build Coastguard Worker
115*2d1272b8SAndroid Build Coastguard Worker ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
116*2d1272b8SAndroid Build Coastguard Worker
117*2d1272b8SAndroid Build Coastguard Worker ft_font->cached_serial = (unsigned) -1;
118*2d1272b8SAndroid Build Coastguard Worker new (&ft_font->advance_cache) hb_ft_advance_cache_t;
119*2d1272b8SAndroid Build Coastguard Worker
120*2d1272b8SAndroid Build Coastguard Worker return ft_font;
121*2d1272b8SAndroid Build Coastguard Worker }
122*2d1272b8SAndroid Build Coastguard Worker
123*2d1272b8SAndroid Build Coastguard Worker static void
_hb_ft_face_destroy(void * data)124*2d1272b8SAndroid Build Coastguard Worker _hb_ft_face_destroy (void *data)
125*2d1272b8SAndroid Build Coastguard Worker {
126*2d1272b8SAndroid Build Coastguard Worker FT_Done_Face ((FT_Face) data);
127*2d1272b8SAndroid Build Coastguard Worker }
128*2d1272b8SAndroid Build Coastguard Worker
129*2d1272b8SAndroid Build Coastguard Worker static void
_hb_ft_font_destroy(void * data)130*2d1272b8SAndroid Build Coastguard Worker _hb_ft_font_destroy (void *data)
131*2d1272b8SAndroid Build Coastguard Worker {
132*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
133*2d1272b8SAndroid Build Coastguard Worker
134*2d1272b8SAndroid Build Coastguard Worker if (ft_font->unref)
135*2d1272b8SAndroid Build Coastguard Worker _hb_ft_face_destroy (ft_font->ft_face);
136*2d1272b8SAndroid Build Coastguard Worker
137*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.fini ();
138*2d1272b8SAndroid Build Coastguard Worker
139*2d1272b8SAndroid Build Coastguard Worker hb_free (ft_font);
140*2d1272b8SAndroid Build Coastguard Worker }
141*2d1272b8SAndroid Build Coastguard Worker
142*2d1272b8SAndroid Build Coastguard Worker
143*2d1272b8SAndroid Build Coastguard Worker /* hb_font changed, update FT_Face. */
_hb_ft_hb_font_changed(hb_font_t * font,FT_Face ft_face)144*2d1272b8SAndroid Build Coastguard Worker static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
145*2d1272b8SAndroid Build Coastguard Worker {
146*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
147*2d1272b8SAndroid Build Coastguard Worker
148*2d1272b8SAndroid Build Coastguard Worker float x_mult = 1.f, y_mult = 1.f;
149*2d1272b8SAndroid Build Coastguard Worker
150*2d1272b8SAndroid Build Coastguard Worker if (font->x_scale < 0) x_mult = -x_mult;
151*2d1272b8SAndroid Build Coastguard Worker if (font->y_scale < 0) y_mult = -y_mult;
152*2d1272b8SAndroid Build Coastguard Worker
153*2d1272b8SAndroid Build Coastguard Worker if (FT_Set_Char_Size (ft_face,
154*2d1272b8SAndroid Build Coastguard Worker abs (font->x_scale), abs (font->y_scale),
155*2d1272b8SAndroid Build Coastguard Worker 0, 0
156*2d1272b8SAndroid Build Coastguard Worker #if 0
157*2d1272b8SAndroid Build Coastguard Worker font->x_ppem * 72 * 64 / font->x_scale,
158*2d1272b8SAndroid Build Coastguard Worker font->y_ppem * 72 * 64 / font->y_scale
159*2d1272b8SAndroid Build Coastguard Worker #endif
160*2d1272b8SAndroid Build Coastguard Worker ) && ft_face->num_fixed_sizes)
161*2d1272b8SAndroid Build Coastguard Worker {
162*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FT_GET_TRANSFORM
163*2d1272b8SAndroid Build Coastguard Worker /* Bitmap font, eg. bitmap color emoji. */
164*2d1272b8SAndroid Build Coastguard Worker /* Pick largest size? */
165*2d1272b8SAndroid Build Coastguard Worker int x_scale = ft_face->available_sizes[ft_face->num_fixed_sizes - 1].x_ppem;
166*2d1272b8SAndroid Build Coastguard Worker int y_scale = ft_face->available_sizes[ft_face->num_fixed_sizes - 1].y_ppem;
167*2d1272b8SAndroid Build Coastguard Worker FT_Set_Char_Size (ft_face,
168*2d1272b8SAndroid Build Coastguard Worker x_scale, y_scale,
169*2d1272b8SAndroid Build Coastguard Worker 0, 0);
170*2d1272b8SAndroid Build Coastguard Worker
171*2d1272b8SAndroid Build Coastguard Worker /* This contains the sign that was previously in x_mult/y_mult. */
172*2d1272b8SAndroid Build Coastguard Worker x_mult = (float) font->x_scale / x_scale;
173*2d1272b8SAndroid Build Coastguard Worker y_mult = (float) font->y_scale / y_scale;
174*2d1272b8SAndroid Build Coastguard Worker #endif
175*2d1272b8SAndroid Build Coastguard Worker }
176*2d1272b8SAndroid Build Coastguard Worker else
177*2d1272b8SAndroid Build Coastguard Worker { /* Shrug */ }
178*2d1272b8SAndroid Build Coastguard Worker
179*2d1272b8SAndroid Build Coastguard Worker
180*2d1272b8SAndroid Build Coastguard Worker if (x_mult != 1.f || y_mult != 1.f)
181*2d1272b8SAndroid Build Coastguard Worker {
182*2d1272b8SAndroid Build Coastguard Worker FT_Matrix matrix = { (int) roundf (x_mult * (1<<16)), 0,
183*2d1272b8SAndroid Build Coastguard Worker 0, (int) roundf (y_mult * (1<<16))};
184*2d1272b8SAndroid Build Coastguard Worker FT_Set_Transform (ft_face, &matrix, nullptr);
185*2d1272b8SAndroid Build Coastguard Worker ft_font->transform = true;
186*2d1272b8SAndroid Build Coastguard Worker }
187*2d1272b8SAndroid Build Coastguard Worker
188*2d1272b8SAndroid Build Coastguard Worker #if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
189*2d1272b8SAndroid Build Coastguard Worker unsigned int num_coords;
190*2d1272b8SAndroid Build Coastguard Worker const float *coords = hb_font_get_var_coords_design (font, &num_coords);
191*2d1272b8SAndroid Build Coastguard Worker if (num_coords)
192*2d1272b8SAndroid Build Coastguard Worker {
193*2d1272b8SAndroid Build Coastguard Worker FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
194*2d1272b8SAndroid Build Coastguard Worker if (ft_coords)
195*2d1272b8SAndroid Build Coastguard Worker {
196*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < num_coords; i++)
197*2d1272b8SAndroid Build Coastguard Worker ft_coords[i] = coords[i] * 65536.f;
198*2d1272b8SAndroid Build Coastguard Worker FT_Set_Var_Design_Coordinates (ft_face, num_coords, ft_coords);
199*2d1272b8SAndroid Build Coastguard Worker hb_free (ft_coords);
200*2d1272b8SAndroid Build Coastguard Worker }
201*2d1272b8SAndroid Build Coastguard Worker }
202*2d1272b8SAndroid Build Coastguard Worker #endif
203*2d1272b8SAndroid Build Coastguard Worker }
204*2d1272b8SAndroid Build Coastguard Worker
205*2d1272b8SAndroid Build Coastguard Worker /* Check if hb_font changed, update FT_Face. */
206*2d1272b8SAndroid Build Coastguard Worker static inline bool
_hb_ft_hb_font_check_changed(hb_font_t * font,const hb_ft_font_t * ft_font)207*2d1272b8SAndroid Build Coastguard Worker _hb_ft_hb_font_check_changed (hb_font_t *font,
208*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font)
209*2d1272b8SAndroid Build Coastguard Worker {
210*2d1272b8SAndroid Build Coastguard Worker if (font->serial != ft_font->cached_serial)
211*2d1272b8SAndroid Build Coastguard Worker {
212*2d1272b8SAndroid Build Coastguard Worker _hb_ft_hb_font_changed (font, ft_font->ft_face);
213*2d1272b8SAndroid Build Coastguard Worker ft_font->advance_cache.clear ();
214*2d1272b8SAndroid Build Coastguard Worker ft_font->cached_serial = font->serial;
215*2d1272b8SAndroid Build Coastguard Worker return true;
216*2d1272b8SAndroid Build Coastguard Worker }
217*2d1272b8SAndroid Build Coastguard Worker return false;
218*2d1272b8SAndroid Build Coastguard Worker }
219*2d1272b8SAndroid Build Coastguard Worker
220*2d1272b8SAndroid Build Coastguard Worker
221*2d1272b8SAndroid Build Coastguard Worker /**
222*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_set_load_flags:
223*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
224*2d1272b8SAndroid Build Coastguard Worker * @load_flags: The FreeType load flags to set
225*2d1272b8SAndroid Build Coastguard Worker *
226*2d1272b8SAndroid Build Coastguard Worker * Sets the FT_Load_Glyph load flags for the specified #hb_font_t.
227*2d1272b8SAndroid Build Coastguard Worker *
228*2d1272b8SAndroid Build Coastguard Worker * For more information, see
229*2d1272b8SAndroid Build Coastguard Worker * <https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_load_xxx>
230*2d1272b8SAndroid Build Coastguard Worker *
231*2d1272b8SAndroid Build Coastguard Worker * This function works with #hb_font_t objects created by
232*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create() or hb_ft_font_create_referenced().
233*2d1272b8SAndroid Build Coastguard Worker *
234*2d1272b8SAndroid Build Coastguard Worker * Since: 1.0.5
235*2d1272b8SAndroid Build Coastguard Worker **/
236*2d1272b8SAndroid Build Coastguard Worker void
hb_ft_font_set_load_flags(hb_font_t * font,int load_flags)237*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
238*2d1272b8SAndroid Build Coastguard Worker {
239*2d1272b8SAndroid Build Coastguard Worker if (hb_object_is_immutable (font))
240*2d1272b8SAndroid Build Coastguard Worker return;
241*2d1272b8SAndroid Build Coastguard Worker
242*2d1272b8SAndroid Build Coastguard Worker if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
243*2d1272b8SAndroid Build Coastguard Worker return;
244*2d1272b8SAndroid Build Coastguard Worker
245*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
246*2d1272b8SAndroid Build Coastguard Worker
247*2d1272b8SAndroid Build Coastguard Worker ft_font->load_flags = load_flags;
248*2d1272b8SAndroid Build Coastguard Worker }
249*2d1272b8SAndroid Build Coastguard Worker
250*2d1272b8SAndroid Build Coastguard Worker /**
251*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_get_load_flags:
252*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
253*2d1272b8SAndroid Build Coastguard Worker *
254*2d1272b8SAndroid Build Coastguard Worker * Fetches the FT_Load_Glyph load flags of the specified #hb_font_t.
255*2d1272b8SAndroid Build Coastguard Worker *
256*2d1272b8SAndroid Build Coastguard Worker * For more information, see
257*2d1272b8SAndroid Build Coastguard Worker * <https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_load_xxx>
258*2d1272b8SAndroid Build Coastguard Worker *
259*2d1272b8SAndroid Build Coastguard Worker * This function works with #hb_font_t objects created by
260*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create() or hb_ft_font_create_referenced().
261*2d1272b8SAndroid Build Coastguard Worker *
262*2d1272b8SAndroid Build Coastguard Worker * Return value: FT_Load_Glyph flags found, or 0
263*2d1272b8SAndroid Build Coastguard Worker *
264*2d1272b8SAndroid Build Coastguard Worker * Since: 1.0.5
265*2d1272b8SAndroid Build Coastguard Worker **/
266*2d1272b8SAndroid Build Coastguard Worker int
hb_ft_font_get_load_flags(hb_font_t * font)267*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_get_load_flags (hb_font_t *font)
268*2d1272b8SAndroid Build Coastguard Worker {
269*2d1272b8SAndroid Build Coastguard Worker if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
270*2d1272b8SAndroid Build Coastguard Worker return 0;
271*2d1272b8SAndroid Build Coastguard Worker
272*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
273*2d1272b8SAndroid Build Coastguard Worker
274*2d1272b8SAndroid Build Coastguard Worker return ft_font->load_flags;
275*2d1272b8SAndroid Build Coastguard Worker }
276*2d1272b8SAndroid Build Coastguard Worker
277*2d1272b8SAndroid Build Coastguard Worker /**
278*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_get_face: (skip)
279*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
280*2d1272b8SAndroid Build Coastguard Worker *
281*2d1272b8SAndroid Build Coastguard Worker * Fetches the FT_Face associated with the specified #hb_font_t
282*2d1272b8SAndroid Build Coastguard Worker * font object.
283*2d1272b8SAndroid Build Coastguard Worker *
284*2d1272b8SAndroid Build Coastguard Worker * This function works with #hb_font_t objects created by
285*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create() or hb_ft_font_create_referenced().
286*2d1272b8SAndroid Build Coastguard Worker *
287*2d1272b8SAndroid Build Coastguard Worker * Return value: (nullable): the FT_Face found or `NULL`
288*2d1272b8SAndroid Build Coastguard Worker *
289*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.2
290*2d1272b8SAndroid Build Coastguard Worker **/
291*2d1272b8SAndroid Build Coastguard Worker FT_Face
hb_ft_font_get_face(hb_font_t * font)292*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_get_face (hb_font_t *font)
293*2d1272b8SAndroid Build Coastguard Worker {
294*2d1272b8SAndroid Build Coastguard Worker if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
295*2d1272b8SAndroid Build Coastguard Worker return nullptr;
296*2d1272b8SAndroid Build Coastguard Worker
297*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
298*2d1272b8SAndroid Build Coastguard Worker
299*2d1272b8SAndroid Build Coastguard Worker return ft_font->ft_face;
300*2d1272b8SAndroid Build Coastguard Worker }
301*2d1272b8SAndroid Build Coastguard Worker
302*2d1272b8SAndroid Build Coastguard Worker /**
303*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_lock_face: (skip)
304*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
305*2d1272b8SAndroid Build Coastguard Worker *
306*2d1272b8SAndroid Build Coastguard Worker * Gets the FT_Face associated with @font.
307*2d1272b8SAndroid Build Coastguard Worker *
308*2d1272b8SAndroid Build Coastguard Worker * This face will be kept around and access to the FT_Face object
309*2d1272b8SAndroid Build Coastguard Worker * from other HarfBuzz API wil be blocked until you call hb_ft_font_unlock_face().
310*2d1272b8SAndroid Build Coastguard Worker *
311*2d1272b8SAndroid Build Coastguard Worker * This function works with #hb_font_t objects created by
312*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create() or hb_ft_font_create_referenced().
313*2d1272b8SAndroid Build Coastguard Worker *
314*2d1272b8SAndroid Build Coastguard Worker * Return value: (nullable) (transfer none): the FT_Face associated with @font or `NULL`
315*2d1272b8SAndroid Build Coastguard Worker * Since: 2.6.5
316*2d1272b8SAndroid Build Coastguard Worker **/
317*2d1272b8SAndroid Build Coastguard Worker FT_Face
hb_ft_font_lock_face(hb_font_t * font)318*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_lock_face (hb_font_t *font)
319*2d1272b8SAndroid Build Coastguard Worker {
320*2d1272b8SAndroid Build Coastguard Worker if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
321*2d1272b8SAndroid Build Coastguard Worker return nullptr;
322*2d1272b8SAndroid Build Coastguard Worker
323*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
324*2d1272b8SAndroid Build Coastguard Worker
325*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.lock ();
326*2d1272b8SAndroid Build Coastguard Worker
327*2d1272b8SAndroid Build Coastguard Worker return ft_font->ft_face;
328*2d1272b8SAndroid Build Coastguard Worker }
329*2d1272b8SAndroid Build Coastguard Worker
330*2d1272b8SAndroid Build Coastguard Worker /**
331*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_unlock_face: (skip)
332*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
333*2d1272b8SAndroid Build Coastguard Worker *
334*2d1272b8SAndroid Build Coastguard Worker * Releases an FT_Face previously obtained with hb_ft_font_lock_face().
335*2d1272b8SAndroid Build Coastguard Worker *
336*2d1272b8SAndroid Build Coastguard Worker * Since: 2.6.5
337*2d1272b8SAndroid Build Coastguard Worker **/
338*2d1272b8SAndroid Build Coastguard Worker void
hb_ft_font_unlock_face(hb_font_t * font)339*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_unlock_face (hb_font_t *font)
340*2d1272b8SAndroid Build Coastguard Worker {
341*2d1272b8SAndroid Build Coastguard Worker if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
342*2d1272b8SAndroid Build Coastguard Worker return;
343*2d1272b8SAndroid Build Coastguard Worker
344*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
345*2d1272b8SAndroid Build Coastguard Worker
346*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.unlock ();
347*2d1272b8SAndroid Build Coastguard Worker }
348*2d1272b8SAndroid Build Coastguard Worker
349*2d1272b8SAndroid Build Coastguard Worker
350*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_get_nominal_glyph(hb_font_t * font,void * font_data,hb_codepoint_t unicode,hb_codepoint_t * glyph,void * user_data HB_UNUSED)351*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_nominal_glyph (hb_font_t *font,
352*2d1272b8SAndroid Build Coastguard Worker void *font_data,
353*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t unicode,
354*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *glyph,
355*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
356*2d1272b8SAndroid Build Coastguard Worker {
357*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
358*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
359*2d1272b8SAndroid Build Coastguard Worker unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
360*2d1272b8SAndroid Build Coastguard Worker
361*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!g))
362*2d1272b8SAndroid Build Coastguard Worker {
363*2d1272b8SAndroid Build Coastguard Worker if (unlikely (ft_font->symbol))
364*2d1272b8SAndroid Build Coastguard Worker {
365*2d1272b8SAndroid Build Coastguard Worker switch ((unsigned) font->face->table.OS2->get_font_page ()) {
366*2d1272b8SAndroid Build Coastguard Worker case OT::OS2::font_page_t::FONT_PAGE_NONE:
367*2d1272b8SAndroid Build Coastguard Worker if (unicode <= 0x00FFu)
368*2d1272b8SAndroid Build Coastguard Worker /* For symbol-encoded OpenType fonts, we duplicate the
369*2d1272b8SAndroid Build Coastguard Worker * U+F000..F0FF range at U+0000..U+00FF. That's what
370*2d1272b8SAndroid Build Coastguard Worker * Windows seems to do, and that's hinted about at:
371*2d1272b8SAndroid Build Coastguard Worker * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
372*2d1272b8SAndroid Build Coastguard Worker * under "Non-Standard (Symbol) Fonts". */
373*2d1272b8SAndroid Build Coastguard Worker g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
374*2d1272b8SAndroid Build Coastguard Worker break;
375*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
376*2d1272b8SAndroid Build Coastguard Worker case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
377*2d1272b8SAndroid Build Coastguard Worker g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_simp_map (unicode));
378*2d1272b8SAndroid Build Coastguard Worker break;
379*2d1272b8SAndroid Build Coastguard Worker case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
380*2d1272b8SAndroid Build Coastguard Worker g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_trad_map (unicode));
381*2d1272b8SAndroid Build Coastguard Worker break;
382*2d1272b8SAndroid Build Coastguard Worker #endif
383*2d1272b8SAndroid Build Coastguard Worker default:
384*2d1272b8SAndroid Build Coastguard Worker break;
385*2d1272b8SAndroid Build Coastguard Worker }
386*2d1272b8SAndroid Build Coastguard Worker if (!g)
387*2d1272b8SAndroid Build Coastguard Worker return false;
388*2d1272b8SAndroid Build Coastguard Worker }
389*2d1272b8SAndroid Build Coastguard Worker else
390*2d1272b8SAndroid Build Coastguard Worker return false;
391*2d1272b8SAndroid Build Coastguard Worker }
392*2d1272b8SAndroid Build Coastguard Worker
393*2d1272b8SAndroid Build Coastguard Worker *glyph = g;
394*2d1272b8SAndroid Build Coastguard Worker return true;
395*2d1272b8SAndroid Build Coastguard Worker }
396*2d1272b8SAndroid Build Coastguard Worker
397*2d1272b8SAndroid Build Coastguard Worker static unsigned int
hb_ft_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)398*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
399*2d1272b8SAndroid Build Coastguard Worker void *font_data,
400*2d1272b8SAndroid Build Coastguard Worker unsigned int count,
401*2d1272b8SAndroid Build Coastguard Worker const hb_codepoint_t *first_unicode,
402*2d1272b8SAndroid Build Coastguard Worker unsigned int unicode_stride,
403*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *first_glyph,
404*2d1272b8SAndroid Build Coastguard Worker unsigned int glyph_stride,
405*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
406*2d1272b8SAndroid Build Coastguard Worker {
407*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
408*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
409*2d1272b8SAndroid Build Coastguard Worker unsigned int done;
410*2d1272b8SAndroid Build Coastguard Worker for (done = 0;
411*2d1272b8SAndroid Build Coastguard Worker done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
412*2d1272b8SAndroid Build Coastguard Worker done++)
413*2d1272b8SAndroid Build Coastguard Worker {
414*2d1272b8SAndroid Build Coastguard Worker first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
415*2d1272b8SAndroid Build Coastguard Worker first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
416*2d1272b8SAndroid Build Coastguard Worker }
417*2d1272b8SAndroid Build Coastguard Worker /* We don't need to do ft_font->symbol dance here, since HB calls the singular
418*2d1272b8SAndroid Build Coastguard Worker * nominal_glyph() for what we don't handle here. */
419*2d1272b8SAndroid Build Coastguard Worker return done;
420*2d1272b8SAndroid Build Coastguard Worker }
421*2d1272b8SAndroid Build Coastguard Worker
422*2d1272b8SAndroid Build Coastguard Worker
423*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_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)424*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
425*2d1272b8SAndroid Build Coastguard Worker void *font_data,
426*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t unicode,
427*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t variation_selector,
428*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *glyph,
429*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
430*2d1272b8SAndroid Build Coastguard Worker {
431*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
432*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
433*2d1272b8SAndroid Build Coastguard Worker unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
434*2d1272b8SAndroid Build Coastguard Worker
435*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!g))
436*2d1272b8SAndroid Build Coastguard Worker return false;
437*2d1272b8SAndroid Build Coastguard Worker
438*2d1272b8SAndroid Build Coastguard Worker *glyph = g;
439*2d1272b8SAndroid Build Coastguard Worker return true;
440*2d1272b8SAndroid Build Coastguard Worker }
441*2d1272b8SAndroid Build Coastguard Worker
442*2d1272b8SAndroid Build Coastguard Worker static void
hb_ft_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)443*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
444*2d1272b8SAndroid Build Coastguard Worker unsigned count,
445*2d1272b8SAndroid Build Coastguard Worker const hb_codepoint_t *first_glyph,
446*2d1272b8SAndroid Build Coastguard Worker unsigned glyph_stride,
447*2d1272b8SAndroid Build Coastguard Worker hb_position_t *first_advance,
448*2d1272b8SAndroid Build Coastguard Worker unsigned advance_stride,
449*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
450*2d1272b8SAndroid Build Coastguard Worker {
451*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
452*2d1272b8SAndroid Build Coastguard Worker hb_position_t *orig_first_advance = first_advance;
453*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
454*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
455*2d1272b8SAndroid Build Coastguard Worker int load_flags = ft_font->load_flags;
456*2d1272b8SAndroid Build Coastguard Worker float x_mult;
457*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FT_GET_TRANSFORM
458*2d1272b8SAndroid Build Coastguard Worker if (ft_font->transform)
459*2d1272b8SAndroid Build Coastguard Worker {
460*2d1272b8SAndroid Build Coastguard Worker FT_Matrix matrix;
461*2d1272b8SAndroid Build Coastguard Worker FT_Get_Transform (ft_face, &matrix, nullptr);
462*2d1272b8SAndroid Build Coastguard Worker x_mult = sqrtf ((float)matrix.xx * matrix.xx + (float)matrix.xy * matrix.xy) / 65536.f;
463*2d1272b8SAndroid Build Coastguard Worker x_mult *= font->x_scale < 0 ? -1 : +1;
464*2d1272b8SAndroid Build Coastguard Worker }
465*2d1272b8SAndroid Build Coastguard Worker else
466*2d1272b8SAndroid Build Coastguard Worker #endif
467*2d1272b8SAndroid Build Coastguard Worker {
468*2d1272b8SAndroid Build Coastguard Worker x_mult = font->x_scale < 0 ? -1 : +1;
469*2d1272b8SAndroid Build Coastguard Worker }
470*2d1272b8SAndroid Build Coastguard Worker
471*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
472*2d1272b8SAndroid Build Coastguard Worker {
473*2d1272b8SAndroid Build Coastguard Worker FT_Fixed v = 0;
474*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph = *first_glyph;
475*2d1272b8SAndroid Build Coastguard Worker
476*2d1272b8SAndroid Build Coastguard Worker unsigned int cv;
477*2d1272b8SAndroid Build Coastguard Worker if (ft_font->advance_cache.get (glyph, &cv))
478*2d1272b8SAndroid Build Coastguard Worker v = cv;
479*2d1272b8SAndroid Build Coastguard Worker else
480*2d1272b8SAndroid Build Coastguard Worker {
481*2d1272b8SAndroid Build Coastguard Worker FT_Get_Advance (ft_face, glyph, load_flags, &v);
482*2d1272b8SAndroid Build Coastguard Worker /* Work around bug that FreeType seems to return negative advance
483*2d1272b8SAndroid Build Coastguard Worker * for variable-set fonts if x_scale is negative! */
484*2d1272b8SAndroid Build Coastguard Worker v = abs (v);
485*2d1272b8SAndroid Build Coastguard Worker v = (int) (v * x_mult + (1<<9)) >> 10;
486*2d1272b8SAndroid Build Coastguard Worker ft_font->advance_cache.set (glyph, v);
487*2d1272b8SAndroid Build Coastguard Worker }
488*2d1272b8SAndroid Build Coastguard Worker
489*2d1272b8SAndroid Build Coastguard Worker *first_advance = v;
490*2d1272b8SAndroid Build Coastguard Worker first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
491*2d1272b8SAndroid Build Coastguard Worker first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
492*2d1272b8SAndroid Build Coastguard Worker }
493*2d1272b8SAndroid Build Coastguard Worker
494*2d1272b8SAndroid Build Coastguard Worker if (font->x_strength && !font->embolden_in_place)
495*2d1272b8SAndroid Build Coastguard Worker {
496*2d1272b8SAndroid Build Coastguard Worker /* Emboldening. */
497*2d1272b8SAndroid Build Coastguard Worker hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
498*2d1272b8SAndroid Build Coastguard Worker first_advance = orig_first_advance;
499*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
500*2d1272b8SAndroid Build Coastguard Worker {
501*2d1272b8SAndroid Build Coastguard Worker *first_advance += *first_advance ? x_strength : 0;
502*2d1272b8SAndroid Build Coastguard Worker first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
503*2d1272b8SAndroid Build Coastguard Worker }
504*2d1272b8SAndroid Build Coastguard Worker }
505*2d1272b8SAndroid Build Coastguard Worker }
506*2d1272b8SAndroid Build Coastguard Worker
507*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
508*2d1272b8SAndroid Build Coastguard Worker static hb_position_t
hb_ft_get_glyph_v_advance(hb_font_t * font,void * font_data,hb_codepoint_t glyph,void * user_data HB_UNUSED)509*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_v_advance (hb_font_t *font,
510*2d1272b8SAndroid Build Coastguard Worker void *font_data,
511*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph,
512*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
513*2d1272b8SAndroid Build Coastguard Worker {
514*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
515*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
516*2d1272b8SAndroid Build Coastguard Worker FT_Fixed v;
517*2d1272b8SAndroid Build Coastguard Worker float y_mult;
518*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FT_GET_TRANSFORM
519*2d1272b8SAndroid Build Coastguard Worker if (ft_font->transform)
520*2d1272b8SAndroid Build Coastguard Worker {
521*2d1272b8SAndroid Build Coastguard Worker FT_Matrix matrix;
522*2d1272b8SAndroid Build Coastguard Worker FT_Get_Transform (ft_font->ft_face, &matrix, nullptr);
523*2d1272b8SAndroid Build Coastguard Worker y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
524*2d1272b8SAndroid Build Coastguard Worker y_mult *= font->y_scale < 0 ? -1 : +1;
525*2d1272b8SAndroid Build Coastguard Worker }
526*2d1272b8SAndroid Build Coastguard Worker else
527*2d1272b8SAndroid Build Coastguard Worker #endif
528*2d1272b8SAndroid Build Coastguard Worker {
529*2d1272b8SAndroid Build Coastguard Worker y_mult = font->y_scale < 0 ? -1 : +1;
530*2d1272b8SAndroid Build Coastguard Worker }
531*2d1272b8SAndroid Build Coastguard Worker
532*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
533*2d1272b8SAndroid Build Coastguard Worker return 0;
534*2d1272b8SAndroid Build Coastguard Worker
535*2d1272b8SAndroid Build Coastguard Worker v = (int) (y_mult * v);
536*2d1272b8SAndroid Build Coastguard Worker
537*2d1272b8SAndroid Build Coastguard Worker /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
538*2d1272b8SAndroid Build Coastguard Worker * have a Y growing upward. Hence the extra negation. */
539*2d1272b8SAndroid Build Coastguard Worker
540*2d1272b8SAndroid Build Coastguard Worker hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
541*2d1272b8SAndroid Build Coastguard Worker return ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
542*2d1272b8SAndroid Build Coastguard Worker }
543*2d1272b8SAndroid Build Coastguard Worker #endif
544*2d1272b8SAndroid Build Coastguard Worker
545*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
546*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_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)547*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_v_origin (hb_font_t *font,
548*2d1272b8SAndroid Build Coastguard Worker void *font_data,
549*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph,
550*2d1272b8SAndroid Build Coastguard Worker hb_position_t *x,
551*2d1272b8SAndroid Build Coastguard Worker hb_position_t *y,
552*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
553*2d1272b8SAndroid Build Coastguard Worker {
554*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
555*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
556*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
557*2d1272b8SAndroid Build Coastguard Worker float x_mult, y_mult;
558*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FT_GET_TRANSFORM
559*2d1272b8SAndroid Build Coastguard Worker if (ft_font->transform)
560*2d1272b8SAndroid Build Coastguard Worker {
561*2d1272b8SAndroid Build Coastguard Worker FT_Matrix matrix;
562*2d1272b8SAndroid Build Coastguard Worker FT_Get_Transform (ft_face, &matrix, nullptr);
563*2d1272b8SAndroid Build Coastguard Worker x_mult = sqrtf ((float)matrix.xx * matrix.xx + (float)matrix.xy * matrix.xy) / 65536.f;
564*2d1272b8SAndroid Build Coastguard Worker x_mult *= font->x_scale < 0 ? -1 : +1;
565*2d1272b8SAndroid Build Coastguard Worker y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
566*2d1272b8SAndroid Build Coastguard Worker y_mult *= font->y_scale < 0 ? -1 : +1;
567*2d1272b8SAndroid Build Coastguard Worker }
568*2d1272b8SAndroid Build Coastguard Worker else
569*2d1272b8SAndroid Build Coastguard Worker #endif
570*2d1272b8SAndroid Build Coastguard Worker {
571*2d1272b8SAndroid Build Coastguard Worker x_mult = font->x_scale < 0 ? -1 : +1;
572*2d1272b8SAndroid Build Coastguard Worker y_mult = font->y_scale < 0 ? -1 : +1;
573*2d1272b8SAndroid Build Coastguard Worker }
574*2d1272b8SAndroid Build Coastguard Worker
575*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
576*2d1272b8SAndroid Build Coastguard Worker return false;
577*2d1272b8SAndroid Build Coastguard Worker
578*2d1272b8SAndroid Build Coastguard Worker /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
579*2d1272b8SAndroid Build Coastguard Worker * have a Y growing upward. Hence the extra negation. */
580*2d1272b8SAndroid Build Coastguard Worker *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX;
581*2d1272b8SAndroid Build Coastguard Worker *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
582*2d1272b8SAndroid Build Coastguard Worker
583*2d1272b8SAndroid Build Coastguard Worker *x = (hb_position_t) (x_mult * *x);
584*2d1272b8SAndroid Build Coastguard Worker *y = (hb_position_t) (y_mult * *y);
585*2d1272b8SAndroid Build Coastguard Worker
586*2d1272b8SAndroid Build Coastguard Worker return true;
587*2d1272b8SAndroid Build Coastguard Worker }
588*2d1272b8SAndroid Build Coastguard Worker #endif
589*2d1272b8SAndroid Build Coastguard Worker
590*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_SHAPE_FALLBACK
591*2d1272b8SAndroid Build Coastguard Worker static hb_position_t
hb_ft_get_glyph_h_kerning(hb_font_t * font,void * font_data,hb_codepoint_t left_glyph,hb_codepoint_t right_glyph,void * user_data HB_UNUSED)592*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_h_kerning (hb_font_t *font,
593*2d1272b8SAndroid Build Coastguard Worker void *font_data,
594*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t left_glyph,
595*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t right_glyph,
596*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
597*2d1272b8SAndroid Build Coastguard Worker {
598*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
599*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
600*2d1272b8SAndroid Build Coastguard Worker FT_Vector kerningv;
601*2d1272b8SAndroid Build Coastguard Worker
602*2d1272b8SAndroid Build Coastguard Worker FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
603*2d1272b8SAndroid Build Coastguard Worker if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
604*2d1272b8SAndroid Build Coastguard Worker return 0;
605*2d1272b8SAndroid Build Coastguard Worker
606*2d1272b8SAndroid Build Coastguard Worker return kerningv.x;
607*2d1272b8SAndroid Build Coastguard Worker }
608*2d1272b8SAndroid Build Coastguard Worker #endif
609*2d1272b8SAndroid Build Coastguard Worker
610*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_get_glyph_extents(hb_font_t * font,void * font_data,hb_codepoint_t glyph,hb_glyph_extents_t * extents,void * user_data HB_UNUSED)611*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_extents (hb_font_t *font,
612*2d1272b8SAndroid Build Coastguard Worker void *font_data,
613*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph,
614*2d1272b8SAndroid Build Coastguard Worker hb_glyph_extents_t *extents,
615*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
616*2d1272b8SAndroid Build Coastguard Worker {
617*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
618*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
619*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
620*2d1272b8SAndroid Build Coastguard Worker float x_mult, y_mult;
621*2d1272b8SAndroid Build Coastguard Worker float slant_xy = font->slant_xy;
622*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FT_GET_TRANSFORM
623*2d1272b8SAndroid Build Coastguard Worker if (ft_font->transform)
624*2d1272b8SAndroid Build Coastguard Worker {
625*2d1272b8SAndroid Build Coastguard Worker FT_Matrix matrix;
626*2d1272b8SAndroid Build Coastguard Worker FT_Get_Transform (ft_face, &matrix, nullptr);
627*2d1272b8SAndroid Build Coastguard Worker x_mult = sqrtf ((float)matrix.xx * matrix.xx + (float)matrix.xy * matrix.xy) / 65536.f;
628*2d1272b8SAndroid Build Coastguard Worker x_mult *= font->x_scale < 0 ? -1 : +1;
629*2d1272b8SAndroid Build Coastguard Worker y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
630*2d1272b8SAndroid Build Coastguard Worker y_mult *= font->y_scale < 0 ? -1 : +1;
631*2d1272b8SAndroid Build Coastguard Worker }
632*2d1272b8SAndroid Build Coastguard Worker else
633*2d1272b8SAndroid Build Coastguard Worker #endif
634*2d1272b8SAndroid Build Coastguard Worker {
635*2d1272b8SAndroid Build Coastguard Worker x_mult = font->x_scale < 0 ? -1 : +1;
636*2d1272b8SAndroid Build Coastguard Worker y_mult = font->y_scale < 0 ? -1 : +1;
637*2d1272b8SAndroid Build Coastguard Worker }
638*2d1272b8SAndroid Build Coastguard Worker
639*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
640*2d1272b8SAndroid Build Coastguard Worker return false;
641*2d1272b8SAndroid Build Coastguard Worker
642*2d1272b8SAndroid Build Coastguard Worker /* Copied from hb_font_t::scale_glyph_extents. */
643*2d1272b8SAndroid Build Coastguard Worker
644*2d1272b8SAndroid Build Coastguard Worker float x1 = x_mult * ft_face->glyph->metrics.horiBearingX;
645*2d1272b8SAndroid Build Coastguard Worker float y1 = y_mult * ft_face->glyph->metrics.horiBearingY;
646*2d1272b8SAndroid Build Coastguard Worker float x2 = x1 + x_mult * ft_face->glyph->metrics.width;
647*2d1272b8SAndroid Build Coastguard Worker float y2 = y1 + y_mult * -ft_face->glyph->metrics.height;
648*2d1272b8SAndroid Build Coastguard Worker
649*2d1272b8SAndroid Build Coastguard Worker /* Apply slant. */
650*2d1272b8SAndroid Build Coastguard Worker if (slant_xy)
651*2d1272b8SAndroid Build Coastguard Worker {
652*2d1272b8SAndroid Build Coastguard Worker x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
653*2d1272b8SAndroid Build Coastguard Worker x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
654*2d1272b8SAndroid Build Coastguard Worker }
655*2d1272b8SAndroid Build Coastguard Worker
656*2d1272b8SAndroid Build Coastguard Worker extents->x_bearing = floorf (x1);
657*2d1272b8SAndroid Build Coastguard Worker extents->y_bearing = floorf (y1);
658*2d1272b8SAndroid Build Coastguard Worker extents->width = ceilf (x2) - extents->x_bearing;
659*2d1272b8SAndroid Build Coastguard Worker extents->height = ceilf (y2) - extents->y_bearing;
660*2d1272b8SAndroid Build Coastguard Worker
661*2d1272b8SAndroid Build Coastguard Worker if (font->x_strength || font->y_strength)
662*2d1272b8SAndroid Build Coastguard Worker {
663*2d1272b8SAndroid Build Coastguard Worker /* Y */
664*2d1272b8SAndroid Build Coastguard Worker int y_shift = font->y_strength;
665*2d1272b8SAndroid Build Coastguard Worker if (font->y_scale < 0) y_shift = -y_shift;
666*2d1272b8SAndroid Build Coastguard Worker extents->y_bearing += y_shift;
667*2d1272b8SAndroid Build Coastguard Worker extents->height -= y_shift;
668*2d1272b8SAndroid Build Coastguard Worker
669*2d1272b8SAndroid Build Coastguard Worker /* X */
670*2d1272b8SAndroid Build Coastguard Worker int x_shift = font->x_strength;
671*2d1272b8SAndroid Build Coastguard Worker if (font->x_scale < 0) x_shift = -x_shift;
672*2d1272b8SAndroid Build Coastguard Worker if (font->embolden_in_place)
673*2d1272b8SAndroid Build Coastguard Worker extents->x_bearing -= x_shift / 2;
674*2d1272b8SAndroid Build Coastguard Worker extents->width += x_shift;
675*2d1272b8SAndroid Build Coastguard Worker }
676*2d1272b8SAndroid Build Coastguard Worker
677*2d1272b8SAndroid Build Coastguard Worker return true;
678*2d1272b8SAndroid Build Coastguard Worker }
679*2d1272b8SAndroid Build Coastguard Worker
680*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_get_glyph_contour_point(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t glyph,unsigned int point_index,hb_position_t * x,hb_position_t * y,void * user_data HB_UNUSED)681*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
682*2d1272b8SAndroid Build Coastguard Worker void *font_data,
683*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph,
684*2d1272b8SAndroid Build Coastguard Worker unsigned int point_index,
685*2d1272b8SAndroid Build Coastguard Worker hb_position_t *x,
686*2d1272b8SAndroid Build Coastguard Worker hb_position_t *y,
687*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
688*2d1272b8SAndroid Build Coastguard Worker {
689*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
690*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
691*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
692*2d1272b8SAndroid Build Coastguard Worker
693*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
694*2d1272b8SAndroid Build Coastguard Worker return false;
695*2d1272b8SAndroid Build Coastguard Worker
696*2d1272b8SAndroid Build Coastguard Worker if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
697*2d1272b8SAndroid Build Coastguard Worker return false;
698*2d1272b8SAndroid Build Coastguard Worker
699*2d1272b8SAndroid Build Coastguard Worker if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
700*2d1272b8SAndroid Build Coastguard Worker return false;
701*2d1272b8SAndroid Build Coastguard Worker
702*2d1272b8SAndroid Build Coastguard Worker *x = ft_face->glyph->outline.points[point_index].x;
703*2d1272b8SAndroid Build Coastguard Worker *y = ft_face->glyph->outline.points[point_index].y;
704*2d1272b8SAndroid Build Coastguard Worker
705*2d1272b8SAndroid Build Coastguard Worker return true;
706*2d1272b8SAndroid Build Coastguard Worker }
707*2d1272b8SAndroid Build Coastguard Worker
708*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_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)709*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED,
710*2d1272b8SAndroid Build Coastguard Worker void *font_data,
711*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph,
712*2d1272b8SAndroid Build Coastguard Worker char *name, unsigned int size,
713*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
714*2d1272b8SAndroid Build Coastguard Worker {
715*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
716*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
717*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
718*2d1272b8SAndroid Build Coastguard Worker
719*2d1272b8SAndroid Build Coastguard Worker hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
720*2d1272b8SAndroid Build Coastguard Worker if (ret && (size && !*name))
721*2d1272b8SAndroid Build Coastguard Worker ret = false;
722*2d1272b8SAndroid Build Coastguard Worker
723*2d1272b8SAndroid Build Coastguard Worker return ret;
724*2d1272b8SAndroid Build Coastguard Worker }
725*2d1272b8SAndroid Build Coastguard Worker
726*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_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)727*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
728*2d1272b8SAndroid Build Coastguard Worker void *font_data,
729*2d1272b8SAndroid Build Coastguard Worker const char *name, int len, /* -1 means nul-terminated */
730*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *glyph,
731*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
732*2d1272b8SAndroid Build Coastguard Worker {
733*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
734*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
735*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
736*2d1272b8SAndroid Build Coastguard Worker
737*2d1272b8SAndroid Build Coastguard Worker if (len < 0)
738*2d1272b8SAndroid Build Coastguard Worker *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name);
739*2d1272b8SAndroid Build Coastguard Worker else {
740*2d1272b8SAndroid Build Coastguard Worker /* Make a nul-terminated version. */
741*2d1272b8SAndroid Build Coastguard Worker char buf[128];
742*2d1272b8SAndroid Build Coastguard Worker len = hb_min (len, (int) sizeof (buf) - 1);
743*2d1272b8SAndroid Build Coastguard Worker strncpy (buf, name, len);
744*2d1272b8SAndroid Build Coastguard Worker buf[len] = '\0';
745*2d1272b8SAndroid Build Coastguard Worker *glyph = FT_Get_Name_Index (ft_face, buf);
746*2d1272b8SAndroid Build Coastguard Worker }
747*2d1272b8SAndroid Build Coastguard Worker
748*2d1272b8SAndroid Build Coastguard Worker if (*glyph == 0)
749*2d1272b8SAndroid Build Coastguard Worker {
750*2d1272b8SAndroid Build Coastguard Worker /* Check whether the given name was actually the name of glyph 0. */
751*2d1272b8SAndroid Build Coastguard Worker char buf[128];
752*2d1272b8SAndroid Build Coastguard Worker if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) &&
753*2d1272b8SAndroid Build Coastguard Worker len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len))
754*2d1272b8SAndroid Build Coastguard Worker return true;
755*2d1272b8SAndroid Build Coastguard Worker }
756*2d1272b8SAndroid Build Coastguard Worker
757*2d1272b8SAndroid Build Coastguard Worker return *glyph != 0;
758*2d1272b8SAndroid Build Coastguard Worker }
759*2d1272b8SAndroid Build Coastguard Worker
760*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ft_get_font_h_extents(hb_font_t * font HB_UNUSED,void * font_data,hb_font_extents_t * metrics,void * user_data HB_UNUSED)761*2d1272b8SAndroid Build Coastguard Worker hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
762*2d1272b8SAndroid Build Coastguard Worker void *font_data,
763*2d1272b8SAndroid Build Coastguard Worker hb_font_extents_t *metrics,
764*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
765*2d1272b8SAndroid Build Coastguard Worker {
766*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
767*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
768*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
769*2d1272b8SAndroid Build Coastguard Worker float y_mult;
770*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FT_GET_TRANSFORM
771*2d1272b8SAndroid Build Coastguard Worker if (ft_font->transform)
772*2d1272b8SAndroid Build Coastguard Worker {
773*2d1272b8SAndroid Build Coastguard Worker FT_Matrix matrix;
774*2d1272b8SAndroid Build Coastguard Worker FT_Get_Transform (ft_face, &matrix, nullptr);
775*2d1272b8SAndroid Build Coastguard Worker y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
776*2d1272b8SAndroid Build Coastguard Worker y_mult *= font->y_scale < 0 ? -1 : +1;
777*2d1272b8SAndroid Build Coastguard Worker }
778*2d1272b8SAndroid Build Coastguard Worker else
779*2d1272b8SAndroid Build Coastguard Worker #endif
780*2d1272b8SAndroid Build Coastguard Worker {
781*2d1272b8SAndroid Build Coastguard Worker y_mult = font->y_scale < 0 ? -1 : +1;
782*2d1272b8SAndroid Build Coastguard Worker }
783*2d1272b8SAndroid Build Coastguard Worker
784*2d1272b8SAndroid Build Coastguard Worker if (ft_face->units_per_EM != 0)
785*2d1272b8SAndroid Build Coastguard Worker {
786*2d1272b8SAndroid Build Coastguard Worker metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
787*2d1272b8SAndroid Build Coastguard Worker metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
788*2d1272b8SAndroid Build Coastguard Worker metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
789*2d1272b8SAndroid Build Coastguard Worker }
790*2d1272b8SAndroid Build Coastguard Worker else
791*2d1272b8SAndroid Build Coastguard Worker {
792*2d1272b8SAndroid Build Coastguard Worker /* Bitmap-only font, eg. color bitmap font. */
793*2d1272b8SAndroid Build Coastguard Worker metrics->ascender = ft_face->size->metrics.ascender;
794*2d1272b8SAndroid Build Coastguard Worker metrics->descender = ft_face->size->metrics.descender;
795*2d1272b8SAndroid Build Coastguard Worker metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
796*2d1272b8SAndroid Build Coastguard Worker }
797*2d1272b8SAndroid Build Coastguard Worker
798*2d1272b8SAndroid Build Coastguard Worker metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength));
799*2d1272b8SAndroid Build Coastguard Worker metrics->descender = (hb_position_t) (y_mult * metrics->descender);
800*2d1272b8SAndroid Build Coastguard Worker metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
801*2d1272b8SAndroid Build Coastguard Worker
802*2d1272b8SAndroid Build Coastguard Worker return true;
803*2d1272b8SAndroid Build Coastguard Worker }
804*2d1272b8SAndroid Build Coastguard Worker
805*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_DRAW
806*2d1272b8SAndroid Build Coastguard Worker
807*2d1272b8SAndroid Build Coastguard Worker static int
_hb_ft_move_to(const FT_Vector * to,void * arg)808*2d1272b8SAndroid Build Coastguard Worker _hb_ft_move_to (const FT_Vector *to,
809*2d1272b8SAndroid Build Coastguard Worker void *arg)
810*2d1272b8SAndroid Build Coastguard Worker {
811*2d1272b8SAndroid Build Coastguard Worker hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
812*2d1272b8SAndroid Build Coastguard Worker drawing->move_to (to->x, to->y);
813*2d1272b8SAndroid Build Coastguard Worker return FT_Err_Ok;
814*2d1272b8SAndroid Build Coastguard Worker }
815*2d1272b8SAndroid Build Coastguard Worker
816*2d1272b8SAndroid Build Coastguard Worker static int
_hb_ft_line_to(const FT_Vector * to,void * arg)817*2d1272b8SAndroid Build Coastguard Worker _hb_ft_line_to (const FT_Vector *to,
818*2d1272b8SAndroid Build Coastguard Worker void *arg)
819*2d1272b8SAndroid Build Coastguard Worker {
820*2d1272b8SAndroid Build Coastguard Worker hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
821*2d1272b8SAndroid Build Coastguard Worker drawing->line_to (to->x, to->y);
822*2d1272b8SAndroid Build Coastguard Worker return FT_Err_Ok;
823*2d1272b8SAndroid Build Coastguard Worker }
824*2d1272b8SAndroid Build Coastguard Worker
825*2d1272b8SAndroid Build Coastguard Worker static int
_hb_ft_conic_to(const FT_Vector * control,const FT_Vector * to,void * arg)826*2d1272b8SAndroid Build Coastguard Worker _hb_ft_conic_to (const FT_Vector *control,
827*2d1272b8SAndroid Build Coastguard Worker const FT_Vector *to,
828*2d1272b8SAndroid Build Coastguard Worker void *arg)
829*2d1272b8SAndroid Build Coastguard Worker {
830*2d1272b8SAndroid Build Coastguard Worker hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
831*2d1272b8SAndroid Build Coastguard Worker drawing->quadratic_to (control->x, control->y,
832*2d1272b8SAndroid Build Coastguard Worker to->x, to->y);
833*2d1272b8SAndroid Build Coastguard Worker return FT_Err_Ok;
834*2d1272b8SAndroid Build Coastguard Worker }
835*2d1272b8SAndroid Build Coastguard Worker
836*2d1272b8SAndroid Build Coastguard Worker static int
_hb_ft_cubic_to(const FT_Vector * control1,const FT_Vector * control2,const FT_Vector * to,void * arg)837*2d1272b8SAndroid Build Coastguard Worker _hb_ft_cubic_to (const FT_Vector *control1,
838*2d1272b8SAndroid Build Coastguard Worker const FT_Vector *control2,
839*2d1272b8SAndroid Build Coastguard Worker const FT_Vector *to,
840*2d1272b8SAndroid Build Coastguard Worker void *arg)
841*2d1272b8SAndroid Build Coastguard Worker {
842*2d1272b8SAndroid Build Coastguard Worker hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
843*2d1272b8SAndroid Build Coastguard Worker drawing->cubic_to (control1->x, control1->y,
844*2d1272b8SAndroid Build Coastguard Worker control2->x, control2->y,
845*2d1272b8SAndroid Build Coastguard Worker to->x, to->y);
846*2d1272b8SAndroid Build Coastguard Worker return FT_Err_Ok;
847*2d1272b8SAndroid Build Coastguard Worker }
848*2d1272b8SAndroid Build Coastguard Worker
849*2d1272b8SAndroid Build Coastguard Worker static void
hb_ft_draw_glyph(hb_font_t * font,void * font_data,hb_codepoint_t glyph,hb_draw_funcs_t * draw_funcs,void * draw_data,void * user_data HB_UNUSED)850*2d1272b8SAndroid Build Coastguard Worker hb_ft_draw_glyph (hb_font_t *font,
851*2d1272b8SAndroid Build Coastguard Worker void *font_data,
852*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph,
853*2d1272b8SAndroid Build Coastguard Worker hb_draw_funcs_t *draw_funcs, void *draw_data,
854*2d1272b8SAndroid Build Coastguard Worker void *user_data HB_UNUSED)
855*2d1272b8SAndroid Build Coastguard Worker {
856*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
857*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
858*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
859*2d1272b8SAndroid Build Coastguard Worker
860*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_Load_Glyph (ft_face, glyph,
861*2d1272b8SAndroid Build Coastguard Worker FT_LOAD_NO_BITMAP | ft_font->load_flags)))
862*2d1272b8SAndroid Build Coastguard Worker return;
863*2d1272b8SAndroid Build Coastguard Worker
864*2d1272b8SAndroid Build Coastguard Worker if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
865*2d1272b8SAndroid Build Coastguard Worker return;
866*2d1272b8SAndroid Build Coastguard Worker
867*2d1272b8SAndroid Build Coastguard Worker const FT_Outline_Funcs outline_funcs = {
868*2d1272b8SAndroid Build Coastguard Worker _hb_ft_move_to,
869*2d1272b8SAndroid Build Coastguard Worker _hb_ft_line_to,
870*2d1272b8SAndroid Build Coastguard Worker _hb_ft_conic_to,
871*2d1272b8SAndroid Build Coastguard Worker _hb_ft_cubic_to,
872*2d1272b8SAndroid Build Coastguard Worker 0, /* shift */
873*2d1272b8SAndroid Build Coastguard Worker 0, /* delta */
874*2d1272b8SAndroid Build Coastguard Worker };
875*2d1272b8SAndroid Build Coastguard Worker
876*2d1272b8SAndroid Build Coastguard Worker hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
877*2d1272b8SAndroid Build Coastguard Worker
878*2d1272b8SAndroid Build Coastguard Worker /* Embolden */
879*2d1272b8SAndroid Build Coastguard Worker if (font->x_strength || font->y_strength)
880*2d1272b8SAndroid Build Coastguard Worker {
881*2d1272b8SAndroid Build Coastguard Worker FT_Outline_EmboldenXY (&ft_face->glyph->outline, font->x_strength, font->y_strength);
882*2d1272b8SAndroid Build Coastguard Worker
883*2d1272b8SAndroid Build Coastguard Worker int x_shift = 0;
884*2d1272b8SAndroid Build Coastguard Worker int y_shift = 0;
885*2d1272b8SAndroid Build Coastguard Worker if (font->embolden_in_place)
886*2d1272b8SAndroid Build Coastguard Worker {
887*2d1272b8SAndroid Build Coastguard Worker /* Undo the FreeType shift. */
888*2d1272b8SAndroid Build Coastguard Worker x_shift = -font->x_strength / 2;
889*2d1272b8SAndroid Build Coastguard Worker y_shift = 0;
890*2d1272b8SAndroid Build Coastguard Worker if (font->y_scale < 0) y_shift = -font->y_strength;
891*2d1272b8SAndroid Build Coastguard Worker }
892*2d1272b8SAndroid Build Coastguard Worker else
893*2d1272b8SAndroid Build Coastguard Worker {
894*2d1272b8SAndroid Build Coastguard Worker /* FreeType applied things in the wrong direction for negative scale; fix up. */
895*2d1272b8SAndroid Build Coastguard Worker if (font->x_scale < 0) x_shift = -font->x_strength;
896*2d1272b8SAndroid Build Coastguard Worker if (font->y_scale < 0) y_shift = -font->y_strength;
897*2d1272b8SAndroid Build Coastguard Worker }
898*2d1272b8SAndroid Build Coastguard Worker if (x_shift || y_shift)
899*2d1272b8SAndroid Build Coastguard Worker {
900*2d1272b8SAndroid Build Coastguard Worker auto &outline = ft_face->glyph->outline;
901*2d1272b8SAndroid Build Coastguard Worker for (auto &point : hb_iter (outline.points, outline.contours[outline.n_contours - 1] + 1))
902*2d1272b8SAndroid Build Coastguard Worker {
903*2d1272b8SAndroid Build Coastguard Worker point.x += x_shift;
904*2d1272b8SAndroid Build Coastguard Worker point.y += y_shift;
905*2d1272b8SAndroid Build Coastguard Worker }
906*2d1272b8SAndroid Build Coastguard Worker }
907*2d1272b8SAndroid Build Coastguard Worker }
908*2d1272b8SAndroid Build Coastguard Worker
909*2d1272b8SAndroid Build Coastguard Worker
910*2d1272b8SAndroid Build Coastguard Worker FT_Outline_Decompose (&ft_face->glyph->outline,
911*2d1272b8SAndroid Build Coastguard Worker &outline_funcs,
912*2d1272b8SAndroid Build Coastguard Worker &draw_session);
913*2d1272b8SAndroid Build Coastguard Worker }
914*2d1272b8SAndroid Build Coastguard Worker #endif
915*2d1272b8SAndroid Build Coastguard Worker
916*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_PAINT
917*2d1272b8SAndroid Build Coastguard Worker #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
918*2d1272b8SAndroid Build Coastguard Worker
919*2d1272b8SAndroid Build Coastguard Worker #include "hb-ft-colr.hh"
920*2d1272b8SAndroid Build Coastguard Worker
921*2d1272b8SAndroid Build Coastguard Worker static void
hb_ft_paint_glyph(hb_font_t * font,void * font_data,hb_codepoint_t gid,hb_paint_funcs_t * paint_funcs,void * paint_data,unsigned int palette_index,hb_color_t foreground,void * user_data)922*2d1272b8SAndroid Build Coastguard Worker hb_ft_paint_glyph (hb_font_t *font,
923*2d1272b8SAndroid Build Coastguard Worker void *font_data,
924*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid,
925*2d1272b8SAndroid Build Coastguard Worker hb_paint_funcs_t *paint_funcs, void *paint_data,
926*2d1272b8SAndroid Build Coastguard Worker unsigned int palette_index,
927*2d1272b8SAndroid Build Coastguard Worker hb_color_t foreground,
928*2d1272b8SAndroid Build Coastguard Worker void *user_data)
929*2d1272b8SAndroid Build Coastguard Worker {
930*2d1272b8SAndroid Build Coastguard Worker const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
931*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (ft_font->lock);
932*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
933*2d1272b8SAndroid Build Coastguard Worker
934*2d1272b8SAndroid Build Coastguard Worker /* We release the lock before calling into glyph callbacks, such that
935*2d1272b8SAndroid Build Coastguard Worker * eg. draw API can call back into the face.*/
936*2d1272b8SAndroid Build Coastguard Worker
937*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_Load_Glyph (ft_face, gid,
938*2d1272b8SAndroid Build Coastguard Worker ft_font->load_flags | FT_LOAD_COLOR)))
939*2d1272b8SAndroid Build Coastguard Worker return;
940*2d1272b8SAndroid Build Coastguard Worker
941*2d1272b8SAndroid Build Coastguard Worker if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
942*2d1272b8SAndroid Build Coastguard Worker {
943*2d1272b8SAndroid Build Coastguard Worker if (hb_ft_paint_glyph_colr (font, font_data, gid,
944*2d1272b8SAndroid Build Coastguard Worker paint_funcs, paint_data,
945*2d1272b8SAndroid Build Coastguard Worker palette_index, foreground,
946*2d1272b8SAndroid Build Coastguard Worker user_data))
947*2d1272b8SAndroid Build Coastguard Worker return;
948*2d1272b8SAndroid Build Coastguard Worker
949*2d1272b8SAndroid Build Coastguard Worker /* Simple outline. */
950*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.unlock ();
951*2d1272b8SAndroid Build Coastguard Worker paint_funcs->push_clip_glyph (paint_data, gid, font);
952*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.lock ();
953*2d1272b8SAndroid Build Coastguard Worker paint_funcs->color (paint_data, true, foreground);
954*2d1272b8SAndroid Build Coastguard Worker paint_funcs->pop_clip (paint_data);
955*2d1272b8SAndroid Build Coastguard Worker
956*2d1272b8SAndroid Build Coastguard Worker return;
957*2d1272b8SAndroid Build Coastguard Worker }
958*2d1272b8SAndroid Build Coastguard Worker
959*2d1272b8SAndroid Build Coastguard Worker auto *glyph = ft_face->glyph;
960*2d1272b8SAndroid Build Coastguard Worker if (glyph->format == FT_GLYPH_FORMAT_BITMAP)
961*2d1272b8SAndroid Build Coastguard Worker {
962*2d1272b8SAndroid Build Coastguard Worker auto &bitmap = glyph->bitmap;
963*2d1272b8SAndroid Build Coastguard Worker if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
964*2d1272b8SAndroid Build Coastguard Worker {
965*2d1272b8SAndroid Build Coastguard Worker if (bitmap.pitch != (signed) bitmap.width * 4)
966*2d1272b8SAndroid Build Coastguard Worker return;
967*2d1272b8SAndroid Build Coastguard Worker
968*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.unlock ();
969*2d1272b8SAndroid Build Coastguard Worker
970*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *blob = hb_blob_create ((const char *) bitmap.buffer,
971*2d1272b8SAndroid Build Coastguard Worker bitmap.pitch * bitmap.rows,
972*2d1272b8SAndroid Build Coastguard Worker HB_MEMORY_MODE_DUPLICATE,
973*2d1272b8SAndroid Build Coastguard Worker nullptr, nullptr);
974*2d1272b8SAndroid Build Coastguard Worker
975*2d1272b8SAndroid Build Coastguard Worker hb_glyph_extents_t extents;
976*2d1272b8SAndroid Build Coastguard Worker if (!hb_font_get_glyph_extents (font, gid, &extents))
977*2d1272b8SAndroid Build Coastguard Worker goto out;
978*2d1272b8SAndroid Build Coastguard Worker
979*2d1272b8SAndroid Build Coastguard Worker if (!paint_funcs->image (paint_data,
980*2d1272b8SAndroid Build Coastguard Worker blob,
981*2d1272b8SAndroid Build Coastguard Worker bitmap.width,
982*2d1272b8SAndroid Build Coastguard Worker bitmap.rows,
983*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_IMAGE_FORMAT_BGRA,
984*2d1272b8SAndroid Build Coastguard Worker font->slant_xy,
985*2d1272b8SAndroid Build Coastguard Worker &extents))
986*2d1272b8SAndroid Build Coastguard Worker {
987*2d1272b8SAndroid Build Coastguard Worker /* TODO Try a forced outline load and paint? */
988*2d1272b8SAndroid Build Coastguard Worker }
989*2d1272b8SAndroid Build Coastguard Worker
990*2d1272b8SAndroid Build Coastguard Worker out:
991*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (blob);
992*2d1272b8SAndroid Build Coastguard Worker ft_font->lock.lock ();
993*2d1272b8SAndroid Build Coastguard Worker }
994*2d1272b8SAndroid Build Coastguard Worker
995*2d1272b8SAndroid Build Coastguard Worker return;
996*2d1272b8SAndroid Build Coastguard Worker }
997*2d1272b8SAndroid Build Coastguard Worker }
998*2d1272b8SAndroid Build Coastguard Worker #endif
999*2d1272b8SAndroid Build Coastguard Worker #endif
1000*2d1272b8SAndroid Build Coastguard Worker
1001*2d1272b8SAndroid Build Coastguard Worker
1002*2d1272b8SAndroid Build Coastguard Worker static inline void free_static_ft_funcs ();
1003*2d1272b8SAndroid Build Coastguard Worker
1004*2d1272b8SAndroid Build Coastguard Worker static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
1005*2d1272b8SAndroid Build Coastguard Worker {
createhb_ft_font_funcs_lazy_loader_t1006*2d1272b8SAndroid Build Coastguard Worker static hb_font_funcs_t *create ()
1007*2d1272b8SAndroid Build Coastguard Worker {
1008*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_t *funcs = hb_font_funcs_create ();
1009*2d1272b8SAndroid Build Coastguard Worker
1010*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
1011*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
1012*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
1013*2d1272b8SAndroid Build Coastguard Worker
1014*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
1015*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
1016*2d1272b8SAndroid Build Coastguard Worker //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
1017*2d1272b8SAndroid Build Coastguard Worker
1018*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
1019*2d1272b8SAndroid Build Coastguard Worker //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
1020*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
1021*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
1022*2d1272b8SAndroid Build Coastguard Worker #endif
1023*2d1272b8SAndroid Build Coastguard Worker
1024*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_SHAPE_FALLBACK
1025*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
1026*2d1272b8SAndroid Build Coastguard Worker #endif
1027*2d1272b8SAndroid Build Coastguard Worker //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
1028*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
1029*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
1030*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
1031*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
1032*2d1272b8SAndroid Build Coastguard Worker
1033*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_DRAW
1034*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_draw_glyph_func (funcs, hb_ft_draw_glyph, nullptr, nullptr);
1035*2d1272b8SAndroid Build Coastguard Worker #endif
1036*2d1272b8SAndroid Build Coastguard Worker
1037*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_PAINT
1038*2d1272b8SAndroid Build Coastguard Worker #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
1039*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr);
1040*2d1272b8SAndroid Build Coastguard Worker #endif
1041*2d1272b8SAndroid Build Coastguard Worker #endif
1042*2d1272b8SAndroid Build Coastguard Worker
1043*2d1272b8SAndroid Build Coastguard Worker hb_font_funcs_make_immutable (funcs);
1044*2d1272b8SAndroid Build Coastguard Worker
1045*2d1272b8SAndroid Build Coastguard Worker hb_atexit (free_static_ft_funcs);
1046*2d1272b8SAndroid Build Coastguard Worker
1047*2d1272b8SAndroid Build Coastguard Worker return funcs;
1048*2d1272b8SAndroid Build Coastguard Worker }
1049*2d1272b8SAndroid Build Coastguard Worker } static_ft_funcs;
1050*2d1272b8SAndroid Build Coastguard Worker
1051*2d1272b8SAndroid Build Coastguard Worker static inline
free_static_ft_funcs()1052*2d1272b8SAndroid Build Coastguard Worker void free_static_ft_funcs ()
1053*2d1272b8SAndroid Build Coastguard Worker {
1054*2d1272b8SAndroid Build Coastguard Worker static_ft_funcs.free_instance ();
1055*2d1272b8SAndroid Build Coastguard Worker }
1056*2d1272b8SAndroid Build Coastguard Worker
1057*2d1272b8SAndroid Build Coastguard Worker static hb_font_funcs_t *
_hb_ft_get_font_funcs()1058*2d1272b8SAndroid Build Coastguard Worker _hb_ft_get_font_funcs ()
1059*2d1272b8SAndroid Build Coastguard Worker {
1060*2d1272b8SAndroid Build Coastguard Worker return static_ft_funcs.get_unconst ();
1061*2d1272b8SAndroid Build Coastguard Worker }
1062*2d1272b8SAndroid Build Coastguard Worker
1063*2d1272b8SAndroid Build Coastguard Worker static void
_hb_ft_font_set_funcs(hb_font_t * font,FT_Face ft_face,bool unref)1064*2d1272b8SAndroid Build Coastguard Worker _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
1065*2d1272b8SAndroid Build Coastguard Worker {
1066*2d1272b8SAndroid Build Coastguard Worker bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
1067*2d1272b8SAndroid Build Coastguard Worker
1068*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_t *ft_font = _hb_ft_font_create (ft_face, symbol, unref);
1069*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!ft_font)) return;
1070*2d1272b8SAndroid Build Coastguard Worker
1071*2d1272b8SAndroid Build Coastguard Worker hb_font_set_funcs (font,
1072*2d1272b8SAndroid Build Coastguard Worker _hb_ft_get_font_funcs (),
1073*2d1272b8SAndroid Build Coastguard Worker ft_font,
1074*2d1272b8SAndroid Build Coastguard Worker _hb_ft_font_destroy);
1075*2d1272b8SAndroid Build Coastguard Worker }
1076*2d1272b8SAndroid Build Coastguard Worker
1077*2d1272b8SAndroid Build Coastguard Worker
1078*2d1272b8SAndroid Build Coastguard Worker static hb_blob_t *
_hb_ft_reference_table(hb_face_t * face HB_UNUSED,hb_tag_t tag,void * user_data)1079*2d1272b8SAndroid Build Coastguard Worker _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
1080*2d1272b8SAndroid Build Coastguard Worker {
1081*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = (FT_Face) user_data;
1082*2d1272b8SAndroid Build Coastguard Worker FT_Byte *buffer;
1083*2d1272b8SAndroid Build Coastguard Worker FT_ULong length = 0;
1084*2d1272b8SAndroid Build Coastguard Worker FT_Error error;
1085*2d1272b8SAndroid Build Coastguard Worker
1086*2d1272b8SAndroid Build Coastguard Worker /* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */
1087*2d1272b8SAndroid Build Coastguard Worker
1088*2d1272b8SAndroid Build Coastguard Worker error = FT_Load_Sfnt_Table (ft_face, tag, 0, nullptr, &length);
1089*2d1272b8SAndroid Build Coastguard Worker if (error)
1090*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1091*2d1272b8SAndroid Build Coastguard Worker
1092*2d1272b8SAndroid Build Coastguard Worker buffer = (FT_Byte *) hb_malloc (length);
1093*2d1272b8SAndroid Build Coastguard Worker if (!buffer)
1094*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1095*2d1272b8SAndroid Build Coastguard Worker
1096*2d1272b8SAndroid Build Coastguard Worker error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
1097*2d1272b8SAndroid Build Coastguard Worker if (error)
1098*2d1272b8SAndroid Build Coastguard Worker {
1099*2d1272b8SAndroid Build Coastguard Worker hb_free (buffer);
1100*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1101*2d1272b8SAndroid Build Coastguard Worker }
1102*2d1272b8SAndroid Build Coastguard Worker
1103*2d1272b8SAndroid Build Coastguard Worker return hb_blob_create ((const char *) buffer, length,
1104*2d1272b8SAndroid Build Coastguard Worker HB_MEMORY_MODE_WRITABLE,
1105*2d1272b8SAndroid Build Coastguard Worker buffer, hb_free);
1106*2d1272b8SAndroid Build Coastguard Worker }
1107*2d1272b8SAndroid Build Coastguard Worker
1108*2d1272b8SAndroid Build Coastguard Worker static unsigned
_hb_ft_get_table_tags(const hb_face_t * face HB_UNUSED,unsigned int start_offset,unsigned int * table_count,hb_tag_t * table_tags,void * user_data)1109*2d1272b8SAndroid Build Coastguard Worker _hb_ft_get_table_tags (const hb_face_t *face HB_UNUSED,
1110*2d1272b8SAndroid Build Coastguard Worker unsigned int start_offset,
1111*2d1272b8SAndroid Build Coastguard Worker unsigned int *table_count,
1112*2d1272b8SAndroid Build Coastguard Worker hb_tag_t *table_tags,
1113*2d1272b8SAndroid Build Coastguard Worker void *user_data)
1114*2d1272b8SAndroid Build Coastguard Worker {
1115*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = (FT_Face) user_data;
1116*2d1272b8SAndroid Build Coastguard Worker
1117*2d1272b8SAndroid Build Coastguard Worker FT_ULong population = 0;
1118*2d1272b8SAndroid Build Coastguard Worker FT_Sfnt_Table_Info (ft_face,
1119*2d1272b8SAndroid Build Coastguard Worker 0, // table_index; ignored
1120*2d1272b8SAndroid Build Coastguard Worker nullptr,
1121*2d1272b8SAndroid Build Coastguard Worker &population);
1122*2d1272b8SAndroid Build Coastguard Worker
1123*2d1272b8SAndroid Build Coastguard Worker if (!table_count)
1124*2d1272b8SAndroid Build Coastguard Worker return population;
1125*2d1272b8SAndroid Build Coastguard Worker else
1126*2d1272b8SAndroid Build Coastguard Worker *table_count = 0;
1127*2d1272b8SAndroid Build Coastguard Worker
1128*2d1272b8SAndroid Build Coastguard Worker if (unlikely (start_offset >= population))
1129*2d1272b8SAndroid Build Coastguard Worker return population;
1130*2d1272b8SAndroid Build Coastguard Worker
1131*2d1272b8SAndroid Build Coastguard Worker unsigned end_offset = hb_min (start_offset + *table_count, (unsigned) population);
1132*2d1272b8SAndroid Build Coastguard Worker if (unlikely (end_offset < start_offset))
1133*2d1272b8SAndroid Build Coastguard Worker return population;
1134*2d1272b8SAndroid Build Coastguard Worker
1135*2d1272b8SAndroid Build Coastguard Worker *table_count = end_offset - start_offset;
1136*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = start_offset; i < end_offset; i++)
1137*2d1272b8SAndroid Build Coastguard Worker {
1138*2d1272b8SAndroid Build Coastguard Worker FT_ULong tag = 0, length;
1139*2d1272b8SAndroid Build Coastguard Worker FT_Sfnt_Table_Info (ft_face, i, &tag, &length);
1140*2d1272b8SAndroid Build Coastguard Worker table_tags[i - start_offset] = tag;
1141*2d1272b8SAndroid Build Coastguard Worker }
1142*2d1272b8SAndroid Build Coastguard Worker
1143*2d1272b8SAndroid Build Coastguard Worker return population;
1144*2d1272b8SAndroid Build Coastguard Worker }
1145*2d1272b8SAndroid Build Coastguard Worker
1146*2d1272b8SAndroid Build Coastguard Worker
1147*2d1272b8SAndroid Build Coastguard Worker /**
1148*2d1272b8SAndroid Build Coastguard Worker * hb_ft_face_create:
1149*2d1272b8SAndroid Build Coastguard Worker * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
1150*2d1272b8SAndroid Build Coastguard Worker * @destroy: (nullable): A callback to call when the face object is not needed anymore
1151*2d1272b8SAndroid Build Coastguard Worker *
1152*2d1272b8SAndroid Build Coastguard Worker * Creates an #hb_face_t face object from the specified FT_Face.
1153*2d1272b8SAndroid Build Coastguard Worker *
1154*2d1272b8SAndroid Build Coastguard Worker * Note that this is using the FT_Face object just to get at the underlying
1155*2d1272b8SAndroid Build Coastguard Worker * font data, and fonts created from the returned #hb_face_t will use the native
1156*2d1272b8SAndroid Build Coastguard Worker * HarfBuzz font implementation, unless you call hb_ft_font_set_funcs() on them.
1157*2d1272b8SAndroid Build Coastguard Worker *
1158*2d1272b8SAndroid Build Coastguard Worker * This variant of the function does not provide any life-cycle management.
1159*2d1272b8SAndroid Build Coastguard Worker *
1160*2d1272b8SAndroid Build Coastguard Worker * Most client programs should use hb_ft_face_create_referenced()
1161*2d1272b8SAndroid Build Coastguard Worker * (or, perhaps, hb_ft_face_create_cached()) instead.
1162*2d1272b8SAndroid Build Coastguard Worker *
1163*2d1272b8SAndroid Build Coastguard Worker * If you know you have valid reasons not to use hb_ft_face_create_referenced(),
1164*2d1272b8SAndroid Build Coastguard Worker * then it is the client program's responsibility to destroy @ft_face
1165*2d1272b8SAndroid Build Coastguard Worker * after the #hb_face_t face object has been destroyed.
1166*2d1272b8SAndroid Build Coastguard Worker *
1167*2d1272b8SAndroid Build Coastguard Worker * Return value: (transfer full): the new #hb_face_t face object
1168*2d1272b8SAndroid Build Coastguard Worker *
1169*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.2
1170*2d1272b8SAndroid Build Coastguard Worker **/
1171*2d1272b8SAndroid Build Coastguard Worker hb_face_t *
hb_ft_face_create(FT_Face ft_face,hb_destroy_func_t destroy)1172*2d1272b8SAndroid Build Coastguard Worker hb_ft_face_create (FT_Face ft_face,
1173*2d1272b8SAndroid Build Coastguard Worker hb_destroy_func_t destroy)
1174*2d1272b8SAndroid Build Coastguard Worker {
1175*2d1272b8SAndroid Build Coastguard Worker hb_face_t *face;
1176*2d1272b8SAndroid Build Coastguard Worker
1177*2d1272b8SAndroid Build Coastguard Worker if (!ft_face->stream->read) {
1178*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *blob;
1179*2d1272b8SAndroid Build Coastguard Worker
1180*2d1272b8SAndroid Build Coastguard Worker blob = hb_blob_create ((const char *) ft_face->stream->base,
1181*2d1272b8SAndroid Build Coastguard Worker (unsigned int) ft_face->stream->size,
1182*2d1272b8SAndroid Build Coastguard Worker HB_MEMORY_MODE_READONLY,
1183*2d1272b8SAndroid Build Coastguard Worker ft_face, destroy);
1184*2d1272b8SAndroid Build Coastguard Worker face = hb_face_create (blob, ft_face->face_index);
1185*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (blob);
1186*2d1272b8SAndroid Build Coastguard Worker } else {
1187*2d1272b8SAndroid Build Coastguard Worker face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy);
1188*2d1272b8SAndroid Build Coastguard Worker hb_face_set_get_table_tags_func (face, _hb_ft_get_table_tags, ft_face, nullptr);
1189*2d1272b8SAndroid Build Coastguard Worker }
1190*2d1272b8SAndroid Build Coastguard Worker
1191*2d1272b8SAndroid Build Coastguard Worker hb_face_set_index (face, ft_face->face_index);
1192*2d1272b8SAndroid Build Coastguard Worker hb_face_set_upem (face, ft_face->units_per_EM);
1193*2d1272b8SAndroid Build Coastguard Worker
1194*2d1272b8SAndroid Build Coastguard Worker return face;
1195*2d1272b8SAndroid Build Coastguard Worker }
1196*2d1272b8SAndroid Build Coastguard Worker
1197*2d1272b8SAndroid Build Coastguard Worker /**
1198*2d1272b8SAndroid Build Coastguard Worker * hb_ft_face_create_referenced:
1199*2d1272b8SAndroid Build Coastguard Worker * @ft_face: FT_Face to work upon
1200*2d1272b8SAndroid Build Coastguard Worker *
1201*2d1272b8SAndroid Build Coastguard Worker * Creates an #hb_face_t face object from the specified FT_Face.
1202*2d1272b8SAndroid Build Coastguard Worker *
1203*2d1272b8SAndroid Build Coastguard Worker * Note that this is using the FT_Face object just to get at the underlying
1204*2d1272b8SAndroid Build Coastguard Worker * font data, and fonts created from the returned #hb_face_t will use the native
1205*2d1272b8SAndroid Build Coastguard Worker * HarfBuzz font implementation, unless you call hb_ft_font_set_funcs() on them.
1206*2d1272b8SAndroid Build Coastguard Worker *
1207*2d1272b8SAndroid Build Coastguard Worker * This is the preferred variant of the hb_ft_face_create*
1208*2d1272b8SAndroid Build Coastguard Worker * function family, because it calls FT_Reference_Face() on @ft_face,
1209*2d1272b8SAndroid Build Coastguard Worker * ensuring that @ft_face remains alive as long as the resulting
1210*2d1272b8SAndroid Build Coastguard Worker * #hb_face_t face object remains alive. Also calls FT_Done_Face()
1211*2d1272b8SAndroid Build Coastguard Worker * when the #hb_face_t face object is destroyed.
1212*2d1272b8SAndroid Build Coastguard Worker *
1213*2d1272b8SAndroid Build Coastguard Worker * Use this version unless you know you have good reasons not to.
1214*2d1272b8SAndroid Build Coastguard Worker *
1215*2d1272b8SAndroid Build Coastguard Worker * Return value: (transfer full): the new #hb_face_t face object
1216*2d1272b8SAndroid Build Coastguard Worker *
1217*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.38
1218*2d1272b8SAndroid Build Coastguard Worker **/
1219*2d1272b8SAndroid Build Coastguard Worker hb_face_t *
hb_ft_face_create_referenced(FT_Face ft_face)1220*2d1272b8SAndroid Build Coastguard Worker hb_ft_face_create_referenced (FT_Face ft_face)
1221*2d1272b8SAndroid Build Coastguard Worker {
1222*2d1272b8SAndroid Build Coastguard Worker FT_Reference_Face (ft_face);
1223*2d1272b8SAndroid Build Coastguard Worker return hb_ft_face_create (ft_face, _hb_ft_face_destroy);
1224*2d1272b8SAndroid Build Coastguard Worker }
1225*2d1272b8SAndroid Build Coastguard Worker
1226*2d1272b8SAndroid Build Coastguard Worker static void
hb_ft_face_finalize(void * arg)1227*2d1272b8SAndroid Build Coastguard Worker hb_ft_face_finalize (void *arg)
1228*2d1272b8SAndroid Build Coastguard Worker {
1229*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = (FT_Face) arg;
1230*2d1272b8SAndroid Build Coastguard Worker hb_face_destroy ((hb_face_t *) ft_face->generic.data);
1231*2d1272b8SAndroid Build Coastguard Worker }
1232*2d1272b8SAndroid Build Coastguard Worker
1233*2d1272b8SAndroid Build Coastguard Worker /**
1234*2d1272b8SAndroid Build Coastguard Worker * hb_ft_face_create_cached:
1235*2d1272b8SAndroid Build Coastguard Worker * @ft_face: FT_Face to work upon
1236*2d1272b8SAndroid Build Coastguard Worker *
1237*2d1272b8SAndroid Build Coastguard Worker * Creates an #hb_face_t face object from the specified FT_Face.
1238*2d1272b8SAndroid Build Coastguard Worker *
1239*2d1272b8SAndroid Build Coastguard Worker * Note that this is using the FT_Face object just to get at the underlying
1240*2d1272b8SAndroid Build Coastguard Worker * font data, and fonts created from the returned #hb_face_t will use the native
1241*2d1272b8SAndroid Build Coastguard Worker * HarfBuzz font implementation, unless you call hb_ft_font_set_funcs() on them.
1242*2d1272b8SAndroid Build Coastguard Worker *
1243*2d1272b8SAndroid Build Coastguard Worker * This variant of the function caches the newly created #hb_face_t
1244*2d1272b8SAndroid Build Coastguard Worker * face object, using the @generic pointer of @ft_face. Subsequent function
1245*2d1272b8SAndroid Build Coastguard Worker * calls that are passed the same @ft_face parameter will have the same
1246*2d1272b8SAndroid Build Coastguard Worker * #hb_face_t returned to them, and that #hb_face_t will be correctly
1247*2d1272b8SAndroid Build Coastguard Worker * reference counted.
1248*2d1272b8SAndroid Build Coastguard Worker *
1249*2d1272b8SAndroid Build Coastguard Worker * However, client programs are still responsible for destroying
1250*2d1272b8SAndroid Build Coastguard Worker * @ft_face after the last #hb_face_t face object has been destroyed.
1251*2d1272b8SAndroid Build Coastguard Worker *
1252*2d1272b8SAndroid Build Coastguard Worker * Return value: (transfer full): the new #hb_face_t face object
1253*2d1272b8SAndroid Build Coastguard Worker *
1254*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.2
1255*2d1272b8SAndroid Build Coastguard Worker **/
1256*2d1272b8SAndroid Build Coastguard Worker hb_face_t *
hb_ft_face_create_cached(FT_Face ft_face)1257*2d1272b8SAndroid Build Coastguard Worker hb_ft_face_create_cached (FT_Face ft_face)
1258*2d1272b8SAndroid Build Coastguard Worker {
1259*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != hb_ft_face_finalize))
1260*2d1272b8SAndroid Build Coastguard Worker {
1261*2d1272b8SAndroid Build Coastguard Worker if (ft_face->generic.finalizer)
1262*2d1272b8SAndroid Build Coastguard Worker ft_face->generic.finalizer (ft_face);
1263*2d1272b8SAndroid Build Coastguard Worker
1264*2d1272b8SAndroid Build Coastguard Worker ft_face->generic.data = hb_ft_face_create (ft_face, nullptr);
1265*2d1272b8SAndroid Build Coastguard Worker ft_face->generic.finalizer = hb_ft_face_finalize;
1266*2d1272b8SAndroid Build Coastguard Worker }
1267*2d1272b8SAndroid Build Coastguard Worker
1268*2d1272b8SAndroid Build Coastguard Worker return hb_face_reference ((hb_face_t *) ft_face->generic.data);
1269*2d1272b8SAndroid Build Coastguard Worker }
1270*2d1272b8SAndroid Build Coastguard Worker
1271*2d1272b8SAndroid Build Coastguard Worker /**
1272*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create:
1273*2d1272b8SAndroid Build Coastguard Worker * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
1274*2d1272b8SAndroid Build Coastguard Worker * @destroy: (nullable): A callback to call when the font object is not needed anymore
1275*2d1272b8SAndroid Build Coastguard Worker *
1276*2d1272b8SAndroid Build Coastguard Worker * Creates an #hb_font_t font object from the specified FT_Face.
1277*2d1272b8SAndroid Build Coastguard Worker *
1278*2d1272b8SAndroid Build Coastguard Worker * <note>Note: You must set the face size on @ft_face before calling
1279*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create() on it. HarfBuzz assumes size is always set and will
1280*2d1272b8SAndroid Build Coastguard Worker * access `size` member of FT_Face unconditionally.</note>
1281*2d1272b8SAndroid Build Coastguard Worker *
1282*2d1272b8SAndroid Build Coastguard Worker * This variant of the function does not provide any life-cycle management.
1283*2d1272b8SAndroid Build Coastguard Worker *
1284*2d1272b8SAndroid Build Coastguard Worker * Most client programs should use hb_ft_font_create_referenced()
1285*2d1272b8SAndroid Build Coastguard Worker * instead.
1286*2d1272b8SAndroid Build Coastguard Worker *
1287*2d1272b8SAndroid Build Coastguard Worker * If you know you have valid reasons not to use hb_ft_font_create_referenced(),
1288*2d1272b8SAndroid Build Coastguard Worker * then it is the client program's responsibility to destroy @ft_face
1289*2d1272b8SAndroid Build Coastguard Worker * after the #hb_font_t font object has been destroyed.
1290*2d1272b8SAndroid Build Coastguard Worker *
1291*2d1272b8SAndroid Build Coastguard Worker * HarfBuzz will use the @destroy callback on the #hb_font_t font object
1292*2d1272b8SAndroid Build Coastguard Worker * if it is supplied when you use this function. However, even if @destroy
1293*2d1272b8SAndroid Build Coastguard Worker * is provided, it is the client program's responsibility to destroy @ft_face,
1294*2d1272b8SAndroid Build Coastguard Worker * and it is the client program's responsibility to ensure that @ft_face is
1295*2d1272b8SAndroid Build Coastguard Worker * destroyed only after the #hb_font_t font object has been destroyed.
1296*2d1272b8SAndroid Build Coastguard Worker *
1297*2d1272b8SAndroid Build Coastguard Worker * Return value: (transfer full): the new #hb_font_t font object
1298*2d1272b8SAndroid Build Coastguard Worker *
1299*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.2
1300*2d1272b8SAndroid Build Coastguard Worker **/
1301*2d1272b8SAndroid Build Coastguard Worker hb_font_t *
hb_ft_font_create(FT_Face ft_face,hb_destroy_func_t destroy)1302*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_create (FT_Face ft_face,
1303*2d1272b8SAndroid Build Coastguard Worker hb_destroy_func_t destroy)
1304*2d1272b8SAndroid Build Coastguard Worker {
1305*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font;
1306*2d1272b8SAndroid Build Coastguard Worker hb_face_t *face;
1307*2d1272b8SAndroid Build Coastguard Worker
1308*2d1272b8SAndroid Build Coastguard Worker face = hb_ft_face_create (ft_face, destroy);
1309*2d1272b8SAndroid Build Coastguard Worker font = hb_font_create (face);
1310*2d1272b8SAndroid Build Coastguard Worker hb_face_destroy (face);
1311*2d1272b8SAndroid Build Coastguard Worker _hb_ft_font_set_funcs (font, ft_face, false);
1312*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_changed (font);
1313*2d1272b8SAndroid Build Coastguard Worker return font;
1314*2d1272b8SAndroid Build Coastguard Worker }
1315*2d1272b8SAndroid Build Coastguard Worker
1316*2d1272b8SAndroid Build Coastguard Worker /**
1317*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_changed:
1318*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
1319*2d1272b8SAndroid Build Coastguard Worker *
1320*2d1272b8SAndroid Build Coastguard Worker * Refreshes the state of @font when the underlying FT_Face has changed.
1321*2d1272b8SAndroid Build Coastguard Worker * This function should be called after changing the size or
1322*2d1272b8SAndroid Build Coastguard Worker * variation-axis settings on the FT_Face.
1323*2d1272b8SAndroid Build Coastguard Worker *
1324*2d1272b8SAndroid Build Coastguard Worker * Since: 1.0.5
1325*2d1272b8SAndroid Build Coastguard Worker **/
1326*2d1272b8SAndroid Build Coastguard Worker void
hb_ft_font_changed(hb_font_t * font)1327*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_changed (hb_font_t *font)
1328*2d1272b8SAndroid Build Coastguard Worker {
1329*2d1272b8SAndroid Build Coastguard Worker if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
1330*2d1272b8SAndroid Build Coastguard Worker return;
1331*2d1272b8SAndroid Build Coastguard Worker
1332*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
1333*2d1272b8SAndroid Build Coastguard Worker
1334*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = ft_font->ft_face;
1335*2d1272b8SAndroid Build Coastguard Worker
1336*2d1272b8SAndroid Build Coastguard Worker hb_font_set_scale (font,
1337*2d1272b8SAndroid Build Coastguard Worker (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16),
1338*2d1272b8SAndroid Build Coastguard Worker (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16));
1339*2d1272b8SAndroid Build Coastguard Worker #if 0 /* hb-ft works in no-hinting model */
1340*2d1272b8SAndroid Build Coastguard Worker hb_font_set_ppem (font,
1341*2d1272b8SAndroid Build Coastguard Worker ft_face->size->metrics.x_ppem,
1342*2d1272b8SAndroid Build Coastguard Worker ft_face->size->metrics.y_ppem);
1343*2d1272b8SAndroid Build Coastguard Worker #endif
1344*2d1272b8SAndroid Build Coastguard Worker
1345*2d1272b8SAndroid Build Coastguard Worker #if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
1346*2d1272b8SAndroid Build Coastguard Worker FT_MM_Var *mm_var = nullptr;
1347*2d1272b8SAndroid Build Coastguard Worker if (!FT_Get_MM_Var (ft_face, &mm_var))
1348*2d1272b8SAndroid Build Coastguard Worker {
1349*2d1272b8SAndroid Build Coastguard Worker FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (mm_var->num_axis, sizeof (FT_Fixed));
1350*2d1272b8SAndroid Build Coastguard Worker int *coords = (int *) hb_calloc (mm_var->num_axis, sizeof (int));
1351*2d1272b8SAndroid Build Coastguard Worker if (coords && ft_coords)
1352*2d1272b8SAndroid Build Coastguard Worker {
1353*2d1272b8SAndroid Build Coastguard Worker if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
1354*2d1272b8SAndroid Build Coastguard Worker {
1355*2d1272b8SAndroid Build Coastguard Worker bool nonzero = false;
1356*2d1272b8SAndroid Build Coastguard Worker
1357*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < mm_var->num_axis; ++i)
1358*2d1272b8SAndroid Build Coastguard Worker {
1359*2d1272b8SAndroid Build Coastguard Worker coords[i] = ft_coords[i] >>= 2;
1360*2d1272b8SAndroid Build Coastguard Worker nonzero = nonzero || coords[i];
1361*2d1272b8SAndroid Build Coastguard Worker }
1362*2d1272b8SAndroid Build Coastguard Worker
1363*2d1272b8SAndroid Build Coastguard Worker if (nonzero)
1364*2d1272b8SAndroid Build Coastguard Worker hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis);
1365*2d1272b8SAndroid Build Coastguard Worker else
1366*2d1272b8SAndroid Build Coastguard Worker hb_font_set_var_coords_normalized (font, nullptr, 0);
1367*2d1272b8SAndroid Build Coastguard Worker }
1368*2d1272b8SAndroid Build Coastguard Worker }
1369*2d1272b8SAndroid Build Coastguard Worker hb_free (coords);
1370*2d1272b8SAndroid Build Coastguard Worker hb_free (ft_coords);
1371*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_FT_DONE_MM_VAR
1372*2d1272b8SAndroid Build Coastguard Worker FT_Done_MM_Var (ft_face->glyph->library, mm_var);
1373*2d1272b8SAndroid Build Coastguard Worker #else
1374*2d1272b8SAndroid Build Coastguard Worker hb_free (mm_var);
1375*2d1272b8SAndroid Build Coastguard Worker #endif
1376*2d1272b8SAndroid Build Coastguard Worker }
1377*2d1272b8SAndroid Build Coastguard Worker #endif
1378*2d1272b8SAndroid Build Coastguard Worker
1379*2d1272b8SAndroid Build Coastguard Worker ft_font->advance_cache.clear ();
1380*2d1272b8SAndroid Build Coastguard Worker ft_font->cached_serial = font->serial;
1381*2d1272b8SAndroid Build Coastguard Worker }
1382*2d1272b8SAndroid Build Coastguard Worker
1383*2d1272b8SAndroid Build Coastguard Worker /**
1384*2d1272b8SAndroid Build Coastguard Worker * hb_ft_hb_font_changed:
1385*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
1386*2d1272b8SAndroid Build Coastguard Worker *
1387*2d1272b8SAndroid Build Coastguard Worker * Refreshes the state of the underlying FT_Face of @font when the hb_font_t
1388*2d1272b8SAndroid Build Coastguard Worker * @font has changed.
1389*2d1272b8SAndroid Build Coastguard Worker * This function should be called after changing the size or
1390*2d1272b8SAndroid Build Coastguard Worker * variation-axis settings on the @font.
1391*2d1272b8SAndroid Build Coastguard Worker * This call is fast if nothing has changed on @font.
1392*2d1272b8SAndroid Build Coastguard Worker *
1393*2d1272b8SAndroid Build Coastguard Worker * Return value: true if changed, false otherwise
1394*2d1272b8SAndroid Build Coastguard Worker *
1395*2d1272b8SAndroid Build Coastguard Worker * Since: 4.4.0
1396*2d1272b8SAndroid Build Coastguard Worker **/
1397*2d1272b8SAndroid Build Coastguard Worker hb_bool_t
hb_ft_hb_font_changed(hb_font_t * font)1398*2d1272b8SAndroid Build Coastguard Worker hb_ft_hb_font_changed (hb_font_t *font)
1399*2d1272b8SAndroid Build Coastguard Worker {
1400*2d1272b8SAndroid Build Coastguard Worker if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
1401*2d1272b8SAndroid Build Coastguard Worker return false;
1402*2d1272b8SAndroid Build Coastguard Worker
1403*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
1404*2d1272b8SAndroid Build Coastguard Worker
1405*2d1272b8SAndroid Build Coastguard Worker return _hb_ft_hb_font_check_changed (font, ft_font);
1406*2d1272b8SAndroid Build Coastguard Worker }
1407*2d1272b8SAndroid Build Coastguard Worker
1408*2d1272b8SAndroid Build Coastguard Worker /**
1409*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create_referenced:
1410*2d1272b8SAndroid Build Coastguard Worker * @ft_face: FT_Face to work upon
1411*2d1272b8SAndroid Build Coastguard Worker *
1412*2d1272b8SAndroid Build Coastguard Worker * Creates an #hb_font_t font object from the specified FT_Face.
1413*2d1272b8SAndroid Build Coastguard Worker *
1414*2d1272b8SAndroid Build Coastguard Worker * <note>Note: You must set the face size on @ft_face before calling
1415*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_create_referenced() on it. HarfBuzz assumes size is always set
1416*2d1272b8SAndroid Build Coastguard Worker * and will access `size` member of FT_Face unconditionally.</note>
1417*2d1272b8SAndroid Build Coastguard Worker *
1418*2d1272b8SAndroid Build Coastguard Worker * This is the preferred variant of the hb_ft_font_create*
1419*2d1272b8SAndroid Build Coastguard Worker * function family, because it calls FT_Reference_Face() on @ft_face,
1420*2d1272b8SAndroid Build Coastguard Worker * ensuring that @ft_face remains alive as long as the resulting
1421*2d1272b8SAndroid Build Coastguard Worker * #hb_font_t font object remains alive.
1422*2d1272b8SAndroid Build Coastguard Worker *
1423*2d1272b8SAndroid Build Coastguard Worker * Use this version unless you know you have good reasons not to.
1424*2d1272b8SAndroid Build Coastguard Worker *
1425*2d1272b8SAndroid Build Coastguard Worker * Return value: (transfer full): the new #hb_font_t font object
1426*2d1272b8SAndroid Build Coastguard Worker *
1427*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.38
1428*2d1272b8SAndroid Build Coastguard Worker **/
1429*2d1272b8SAndroid Build Coastguard Worker hb_font_t *
hb_ft_font_create_referenced(FT_Face ft_face)1430*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_create_referenced (FT_Face ft_face)
1431*2d1272b8SAndroid Build Coastguard Worker {
1432*2d1272b8SAndroid Build Coastguard Worker FT_Reference_Face (ft_face);
1433*2d1272b8SAndroid Build Coastguard Worker return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
1434*2d1272b8SAndroid Build Coastguard Worker }
1435*2d1272b8SAndroid Build Coastguard Worker
1436*2d1272b8SAndroid Build Coastguard Worker
_hb_ft_alloc(FT_Memory memory,long size)1437*2d1272b8SAndroid Build Coastguard Worker static void * _hb_ft_alloc (FT_Memory memory, long size)
1438*2d1272b8SAndroid Build Coastguard Worker { return hb_malloc (size); }
1439*2d1272b8SAndroid Build Coastguard Worker
_hb_ft_free(FT_Memory memory,void * block)1440*2d1272b8SAndroid Build Coastguard Worker static void _hb_ft_free (FT_Memory memory, void *block)
1441*2d1272b8SAndroid Build Coastguard Worker { hb_free (block); }
1442*2d1272b8SAndroid Build Coastguard Worker
_hb_ft_realloc(FT_Memory memory,long cur_size,long new_size,void * block)1443*2d1272b8SAndroid Build Coastguard Worker static void * _hb_ft_realloc (FT_Memory memory, long cur_size, long new_size, void *block)
1444*2d1272b8SAndroid Build Coastguard Worker { return hb_realloc (block, new_size); }
1445*2d1272b8SAndroid Build Coastguard Worker
1446*2d1272b8SAndroid Build Coastguard Worker static FT_MemoryRec_ m =
1447*2d1272b8SAndroid Build Coastguard Worker {
1448*2d1272b8SAndroid Build Coastguard Worker nullptr,
1449*2d1272b8SAndroid Build Coastguard Worker _hb_ft_alloc,
1450*2d1272b8SAndroid Build Coastguard Worker _hb_ft_free,
1451*2d1272b8SAndroid Build Coastguard Worker _hb_ft_realloc
1452*2d1272b8SAndroid Build Coastguard Worker };
1453*2d1272b8SAndroid Build Coastguard Worker
1454*2d1272b8SAndroid Build Coastguard Worker static inline void free_static_ft_library ();
1455*2d1272b8SAndroid Build Coastguard Worker
1456*2d1272b8SAndroid Build Coastguard Worker static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>,
1457*2d1272b8SAndroid Build Coastguard Worker hb_ft_library_lazy_loader_t>
1458*2d1272b8SAndroid Build Coastguard Worker {
createhb_ft_library_lazy_loader_t1459*2d1272b8SAndroid Build Coastguard Worker static FT_Library create ()
1460*2d1272b8SAndroid Build Coastguard Worker {
1461*2d1272b8SAndroid Build Coastguard Worker FT_Library l;
1462*2d1272b8SAndroid Build Coastguard Worker if (FT_New_Library (&m, &l))
1463*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1464*2d1272b8SAndroid Build Coastguard Worker
1465*2d1272b8SAndroid Build Coastguard Worker FT_Add_Default_Modules (l);
1466*2d1272b8SAndroid Build Coastguard Worker FT_Set_Default_Properties (l);
1467*2d1272b8SAndroid Build Coastguard Worker
1468*2d1272b8SAndroid Build Coastguard Worker hb_atexit (free_static_ft_library);
1469*2d1272b8SAndroid Build Coastguard Worker
1470*2d1272b8SAndroid Build Coastguard Worker return l;
1471*2d1272b8SAndroid Build Coastguard Worker }
destroyhb_ft_library_lazy_loader_t1472*2d1272b8SAndroid Build Coastguard Worker static void destroy (FT_Library l)
1473*2d1272b8SAndroid Build Coastguard Worker {
1474*2d1272b8SAndroid Build Coastguard Worker FT_Done_Library (l);
1475*2d1272b8SAndroid Build Coastguard Worker }
get_nullhb_ft_library_lazy_loader_t1476*2d1272b8SAndroid Build Coastguard Worker static FT_Library get_null ()
1477*2d1272b8SAndroid Build Coastguard Worker {
1478*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1479*2d1272b8SAndroid Build Coastguard Worker }
1480*2d1272b8SAndroid Build Coastguard Worker } static_ft_library;
1481*2d1272b8SAndroid Build Coastguard Worker
1482*2d1272b8SAndroid Build Coastguard Worker static inline
free_static_ft_library()1483*2d1272b8SAndroid Build Coastguard Worker void free_static_ft_library ()
1484*2d1272b8SAndroid Build Coastguard Worker {
1485*2d1272b8SAndroid Build Coastguard Worker static_ft_library.free_instance ();
1486*2d1272b8SAndroid Build Coastguard Worker }
1487*2d1272b8SAndroid Build Coastguard Worker
1488*2d1272b8SAndroid Build Coastguard Worker static FT_Library
reference_ft_library()1489*2d1272b8SAndroid Build Coastguard Worker reference_ft_library ()
1490*2d1272b8SAndroid Build Coastguard Worker {
1491*2d1272b8SAndroid Build Coastguard Worker FT_Library l = static_ft_library.get_unconst ();
1492*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_Reference_Library (l)))
1493*2d1272b8SAndroid Build Coastguard Worker {
1494*2d1272b8SAndroid Build Coastguard Worker DEBUG_MSG (FT, l, "FT_Reference_Library() failed");
1495*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1496*2d1272b8SAndroid Build Coastguard Worker }
1497*2d1272b8SAndroid Build Coastguard Worker return l;
1498*2d1272b8SAndroid Build Coastguard Worker }
1499*2d1272b8SAndroid Build Coastguard Worker
1500*2d1272b8SAndroid Build Coastguard Worker static hb_user_data_key_t ft_library_key = {0};
1501*2d1272b8SAndroid Build Coastguard Worker
1502*2d1272b8SAndroid Build Coastguard Worker static void
finalize_ft_library(void * arg)1503*2d1272b8SAndroid Build Coastguard Worker finalize_ft_library (void *arg)
1504*2d1272b8SAndroid Build Coastguard Worker {
1505*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = (FT_Face) arg;
1506*2d1272b8SAndroid Build Coastguard Worker FT_Done_Library ((FT_Library) ft_face->generic.data);
1507*2d1272b8SAndroid Build Coastguard Worker }
1508*2d1272b8SAndroid Build Coastguard Worker
1509*2d1272b8SAndroid Build Coastguard Worker static void
destroy_ft_library(void * arg)1510*2d1272b8SAndroid Build Coastguard Worker destroy_ft_library (void *arg)
1511*2d1272b8SAndroid Build Coastguard Worker {
1512*2d1272b8SAndroid Build Coastguard Worker FT_Done_Library ((FT_Library) arg);
1513*2d1272b8SAndroid Build Coastguard Worker }
1514*2d1272b8SAndroid Build Coastguard Worker
1515*2d1272b8SAndroid Build Coastguard Worker /**
1516*2d1272b8SAndroid Build Coastguard Worker * hb_ft_face_create_from_file_or_fail:
1517*2d1272b8SAndroid Build Coastguard Worker * @file_name: A font filename
1518*2d1272b8SAndroid Build Coastguard Worker * @index: The index of the face within the file
1519*2d1272b8SAndroid Build Coastguard Worker *
1520*2d1272b8SAndroid Build Coastguard Worker * Creates an #hb_face_t face object from the specified
1521*2d1272b8SAndroid Build Coastguard Worker * font file and face index.
1522*2d1272b8SAndroid Build Coastguard Worker *
1523*2d1272b8SAndroid Build Coastguard Worker * This is similar in functionality to hb_face_create_from_file_or_fail(),
1524*2d1272b8SAndroid Build Coastguard Worker * but uses the FreeType library for loading the font file.
1525*2d1272b8SAndroid Build Coastguard Worker *
1526*2d1272b8SAndroid Build Coastguard Worker * Return value: (transfer full): The new face object, or `NULL` if
1527*2d1272b8SAndroid Build Coastguard Worker * no face is found at the specified index or the file cannot be read.
1528*2d1272b8SAndroid Build Coastguard Worker *
1529*2d1272b8SAndroid Build Coastguard Worker * Since: 10.1.0
1530*2d1272b8SAndroid Build Coastguard Worker */
1531*2d1272b8SAndroid Build Coastguard Worker hb_face_t *
hb_ft_face_create_from_file_or_fail(const char * file_name,unsigned int index)1532*2d1272b8SAndroid Build Coastguard Worker hb_ft_face_create_from_file_or_fail (const char *file_name,
1533*2d1272b8SAndroid Build Coastguard Worker unsigned int index)
1534*2d1272b8SAndroid Build Coastguard Worker {
1535*2d1272b8SAndroid Build Coastguard Worker FT_Library ft_library = reference_ft_library ();
1536*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!ft_library))
1537*2d1272b8SAndroid Build Coastguard Worker {
1538*2d1272b8SAndroid Build Coastguard Worker DEBUG_MSG (FT, ft_library, "reference_ft_library failed");
1539*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1540*2d1272b8SAndroid Build Coastguard Worker }
1541*2d1272b8SAndroid Build Coastguard Worker
1542*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face;
1543*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_New_Face (ft_library,
1544*2d1272b8SAndroid Build Coastguard Worker file_name,
1545*2d1272b8SAndroid Build Coastguard Worker index,
1546*2d1272b8SAndroid Build Coastguard Worker &ft_face)))
1547*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1548*2d1272b8SAndroid Build Coastguard Worker
1549*2d1272b8SAndroid Build Coastguard Worker hb_face_t *face = hb_ft_face_create_referenced (ft_face);
1550*2d1272b8SAndroid Build Coastguard Worker FT_Done_Face (ft_face);
1551*2d1272b8SAndroid Build Coastguard Worker
1552*2d1272b8SAndroid Build Coastguard Worker ft_face->generic.data = ft_library;
1553*2d1272b8SAndroid Build Coastguard Worker ft_face->generic.finalizer = finalize_ft_library;
1554*2d1272b8SAndroid Build Coastguard Worker
1555*2d1272b8SAndroid Build Coastguard Worker if (hb_face_is_immutable (face))
1556*2d1272b8SAndroid Build Coastguard Worker return nullptr;
1557*2d1272b8SAndroid Build Coastguard Worker
1558*2d1272b8SAndroid Build Coastguard Worker return face;
1559*2d1272b8SAndroid Build Coastguard Worker }
1560*2d1272b8SAndroid Build Coastguard Worker
1561*2d1272b8SAndroid Build Coastguard Worker static void
_release_blob(void * arg)1562*2d1272b8SAndroid Build Coastguard Worker _release_blob (void *arg)
1563*2d1272b8SAndroid Build Coastguard Worker {
1564*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = (FT_Face) arg;
1565*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
1566*2d1272b8SAndroid Build Coastguard Worker }
1567*2d1272b8SAndroid Build Coastguard Worker
1568*2d1272b8SAndroid Build Coastguard Worker /**
1569*2d1272b8SAndroid Build Coastguard Worker * hb_ft_font_set_funcs:
1570*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
1571*2d1272b8SAndroid Build Coastguard Worker *
1572*2d1272b8SAndroid Build Coastguard Worker * Configures the font-functions structure of the specified
1573*2d1272b8SAndroid Build Coastguard Worker * #hb_font_t font object to use FreeType font functions.
1574*2d1272b8SAndroid Build Coastguard Worker *
1575*2d1272b8SAndroid Build Coastguard Worker * In particular, you can use this function to configure an
1576*2d1272b8SAndroid Build Coastguard Worker * existing #hb_face_t face object for use with FreeType font
1577*2d1272b8SAndroid Build Coastguard Worker * functions even if that #hb_face_t face object was initially
1578*2d1272b8SAndroid Build Coastguard Worker * created with hb_face_create(), and therefore was not
1579*2d1272b8SAndroid Build Coastguard Worker * initially configured to use FreeType font functions.
1580*2d1272b8SAndroid Build Coastguard Worker *
1581*2d1272b8SAndroid Build Coastguard Worker * An #hb_font_t object created with hb_ft_font_create()
1582*2d1272b8SAndroid Build Coastguard Worker * is preconfigured for FreeType font functions and does not
1583*2d1272b8SAndroid Build Coastguard Worker * require this function to be used.
1584*2d1272b8SAndroid Build Coastguard Worker *
1585*2d1272b8SAndroid Build Coastguard Worker * Note that if you modify the underlying #hb_font_t after
1586*2d1272b8SAndroid Build Coastguard Worker * calling this function, you need to call hb_ft_hb_font_changed()
1587*2d1272b8SAndroid Build Coastguard Worker * to update the underlying FT_Face.
1588*2d1272b8SAndroid Build Coastguard Worker *
1589*2d1272b8SAndroid Build Coastguard Worker * <note>Note: Internally, this function creates an FT_Face.
1590*2d1272b8SAndroid Build Coastguard Worker * </note>
1591*2d1272b8SAndroid Build Coastguard Worker *
1592*2d1272b8SAndroid Build Coastguard Worker * Since: 1.0.5
1593*2d1272b8SAndroid Build Coastguard Worker **/
1594*2d1272b8SAndroid Build Coastguard Worker void
hb_ft_font_set_funcs(hb_font_t * font)1595*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_set_funcs (hb_font_t *font)
1596*2d1272b8SAndroid Build Coastguard Worker {
1597*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *blob = hb_face_reference_blob (font->face);
1598*2d1272b8SAndroid Build Coastguard Worker unsigned int blob_length;
1599*2d1272b8SAndroid Build Coastguard Worker const char *blob_data = hb_blob_get_data (blob, &blob_length);
1600*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!blob_length))
1601*2d1272b8SAndroid Build Coastguard Worker DEBUG_MSG (FT, font, "Font face has empty blob");
1602*2d1272b8SAndroid Build Coastguard Worker
1603*2d1272b8SAndroid Build Coastguard Worker FT_Library ft_library = reference_ft_library ();
1604*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!ft_library))
1605*2d1272b8SAndroid Build Coastguard Worker {
1606*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (blob);
1607*2d1272b8SAndroid Build Coastguard Worker DEBUG_MSG (FT, font, "reference_ft_library failed");
1608*2d1272b8SAndroid Build Coastguard Worker return;
1609*2d1272b8SAndroid Build Coastguard Worker }
1610*2d1272b8SAndroid Build Coastguard Worker
1611*2d1272b8SAndroid Build Coastguard Worker FT_Face ft_face = nullptr;
1612*2d1272b8SAndroid Build Coastguard Worker if (unlikely (FT_New_Memory_Face (ft_library,
1613*2d1272b8SAndroid Build Coastguard Worker (const FT_Byte *) blob_data,
1614*2d1272b8SAndroid Build Coastguard Worker blob_length,
1615*2d1272b8SAndroid Build Coastguard Worker hb_face_get_index (font->face),
1616*2d1272b8SAndroid Build Coastguard Worker &ft_face)))
1617*2d1272b8SAndroid Build Coastguard Worker {
1618*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (blob);
1619*2d1272b8SAndroid Build Coastguard Worker DEBUG_MSG (FT, font, "FT_New_Memory_Face() failed");
1620*2d1272b8SAndroid Build Coastguard Worker return;
1621*2d1272b8SAndroid Build Coastguard Worker }
1622*2d1272b8SAndroid Build Coastguard Worker
1623*2d1272b8SAndroid Build Coastguard Worker if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL))
1624*2d1272b8SAndroid Build Coastguard Worker FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
1625*2d1272b8SAndroid Build Coastguard Worker
1626*2d1272b8SAndroid Build Coastguard Worker // Hook the blob to the FT_Face
1627*2d1272b8SAndroid Build Coastguard Worker ft_face->generic.data = blob;
1628*2d1272b8SAndroid Build Coastguard Worker ft_face->generic.finalizer = _release_blob;
1629*2d1272b8SAndroid Build Coastguard Worker
1630*2d1272b8SAndroid Build Coastguard Worker // And the FT_Library to the blob
1631*2d1272b8SAndroid Build Coastguard Worker hb_blob_set_user_data (blob, &ft_library_key, ft_library, destroy_ft_library, true);
1632*2d1272b8SAndroid Build Coastguard Worker
1633*2d1272b8SAndroid Build Coastguard Worker _hb_ft_font_set_funcs (font, ft_face, true);
1634*2d1272b8SAndroid Build Coastguard Worker hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
1635*2d1272b8SAndroid Build Coastguard Worker
1636*2d1272b8SAndroid Build Coastguard Worker _hb_ft_hb_font_changed (font, ft_face);
1637*2d1272b8SAndroid Build Coastguard Worker }
1638*2d1272b8SAndroid Build Coastguard Worker
1639*2d1272b8SAndroid Build Coastguard Worker #endif
1640