1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2009,2010 Red Hat, Inc.
3*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2010,2011,2012 Google, Inc.
4*2d1272b8SAndroid Build Coastguard Worker *
5*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library.
6*2d1272b8SAndroid Build Coastguard Worker *
7*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without
8*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this
9*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the
10*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in
11*2d1272b8SAndroid Build Coastguard Worker * all copies of this software.
12*2d1272b8SAndroid Build Coastguard Worker *
13*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17*2d1272b8SAndroid Build Coastguard Worker * DAMAGE.
18*2d1272b8SAndroid Build Coastguard Worker *
19*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24*2d1272b8SAndroid Build Coastguard Worker *
25*2d1272b8SAndroid Build Coastguard Worker * Red Hat Author(s): Behdad Esfahbod
26*2d1272b8SAndroid Build Coastguard Worker * Google Author(s): Behdad Esfahbod
27*2d1272b8SAndroid Build Coastguard Worker */
28*2d1272b8SAndroid Build Coastguard Worker
29*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
30*2d1272b8SAndroid Build Coastguard Worker
31*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_SHAPE
32*2d1272b8SAndroid Build Coastguard Worker
33*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_NO_OT_LAYOUT
34*2d1272b8SAndroid Build Coastguard Worker #error "Cannot compile 'ot' shaper with HB_NO_OT_LAYOUT."
35*2d1272b8SAndroid Build Coastguard Worker #endif
36*2d1272b8SAndroid Build Coastguard Worker
37*2d1272b8SAndroid Build Coastguard Worker #include "hb-shaper-impl.hh"
38*2d1272b8SAndroid Build Coastguard Worker
39*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-shape.hh"
40*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-shaper.hh"
41*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-shape-fallback.hh"
42*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-shape-normalize.hh"
43*2d1272b8SAndroid Build Coastguard Worker
44*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-face.hh"
45*2d1272b8SAndroid Build Coastguard Worker
46*2d1272b8SAndroid Build Coastguard Worker #include "hb-set.hh"
47*2d1272b8SAndroid Build Coastguard Worker
48*2d1272b8SAndroid Build Coastguard Worker #include "hb-aat-layout.hh"
49*2d1272b8SAndroid Build Coastguard Worker
50*2d1272b8SAndroid Build Coastguard Worker static inline bool
_hb_codepoint_is_regional_indicator(hb_codepoint_t u)51*2d1272b8SAndroid Build Coastguard Worker _hb_codepoint_is_regional_indicator (hb_codepoint_t u)
52*2d1272b8SAndroid Build Coastguard Worker { return hb_in_range<hb_codepoint_t> (u, 0x1F1E6u, 0x1F1FFu); }
53*2d1272b8SAndroid Build Coastguard Worker
54*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
55*2d1272b8SAndroid Build Coastguard Worker static inline bool
_hb_apply_morx(hb_face_t * face,const hb_segment_properties_t & props)56*2d1272b8SAndroid Build Coastguard Worker _hb_apply_morx (hb_face_t *face, const hb_segment_properties_t &props)
57*2d1272b8SAndroid Build Coastguard Worker {
58*2d1272b8SAndroid Build Coastguard Worker /* https://github.com/harfbuzz/harfbuzz/issues/2124 */
59*2d1272b8SAndroid Build Coastguard Worker return hb_aat_layout_has_substitution (face) &&
60*2d1272b8SAndroid Build Coastguard Worker (HB_DIRECTION_IS_HORIZONTAL (props.direction) || !hb_ot_layout_has_substitution (face));
61*2d1272b8SAndroid Build Coastguard Worker }
62*2d1272b8SAndroid Build Coastguard Worker #endif
63*2d1272b8SAndroid Build Coastguard Worker
64*2d1272b8SAndroid Build Coastguard Worker /**
65*2d1272b8SAndroid Build Coastguard Worker * SECTION:hb-ot-shape
66*2d1272b8SAndroid Build Coastguard Worker * @title: hb-ot-shape
67*2d1272b8SAndroid Build Coastguard Worker * @short_description: OpenType shaping support
68*2d1272b8SAndroid Build Coastguard Worker * @include: hb-ot.h
69*2d1272b8SAndroid Build Coastguard Worker *
70*2d1272b8SAndroid Build Coastguard Worker * Support functions for OpenType shaping related queries.
71*2d1272b8SAndroid Build Coastguard Worker **/
72*2d1272b8SAndroid Build Coastguard Worker
73*2d1272b8SAndroid Build Coastguard Worker
74*2d1272b8SAndroid Build Coastguard Worker static void
75*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
76*2d1272b8SAndroid Build Coastguard Worker const hb_feature_t *user_features,
77*2d1272b8SAndroid Build Coastguard Worker unsigned int num_user_features);
78*2d1272b8SAndroid Build Coastguard Worker
hb_ot_shape_planner_t(hb_face_t * face,const hb_segment_properties_t & props)79*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face,
80*2d1272b8SAndroid Build Coastguard Worker const hb_segment_properties_t &props) :
81*2d1272b8SAndroid Build Coastguard Worker face (face),
82*2d1272b8SAndroid Build Coastguard Worker props (props),
83*2d1272b8SAndroid Build Coastguard Worker map (face, props)
84*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
85*2d1272b8SAndroid Build Coastguard Worker , apply_morx (_hb_apply_morx (face, props))
86*2d1272b8SAndroid Build Coastguard Worker #endif
87*2d1272b8SAndroid Build Coastguard Worker {
88*2d1272b8SAndroid Build Coastguard Worker shaper = hb_ot_shaper_categorize (props.script, props.direction, map.chosen_script[0]);
89*2d1272b8SAndroid Build Coastguard Worker
90*2d1272b8SAndroid Build Coastguard Worker script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
91*2d1272b8SAndroid Build Coastguard Worker script_fallback_mark_positioning = shaper->fallback_position;
92*2d1272b8SAndroid Build Coastguard Worker
93*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
94*2d1272b8SAndroid Build Coastguard Worker /* https://github.com/harfbuzz/harfbuzz/issues/1528 */
95*2d1272b8SAndroid Build Coastguard Worker if (apply_morx && shaper != &_hb_ot_shaper_default)
96*2d1272b8SAndroid Build Coastguard Worker shaper = &_hb_ot_shaper_dumber;
97*2d1272b8SAndroid Build Coastguard Worker #endif
98*2d1272b8SAndroid Build Coastguard Worker }
99*2d1272b8SAndroid Build Coastguard Worker
100*2d1272b8SAndroid Build Coastguard Worker void
compile(hb_ot_shape_plan_t & plan,const hb_ot_shape_plan_key_t & key)101*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
102*2d1272b8SAndroid Build Coastguard Worker const hb_ot_shape_plan_key_t &key)
103*2d1272b8SAndroid Build Coastguard Worker {
104*2d1272b8SAndroid Build Coastguard Worker plan.props = props;
105*2d1272b8SAndroid Build Coastguard Worker plan.shaper = shaper;
106*2d1272b8SAndroid Build Coastguard Worker map.compile (plan.map, key);
107*2d1272b8SAndroid Build Coastguard Worker
108*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_SHAPE_FRACTIONS
109*2d1272b8SAndroid Build Coastguard Worker plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
110*2d1272b8SAndroid Build Coastguard Worker plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
111*2d1272b8SAndroid Build Coastguard Worker plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
112*2d1272b8SAndroid Build Coastguard Worker plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
113*2d1272b8SAndroid Build Coastguard Worker #endif
114*2d1272b8SAndroid Build Coastguard Worker
115*2d1272b8SAndroid Build Coastguard Worker plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
116*2d1272b8SAndroid Build Coastguard Worker plan.has_vert = !!plan.map.get_1_mask (HB_TAG ('v','e','r','t'));
117*2d1272b8SAndroid Build Coastguard Worker
118*2d1272b8SAndroid Build Coastguard Worker hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
119*2d1272b8SAndroid Build Coastguard Worker HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
120*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_KERN
121*2d1272b8SAndroid Build Coastguard Worker plan.kern_mask = plan.map.get_mask (kern_tag);
122*2d1272b8SAndroid Build Coastguard Worker plan.requested_kerning = !!plan.kern_mask;
123*2d1272b8SAndroid Build Coastguard Worker #endif
124*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
125*2d1272b8SAndroid Build Coastguard Worker plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
126*2d1272b8SAndroid Build Coastguard Worker plan.requested_tracking = !!plan.trak_mask;
127*2d1272b8SAndroid Build Coastguard Worker #endif
128*2d1272b8SAndroid Build Coastguard Worker
129*2d1272b8SAndroid Build Coastguard Worker bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
130*2d1272b8SAndroid Build Coastguard Worker bool disable_gpos = plan.shaper->gpos_tag &&
131*2d1272b8SAndroid Build Coastguard Worker plan.shaper->gpos_tag != plan.map.chosen_script[1];
132*2d1272b8SAndroid Build Coastguard Worker
133*2d1272b8SAndroid Build Coastguard Worker /*
134*2d1272b8SAndroid Build Coastguard Worker * Decide who provides glyph classes. GDEF or Unicode.
135*2d1272b8SAndroid Build Coastguard Worker */
136*2d1272b8SAndroid Build Coastguard Worker
137*2d1272b8SAndroid Build Coastguard Worker if (!hb_ot_layout_has_glyph_classes (face))
138*2d1272b8SAndroid Build Coastguard Worker plan.fallback_glyph_classes = true;
139*2d1272b8SAndroid Build Coastguard Worker
140*2d1272b8SAndroid Build Coastguard Worker /*
141*2d1272b8SAndroid Build Coastguard Worker * Decide who does substitutions. GSUB, morx, or fallback.
142*2d1272b8SAndroid Build Coastguard Worker */
143*2d1272b8SAndroid Build Coastguard Worker
144*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
145*2d1272b8SAndroid Build Coastguard Worker plan.apply_morx = apply_morx;
146*2d1272b8SAndroid Build Coastguard Worker #endif
147*2d1272b8SAndroid Build Coastguard Worker
148*2d1272b8SAndroid Build Coastguard Worker /*
149*2d1272b8SAndroid Build Coastguard Worker * Decide who does positioning. GPOS, kerx, kern, or fallback.
150*2d1272b8SAndroid Build Coastguard Worker */
151*2d1272b8SAndroid Build Coastguard Worker
152*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
153*2d1272b8SAndroid Build Coastguard Worker bool has_kerx = hb_aat_layout_has_positioning (face);
154*2d1272b8SAndroid Build Coastguard Worker bool has_gsub = !apply_morx && hb_ot_layout_has_substitution (face);
155*2d1272b8SAndroid Build Coastguard Worker #endif
156*2d1272b8SAndroid Build Coastguard Worker bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
157*2d1272b8SAndroid Build Coastguard Worker if (false)
158*2d1272b8SAndroid Build Coastguard Worker {}
159*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
160*2d1272b8SAndroid Build Coastguard Worker /* Prefer GPOS over kerx if GSUB is present;
161*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/3008 */
162*2d1272b8SAndroid Build Coastguard Worker else if (has_kerx && !(has_gsub && has_gpos))
163*2d1272b8SAndroid Build Coastguard Worker plan.apply_kerx = true;
164*2d1272b8SAndroid Build Coastguard Worker #endif
165*2d1272b8SAndroid Build Coastguard Worker else if (has_gpos)
166*2d1272b8SAndroid Build Coastguard Worker plan.apply_gpos = true;
167*2d1272b8SAndroid Build Coastguard Worker
168*2d1272b8SAndroid Build Coastguard Worker if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
169*2d1272b8SAndroid Build Coastguard Worker {
170*2d1272b8SAndroid Build Coastguard Worker if (false) {}
171*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
172*2d1272b8SAndroid Build Coastguard Worker else if (has_kerx)
173*2d1272b8SAndroid Build Coastguard Worker plan.apply_kerx = true;
174*2d1272b8SAndroid Build Coastguard Worker #endif
175*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_KERN
176*2d1272b8SAndroid Build Coastguard Worker else if (hb_ot_layout_has_kerning (face))
177*2d1272b8SAndroid Build Coastguard Worker plan.apply_kern = true;
178*2d1272b8SAndroid Build Coastguard Worker #endif
179*2d1272b8SAndroid Build Coastguard Worker else {}
180*2d1272b8SAndroid Build Coastguard Worker }
181*2d1272b8SAndroid Build Coastguard Worker
182*2d1272b8SAndroid Build Coastguard Worker plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern);
183*2d1272b8SAndroid Build Coastguard Worker
184*2d1272b8SAndroid Build Coastguard Worker plan.zero_marks = script_zero_marks &&
185*2d1272b8SAndroid Build Coastguard Worker !plan.apply_kerx &&
186*2d1272b8SAndroid Build Coastguard Worker (!plan.apply_kern
187*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_KERN
188*2d1272b8SAndroid Build Coastguard Worker || !hb_ot_layout_has_machine_kerning (face)
189*2d1272b8SAndroid Build Coastguard Worker #endif
190*2d1272b8SAndroid Build Coastguard Worker );
191*2d1272b8SAndroid Build Coastguard Worker plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
192*2d1272b8SAndroid Build Coastguard Worker
193*2d1272b8SAndroid Build Coastguard Worker plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
194*2d1272b8SAndroid Build Coastguard Worker !plan.apply_kerx &&
195*2d1272b8SAndroid Build Coastguard Worker (!plan.apply_kern
196*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_KERN
197*2d1272b8SAndroid Build Coastguard Worker || !hb_ot_layout_has_cross_kerning (face)
198*2d1272b8SAndroid Build Coastguard Worker #endif
199*2d1272b8SAndroid Build Coastguard Worker );
200*2d1272b8SAndroid Build Coastguard Worker
201*2d1272b8SAndroid Build Coastguard Worker plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
202*2d1272b8SAndroid Build Coastguard Worker script_fallback_mark_positioning;
203*2d1272b8SAndroid Build Coastguard Worker
204*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
205*2d1272b8SAndroid Build Coastguard Worker /* If we're using morx shaping, we cancel mark position adjustment because
206*2d1272b8SAndroid Build Coastguard Worker Apple Color Emoji assumes this will NOT be done when forming emoji sequences;
207*2d1272b8SAndroid Build Coastguard Worker https://github.com/harfbuzz/harfbuzz/issues/2967. */
208*2d1272b8SAndroid Build Coastguard Worker if (plan.apply_morx)
209*2d1272b8SAndroid Build Coastguard Worker plan.adjust_mark_positioning_when_zeroing = false;
210*2d1272b8SAndroid Build Coastguard Worker
211*2d1272b8SAndroid Build Coastguard Worker /* Currently we always apply trak. */
212*2d1272b8SAndroid Build Coastguard Worker plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
213*2d1272b8SAndroid Build Coastguard Worker #endif
214*2d1272b8SAndroid Build Coastguard Worker }
215*2d1272b8SAndroid Build Coastguard Worker
216*2d1272b8SAndroid Build Coastguard Worker bool
init0(hb_face_t * face,const hb_shape_plan_key_t * key)217*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_plan_t::init0 (hb_face_t *face,
218*2d1272b8SAndroid Build Coastguard Worker const hb_shape_plan_key_t *key)
219*2d1272b8SAndroid Build Coastguard Worker {
220*2d1272b8SAndroid Build Coastguard Worker map.init ();
221*2d1272b8SAndroid Build Coastguard Worker
222*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_planner_t planner (face,
223*2d1272b8SAndroid Build Coastguard Worker key->props);
224*2d1272b8SAndroid Build Coastguard Worker
225*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_collect_features (&planner,
226*2d1272b8SAndroid Build Coastguard Worker key->user_features,
227*2d1272b8SAndroid Build Coastguard Worker key->num_user_features);
228*2d1272b8SAndroid Build Coastguard Worker
229*2d1272b8SAndroid Build Coastguard Worker planner.compile (*this, key->ot);
230*2d1272b8SAndroid Build Coastguard Worker
231*2d1272b8SAndroid Build Coastguard Worker if (shaper->data_create)
232*2d1272b8SAndroid Build Coastguard Worker {
233*2d1272b8SAndroid Build Coastguard Worker data = shaper->data_create (this);
234*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!data))
235*2d1272b8SAndroid Build Coastguard Worker {
236*2d1272b8SAndroid Build Coastguard Worker map.fini ();
237*2d1272b8SAndroid Build Coastguard Worker return false;
238*2d1272b8SAndroid Build Coastguard Worker }
239*2d1272b8SAndroid Build Coastguard Worker }
240*2d1272b8SAndroid Build Coastguard Worker
241*2d1272b8SAndroid Build Coastguard Worker return true;
242*2d1272b8SAndroid Build Coastguard Worker }
243*2d1272b8SAndroid Build Coastguard Worker
244*2d1272b8SAndroid Build Coastguard Worker void
fini()245*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_plan_t::fini ()
246*2d1272b8SAndroid Build Coastguard Worker {
247*2d1272b8SAndroid Build Coastguard Worker if (shaper->data_destroy)
248*2d1272b8SAndroid Build Coastguard Worker shaper->data_destroy (const_cast<void *> (data));
249*2d1272b8SAndroid Build Coastguard Worker
250*2d1272b8SAndroid Build Coastguard Worker map.fini ();
251*2d1272b8SAndroid Build Coastguard Worker }
252*2d1272b8SAndroid Build Coastguard Worker
253*2d1272b8SAndroid Build Coastguard Worker void
substitute(hb_font_t * font,hb_buffer_t * buffer) const254*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_plan_t::substitute (hb_font_t *font,
255*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer) const
256*2d1272b8SAndroid Build Coastguard Worker {
257*2d1272b8SAndroid Build Coastguard Worker map.substitute (this, font, buffer);
258*2d1272b8SAndroid Build Coastguard Worker }
259*2d1272b8SAndroid Build Coastguard Worker
260*2d1272b8SAndroid Build Coastguard Worker void
position(hb_font_t * font,hb_buffer_t * buffer) const261*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_plan_t::position (hb_font_t *font,
262*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer) const
263*2d1272b8SAndroid Build Coastguard Worker {
264*2d1272b8SAndroid Build Coastguard Worker if (this->apply_gpos)
265*2d1272b8SAndroid Build Coastguard Worker map.position (this, font, buffer);
266*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
267*2d1272b8SAndroid Build Coastguard Worker else if (this->apply_kerx)
268*2d1272b8SAndroid Build Coastguard Worker hb_aat_layout_position (this, font, buffer);
269*2d1272b8SAndroid Build Coastguard Worker #endif
270*2d1272b8SAndroid Build Coastguard Worker
271*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_KERN
272*2d1272b8SAndroid Build Coastguard Worker if (this->apply_kern)
273*2d1272b8SAndroid Build Coastguard Worker hb_ot_layout_kern (this, font, buffer);
274*2d1272b8SAndroid Build Coastguard Worker #endif
275*2d1272b8SAndroid Build Coastguard Worker else if (this->apply_fallback_kern)
276*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shape_fallback_kern (this, font, buffer);
277*2d1272b8SAndroid Build Coastguard Worker
278*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
279*2d1272b8SAndroid Build Coastguard Worker if (this->apply_trak)
280*2d1272b8SAndroid Build Coastguard Worker hb_aat_layout_track (this, font, buffer);
281*2d1272b8SAndroid Build Coastguard Worker #endif
282*2d1272b8SAndroid Build Coastguard Worker }
283*2d1272b8SAndroid Build Coastguard Worker
284*2d1272b8SAndroid Build Coastguard Worker
285*2d1272b8SAndroid Build Coastguard Worker static const hb_ot_map_feature_t
286*2d1272b8SAndroid Build Coastguard Worker common_features[] =
287*2d1272b8SAndroid Build Coastguard Worker {
288*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('a','b','v','m'), F_GLOBAL},
289*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('b','l','w','m'), F_GLOBAL},
290*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('c','c','m','p'), F_GLOBAL},
291*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('l','o','c','l'), F_GLOBAL},
292*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
293*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS},
294*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('r','l','i','g'), F_GLOBAL},
295*2d1272b8SAndroid Build Coastguard Worker };
296*2d1272b8SAndroid Build Coastguard Worker
297*2d1272b8SAndroid Build Coastguard Worker
298*2d1272b8SAndroid Build Coastguard Worker static const hb_ot_map_feature_t
299*2d1272b8SAndroid Build Coastguard Worker horizontal_features[] =
300*2d1272b8SAndroid Build Coastguard Worker {
301*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('c','a','l','t'), F_GLOBAL},
302*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('c','l','i','g'), F_GLOBAL},
303*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('c','u','r','s'), F_GLOBAL},
304*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('d','i','s','t'), F_GLOBAL},
305*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
306*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('l','i','g','a'), F_GLOBAL},
307*2d1272b8SAndroid Build Coastguard Worker {HB_TAG('r','c','l','t'), F_GLOBAL},
308*2d1272b8SAndroid Build Coastguard Worker };
309*2d1272b8SAndroid Build Coastguard Worker
310*2d1272b8SAndroid Build Coastguard Worker static void
hb_ot_shape_collect_features(hb_ot_shape_planner_t * planner,const hb_feature_t * user_features,unsigned int num_user_features)311*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
312*2d1272b8SAndroid Build Coastguard Worker const hb_feature_t *user_features,
313*2d1272b8SAndroid Build Coastguard Worker unsigned int num_user_features)
314*2d1272b8SAndroid Build Coastguard Worker {
315*2d1272b8SAndroid Build Coastguard Worker hb_ot_map_builder_t *map = &planner->map;
316*2d1272b8SAndroid Build Coastguard Worker
317*2d1272b8SAndroid Build Coastguard Worker map->is_simple = true;
318*2d1272b8SAndroid Build Coastguard Worker
319*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG('r','v','r','n'));
320*2d1272b8SAndroid Build Coastguard Worker map->add_gsub_pause (nullptr);
321*2d1272b8SAndroid Build Coastguard Worker
322*2d1272b8SAndroid Build Coastguard Worker switch (planner->props.direction)
323*2d1272b8SAndroid Build Coastguard Worker {
324*2d1272b8SAndroid Build Coastguard Worker case HB_DIRECTION_LTR:
325*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('l','t','r','a'));
326*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('l','t','r','m'));
327*2d1272b8SAndroid Build Coastguard Worker break;
328*2d1272b8SAndroid Build Coastguard Worker case HB_DIRECTION_RTL:
329*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('r','t','l','a'));
330*2d1272b8SAndroid Build Coastguard Worker map->add_feature (HB_TAG ('r','t','l','m'));
331*2d1272b8SAndroid Build Coastguard Worker break;
332*2d1272b8SAndroid Build Coastguard Worker case HB_DIRECTION_TTB:
333*2d1272b8SAndroid Build Coastguard Worker case HB_DIRECTION_BTT:
334*2d1272b8SAndroid Build Coastguard Worker case HB_DIRECTION_INVALID:
335*2d1272b8SAndroid Build Coastguard Worker default:
336*2d1272b8SAndroid Build Coastguard Worker break;
337*2d1272b8SAndroid Build Coastguard Worker }
338*2d1272b8SAndroid Build Coastguard Worker
339*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_OT_SHAPE_FRACTIONS
340*2d1272b8SAndroid Build Coastguard Worker /* Automatic fractions. */
341*2d1272b8SAndroid Build Coastguard Worker map->add_feature (HB_TAG ('f','r','a','c'));
342*2d1272b8SAndroid Build Coastguard Worker map->add_feature (HB_TAG ('n','u','m','r'));
343*2d1272b8SAndroid Build Coastguard Worker map->add_feature (HB_TAG ('d','n','o','m'));
344*2d1272b8SAndroid Build Coastguard Worker #endif
345*2d1272b8SAndroid Build Coastguard Worker
346*2d1272b8SAndroid Build Coastguard Worker /* Random! */
347*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
348*2d1272b8SAndroid Build Coastguard Worker
349*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
350*2d1272b8SAndroid Build Coastguard Worker /* Tracking. We enable dummy feature here just to allow disabling
351*2d1272b8SAndroid Build Coastguard Worker * AAT 'trak' table using features.
352*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/1303 */
353*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
354*2d1272b8SAndroid Build Coastguard Worker #endif
355*2d1272b8SAndroid Build Coastguard Worker
356*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('H','a','r','f')); /* Considered required. */
357*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
358*2d1272b8SAndroid Build Coastguard Worker
359*2d1272b8SAndroid Build Coastguard Worker if (planner->shaper->collect_features)
360*2d1272b8SAndroid Build Coastguard Worker {
361*2d1272b8SAndroid Build Coastguard Worker map->is_simple = false;
362*2d1272b8SAndroid Build Coastguard Worker planner->shaper->collect_features (planner);
363*2d1272b8SAndroid Build Coastguard Worker }
364*2d1272b8SAndroid Build Coastguard Worker
365*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('B','u','z','z')); /* Considered required. */
366*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('B','U','Z','Z')); /* Considered discretionary. */
367*2d1272b8SAndroid Build Coastguard Worker
368*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
369*2d1272b8SAndroid Build Coastguard Worker map->add_feature (common_features[i]);
370*2d1272b8SAndroid Build Coastguard Worker
371*2d1272b8SAndroid Build Coastguard Worker if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction))
372*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
373*2d1272b8SAndroid Build Coastguard Worker map->add_feature (horizontal_features[i]);
374*2d1272b8SAndroid Build Coastguard Worker else
375*2d1272b8SAndroid Build Coastguard Worker {
376*2d1272b8SAndroid Build Coastguard Worker /* We only apply `vert` feature. See:
377*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/commit/d71c0df2d17f4590d5611239577a6cb532c26528
378*2d1272b8SAndroid Build Coastguard Worker * https://lists.freedesktop.org/archives/harfbuzz/2013-August/003490.html */
379*2d1272b8SAndroid Build Coastguard Worker
380*2d1272b8SAndroid Build Coastguard Worker /* We really want to find a 'vert' feature if there's any in the font, no
381*2d1272b8SAndroid Build Coastguard Worker * matter which script/langsys it is listed (or not) under.
382*2d1272b8SAndroid Build Coastguard Worker * See various bugs referenced from:
383*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/63 */
384*2d1272b8SAndroid Build Coastguard Worker map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
385*2d1272b8SAndroid Build Coastguard Worker }
386*2d1272b8SAndroid Build Coastguard Worker
387*2d1272b8SAndroid Build Coastguard Worker if (num_user_features)
388*2d1272b8SAndroid Build Coastguard Worker map->is_simple = false;
389*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < num_user_features; i++)
390*2d1272b8SAndroid Build Coastguard Worker {
391*2d1272b8SAndroid Build Coastguard Worker const hb_feature_t *feature = &user_features[i];
392*2d1272b8SAndroid Build Coastguard Worker map->add_feature (feature->tag,
393*2d1272b8SAndroid Build Coastguard Worker (feature->start == HB_FEATURE_GLOBAL_START &&
394*2d1272b8SAndroid Build Coastguard Worker feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE,
395*2d1272b8SAndroid Build Coastguard Worker feature->value);
396*2d1272b8SAndroid Build Coastguard Worker }
397*2d1272b8SAndroid Build Coastguard Worker
398*2d1272b8SAndroid Build Coastguard Worker if (planner->shaper->override_features)
399*2d1272b8SAndroid Build Coastguard Worker planner->shaper->override_features (planner);
400*2d1272b8SAndroid Build Coastguard Worker }
401*2d1272b8SAndroid Build Coastguard Worker
402*2d1272b8SAndroid Build Coastguard Worker
403*2d1272b8SAndroid Build Coastguard Worker /*
404*2d1272b8SAndroid Build Coastguard Worker * shaper face data
405*2d1272b8SAndroid Build Coastguard Worker */
406*2d1272b8SAndroid Build Coastguard Worker
407*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_face_data_t {};
408*2d1272b8SAndroid Build Coastguard Worker
409*2d1272b8SAndroid Build Coastguard Worker hb_ot_face_data_t *
_hb_ot_shaper_face_data_create(hb_face_t * face)410*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shaper_face_data_create (hb_face_t *face)
411*2d1272b8SAndroid Build Coastguard Worker {
412*2d1272b8SAndroid Build Coastguard Worker return (hb_ot_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
413*2d1272b8SAndroid Build Coastguard Worker }
414*2d1272b8SAndroid Build Coastguard Worker
415*2d1272b8SAndroid Build Coastguard Worker void
_hb_ot_shaper_face_data_destroy(hb_ot_face_data_t * data)416*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
417*2d1272b8SAndroid Build Coastguard Worker {
418*2d1272b8SAndroid Build Coastguard Worker }
419*2d1272b8SAndroid Build Coastguard Worker
420*2d1272b8SAndroid Build Coastguard Worker
421*2d1272b8SAndroid Build Coastguard Worker /*
422*2d1272b8SAndroid Build Coastguard Worker * shaper font data
423*2d1272b8SAndroid Build Coastguard Worker */
424*2d1272b8SAndroid Build Coastguard Worker
425*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_font_data_t {};
426*2d1272b8SAndroid Build Coastguard Worker
427*2d1272b8SAndroid Build Coastguard Worker hb_ot_font_data_t *
_hb_ot_shaper_font_data_create(hb_font_t * font HB_UNUSED)428*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
429*2d1272b8SAndroid Build Coastguard Worker {
430*2d1272b8SAndroid Build Coastguard Worker return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
431*2d1272b8SAndroid Build Coastguard Worker }
432*2d1272b8SAndroid Build Coastguard Worker
433*2d1272b8SAndroid Build Coastguard Worker void
_hb_ot_shaper_font_data_destroy(hb_ot_font_data_t * data HB_UNUSED)434*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED)
435*2d1272b8SAndroid Build Coastguard Worker {
436*2d1272b8SAndroid Build Coastguard Worker }
437*2d1272b8SAndroid Build Coastguard Worker
438*2d1272b8SAndroid Build Coastguard Worker
439*2d1272b8SAndroid Build Coastguard Worker /*
440*2d1272b8SAndroid Build Coastguard Worker * shaper
441*2d1272b8SAndroid Build Coastguard Worker */
442*2d1272b8SAndroid Build Coastguard Worker
443*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_shape_context_t
444*2d1272b8SAndroid Build Coastguard Worker {
445*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_plan_t *plan;
446*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font;
447*2d1272b8SAndroid Build Coastguard Worker hb_face_t *face;
448*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer;
449*2d1272b8SAndroid Build Coastguard Worker const hb_feature_t *user_features;
450*2d1272b8SAndroid Build Coastguard Worker unsigned int num_user_features;
451*2d1272b8SAndroid Build Coastguard Worker
452*2d1272b8SAndroid Build Coastguard Worker /* Transient stuff */
453*2d1272b8SAndroid Build Coastguard Worker hb_direction_t target_direction;
454*2d1272b8SAndroid Build Coastguard Worker };
455*2d1272b8SAndroid Build Coastguard Worker
456*2d1272b8SAndroid Build Coastguard Worker
457*2d1272b8SAndroid Build Coastguard Worker
458*2d1272b8SAndroid Build Coastguard Worker /* Main shaper */
459*2d1272b8SAndroid Build Coastguard Worker
460*2d1272b8SAndroid Build Coastguard Worker
461*2d1272b8SAndroid Build Coastguard Worker /* Prepare */
462*2d1272b8SAndroid Build Coastguard Worker
463*2d1272b8SAndroid Build Coastguard Worker static void
hb_set_unicode_props(hb_buffer_t * buffer)464*2d1272b8SAndroid Build Coastguard Worker hb_set_unicode_props (hb_buffer_t *buffer)
465*2d1272b8SAndroid Build Coastguard Worker {
466*2d1272b8SAndroid Build Coastguard Worker /* Implement enough of Unicode Graphemes here that shaping
467*2d1272b8SAndroid Build Coastguard Worker * in reverse-direction wouldn't break graphemes. Namely,
468*2d1272b8SAndroid Build Coastguard Worker * we mark all marks and ZWJ and ZWJ,Extended_Pictographic
469*2d1272b8SAndroid Build Coastguard Worker * sequences as continuations. The foreach_grapheme()
470*2d1272b8SAndroid Build Coastguard Worker * macro uses this bit.
471*2d1272b8SAndroid Build Coastguard Worker *
472*2d1272b8SAndroid Build Coastguard Worker * https://www.unicode.org/reports/tr29/#Regex_Definitions
473*2d1272b8SAndroid Build Coastguard Worker */
474*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
475*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
476*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
477*2d1272b8SAndroid Build Coastguard Worker {
478*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_unicode_props (&info[i], buffer);
479*2d1272b8SAndroid Build Coastguard Worker
480*2d1272b8SAndroid Build Coastguard Worker unsigned gen_cat = _hb_glyph_info_get_general_category (&info[i]);
481*2d1272b8SAndroid Build Coastguard Worker if (FLAG_UNSAFE (gen_cat) &
482*2d1272b8SAndroid Build Coastguard Worker (FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |
483*2d1272b8SAndroid Build Coastguard Worker FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |
484*2d1272b8SAndroid Build Coastguard Worker FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |
485*2d1272b8SAndroid Build Coastguard Worker FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) |
486*2d1272b8SAndroid Build Coastguard Worker FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR)))
487*2d1272b8SAndroid Build Coastguard Worker continue;
488*2d1272b8SAndroid Build Coastguard Worker
489*2d1272b8SAndroid Build Coastguard Worker /* Marks are already set as continuation by the above line.
490*2d1272b8SAndroid Build Coastguard Worker * Handle Emoji_Modifier and ZWJ-continuation. */
491*2d1272b8SAndroid Build Coastguard Worker if (unlikely (gen_cat == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
492*2d1272b8SAndroid Build Coastguard Worker hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
493*2d1272b8SAndroid Build Coastguard Worker {
494*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_continuation (&info[i]);
495*2d1272b8SAndroid Build Coastguard Worker }
496*2d1272b8SAndroid Build Coastguard Worker /* Regional_Indicators are hairy as hell...
497*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/2265 */
498*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (i && _hb_codepoint_is_regional_indicator (info[i].codepoint)))
499*2d1272b8SAndroid Build Coastguard Worker {
500*2d1272b8SAndroid Build Coastguard Worker if (_hb_codepoint_is_regional_indicator (info[i - 1].codepoint) &&
501*2d1272b8SAndroid Build Coastguard Worker !_hb_glyph_info_is_continuation (&info[i - 1]))
502*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_continuation (&info[i]);
503*2d1272b8SAndroid Build Coastguard Worker }
504*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_EMOJI_SEQUENCES
505*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (_hb_glyph_info_is_zwj (&info[i])))
506*2d1272b8SAndroid Build Coastguard Worker {
507*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_continuation (&info[i]);
508*2d1272b8SAndroid Build Coastguard Worker if (i + 1 < count &&
509*2d1272b8SAndroid Build Coastguard Worker _hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint))
510*2d1272b8SAndroid Build Coastguard Worker {
511*2d1272b8SAndroid Build Coastguard Worker i++;
512*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_unicode_props (&info[i], buffer);
513*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_continuation (&info[i]);
514*2d1272b8SAndroid Build Coastguard Worker }
515*2d1272b8SAndroid Build Coastguard Worker }
516*2d1272b8SAndroid Build Coastguard Worker #endif
517*2d1272b8SAndroid Build Coastguard Worker /* Or part of the Other_Grapheme_Extend that is not marks.
518*2d1272b8SAndroid Build Coastguard Worker * As of Unicode 15 that is just:
519*2d1272b8SAndroid Build Coastguard Worker *
520*2d1272b8SAndroid Build Coastguard Worker * 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER
521*2d1272b8SAndroid Build Coastguard Worker * FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
522*2d1272b8SAndroid Build Coastguard Worker * E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
523*2d1272b8SAndroid Build Coastguard Worker *
524*2d1272b8SAndroid Build Coastguard Worker * ZWNJ is special, we don't want to merge it as there's no need, and keeping
525*2d1272b8SAndroid Build Coastguard Worker * it separate results in more granular clusters.
526*2d1272b8SAndroid Build Coastguard Worker * Tags are used for Emoji sub-region flag sequences:
527*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/1556
528*2d1272b8SAndroid Build Coastguard Worker * Katakana ones were requested:
529*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/3844
530*2d1272b8SAndroid Build Coastguard Worker */
531*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0xFF9Eu, 0xFF9Fu, 0xE0020u, 0xE007Fu)))
532*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_continuation (&info[i]);
533*2d1272b8SAndroid Build Coastguard Worker }
534*2d1272b8SAndroid Build Coastguard Worker }
535*2d1272b8SAndroid Build Coastguard Worker
536*2d1272b8SAndroid Build Coastguard Worker static void
hb_insert_dotted_circle(hb_buffer_t * buffer,hb_font_t * font)537*2d1272b8SAndroid Build Coastguard Worker hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
538*2d1272b8SAndroid Build Coastguard Worker {
539*2d1272b8SAndroid Build Coastguard Worker if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
540*2d1272b8SAndroid Build Coastguard Worker return;
541*2d1272b8SAndroid Build Coastguard Worker
542*2d1272b8SAndroid Build Coastguard Worker if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
543*2d1272b8SAndroid Build Coastguard Worker buffer->context_len[0] ||
544*2d1272b8SAndroid Build Coastguard Worker !_hb_glyph_info_is_unicode_mark (&buffer->info[0]))
545*2d1272b8SAndroid Build Coastguard Worker return;
546*2d1272b8SAndroid Build Coastguard Worker
547*2d1272b8SAndroid Build Coastguard Worker if (!font->has_glyph (0x25CCu))
548*2d1272b8SAndroid Build Coastguard Worker return;
549*2d1272b8SAndroid Build Coastguard Worker
550*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t dottedcircle = {0};
551*2d1272b8SAndroid Build Coastguard Worker dottedcircle.codepoint = 0x25CCu;
552*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_unicode_props (&dottedcircle, buffer);
553*2d1272b8SAndroid Build Coastguard Worker
554*2d1272b8SAndroid Build Coastguard Worker buffer->clear_output ();
555*2d1272b8SAndroid Build Coastguard Worker
556*2d1272b8SAndroid Build Coastguard Worker buffer->idx = 0;
557*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t info = dottedcircle;
558*2d1272b8SAndroid Build Coastguard Worker info.cluster = buffer->cur().cluster;
559*2d1272b8SAndroid Build Coastguard Worker info.mask = buffer->cur().mask;
560*2d1272b8SAndroid Build Coastguard Worker (void) buffer->output_info (info);
561*2d1272b8SAndroid Build Coastguard Worker
562*2d1272b8SAndroid Build Coastguard Worker buffer->sync ();
563*2d1272b8SAndroid Build Coastguard Worker }
564*2d1272b8SAndroid Build Coastguard Worker
565*2d1272b8SAndroid Build Coastguard Worker static void
hb_form_clusters(hb_buffer_t * buffer)566*2d1272b8SAndroid Build Coastguard Worker hb_form_clusters (hb_buffer_t *buffer)
567*2d1272b8SAndroid Build Coastguard Worker {
568*2d1272b8SAndroid Build Coastguard Worker if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
569*2d1272b8SAndroid Build Coastguard Worker return;
570*2d1272b8SAndroid Build Coastguard Worker
571*2d1272b8SAndroid Build Coastguard Worker if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
572*2d1272b8SAndroid Build Coastguard Worker foreach_grapheme (buffer, start, end)
573*2d1272b8SAndroid Build Coastguard Worker buffer->merge_clusters (start, end);
574*2d1272b8SAndroid Build Coastguard Worker else
575*2d1272b8SAndroid Build Coastguard Worker foreach_grapheme (buffer, start, end)
576*2d1272b8SAndroid Build Coastguard Worker buffer->unsafe_to_break (start, end);
577*2d1272b8SAndroid Build Coastguard Worker }
578*2d1272b8SAndroid Build Coastguard Worker
579*2d1272b8SAndroid Build Coastguard Worker static void
hb_ensure_native_direction(hb_buffer_t * buffer)580*2d1272b8SAndroid Build Coastguard Worker hb_ensure_native_direction (hb_buffer_t *buffer)
581*2d1272b8SAndroid Build Coastguard Worker {
582*2d1272b8SAndroid Build Coastguard Worker hb_direction_t direction = buffer->props.direction;
583*2d1272b8SAndroid Build Coastguard Worker hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script);
584*2d1272b8SAndroid Build Coastguard Worker
585*2d1272b8SAndroid Build Coastguard Worker /* Numeric runs in natively-RTL scripts are actually native-LTR, so we reset
586*2d1272b8SAndroid Build Coastguard Worker * the horiz_dir if the run contains at least one decimal-number char, and no
587*2d1272b8SAndroid Build Coastguard Worker * letter chars (ideally we should be checking for chars with strong
588*2d1272b8SAndroid Build Coastguard Worker * directionality but hb-unicode currently lacks bidi categories).
589*2d1272b8SAndroid Build Coastguard Worker *
590*2d1272b8SAndroid Build Coastguard Worker * This allows digit sequences in Arabic etc to be shaped in "native"
591*2d1272b8SAndroid Build Coastguard Worker * direction, so that features like ligatures will work as intended.
592*2d1272b8SAndroid Build Coastguard Worker *
593*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/501
594*2d1272b8SAndroid Build Coastguard Worker *
595*2d1272b8SAndroid Build Coastguard Worker * Similar thing about Regional_Indicators; They are bidi=L, but Script=Common.
596*2d1272b8SAndroid Build Coastguard Worker * If they are present in a run of natively-RTL text, they get assigned a script
597*2d1272b8SAndroid Build Coastguard Worker * with natively RTL direction, which would result in wrong shaping if we
598*2d1272b8SAndroid Build Coastguard Worker * assign such native RTL direction to them then. Detect that as well.
599*2d1272b8SAndroid Build Coastguard Worker *
600*2d1272b8SAndroid Build Coastguard Worker * https://github.com/harfbuzz/harfbuzz/issues/3314
601*2d1272b8SAndroid Build Coastguard Worker */
602*2d1272b8SAndroid Build Coastguard Worker if (unlikely (horiz_dir == HB_DIRECTION_RTL && direction == HB_DIRECTION_LTR))
603*2d1272b8SAndroid Build Coastguard Worker {
604*2d1272b8SAndroid Build Coastguard Worker bool found_number = false, found_letter = false, found_ri = false;
605*2d1272b8SAndroid Build Coastguard Worker const auto* info = buffer->info;
606*2d1272b8SAndroid Build Coastguard Worker const auto count = buffer->len;
607*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < count; i++)
608*2d1272b8SAndroid Build Coastguard Worker {
609*2d1272b8SAndroid Build Coastguard Worker auto gc = _hb_glyph_info_get_general_category (&info[i]);
610*2d1272b8SAndroid Build Coastguard Worker if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
611*2d1272b8SAndroid Build Coastguard Worker found_number = true;
612*2d1272b8SAndroid Build Coastguard Worker else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc))
613*2d1272b8SAndroid Build Coastguard Worker {
614*2d1272b8SAndroid Build Coastguard Worker found_letter = true;
615*2d1272b8SAndroid Build Coastguard Worker break;
616*2d1272b8SAndroid Build Coastguard Worker }
617*2d1272b8SAndroid Build Coastguard Worker else if (_hb_codepoint_is_regional_indicator (info[i].codepoint))
618*2d1272b8SAndroid Build Coastguard Worker found_ri = true;
619*2d1272b8SAndroid Build Coastguard Worker }
620*2d1272b8SAndroid Build Coastguard Worker if ((found_number || found_ri) && !found_letter)
621*2d1272b8SAndroid Build Coastguard Worker horiz_dir = HB_DIRECTION_LTR;
622*2d1272b8SAndroid Build Coastguard Worker }
623*2d1272b8SAndroid Build Coastguard Worker
624*2d1272b8SAndroid Build Coastguard Worker /* TODO vertical:
625*2d1272b8SAndroid Build Coastguard Worker * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
626*2d1272b8SAndroid Build Coastguard Worker * Ogham fonts are supposed to be implemented BTT or not. Need to research that
627*2d1272b8SAndroid Build Coastguard Worker * first. */
628*2d1272b8SAndroid Build Coastguard Worker if ((HB_DIRECTION_IS_HORIZONTAL (direction) &&
629*2d1272b8SAndroid Build Coastguard Worker direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
630*2d1272b8SAndroid Build Coastguard Worker (HB_DIRECTION_IS_VERTICAL (direction) &&
631*2d1272b8SAndroid Build Coastguard Worker direction != HB_DIRECTION_TTB))
632*2d1272b8SAndroid Build Coastguard Worker {
633*2d1272b8SAndroid Build Coastguard Worker _hb_ot_layout_reverse_graphemes (buffer);
634*2d1272b8SAndroid Build Coastguard Worker buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
635*2d1272b8SAndroid Build Coastguard Worker }
636*2d1272b8SAndroid Build Coastguard Worker }
637*2d1272b8SAndroid Build Coastguard Worker
638*2d1272b8SAndroid Build Coastguard Worker
639*2d1272b8SAndroid Build Coastguard Worker /*
640*2d1272b8SAndroid Build Coastguard Worker * Substitute
641*2d1272b8SAndroid Build Coastguard Worker */
642*2d1272b8SAndroid Build Coastguard Worker
643*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
644*2d1272b8SAndroid Build Coastguard Worker static hb_codepoint_t
hb_vert_char_for(hb_codepoint_t u)645*2d1272b8SAndroid Build Coastguard Worker hb_vert_char_for (hb_codepoint_t u)
646*2d1272b8SAndroid Build Coastguard Worker {
647*2d1272b8SAndroid Build Coastguard Worker switch (u >> 8)
648*2d1272b8SAndroid Build Coastguard Worker {
649*2d1272b8SAndroid Build Coastguard Worker case 0x20: switch (u) {
650*2d1272b8SAndroid Build Coastguard Worker case 0x2013u: return 0xfe32u; // EN DASH
651*2d1272b8SAndroid Build Coastguard Worker case 0x2014u: return 0xfe31u; // EM DASH
652*2d1272b8SAndroid Build Coastguard Worker case 0x2025u: return 0xfe30u; // TWO DOT LEADER
653*2d1272b8SAndroid Build Coastguard Worker case 0x2026u: return 0xfe19u; // HORIZONTAL ELLIPSIS
654*2d1272b8SAndroid Build Coastguard Worker } break;
655*2d1272b8SAndroid Build Coastguard Worker case 0x30: switch (u) {
656*2d1272b8SAndroid Build Coastguard Worker case 0x3001u: return 0xfe11u; // IDEOGRAPHIC COMMA
657*2d1272b8SAndroid Build Coastguard Worker case 0x3002u: return 0xfe12u; // IDEOGRAPHIC FULL STOP
658*2d1272b8SAndroid Build Coastguard Worker case 0x3008u: return 0xfe3fu; // LEFT ANGLE BRACKET
659*2d1272b8SAndroid Build Coastguard Worker case 0x3009u: return 0xfe40u; // RIGHT ANGLE BRACKET
660*2d1272b8SAndroid Build Coastguard Worker case 0x300au: return 0xfe3du; // LEFT DOUBLE ANGLE BRACKET
661*2d1272b8SAndroid Build Coastguard Worker case 0x300bu: return 0xfe3eu; // RIGHT DOUBLE ANGLE BRACKET
662*2d1272b8SAndroid Build Coastguard Worker case 0x300cu: return 0xfe41u; // LEFT CORNER BRACKET
663*2d1272b8SAndroid Build Coastguard Worker case 0x300du: return 0xfe42u; // RIGHT CORNER BRACKET
664*2d1272b8SAndroid Build Coastguard Worker case 0x300eu: return 0xfe43u; // LEFT WHITE CORNER BRACKET
665*2d1272b8SAndroid Build Coastguard Worker case 0x300fu: return 0xfe44u; // RIGHT WHITE CORNER BRACKET
666*2d1272b8SAndroid Build Coastguard Worker case 0x3010u: return 0xfe3bu; // LEFT BLACK LENTICULAR BRACKET
667*2d1272b8SAndroid Build Coastguard Worker case 0x3011u: return 0xfe3cu; // RIGHT BLACK LENTICULAR BRACKET
668*2d1272b8SAndroid Build Coastguard Worker case 0x3014u: return 0xfe39u; // LEFT TORTOISE SHELL BRACKET
669*2d1272b8SAndroid Build Coastguard Worker case 0x3015u: return 0xfe3au; // RIGHT TORTOISE SHELL BRACKET
670*2d1272b8SAndroid Build Coastguard Worker case 0x3016u: return 0xfe17u; // LEFT WHITE LENTICULAR BRACKET
671*2d1272b8SAndroid Build Coastguard Worker case 0x3017u: return 0xfe18u; // RIGHT WHITE LENTICULAR BRACKET
672*2d1272b8SAndroid Build Coastguard Worker } break;
673*2d1272b8SAndroid Build Coastguard Worker case 0xfe: switch (u) {
674*2d1272b8SAndroid Build Coastguard Worker case 0xfe4fu: return 0xfe34u; // WAVY LOW LINE
675*2d1272b8SAndroid Build Coastguard Worker } break;
676*2d1272b8SAndroid Build Coastguard Worker case 0xff: switch (u) {
677*2d1272b8SAndroid Build Coastguard Worker case 0xff01u: return 0xfe15u; // FULLWIDTH EXCLAMATION MARK
678*2d1272b8SAndroid Build Coastguard Worker case 0xff08u: return 0xfe35u; // FULLWIDTH LEFT PARENTHESIS
679*2d1272b8SAndroid Build Coastguard Worker case 0xff09u: return 0xfe36u; // FULLWIDTH RIGHT PARENTHESIS
680*2d1272b8SAndroid Build Coastguard Worker case 0xff0cu: return 0xfe10u; // FULLWIDTH COMMA
681*2d1272b8SAndroid Build Coastguard Worker case 0xff1au: return 0xfe13u; // FULLWIDTH COLON
682*2d1272b8SAndroid Build Coastguard Worker case 0xff1bu: return 0xfe14u; // FULLWIDTH SEMICOLON
683*2d1272b8SAndroid Build Coastguard Worker case 0xff1fu: return 0xfe16u; // FULLWIDTH QUESTION MARK
684*2d1272b8SAndroid Build Coastguard Worker case 0xff3bu: return 0xfe47u; // FULLWIDTH LEFT SQUARE BRACKET
685*2d1272b8SAndroid Build Coastguard Worker case 0xff3du: return 0xfe48u; // FULLWIDTH RIGHT SQUARE BRACKET
686*2d1272b8SAndroid Build Coastguard Worker case 0xff3fu: return 0xfe33u; // FULLWIDTH LOW LINE
687*2d1272b8SAndroid Build Coastguard Worker case 0xff5bu: return 0xfe37u; // FULLWIDTH LEFT CURLY BRACKET
688*2d1272b8SAndroid Build Coastguard Worker case 0xff5du: return 0xfe38u; // FULLWIDTH RIGHT CURLY BRACKET
689*2d1272b8SAndroid Build Coastguard Worker } break;
690*2d1272b8SAndroid Build Coastguard Worker }
691*2d1272b8SAndroid Build Coastguard Worker
692*2d1272b8SAndroid Build Coastguard Worker return u;
693*2d1272b8SAndroid Build Coastguard Worker }
694*2d1272b8SAndroid Build Coastguard Worker #endif
695*2d1272b8SAndroid Build Coastguard Worker
696*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_rotate_chars(const hb_ot_shape_context_t * c)697*2d1272b8SAndroid Build Coastguard Worker hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
698*2d1272b8SAndroid Build Coastguard Worker {
699*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer = c->buffer;
700*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
701*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
702*2d1272b8SAndroid Build Coastguard Worker
703*2d1272b8SAndroid Build Coastguard Worker if (HB_DIRECTION_IS_BACKWARD (c->target_direction))
704*2d1272b8SAndroid Build Coastguard Worker {
705*2d1272b8SAndroid Build Coastguard Worker hb_unicode_funcs_t *unicode = buffer->unicode;
706*2d1272b8SAndroid Build Coastguard Worker hb_mask_t rtlm_mask = c->plan->rtlm_mask;
707*2d1272b8SAndroid Build Coastguard Worker
708*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++) {
709*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
710*2d1272b8SAndroid Build Coastguard Worker if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
711*2d1272b8SAndroid Build Coastguard Worker info[i].codepoint = codepoint;
712*2d1272b8SAndroid Build Coastguard Worker else
713*2d1272b8SAndroid Build Coastguard Worker info[i].mask |= rtlm_mask;
714*2d1272b8SAndroid Build Coastguard Worker }
715*2d1272b8SAndroid Build Coastguard Worker }
716*2d1272b8SAndroid Build Coastguard Worker
717*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
718*2d1272b8SAndroid Build Coastguard Worker if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert)
719*2d1272b8SAndroid Build Coastguard Worker {
720*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++) {
721*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t codepoint = hb_vert_char_for (info[i].codepoint);
722*2d1272b8SAndroid Build Coastguard Worker if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
723*2d1272b8SAndroid Build Coastguard Worker info[i].codepoint = codepoint;
724*2d1272b8SAndroid Build Coastguard Worker }
725*2d1272b8SAndroid Build Coastguard Worker }
726*2d1272b8SAndroid Build Coastguard Worker #endif
727*2d1272b8SAndroid Build Coastguard Worker }
728*2d1272b8SAndroid Build Coastguard Worker
729*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_shape_setup_masks_fraction(const hb_ot_shape_context_t * c)730*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
731*2d1272b8SAndroid Build Coastguard Worker {
732*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_NO_OT_SHAPE_FRACTIONS
733*2d1272b8SAndroid Build Coastguard Worker return;
734*2d1272b8SAndroid Build Coastguard Worker #endif
735*2d1272b8SAndroid Build Coastguard Worker
736*2d1272b8SAndroid Build Coastguard Worker if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
737*2d1272b8SAndroid Build Coastguard Worker !c->plan->has_frac)
738*2d1272b8SAndroid Build Coastguard Worker return;
739*2d1272b8SAndroid Build Coastguard Worker
740*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer = c->buffer;
741*2d1272b8SAndroid Build Coastguard Worker
742*2d1272b8SAndroid Build Coastguard Worker hb_mask_t pre_mask, post_mask;
743*2d1272b8SAndroid Build Coastguard Worker if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
744*2d1272b8SAndroid Build Coastguard Worker {
745*2d1272b8SAndroid Build Coastguard Worker pre_mask = c->plan->numr_mask | c->plan->frac_mask;
746*2d1272b8SAndroid Build Coastguard Worker post_mask = c->plan->frac_mask | c->plan->dnom_mask;
747*2d1272b8SAndroid Build Coastguard Worker }
748*2d1272b8SAndroid Build Coastguard Worker else
749*2d1272b8SAndroid Build Coastguard Worker {
750*2d1272b8SAndroid Build Coastguard Worker pre_mask = c->plan->frac_mask | c->plan->dnom_mask;
751*2d1272b8SAndroid Build Coastguard Worker post_mask = c->plan->numr_mask | c->plan->frac_mask;
752*2d1272b8SAndroid Build Coastguard Worker }
753*2d1272b8SAndroid Build Coastguard Worker
754*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
755*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
756*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
757*2d1272b8SAndroid Build Coastguard Worker {
758*2d1272b8SAndroid Build Coastguard Worker if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
759*2d1272b8SAndroid Build Coastguard Worker {
760*2d1272b8SAndroid Build Coastguard Worker unsigned int start = i, end = i + 1;
761*2d1272b8SAndroid Build Coastguard Worker while (start &&
762*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_get_general_category (&info[start - 1]) ==
763*2d1272b8SAndroid Build Coastguard Worker HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
764*2d1272b8SAndroid Build Coastguard Worker start--;
765*2d1272b8SAndroid Build Coastguard Worker while (end < count &&
766*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_get_general_category (&info[end]) ==
767*2d1272b8SAndroid Build Coastguard Worker HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
768*2d1272b8SAndroid Build Coastguard Worker end++;
769*2d1272b8SAndroid Build Coastguard Worker if (start == i || end == i + 1)
770*2d1272b8SAndroid Build Coastguard Worker {
771*2d1272b8SAndroid Build Coastguard Worker if (start == i)
772*2d1272b8SAndroid Build Coastguard Worker buffer->unsafe_to_concat (start, start + 1);
773*2d1272b8SAndroid Build Coastguard Worker if (end == i + 1)
774*2d1272b8SAndroid Build Coastguard Worker buffer->unsafe_to_concat (end - 1, end);
775*2d1272b8SAndroid Build Coastguard Worker continue;
776*2d1272b8SAndroid Build Coastguard Worker }
777*2d1272b8SAndroid Build Coastguard Worker
778*2d1272b8SAndroid Build Coastguard Worker buffer->unsafe_to_break (start, end);
779*2d1272b8SAndroid Build Coastguard Worker
780*2d1272b8SAndroid Build Coastguard Worker for (unsigned int j = start; j < i; j++)
781*2d1272b8SAndroid Build Coastguard Worker info[j].mask |= pre_mask;
782*2d1272b8SAndroid Build Coastguard Worker info[i].mask |= c->plan->frac_mask;
783*2d1272b8SAndroid Build Coastguard Worker for (unsigned int j = i + 1; j < end; j++)
784*2d1272b8SAndroid Build Coastguard Worker info[j].mask |= post_mask;
785*2d1272b8SAndroid Build Coastguard Worker
786*2d1272b8SAndroid Build Coastguard Worker i = end - 1;
787*2d1272b8SAndroid Build Coastguard Worker }
788*2d1272b8SAndroid Build Coastguard Worker }
789*2d1272b8SAndroid Build Coastguard Worker }
790*2d1272b8SAndroid Build Coastguard Worker
791*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_shape_initialize_masks(const hb_ot_shape_context_t * c)792*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_initialize_masks (const hb_ot_shape_context_t *c)
793*2d1272b8SAndroid Build Coastguard Worker {
794*2d1272b8SAndroid Build Coastguard Worker hb_ot_map_t *map = &c->plan->map;
795*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer = c->buffer;
796*2d1272b8SAndroid Build Coastguard Worker
797*2d1272b8SAndroid Build Coastguard Worker hb_mask_t global_mask = map->get_global_mask ();
798*2d1272b8SAndroid Build Coastguard Worker buffer->reset_masks (global_mask);
799*2d1272b8SAndroid Build Coastguard Worker }
800*2d1272b8SAndroid Build Coastguard Worker
801*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_shape_setup_masks(const hb_ot_shape_context_t * c)802*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c)
803*2d1272b8SAndroid Build Coastguard Worker {
804*2d1272b8SAndroid Build Coastguard Worker hb_ot_map_t *map = &c->plan->map;
805*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer = c->buffer;
806*2d1272b8SAndroid Build Coastguard Worker
807*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_setup_masks_fraction (c);
808*2d1272b8SAndroid Build Coastguard Worker
809*2d1272b8SAndroid Build Coastguard Worker if (c->plan->shaper->setup_masks)
810*2d1272b8SAndroid Build Coastguard Worker c->plan->shaper->setup_masks (c->plan, buffer, c->font);
811*2d1272b8SAndroid Build Coastguard Worker
812*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < c->num_user_features; i++)
813*2d1272b8SAndroid Build Coastguard Worker {
814*2d1272b8SAndroid Build Coastguard Worker const hb_feature_t *feature = &c->user_features[i];
815*2d1272b8SAndroid Build Coastguard Worker if (!(feature->start == HB_FEATURE_GLOBAL_START && feature->end == HB_FEATURE_GLOBAL_END)) {
816*2d1272b8SAndroid Build Coastguard Worker unsigned int shift;
817*2d1272b8SAndroid Build Coastguard Worker hb_mask_t mask = map->get_mask (feature->tag, &shift);
818*2d1272b8SAndroid Build Coastguard Worker buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
819*2d1272b8SAndroid Build Coastguard Worker }
820*2d1272b8SAndroid Build Coastguard Worker }
821*2d1272b8SAndroid Build Coastguard Worker }
822*2d1272b8SAndroid Build Coastguard Worker
823*2d1272b8SAndroid Build Coastguard Worker static void
hb_ot_zero_width_default_ignorables(const hb_buffer_t * buffer)824*2d1272b8SAndroid Build Coastguard Worker hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer)
825*2d1272b8SAndroid Build Coastguard Worker {
826*2d1272b8SAndroid Build Coastguard Worker if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
827*2d1272b8SAndroid Build Coastguard Worker (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) ||
828*2d1272b8SAndroid Build Coastguard Worker (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES))
829*2d1272b8SAndroid Build Coastguard Worker return;
830*2d1272b8SAndroid Build Coastguard Worker
831*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
832*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
833*2d1272b8SAndroid Build Coastguard Worker hb_glyph_position_t *pos = buffer->pos;
834*2d1272b8SAndroid Build Coastguard Worker unsigned int i = 0;
835*2d1272b8SAndroid Build Coastguard Worker for (i = 0; i < count; i++)
836*2d1272b8SAndroid Build Coastguard Worker if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
837*2d1272b8SAndroid Build Coastguard Worker pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
838*2d1272b8SAndroid Build Coastguard Worker }
839*2d1272b8SAndroid Build Coastguard Worker
840*2d1272b8SAndroid Build Coastguard Worker static void
hb_ot_deal_with_variation_selectors(hb_buffer_t * buffer)841*2d1272b8SAndroid Build Coastguard Worker hb_ot_deal_with_variation_selectors (hb_buffer_t *buffer)
842*2d1272b8SAndroid Build Coastguard Worker {
843*2d1272b8SAndroid Build Coastguard Worker if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK) ||
844*2d1272b8SAndroid Build Coastguard Worker buffer->not_found_variation_selector == HB_CODEPOINT_INVALID)
845*2d1272b8SAndroid Build Coastguard Worker return;
846*2d1272b8SAndroid Build Coastguard Worker
847*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
848*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
849*2d1272b8SAndroid Build Coastguard Worker hb_glyph_position_t *pos = buffer->pos;
850*2d1272b8SAndroid Build Coastguard Worker
851*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
852*2d1272b8SAndroid Build Coastguard Worker {
853*2d1272b8SAndroid Build Coastguard Worker if (_hb_glyph_info_is_variation_selector (&info[i]))
854*2d1272b8SAndroid Build Coastguard Worker {
855*2d1272b8SAndroid Build Coastguard Worker info[i].codepoint = buffer->not_found_variation_selector;
856*2d1272b8SAndroid Build Coastguard Worker pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
857*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_variation_selector (&info[i], false);
858*2d1272b8SAndroid Build Coastguard Worker }
859*2d1272b8SAndroid Build Coastguard Worker }
860*2d1272b8SAndroid Build Coastguard Worker }
861*2d1272b8SAndroid Build Coastguard Worker
862*2d1272b8SAndroid Build Coastguard Worker static void
hb_ot_hide_default_ignorables(hb_buffer_t * buffer,hb_font_t * font)863*2d1272b8SAndroid Build Coastguard Worker hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
864*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font)
865*2d1272b8SAndroid Build Coastguard Worker {
866*2d1272b8SAndroid Build Coastguard Worker if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
867*2d1272b8SAndroid Build Coastguard Worker (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
868*2d1272b8SAndroid Build Coastguard Worker return;
869*2d1272b8SAndroid Build Coastguard Worker
870*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
871*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
872*2d1272b8SAndroid Build Coastguard Worker
873*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t invisible = buffer->invisible;
874*2d1272b8SAndroid Build Coastguard Worker if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
875*2d1272b8SAndroid Build Coastguard Worker (invisible || font->get_nominal_glyph (' ', &invisible)))
876*2d1272b8SAndroid Build Coastguard Worker {
877*2d1272b8SAndroid Build Coastguard Worker /* Replace default-ignorables with a zero-advance invisible glyph. */
878*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
879*2d1272b8SAndroid Build Coastguard Worker {
880*2d1272b8SAndroid Build Coastguard Worker if (_hb_glyph_info_is_default_ignorable (&info[i]))
881*2d1272b8SAndroid Build Coastguard Worker info[i].codepoint = invisible;
882*2d1272b8SAndroid Build Coastguard Worker }
883*2d1272b8SAndroid Build Coastguard Worker }
884*2d1272b8SAndroid Build Coastguard Worker else
885*2d1272b8SAndroid Build Coastguard Worker buffer->delete_glyphs_inplace (_hb_glyph_info_is_default_ignorable);
886*2d1272b8SAndroid Build Coastguard Worker }
887*2d1272b8SAndroid Build Coastguard Worker
888*2d1272b8SAndroid Build Coastguard Worker
889*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_map_glyphs_fast(hb_buffer_t * buffer)890*2d1272b8SAndroid Build Coastguard Worker hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
891*2d1272b8SAndroid Build Coastguard Worker {
892*2d1272b8SAndroid Build Coastguard Worker /* Normalization process sets up glyph_index(), we just copy it. */
893*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
894*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
895*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
896*2d1272b8SAndroid Build Coastguard Worker info[i].codepoint = info[i].glyph_index();
897*2d1272b8SAndroid Build Coastguard Worker
898*2d1272b8SAndroid Build Coastguard Worker buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
899*2d1272b8SAndroid Build Coastguard Worker }
900*2d1272b8SAndroid Build Coastguard Worker
901*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_synthesize_glyph_classes(hb_buffer_t * buffer)902*2d1272b8SAndroid Build Coastguard Worker hb_synthesize_glyph_classes (hb_buffer_t *buffer)
903*2d1272b8SAndroid Build Coastguard Worker {
904*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
905*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
906*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
907*2d1272b8SAndroid Build Coastguard Worker {
908*2d1272b8SAndroid Build Coastguard Worker hb_ot_layout_glyph_props_flags_t klass;
909*2d1272b8SAndroid Build Coastguard Worker
910*2d1272b8SAndroid Build Coastguard Worker /* Never mark default-ignorables as marks.
911*2d1272b8SAndroid Build Coastguard Worker * They won't get in the way of lookups anyway,
912*2d1272b8SAndroid Build Coastguard Worker * but having them as mark will cause them to be skipped
913*2d1272b8SAndroid Build Coastguard Worker * over if the lookup-flag says so, but at least for the
914*2d1272b8SAndroid Build Coastguard Worker * Mongolian variation selectors, looks like Uniscribe
915*2d1272b8SAndroid Build Coastguard Worker * marks them as non-mark. Some Mongolian fonts without
916*2d1272b8SAndroid Build Coastguard Worker * GDEF rely on this. Another notable character that
917*2d1272b8SAndroid Build Coastguard Worker * this applies to is COMBINING GRAPHEME JOINER. */
918*2d1272b8SAndroid Build Coastguard Worker klass = (_hb_glyph_info_get_general_category (&info[i]) !=
919*2d1272b8SAndroid Build Coastguard Worker HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
920*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_is_default_ignorable (&info[i])) ?
921*2d1272b8SAndroid Build Coastguard Worker HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
922*2d1272b8SAndroid Build Coastguard Worker HB_OT_LAYOUT_GLYPH_PROPS_MARK;
923*2d1272b8SAndroid Build Coastguard Worker _hb_glyph_info_set_glyph_props (&info[i], klass);
924*2d1272b8SAndroid Build Coastguard Worker }
925*2d1272b8SAndroid Build Coastguard Worker }
926*2d1272b8SAndroid Build Coastguard Worker
927*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_substitute_default(const hb_ot_shape_context_t * c)928*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_default (const hb_ot_shape_context_t *c)
929*2d1272b8SAndroid Build Coastguard Worker {
930*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer = c->buffer;
931*2d1272b8SAndroid Build Coastguard Worker
932*2d1272b8SAndroid Build Coastguard Worker hb_ot_rotate_chars (c);
933*2d1272b8SAndroid Build Coastguard Worker
934*2d1272b8SAndroid Build Coastguard Worker HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
935*2d1272b8SAndroid Build Coastguard Worker
936*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shape_normalize (c->plan, buffer, c->font);
937*2d1272b8SAndroid Build Coastguard Worker
938*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_setup_masks (c);
939*2d1272b8SAndroid Build Coastguard Worker
940*2d1272b8SAndroid Build Coastguard Worker /* This is unfortunate to go here, but necessary... */
941*2d1272b8SAndroid Build Coastguard Worker if (c->plan->fallback_mark_positioning)
942*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shape_fallback_mark_position_recategorize_marks (c->plan, c->font, buffer);
943*2d1272b8SAndroid Build Coastguard Worker
944*2d1272b8SAndroid Build Coastguard Worker hb_ot_map_glyphs_fast (buffer);
945*2d1272b8SAndroid Build Coastguard Worker
946*2d1272b8SAndroid Build Coastguard Worker HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);
947*2d1272b8SAndroid Build Coastguard Worker }
948*2d1272b8SAndroid Build Coastguard Worker
949*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_substitute_plan(const hb_ot_shape_context_t * c)950*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_plan (const hb_ot_shape_context_t *c)
951*2d1272b8SAndroid Build Coastguard Worker {
952*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer = c->buffer;
953*2d1272b8SAndroid Build Coastguard Worker
954*2d1272b8SAndroid Build Coastguard Worker hb_ot_layout_substitute_start (c->font, buffer);
955*2d1272b8SAndroid Build Coastguard Worker
956*2d1272b8SAndroid Build Coastguard Worker if (c->plan->fallback_glyph_classes)
957*2d1272b8SAndroid Build Coastguard Worker hb_synthesize_glyph_classes (c->buffer);
958*2d1272b8SAndroid Build Coastguard Worker
959*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
960*2d1272b8SAndroid Build Coastguard Worker if (unlikely (c->plan->apply_morx))
961*2d1272b8SAndroid Build Coastguard Worker hb_aat_layout_substitute (c->plan, c->font, c->buffer,
962*2d1272b8SAndroid Build Coastguard Worker c->user_features, c->num_user_features);
963*2d1272b8SAndroid Build Coastguard Worker else
964*2d1272b8SAndroid Build Coastguard Worker #endif
965*2d1272b8SAndroid Build Coastguard Worker c->plan->substitute (c->font, buffer);
966*2d1272b8SAndroid Build Coastguard Worker }
967*2d1272b8SAndroid Build Coastguard Worker
968*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_substitute_pre(const hb_ot_shape_context_t * c)969*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
970*2d1272b8SAndroid Build Coastguard Worker {
971*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_default (c);
972*2d1272b8SAndroid Build Coastguard Worker
973*2d1272b8SAndroid Build Coastguard Worker _hb_buffer_allocate_gsubgpos_vars (c->buffer);
974*2d1272b8SAndroid Build Coastguard Worker
975*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_plan (c);
976*2d1272b8SAndroid Build Coastguard Worker
977*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
978*2d1272b8SAndroid Build Coastguard Worker if (c->plan->apply_morx && c->plan->apply_gpos)
979*2d1272b8SAndroid Build Coastguard Worker hb_aat_layout_remove_deleted_glyphs (c->buffer);
980*2d1272b8SAndroid Build Coastguard Worker #endif
981*2d1272b8SAndroid Build Coastguard Worker }
982*2d1272b8SAndroid Build Coastguard Worker
983*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_substitute_post(const hb_ot_shape_context_t * c)984*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_post (const hb_ot_shape_context_t *c)
985*2d1272b8SAndroid Build Coastguard Worker {
986*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
987*2d1272b8SAndroid Build Coastguard Worker if (c->plan->apply_morx && !c->plan->apply_gpos)
988*2d1272b8SAndroid Build Coastguard Worker hb_aat_layout_remove_deleted_glyphs (c->buffer);
989*2d1272b8SAndroid Build Coastguard Worker #endif
990*2d1272b8SAndroid Build Coastguard Worker
991*2d1272b8SAndroid Build Coastguard Worker hb_ot_deal_with_variation_selectors (c->buffer);
992*2d1272b8SAndroid Build Coastguard Worker hb_ot_hide_default_ignorables (c->buffer, c->font);
993*2d1272b8SAndroid Build Coastguard Worker
994*2d1272b8SAndroid Build Coastguard Worker if (c->plan->shaper->postprocess_glyphs &&
995*2d1272b8SAndroid Build Coastguard Worker c->buffer->message(c->font, "start postprocess-glyphs")) {
996*2d1272b8SAndroid Build Coastguard Worker c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
997*2d1272b8SAndroid Build Coastguard Worker (void) c->buffer->message(c->font, "end postprocess-glyphs");
998*2d1272b8SAndroid Build Coastguard Worker }
999*2d1272b8SAndroid Build Coastguard Worker }
1000*2d1272b8SAndroid Build Coastguard Worker
1001*2d1272b8SAndroid Build Coastguard Worker
1002*2d1272b8SAndroid Build Coastguard Worker /*
1003*2d1272b8SAndroid Build Coastguard Worker * Position
1004*2d1272b8SAndroid Build Coastguard Worker */
1005*2d1272b8SAndroid Build Coastguard Worker
1006*2d1272b8SAndroid Build Coastguard Worker static inline void
adjust_mark_offsets(hb_glyph_position_t * pos)1007*2d1272b8SAndroid Build Coastguard Worker adjust_mark_offsets (hb_glyph_position_t *pos)
1008*2d1272b8SAndroid Build Coastguard Worker {
1009*2d1272b8SAndroid Build Coastguard Worker pos->x_offset -= pos->x_advance;
1010*2d1272b8SAndroid Build Coastguard Worker pos->y_offset -= pos->y_advance;
1011*2d1272b8SAndroid Build Coastguard Worker }
1012*2d1272b8SAndroid Build Coastguard Worker
1013*2d1272b8SAndroid Build Coastguard Worker static inline void
zero_mark_width(hb_glyph_position_t * pos)1014*2d1272b8SAndroid Build Coastguard Worker zero_mark_width (hb_glyph_position_t *pos)
1015*2d1272b8SAndroid Build Coastguard Worker {
1016*2d1272b8SAndroid Build Coastguard Worker pos->x_advance = 0;
1017*2d1272b8SAndroid Build Coastguard Worker pos->y_advance = 0;
1018*2d1272b8SAndroid Build Coastguard Worker }
1019*2d1272b8SAndroid Build Coastguard Worker
1020*2d1272b8SAndroid Build Coastguard Worker static inline void
zero_mark_widths_by_gdef(hb_buffer_t * buffer,bool adjust_offsets)1021*2d1272b8SAndroid Build Coastguard Worker zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
1022*2d1272b8SAndroid Build Coastguard Worker {
1023*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
1024*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
1025*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
1026*2d1272b8SAndroid Build Coastguard Worker if (_hb_glyph_info_is_mark (&info[i]))
1027*2d1272b8SAndroid Build Coastguard Worker {
1028*2d1272b8SAndroid Build Coastguard Worker if (adjust_offsets)
1029*2d1272b8SAndroid Build Coastguard Worker adjust_mark_offsets (&buffer->pos[i]);
1030*2d1272b8SAndroid Build Coastguard Worker zero_mark_width (&buffer->pos[i]);
1031*2d1272b8SAndroid Build Coastguard Worker }
1032*2d1272b8SAndroid Build Coastguard Worker }
1033*2d1272b8SAndroid Build Coastguard Worker
1034*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_position_default(const hb_ot_shape_context_t * c)1035*2d1272b8SAndroid Build Coastguard Worker hb_ot_position_default (const hb_ot_shape_context_t *c)
1036*2d1272b8SAndroid Build Coastguard Worker {
1037*2d1272b8SAndroid Build Coastguard Worker hb_direction_t direction = c->buffer->props.direction;
1038*2d1272b8SAndroid Build Coastguard Worker unsigned int count = c->buffer->len;
1039*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = c->buffer->info;
1040*2d1272b8SAndroid Build Coastguard Worker hb_glyph_position_t *pos = c->buffer->pos;
1041*2d1272b8SAndroid Build Coastguard Worker
1042*2d1272b8SAndroid Build Coastguard Worker if (HB_DIRECTION_IS_HORIZONTAL (direction))
1043*2d1272b8SAndroid Build Coastguard Worker {
1044*2d1272b8SAndroid Build Coastguard Worker c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
1045*2d1272b8SAndroid Build Coastguard Worker &pos[0].x_advance, sizeof(pos[0]));
1046*2d1272b8SAndroid Build Coastguard Worker /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
1047*2d1272b8SAndroid Build Coastguard Worker if (c->font->has_glyph_h_origin_func ())
1048*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
1049*2d1272b8SAndroid Build Coastguard Worker c->font->subtract_glyph_h_origin (info[i].codepoint,
1050*2d1272b8SAndroid Build Coastguard Worker &pos[i].x_offset,
1051*2d1272b8SAndroid Build Coastguard Worker &pos[i].y_offset);
1052*2d1272b8SAndroid Build Coastguard Worker }
1053*2d1272b8SAndroid Build Coastguard Worker else
1054*2d1272b8SAndroid Build Coastguard Worker {
1055*2d1272b8SAndroid Build Coastguard Worker c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
1056*2d1272b8SAndroid Build Coastguard Worker &pos[0].y_advance, sizeof(pos[0]));
1057*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
1058*2d1272b8SAndroid Build Coastguard Worker {
1059*2d1272b8SAndroid Build Coastguard Worker c->font->subtract_glyph_v_origin (info[i].codepoint,
1060*2d1272b8SAndroid Build Coastguard Worker &pos[i].x_offset,
1061*2d1272b8SAndroid Build Coastguard Worker &pos[i].y_offset);
1062*2d1272b8SAndroid Build Coastguard Worker }
1063*2d1272b8SAndroid Build Coastguard Worker }
1064*2d1272b8SAndroid Build Coastguard Worker if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
1065*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
1066*2d1272b8SAndroid Build Coastguard Worker }
1067*2d1272b8SAndroid Build Coastguard Worker
1068*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_position_plan(const hb_ot_shape_context_t * c)1069*2d1272b8SAndroid Build Coastguard Worker hb_ot_position_plan (const hb_ot_shape_context_t *c)
1070*2d1272b8SAndroid Build Coastguard Worker {
1071*2d1272b8SAndroid Build Coastguard Worker unsigned int count = c->buffer->len;
1072*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = c->buffer->info;
1073*2d1272b8SAndroid Build Coastguard Worker hb_glyph_position_t *pos = c->buffer->pos;
1074*2d1272b8SAndroid Build Coastguard Worker
1075*2d1272b8SAndroid Build Coastguard Worker /* If the font has no GPOS and direction is forward, then when
1076*2d1272b8SAndroid Build Coastguard Worker * zeroing mark widths, we shift the mark with it, such that the
1077*2d1272b8SAndroid Build Coastguard Worker * mark is positioned hanging over the previous glyph. When
1078*2d1272b8SAndroid Build Coastguard Worker * direction is backward we don't shift and it will end up
1079*2d1272b8SAndroid Build Coastguard Worker * hanging over the next glyph after the final reordering.
1080*2d1272b8SAndroid Build Coastguard Worker *
1081*2d1272b8SAndroid Build Coastguard Worker * Note: If fallback positioning happens, we don't care about
1082*2d1272b8SAndroid Build Coastguard Worker * this as it will be overridden.
1083*2d1272b8SAndroid Build Coastguard Worker */
1084*2d1272b8SAndroid Build Coastguard Worker bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
1085*2d1272b8SAndroid Build Coastguard Worker HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
1086*2d1272b8SAndroid Build Coastguard Worker
1087*2d1272b8SAndroid Build Coastguard Worker /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
1088*2d1272b8SAndroid Build Coastguard Worker
1089*2d1272b8SAndroid Build Coastguard Worker /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
1090*2d1272b8SAndroid Build Coastguard Worker if (c->font->has_glyph_h_origin_func ())
1091*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
1092*2d1272b8SAndroid Build Coastguard Worker c->font->add_glyph_h_origin (info[i].codepoint,
1093*2d1272b8SAndroid Build Coastguard Worker &pos[i].x_offset,
1094*2d1272b8SAndroid Build Coastguard Worker &pos[i].y_offset);
1095*2d1272b8SAndroid Build Coastguard Worker
1096*2d1272b8SAndroid Build Coastguard Worker hb_ot_layout_position_start (c->font, c->buffer);
1097*2d1272b8SAndroid Build Coastguard Worker
1098*2d1272b8SAndroid Build Coastguard Worker if (c->plan->zero_marks)
1099*2d1272b8SAndroid Build Coastguard Worker switch (c->plan->shaper->zero_width_marks)
1100*2d1272b8SAndroid Build Coastguard Worker {
1101*2d1272b8SAndroid Build Coastguard Worker case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
1102*2d1272b8SAndroid Build Coastguard Worker zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
1103*2d1272b8SAndroid Build Coastguard Worker break;
1104*2d1272b8SAndroid Build Coastguard Worker
1105*2d1272b8SAndroid Build Coastguard Worker default:
1106*2d1272b8SAndroid Build Coastguard Worker case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
1107*2d1272b8SAndroid Build Coastguard Worker case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
1108*2d1272b8SAndroid Build Coastguard Worker break;
1109*2d1272b8SAndroid Build Coastguard Worker }
1110*2d1272b8SAndroid Build Coastguard Worker
1111*2d1272b8SAndroid Build Coastguard Worker c->plan->position (c->font, c->buffer);
1112*2d1272b8SAndroid Build Coastguard Worker
1113*2d1272b8SAndroid Build Coastguard Worker if (c->plan->zero_marks)
1114*2d1272b8SAndroid Build Coastguard Worker switch (c->plan->shaper->zero_width_marks)
1115*2d1272b8SAndroid Build Coastguard Worker {
1116*2d1272b8SAndroid Build Coastguard Worker case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
1117*2d1272b8SAndroid Build Coastguard Worker zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
1118*2d1272b8SAndroid Build Coastguard Worker break;
1119*2d1272b8SAndroid Build Coastguard Worker
1120*2d1272b8SAndroid Build Coastguard Worker default:
1121*2d1272b8SAndroid Build Coastguard Worker case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
1122*2d1272b8SAndroid Build Coastguard Worker case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
1123*2d1272b8SAndroid Build Coastguard Worker break;
1124*2d1272b8SAndroid Build Coastguard Worker }
1125*2d1272b8SAndroid Build Coastguard Worker
1126*2d1272b8SAndroid Build Coastguard Worker /* Finish off. Has to follow a certain order. */
1127*2d1272b8SAndroid Build Coastguard Worker hb_ot_layout_position_finish_advances (c->font, c->buffer);
1128*2d1272b8SAndroid Build Coastguard Worker hb_ot_zero_width_default_ignorables (c->buffer);
1129*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
1130*2d1272b8SAndroid Build Coastguard Worker if (c->plan->apply_morx)
1131*2d1272b8SAndroid Build Coastguard Worker hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
1132*2d1272b8SAndroid Build Coastguard Worker #endif
1133*2d1272b8SAndroid Build Coastguard Worker hb_ot_layout_position_finish_offsets (c->font, c->buffer);
1134*2d1272b8SAndroid Build Coastguard Worker
1135*2d1272b8SAndroid Build Coastguard Worker /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
1136*2d1272b8SAndroid Build Coastguard Worker if (c->font->has_glyph_h_origin_func ())
1137*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
1138*2d1272b8SAndroid Build Coastguard Worker c->font->subtract_glyph_h_origin (info[i].codepoint,
1139*2d1272b8SAndroid Build Coastguard Worker &pos[i].x_offset,
1140*2d1272b8SAndroid Build Coastguard Worker &pos[i].y_offset);
1141*2d1272b8SAndroid Build Coastguard Worker
1142*2d1272b8SAndroid Build Coastguard Worker if (c->plan->fallback_mark_positioning)
1143*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer,
1144*2d1272b8SAndroid Build Coastguard Worker adjust_offsets_when_zeroing);
1145*2d1272b8SAndroid Build Coastguard Worker }
1146*2d1272b8SAndroid Build Coastguard Worker
1147*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_ot_position(const hb_ot_shape_context_t * c)1148*2d1272b8SAndroid Build Coastguard Worker hb_ot_position (const hb_ot_shape_context_t *c)
1149*2d1272b8SAndroid Build Coastguard Worker {
1150*2d1272b8SAndroid Build Coastguard Worker c->buffer->clear_positions ();
1151*2d1272b8SAndroid Build Coastguard Worker
1152*2d1272b8SAndroid Build Coastguard Worker hb_ot_position_default (c);
1153*2d1272b8SAndroid Build Coastguard Worker
1154*2d1272b8SAndroid Build Coastguard Worker hb_ot_position_plan (c);
1155*2d1272b8SAndroid Build Coastguard Worker
1156*2d1272b8SAndroid Build Coastguard Worker if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
1157*2d1272b8SAndroid Build Coastguard Worker hb_buffer_reverse (c->buffer);
1158*2d1272b8SAndroid Build Coastguard Worker
1159*2d1272b8SAndroid Build Coastguard Worker _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
1160*2d1272b8SAndroid Build Coastguard Worker }
1161*2d1272b8SAndroid Build Coastguard Worker
1162*2d1272b8SAndroid Build Coastguard Worker static inline void
hb_propagate_flags(hb_buffer_t * buffer)1163*2d1272b8SAndroid Build Coastguard Worker hb_propagate_flags (hb_buffer_t *buffer)
1164*2d1272b8SAndroid Build Coastguard Worker {
1165*2d1272b8SAndroid Build Coastguard Worker /* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
1166*2d1272b8SAndroid Build Coastguard Worker * Simplifies using them. */
1167*2d1272b8SAndroid Build Coastguard Worker
1168*2d1272b8SAndroid Build Coastguard Worker if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
1169*2d1272b8SAndroid Build Coastguard Worker return;
1170*2d1272b8SAndroid Build Coastguard Worker
1171*2d1272b8SAndroid Build Coastguard Worker /* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things:
1172*2d1272b8SAndroid Build Coastguard Worker *
1173*2d1272b8SAndroid Build Coastguard Worker * - If the places that the Arabic shaper marked as SAFE_TO_INSERT_TATWEEL,
1174*2d1272b8SAndroid Build Coastguard Worker * are UNSAFE_TO_BREAK, then clear the SAFE_TO_INSERT_TATWEEL,
1175*2d1272b8SAndroid Build Coastguard Worker * - Any place that is SAFE_TO_INSERT_TATWEEL, is also now UNSAFE_TO_BREAK.
1176*2d1272b8SAndroid Build Coastguard Worker *
1177*2d1272b8SAndroid Build Coastguard Worker * We couldn't make this interaction earlier. It has to be done here.
1178*2d1272b8SAndroid Build Coastguard Worker */
1179*2d1272b8SAndroid Build Coastguard Worker bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
1180*2d1272b8SAndroid Build Coastguard Worker
1181*2d1272b8SAndroid Build Coastguard Worker bool clear_concat = (buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0;
1182*2d1272b8SAndroid Build Coastguard Worker
1183*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
1184*2d1272b8SAndroid Build Coastguard Worker
1185*2d1272b8SAndroid Build Coastguard Worker foreach_cluster (buffer, start, end)
1186*2d1272b8SAndroid Build Coastguard Worker {
1187*2d1272b8SAndroid Build Coastguard Worker unsigned int mask = 0;
1188*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = start; i < end; i++)
1189*2d1272b8SAndroid Build Coastguard Worker mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
1190*2d1272b8SAndroid Build Coastguard Worker
1191*2d1272b8SAndroid Build Coastguard Worker if (flip_tatweel)
1192*2d1272b8SAndroid Build Coastguard Worker {
1193*2d1272b8SAndroid Build Coastguard Worker if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
1194*2d1272b8SAndroid Build Coastguard Worker mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL;
1195*2d1272b8SAndroid Build Coastguard Worker if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL)
1196*2d1272b8SAndroid Build Coastguard Worker mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
1197*2d1272b8SAndroid Build Coastguard Worker }
1198*2d1272b8SAndroid Build Coastguard Worker
1199*2d1272b8SAndroid Build Coastguard Worker if (clear_concat)
1200*2d1272b8SAndroid Build Coastguard Worker mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
1201*2d1272b8SAndroid Build Coastguard Worker
1202*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = start; i < end; i++)
1203*2d1272b8SAndroid Build Coastguard Worker info[i].mask = mask;
1204*2d1272b8SAndroid Build Coastguard Worker }
1205*2d1272b8SAndroid Build Coastguard Worker }
1206*2d1272b8SAndroid Build Coastguard Worker
1207*2d1272b8SAndroid Build Coastguard Worker /* Pull it all together! */
1208*2d1272b8SAndroid Build Coastguard Worker
1209*2d1272b8SAndroid Build Coastguard Worker static void
hb_ot_shape_internal(hb_ot_shape_context_t * c)1210*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_internal (hb_ot_shape_context_t *c)
1211*2d1272b8SAndroid Build Coastguard Worker {
1212*2d1272b8SAndroid Build Coastguard Worker /* Save the original direction, we use it later. */
1213*2d1272b8SAndroid Build Coastguard Worker c->target_direction = c->buffer->props.direction;
1214*2d1272b8SAndroid Build Coastguard Worker
1215*2d1272b8SAndroid Build Coastguard Worker _hb_buffer_allocate_unicode_vars (c->buffer);
1216*2d1272b8SAndroid Build Coastguard Worker
1217*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_initialize_masks (c);
1218*2d1272b8SAndroid Build Coastguard Worker hb_set_unicode_props (c->buffer);
1219*2d1272b8SAndroid Build Coastguard Worker hb_insert_dotted_circle (c->buffer, c->font);
1220*2d1272b8SAndroid Build Coastguard Worker
1221*2d1272b8SAndroid Build Coastguard Worker hb_form_clusters (c->buffer);
1222*2d1272b8SAndroid Build Coastguard Worker
1223*2d1272b8SAndroid Build Coastguard Worker hb_ensure_native_direction (c->buffer);
1224*2d1272b8SAndroid Build Coastguard Worker
1225*2d1272b8SAndroid Build Coastguard Worker if (c->plan->shaper->preprocess_text &&
1226*2d1272b8SAndroid Build Coastguard Worker c->buffer->message(c->font, "start preprocess-text"))
1227*2d1272b8SAndroid Build Coastguard Worker {
1228*2d1272b8SAndroid Build Coastguard Worker c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
1229*2d1272b8SAndroid Build Coastguard Worker (void) c->buffer->message(c->font, "end preprocess-text");
1230*2d1272b8SAndroid Build Coastguard Worker }
1231*2d1272b8SAndroid Build Coastguard Worker
1232*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_pre (c);
1233*2d1272b8SAndroid Build Coastguard Worker hb_ot_position (c);
1234*2d1272b8SAndroid Build Coastguard Worker hb_ot_substitute_post (c);
1235*2d1272b8SAndroid Build Coastguard Worker
1236*2d1272b8SAndroid Build Coastguard Worker hb_propagate_flags (c->buffer);
1237*2d1272b8SAndroid Build Coastguard Worker
1238*2d1272b8SAndroid Build Coastguard Worker _hb_buffer_deallocate_unicode_vars (c->buffer);
1239*2d1272b8SAndroid Build Coastguard Worker
1240*2d1272b8SAndroid Build Coastguard Worker c->buffer->props.direction = c->target_direction;
1241*2d1272b8SAndroid Build Coastguard Worker
1242*2d1272b8SAndroid Build Coastguard Worker c->buffer->leave ();
1243*2d1272b8SAndroid Build Coastguard Worker }
1244*2d1272b8SAndroid Build Coastguard Worker
1245*2d1272b8SAndroid Build Coastguard Worker
1246*2d1272b8SAndroid Build Coastguard Worker hb_bool_t
_hb_ot_shape(hb_shape_plan_t * shape_plan,hb_font_t * font,hb_buffer_t * buffer,const hb_feature_t * features,unsigned int num_features)1247*2d1272b8SAndroid Build Coastguard Worker _hb_ot_shape (hb_shape_plan_t *shape_plan,
1248*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font,
1249*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer,
1250*2d1272b8SAndroid Build Coastguard Worker const hb_feature_t *features,
1251*2d1272b8SAndroid Build Coastguard Worker unsigned int num_features)
1252*2d1272b8SAndroid Build Coastguard Worker {
1253*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_context_t c = {&shape_plan->ot, font, font->face, buffer, features, num_features};
1254*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_internal (&c);
1255*2d1272b8SAndroid Build Coastguard Worker
1256*2d1272b8SAndroid Build Coastguard Worker return true;
1257*2d1272b8SAndroid Build Coastguard Worker }
1258*2d1272b8SAndroid Build Coastguard Worker
1259*2d1272b8SAndroid Build Coastguard Worker
1260*2d1272b8SAndroid Build Coastguard Worker /**
1261*2d1272b8SAndroid Build Coastguard Worker * hb_ot_shape_plan_collect_lookups:
1262*2d1272b8SAndroid Build Coastguard Worker * @shape_plan: #hb_shape_plan_t to query
1263*2d1272b8SAndroid Build Coastguard Worker * @table_tag: GSUB or GPOS
1264*2d1272b8SAndroid Build Coastguard Worker * @lookup_indexes: (out): The #hb_set_t set of lookups returned
1265*2d1272b8SAndroid Build Coastguard Worker *
1266*2d1272b8SAndroid Build Coastguard Worker * Computes the complete set of GSUB or GPOS lookups that are applicable
1267*2d1272b8SAndroid Build Coastguard Worker * under a given @shape_plan.
1268*2d1272b8SAndroid Build Coastguard Worker *
1269*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.7
1270*2d1272b8SAndroid Build Coastguard Worker **/
1271*2d1272b8SAndroid Build Coastguard Worker void
hb_ot_shape_plan_collect_lookups(hb_shape_plan_t * shape_plan,hb_tag_t table_tag,hb_set_t * lookup_indexes)1272*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
1273*2d1272b8SAndroid Build Coastguard Worker hb_tag_t table_tag,
1274*2d1272b8SAndroid Build Coastguard Worker hb_set_t *lookup_indexes /* OUT */)
1275*2d1272b8SAndroid Build Coastguard Worker {
1276*2d1272b8SAndroid Build Coastguard Worker shape_plan->ot.collect_lookups (table_tag, lookup_indexes);
1277*2d1272b8SAndroid Build Coastguard Worker }
1278*2d1272b8SAndroid Build Coastguard Worker
1279*2d1272b8SAndroid Build Coastguard Worker
1280*2d1272b8SAndroid Build Coastguard Worker /* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
1281*2d1272b8SAndroid Build Coastguard Worker static void
add_char(hb_font_t * font,hb_unicode_funcs_t * unicode,hb_bool_t mirror,hb_codepoint_t u,hb_set_t * glyphs)1282*2d1272b8SAndroid Build Coastguard Worker add_char (hb_font_t *font,
1283*2d1272b8SAndroid Build Coastguard Worker hb_unicode_funcs_t *unicode,
1284*2d1272b8SAndroid Build Coastguard Worker hb_bool_t mirror,
1285*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t u,
1286*2d1272b8SAndroid Build Coastguard Worker hb_set_t *glyphs)
1287*2d1272b8SAndroid Build Coastguard Worker {
1288*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph;
1289*2d1272b8SAndroid Build Coastguard Worker if (font->get_nominal_glyph (u, &glyph))
1290*2d1272b8SAndroid Build Coastguard Worker glyphs->add (glyph);
1291*2d1272b8SAndroid Build Coastguard Worker if (mirror)
1292*2d1272b8SAndroid Build Coastguard Worker {
1293*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t m = unicode->mirroring (u);
1294*2d1272b8SAndroid Build Coastguard Worker if (m != u && font->get_nominal_glyph (m, &glyph))
1295*2d1272b8SAndroid Build Coastguard Worker glyphs->add (glyph);
1296*2d1272b8SAndroid Build Coastguard Worker }
1297*2d1272b8SAndroid Build Coastguard Worker }
1298*2d1272b8SAndroid Build Coastguard Worker
1299*2d1272b8SAndroid Build Coastguard Worker
1300*2d1272b8SAndroid Build Coastguard Worker /**
1301*2d1272b8SAndroid Build Coastguard Worker * hb_ot_shape_glyphs_closure:
1302*2d1272b8SAndroid Build Coastguard Worker * @font: #hb_font_t to work upon
1303*2d1272b8SAndroid Build Coastguard Worker * @buffer: The input buffer to compute from
1304*2d1272b8SAndroid Build Coastguard Worker * @features: (array length=num_features): The features enabled on the buffer
1305*2d1272b8SAndroid Build Coastguard Worker * @num_features: The number of features enabled on the buffer
1306*2d1272b8SAndroid Build Coastguard Worker * @glyphs: (out): The #hb_set_t set of glyphs comprising the transitive closure of the query
1307*2d1272b8SAndroid Build Coastguard Worker *
1308*2d1272b8SAndroid Build Coastguard Worker * Computes the transitive closure of glyphs needed for a specified
1309*2d1272b8SAndroid Build Coastguard Worker * input buffer under the given font and feature list. The closure is
1310*2d1272b8SAndroid Build Coastguard Worker * computed as a set, not as a list.
1311*2d1272b8SAndroid Build Coastguard Worker *
1312*2d1272b8SAndroid Build Coastguard Worker * Since: 0.9.2
1313*2d1272b8SAndroid Build Coastguard Worker **/
1314*2d1272b8SAndroid Build Coastguard Worker void
hb_ot_shape_glyphs_closure(hb_font_t * font,hb_buffer_t * buffer,const hb_feature_t * features,unsigned int num_features,hb_set_t * glyphs)1315*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_glyphs_closure (hb_font_t *font,
1316*2d1272b8SAndroid Build Coastguard Worker hb_buffer_t *buffer,
1317*2d1272b8SAndroid Build Coastguard Worker const hb_feature_t *features,
1318*2d1272b8SAndroid Build Coastguard Worker unsigned int num_features,
1319*2d1272b8SAndroid Build Coastguard Worker hb_set_t *glyphs)
1320*2d1272b8SAndroid Build Coastguard Worker {
1321*2d1272b8SAndroid Build Coastguard Worker const char *shapers[] = {"ot", nullptr};
1322*2d1272b8SAndroid Build Coastguard Worker hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
1323*2d1272b8SAndroid Build Coastguard Worker features, num_features, shapers);
1324*2d1272b8SAndroid Build Coastguard Worker
1325*2d1272b8SAndroid Build Coastguard Worker bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
1326*2d1272b8SAndroid Build Coastguard Worker
1327*2d1272b8SAndroid Build Coastguard Worker unsigned int count = buffer->len;
1328*2d1272b8SAndroid Build Coastguard Worker hb_glyph_info_t *info = buffer->info;
1329*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++)
1330*2d1272b8SAndroid Build Coastguard Worker add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
1331*2d1272b8SAndroid Build Coastguard Worker
1332*2d1272b8SAndroid Build Coastguard Worker hb_set_t *lookups = hb_set_create ();
1333*2d1272b8SAndroid Build Coastguard Worker hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups);
1334*2d1272b8SAndroid Build Coastguard Worker hb_ot_layout_lookups_substitute_closure (font->face, lookups, glyphs);
1335*2d1272b8SAndroid Build Coastguard Worker
1336*2d1272b8SAndroid Build Coastguard Worker hb_set_destroy (lookups);
1337*2d1272b8SAndroid Build Coastguard Worker
1338*2d1272b8SAndroid Build Coastguard Worker hb_shape_plan_destroy (shape_plan);
1339*2d1272b8SAndroid Build Coastguard Worker }
1340*2d1272b8SAndroid Build Coastguard Worker
1341*2d1272b8SAndroid Build Coastguard Worker
1342*2d1272b8SAndroid Build Coastguard Worker #endif
1343