xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-shape.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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