xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-map.hh (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,2013  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 #ifndef HB_OT_MAP_HH
30*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_MAP_HH
31*2d1272b8SAndroid Build Coastguard Worker 
32*2d1272b8SAndroid Build Coastguard Worker #include "hb-buffer.hh"
33*2d1272b8SAndroid Build Coastguard Worker 
34*2d1272b8SAndroid Build Coastguard Worker 
35*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_MAP_MAX_BITS 8u
36*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_MAP_MAX_VALUE ((1u << HB_OT_MAP_MAX_BITS) - 1u)
37*2d1272b8SAndroid Build Coastguard Worker 
38*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_shape_plan_t;
39*2d1272b8SAndroid Build Coastguard Worker 
40*2d1272b8SAndroid Build Coastguard Worker static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
41*2d1272b8SAndroid Build Coastguard Worker 
42*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_map_t
43*2d1272b8SAndroid Build Coastguard Worker {
44*2d1272b8SAndroid Build Coastguard Worker   friend struct hb_ot_map_builder_t;
45*2d1272b8SAndroid Build Coastguard Worker 
46*2d1272b8SAndroid Build Coastguard Worker   public:
47*2d1272b8SAndroid Build Coastguard Worker 
48*2d1272b8SAndroid Build Coastguard Worker   struct feature_map_t {
49*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t tag; /* should be first for our bsearch to work */
50*2d1272b8SAndroid Build Coastguard Worker     unsigned int index[2]; /* GSUB/GPOS */
51*2d1272b8SAndroid Build Coastguard Worker     unsigned int stage[2]; /* GSUB/GPOS */
52*2d1272b8SAndroid Build Coastguard Worker     unsigned int shift;
53*2d1272b8SAndroid Build Coastguard Worker     hb_mask_t mask;
54*2d1272b8SAndroid Build Coastguard Worker     hb_mask_t _1_mask; /* mask for value=1, for quick access */
55*2d1272b8SAndroid Build Coastguard Worker     unsigned int needs_fallback : 1;
56*2d1272b8SAndroid Build Coastguard Worker     unsigned int auto_zwnj : 1;
57*2d1272b8SAndroid Build Coastguard Worker     unsigned int auto_zwj : 1;
58*2d1272b8SAndroid Build Coastguard Worker     unsigned int random : 1;
59*2d1272b8SAndroid Build Coastguard Worker     unsigned int per_syllable : 1;
60*2d1272b8SAndroid Build Coastguard Worker 
cmphb_ot_map_t::feature_map_t61*2d1272b8SAndroid Build Coastguard Worker     int cmp (const hb_tag_t tag_) const
62*2d1272b8SAndroid Build Coastguard Worker     { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
63*2d1272b8SAndroid Build Coastguard Worker 
cmphb_ot_map_t::feature_map_t64*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL static int cmp (const void *pa, const void *pb)
65*2d1272b8SAndroid Build Coastguard Worker     {
66*2d1272b8SAndroid Build Coastguard Worker       const feature_map_t *a = (const feature_map_t *) pa;
67*2d1272b8SAndroid Build Coastguard Worker       const feature_map_t *b = (const feature_map_t *) pb;
68*2d1272b8SAndroid Build Coastguard Worker       return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
69*2d1272b8SAndroid Build Coastguard Worker     }
70*2d1272b8SAndroid Build Coastguard Worker   };
71*2d1272b8SAndroid Build Coastguard Worker 
72*2d1272b8SAndroid Build Coastguard Worker   struct lookup_map_t {
73*2d1272b8SAndroid Build Coastguard Worker     unsigned short index;
74*2d1272b8SAndroid Build Coastguard Worker     unsigned short auto_zwnj : 1;
75*2d1272b8SAndroid Build Coastguard Worker     unsigned short auto_zwj : 1;
76*2d1272b8SAndroid Build Coastguard Worker     unsigned short random : 1;
77*2d1272b8SAndroid Build Coastguard Worker     unsigned short per_syllable : 1;
78*2d1272b8SAndroid Build Coastguard Worker     hb_mask_t mask;
79*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t feature_tag;
80*2d1272b8SAndroid Build Coastguard Worker 
cmphb_ot_map_t::lookup_map_t81*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL static int cmp (const void *pa, const void *pb)
82*2d1272b8SAndroid Build Coastguard Worker     {
83*2d1272b8SAndroid Build Coastguard Worker       const lookup_map_t *a = (const lookup_map_t *) pa;
84*2d1272b8SAndroid Build Coastguard Worker       const lookup_map_t *b = (const lookup_map_t *) pb;
85*2d1272b8SAndroid Build Coastguard Worker       return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
86*2d1272b8SAndroid Build Coastguard Worker     }
87*2d1272b8SAndroid Build Coastguard Worker   };
88*2d1272b8SAndroid Build Coastguard Worker 
89*2d1272b8SAndroid Build Coastguard Worker   /* Pause functions return true if new glyph indices might have been
90*2d1272b8SAndroid Build Coastguard Worker    * added to the buffer.  This is used to update buffer digest. */
91*2d1272b8SAndroid Build Coastguard Worker   typedef bool (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
92*2d1272b8SAndroid Build Coastguard Worker 
93*2d1272b8SAndroid Build Coastguard Worker   struct stage_map_t {
94*2d1272b8SAndroid Build Coastguard Worker     unsigned int last_lookup; /* Cumulative */
95*2d1272b8SAndroid Build Coastguard Worker     pause_func_t pause_func;
96*2d1272b8SAndroid Build Coastguard Worker   };
97*2d1272b8SAndroid Build Coastguard Worker 
inithb_ot_map_t98*2d1272b8SAndroid Build Coastguard Worker   void init ()
99*2d1272b8SAndroid Build Coastguard Worker   {
100*2d1272b8SAndroid Build Coastguard Worker     hb_memset (this, 0, sizeof (*this));
101*2d1272b8SAndroid Build Coastguard Worker 
102*2d1272b8SAndroid Build Coastguard Worker     features.init0 ();
103*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int table_index = 0; table_index < 2; table_index++)
104*2d1272b8SAndroid Build Coastguard Worker     {
105*2d1272b8SAndroid Build Coastguard Worker       lookups[table_index].init0 ();
106*2d1272b8SAndroid Build Coastguard Worker       stages[table_index].init0 ();
107*2d1272b8SAndroid Build Coastguard Worker     }
108*2d1272b8SAndroid Build Coastguard Worker   }
finihb_ot_map_t109*2d1272b8SAndroid Build Coastguard Worker   void fini ()
110*2d1272b8SAndroid Build Coastguard Worker   {
111*2d1272b8SAndroid Build Coastguard Worker     features.fini ();
112*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int table_index = 0; table_index < 2; table_index++)
113*2d1272b8SAndroid Build Coastguard Worker     {
114*2d1272b8SAndroid Build Coastguard Worker       lookups[table_index].fini ();
115*2d1272b8SAndroid Build Coastguard Worker       stages[table_index].fini ();
116*2d1272b8SAndroid Build Coastguard Worker     }
117*2d1272b8SAndroid Build Coastguard Worker   }
118*2d1272b8SAndroid Build Coastguard Worker 
get_global_maskhb_ot_map_t119*2d1272b8SAndroid Build Coastguard Worker   hb_mask_t get_global_mask () const { return global_mask; }
120*2d1272b8SAndroid Build Coastguard Worker 
get_maskhb_ot_map_t121*2d1272b8SAndroid Build Coastguard Worker   hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const
122*2d1272b8SAndroid Build Coastguard Worker   {
123*2d1272b8SAndroid Build Coastguard Worker     const feature_map_t *map = features.bsearch (feature_tag);
124*2d1272b8SAndroid Build Coastguard Worker     if (shift) *shift = map ? map->shift : 0;
125*2d1272b8SAndroid Build Coastguard Worker     return map ? map->mask : 0;
126*2d1272b8SAndroid Build Coastguard Worker   }
127*2d1272b8SAndroid Build Coastguard Worker 
needs_fallbackhb_ot_map_t128*2d1272b8SAndroid Build Coastguard Worker   bool needs_fallback (hb_tag_t feature_tag) const
129*2d1272b8SAndroid Build Coastguard Worker   {
130*2d1272b8SAndroid Build Coastguard Worker     const feature_map_t *map = features.bsearch (feature_tag);
131*2d1272b8SAndroid Build Coastguard Worker     return map ? map->needs_fallback : false;
132*2d1272b8SAndroid Build Coastguard Worker   }
133*2d1272b8SAndroid Build Coastguard Worker 
get_1_maskhb_ot_map_t134*2d1272b8SAndroid Build Coastguard Worker   hb_mask_t get_1_mask (hb_tag_t feature_tag) const
135*2d1272b8SAndroid Build Coastguard Worker   {
136*2d1272b8SAndroid Build Coastguard Worker     const feature_map_t *map = features.bsearch (feature_tag);
137*2d1272b8SAndroid Build Coastguard Worker     return map ? map->_1_mask : 0;
138*2d1272b8SAndroid Build Coastguard Worker   }
139*2d1272b8SAndroid Build Coastguard Worker 
get_feature_indexhb_ot_map_t140*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const
141*2d1272b8SAndroid Build Coastguard Worker   {
142*2d1272b8SAndroid Build Coastguard Worker     const feature_map_t *map = features.bsearch (feature_tag);
143*2d1272b8SAndroid Build Coastguard Worker     return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
144*2d1272b8SAndroid Build Coastguard Worker   }
145*2d1272b8SAndroid Build Coastguard Worker 
get_feature_stagehb_ot_map_t146*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const
147*2d1272b8SAndroid Build Coastguard Worker   {
148*2d1272b8SAndroid Build Coastguard Worker     const feature_map_t *map = features.bsearch (feature_tag);
149*2d1272b8SAndroid Build Coastguard Worker     return map ? map->stage[table_index] : UINT_MAX;
150*2d1272b8SAndroid Build Coastguard Worker   }
151*2d1272b8SAndroid Build Coastguard Worker 
152*2d1272b8SAndroid Build Coastguard Worker   hb_array_t<const hb_ot_map_t::lookup_map_t>
get_stage_lookupshb_ot_map_t153*2d1272b8SAndroid Build Coastguard Worker   get_stage_lookups (unsigned int table_index, unsigned int stage) const
154*2d1272b8SAndroid Build Coastguard Worker   {
155*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (stage > stages[table_index].length))
156*2d1272b8SAndroid Build Coastguard Worker       return hb_array<const hb_ot_map_t::lookup_map_t> (nullptr, 0);
157*2d1272b8SAndroid Build Coastguard Worker 
158*2d1272b8SAndroid Build Coastguard Worker     unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
159*2d1272b8SAndroid Build Coastguard Worker     unsigned int end   = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length;
160*2d1272b8SAndroid Build Coastguard Worker     return lookups[table_index].as_array ().sub_array (start, end - start);
161*2d1272b8SAndroid Build Coastguard Worker   }
162*2d1272b8SAndroid Build Coastguard Worker 
163*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
164*2d1272b8SAndroid Build Coastguard Worker   template <typename Proxy>
165*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void apply (const Proxy &proxy,
166*2d1272b8SAndroid Build Coastguard Worker 			  const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
167*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
168*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
169*2d1272b8SAndroid Build Coastguard Worker 
170*2d1272b8SAndroid Build Coastguard Worker   public:
171*2d1272b8SAndroid Build Coastguard Worker   hb_tag_t chosen_script[2];
172*2d1272b8SAndroid Build Coastguard Worker   bool found_script[2];
173*2d1272b8SAndroid Build Coastguard Worker 
174*2d1272b8SAndroid Build Coastguard Worker   private:
175*2d1272b8SAndroid Build Coastguard Worker 
176*2d1272b8SAndroid Build Coastguard Worker   hb_mask_t global_mask = 0;
177*2d1272b8SAndroid Build Coastguard Worker 
178*2d1272b8SAndroid Build Coastguard Worker   hb_sorted_vector_t<feature_map_t> features;
179*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
180*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<stage_map_t> stages[2]; /* GSUB/GPOS */
181*2d1272b8SAndroid Build Coastguard Worker };
182*2d1272b8SAndroid Build Coastguard Worker 
183*2d1272b8SAndroid Build Coastguard Worker enum hb_ot_map_feature_flags_t
184*2d1272b8SAndroid Build Coastguard Worker {
185*2d1272b8SAndroid Build Coastguard Worker   F_NONE		= 0x0000u,
186*2d1272b8SAndroid Build Coastguard Worker   F_GLOBAL		= 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
187*2d1272b8SAndroid Build Coastguard Worker   F_HAS_FALLBACK	= 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
188*2d1272b8SAndroid Build Coastguard Worker   F_MANUAL_ZWNJ		= 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
189*2d1272b8SAndroid Build Coastguard Worker   F_MANUAL_ZWJ		= 0x0008u, /* Don't skip over ZWJ when matching **input**. */
190*2d1272b8SAndroid Build Coastguard Worker   F_MANUAL_JOINERS	= F_MANUAL_ZWNJ | F_MANUAL_ZWJ,
191*2d1272b8SAndroid Build Coastguard Worker   F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS,
192*2d1272b8SAndroid Build Coastguard Worker   F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK,
193*2d1272b8SAndroid Build Coastguard Worker   F_GLOBAL_SEARCH	= 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
194*2d1272b8SAndroid Build Coastguard Worker   F_RANDOM		= 0x0020u, /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
195*2d1272b8SAndroid Build Coastguard Worker   F_PER_SYLLABLE	= 0x0040u  /* Contain lookup application to within syllable. */
196*2d1272b8SAndroid Build Coastguard Worker };
197*2d1272b8SAndroid Build Coastguard Worker HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
198*2d1272b8SAndroid Build Coastguard Worker 
199*2d1272b8SAndroid Build Coastguard Worker 
200*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_map_feature_t
201*2d1272b8SAndroid Build Coastguard Worker {
202*2d1272b8SAndroid Build Coastguard Worker   hb_tag_t tag;
203*2d1272b8SAndroid Build Coastguard Worker   hb_ot_map_feature_flags_t flags;
204*2d1272b8SAndroid Build Coastguard Worker };
205*2d1272b8SAndroid Build Coastguard Worker 
206*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_shape_plan_key_t;
207*2d1272b8SAndroid Build Coastguard Worker 
208*2d1272b8SAndroid Build Coastguard Worker struct hb_ot_map_builder_t
209*2d1272b8SAndroid Build Coastguard Worker {
210*2d1272b8SAndroid Build Coastguard Worker   public:
211*2d1272b8SAndroid Build Coastguard Worker 
212*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
213*2d1272b8SAndroid Build Coastguard Worker 				   const hb_segment_properties_t &props_);
214*2d1272b8SAndroid Build Coastguard Worker 
215*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL ~hb_ot_map_builder_t ();
216*2d1272b8SAndroid Build Coastguard Worker 
217*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void add_feature (hb_tag_t tag,
218*2d1272b8SAndroid Build Coastguard Worker 				hb_ot_map_feature_flags_t flags=F_NONE,
219*2d1272b8SAndroid Build Coastguard Worker 				unsigned int value=1);
220*2d1272b8SAndroid Build Coastguard Worker 
221*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL bool has_feature (hb_tag_t tag);
222*2d1272b8SAndroid Build Coastguard Worker 
add_featurehb_ot_map_builder_t223*2d1272b8SAndroid Build Coastguard Worker   void add_feature (const hb_ot_map_feature_t &feat)
224*2d1272b8SAndroid Build Coastguard Worker   { add_feature (feat.tag, feat.flags); }
225*2d1272b8SAndroid Build Coastguard Worker 
enable_featurehb_ot_map_builder_t226*2d1272b8SAndroid Build Coastguard Worker   void enable_feature (hb_tag_t tag,
227*2d1272b8SAndroid Build Coastguard Worker 		       hb_ot_map_feature_flags_t flags=F_NONE,
228*2d1272b8SAndroid Build Coastguard Worker 		       unsigned int value=1)
229*2d1272b8SAndroid Build Coastguard Worker   { add_feature (tag, F_GLOBAL | flags, value); }
230*2d1272b8SAndroid Build Coastguard Worker 
disable_featurehb_ot_map_builder_t231*2d1272b8SAndroid Build Coastguard Worker   void disable_feature (hb_tag_t tag)
232*2d1272b8SAndroid Build Coastguard Worker   { add_feature (tag, F_GLOBAL, 0); }
233*2d1272b8SAndroid Build Coastguard Worker 
add_gsub_pausehb_ot_map_builder_t234*2d1272b8SAndroid Build Coastguard Worker   void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
235*2d1272b8SAndroid Build Coastguard Worker   { add_pause (0, pause_func); }
add_gpos_pausehb_ot_map_builder_t236*2d1272b8SAndroid Build Coastguard Worker   void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
237*2d1272b8SAndroid Build Coastguard Worker   { add_pause (1, pause_func); }
238*2d1272b8SAndroid Build Coastguard Worker 
239*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void compile (hb_ot_map_t                  &m,
240*2d1272b8SAndroid Build Coastguard Worker 			    const hb_ot_shape_plan_key_t &key);
241*2d1272b8SAndroid Build Coastguard Worker 
242*2d1272b8SAndroid Build Coastguard Worker   private:
243*2d1272b8SAndroid Build Coastguard Worker 
244*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
245*2d1272b8SAndroid Build Coastguard Worker 				unsigned int  table_index,
246*2d1272b8SAndroid Build Coastguard Worker 				unsigned int  feature_index,
247*2d1272b8SAndroid Build Coastguard Worker 				unsigned int  variations_index,
248*2d1272b8SAndroid Build Coastguard Worker 				hb_mask_t     mask,
249*2d1272b8SAndroid Build Coastguard Worker 				bool          auto_zwnj = true,
250*2d1272b8SAndroid Build Coastguard Worker 				bool          auto_zwj = true,
251*2d1272b8SAndroid Build Coastguard Worker 				bool          random = false,
252*2d1272b8SAndroid Build Coastguard Worker 				bool          per_syllable = false,
253*2d1272b8SAndroid Build Coastguard Worker 				hb_tag_t      feature_tag = HB_TAG(' ',' ',' ',' '));
254*2d1272b8SAndroid Build Coastguard Worker 
255*2d1272b8SAndroid Build Coastguard Worker   struct feature_info_t {
256*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t tag;
257*2d1272b8SAndroid Build Coastguard Worker     unsigned int seq; /* sequence#, used for stable sorting only */
258*2d1272b8SAndroid Build Coastguard Worker     unsigned int max_value;
259*2d1272b8SAndroid Build Coastguard Worker     hb_ot_map_feature_flags_t flags;
260*2d1272b8SAndroid Build Coastguard Worker     unsigned int default_value; /* for non-global features, what should the unset glyphs take */
261*2d1272b8SAndroid Build Coastguard Worker     unsigned int stage[2]; /* GSUB/GPOS */
262*2d1272b8SAndroid Build Coastguard Worker 
cmphb_ot_map_builder_t::feature_info_t263*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL static int cmp (const void *pa, const void *pb)
264*2d1272b8SAndroid Build Coastguard Worker     {
265*2d1272b8SAndroid Build Coastguard Worker       const feature_info_t *a = (const feature_info_t *) pa;
266*2d1272b8SAndroid Build Coastguard Worker       const feature_info_t *b = (const feature_info_t *) pb;
267*2d1272b8SAndroid Build Coastguard Worker       return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
268*2d1272b8SAndroid Build Coastguard Worker 	     (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
269*2d1272b8SAndroid Build Coastguard Worker     }
270*2d1272b8SAndroid Build Coastguard Worker   };
271*2d1272b8SAndroid Build Coastguard Worker 
272*2d1272b8SAndroid Build Coastguard Worker   struct stage_info_t {
273*2d1272b8SAndroid Build Coastguard Worker     unsigned int index;
274*2d1272b8SAndroid Build Coastguard Worker     hb_ot_map_t::pause_func_t pause_func;
275*2d1272b8SAndroid Build Coastguard Worker   };
276*2d1272b8SAndroid Build Coastguard Worker 
277*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
278*2d1272b8SAndroid Build Coastguard Worker 
279*2d1272b8SAndroid Build Coastguard Worker   public:
280*2d1272b8SAndroid Build Coastguard Worker 
281*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *face;
282*2d1272b8SAndroid Build Coastguard Worker   hb_segment_properties_t props;
283*2d1272b8SAndroid Build Coastguard Worker   bool is_simple;
284*2d1272b8SAndroid Build Coastguard Worker 
285*2d1272b8SAndroid Build Coastguard Worker   hb_tag_t chosen_script[2];
286*2d1272b8SAndroid Build Coastguard Worker   bool found_script[2];
287*2d1272b8SAndroid Build Coastguard Worker   unsigned int script_index[2], language_index[2];
288*2d1272b8SAndroid Build Coastguard Worker 
289*2d1272b8SAndroid Build Coastguard Worker   private:
290*2d1272b8SAndroid Build Coastguard Worker 
291*2d1272b8SAndroid Build Coastguard Worker   unsigned int current_stage[2]; /* GSUB/GPOS */
292*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<feature_info_t> feature_infos;
293*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<stage_info_t> stages[2]; /* GSUB/GPOS */
294*2d1272b8SAndroid Build Coastguard Worker };
295*2d1272b8SAndroid Build Coastguard Worker 
296*2d1272b8SAndroid Build Coastguard Worker 
297*2d1272b8SAndroid Build Coastguard Worker 
298*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_MAP_HH */
299