xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-var-avar-table.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2017  Google, Inc.
3*2d1272b8SAndroid Build Coastguard Worker  *
4*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker  *
6*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker  *
12*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker  *
18*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker  *
24*2d1272b8SAndroid Build Coastguard Worker  * Google Author(s): Behdad Esfahbod
25*2d1272b8SAndroid Build Coastguard Worker  */
26*2d1272b8SAndroid Build Coastguard Worker 
27*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_OT_VAR_AVAR_TABLE_HH
28*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_VAR_AVAR_TABLE_HH
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #include "hb-open-type.hh"
31*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-var-common.hh"
32*2d1272b8SAndroid Build Coastguard Worker 
33*2d1272b8SAndroid Build Coastguard Worker 
34*2d1272b8SAndroid Build Coastguard Worker /*
35*2d1272b8SAndroid Build Coastguard Worker  * avar -- Axis Variations
36*2d1272b8SAndroid Build Coastguard Worker  * https://docs.microsoft.com/en-us/typography/opentype/spec/avar
37*2d1272b8SAndroid Build Coastguard Worker  */
38*2d1272b8SAndroid Build Coastguard Worker 
39*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_avar HB_TAG('a','v','a','r')
40*2d1272b8SAndroid Build Coastguard Worker 
41*2d1272b8SAndroid Build Coastguard Worker 
42*2d1272b8SAndroid Build Coastguard Worker namespace OT {
43*2d1272b8SAndroid Build Coastguard Worker 
44*2d1272b8SAndroid Build Coastguard Worker 
45*2d1272b8SAndroid Build Coastguard Worker /* "Spec": https://github.com/be-fonts/boring-expansion-spec/issues/14 */
46*2d1272b8SAndroid Build Coastguard Worker struct avarV2Tail
47*2d1272b8SAndroid Build Coastguard Worker {
48*2d1272b8SAndroid Build Coastguard Worker   friend struct avar;
49*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::avarV2Tail50*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c,
51*2d1272b8SAndroid Build Coastguard Worker 		 const void *base) const
52*2d1272b8SAndroid Build Coastguard Worker   {
53*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
54*2d1272b8SAndroid Build Coastguard Worker     return_trace (varIdxMap.sanitize (c, base) &&
55*2d1272b8SAndroid Build Coastguard Worker 		  varStore.sanitize (c, base));
56*2d1272b8SAndroid Build Coastguard Worker   }
57*2d1272b8SAndroid Build Coastguard Worker 
58*2d1272b8SAndroid Build Coastguard Worker   protected:
59*2d1272b8SAndroid Build Coastguard Worker   Offset32To<DeltaSetIndexMap>	varIdxMap;	/* Offset from the beginning of 'avar' table. */
60*2d1272b8SAndroid Build Coastguard Worker   Offset32To<ItemVariationStore>	varStore;	/* Offset from the beginning of 'avar' table. */
61*2d1272b8SAndroid Build Coastguard Worker 
62*2d1272b8SAndroid Build Coastguard Worker   public:
63*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_STATIC (8);
64*2d1272b8SAndroid Build Coastguard Worker };
65*2d1272b8SAndroid Build Coastguard Worker 
66*2d1272b8SAndroid Build Coastguard Worker 
67*2d1272b8SAndroid Build Coastguard Worker struct AxisValueMap
68*2d1272b8SAndroid Build Coastguard Worker {
sanitizeOT::AxisValueMap69*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
70*2d1272b8SAndroid Build Coastguard Worker   {
71*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
72*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->check_struct (this));
73*2d1272b8SAndroid Build Coastguard Worker   }
74*2d1272b8SAndroid Build Coastguard Worker 
set_mappingOT::AxisValueMap75*2d1272b8SAndroid Build Coastguard Worker   void set_mapping (float from_coord, float to_coord)
76*2d1272b8SAndroid Build Coastguard Worker   {
77*2d1272b8SAndroid Build Coastguard Worker     coords[0].set_float (from_coord);
78*2d1272b8SAndroid Build Coastguard Worker     coords[1].set_float (to_coord);
79*2d1272b8SAndroid Build Coastguard Worker   }
80*2d1272b8SAndroid Build Coastguard Worker 
is_outside_axis_rangeOT::AxisValueMap81*2d1272b8SAndroid Build Coastguard Worker   bool is_outside_axis_range (const Triple& axis_range) const
82*2d1272b8SAndroid Build Coastguard Worker   {
83*2d1272b8SAndroid Build Coastguard Worker     double from_coord = (double) coords[0].to_float ();
84*2d1272b8SAndroid Build Coastguard Worker     return !axis_range.contains (from_coord);
85*2d1272b8SAndroid Build Coastguard Worker   }
86*2d1272b8SAndroid Build Coastguard Worker 
must_includeOT::AxisValueMap87*2d1272b8SAndroid Build Coastguard Worker   bool must_include () const
88*2d1272b8SAndroid Build Coastguard Worker   {
89*2d1272b8SAndroid Build Coastguard Worker     float from_coord = coords[0].to_float ();
90*2d1272b8SAndroid Build Coastguard Worker     float to_coord = coords[1].to_float ();
91*2d1272b8SAndroid Build Coastguard Worker     return (from_coord == -1.f && to_coord == -1.f) ||
92*2d1272b8SAndroid Build Coastguard Worker            (from_coord == 0.f && to_coord == 0.f) ||
93*2d1272b8SAndroid Build Coastguard Worker            (from_coord == 1.f && to_coord == 1.f);
94*2d1272b8SAndroid Build Coastguard Worker   }
95*2d1272b8SAndroid Build Coastguard Worker 
instantiateOT::AxisValueMap96*2d1272b8SAndroid Build Coastguard Worker   void instantiate (const Triple& axis_range,
97*2d1272b8SAndroid Build Coastguard Worker                     const Triple& unmapped_range,
98*2d1272b8SAndroid Build Coastguard Worker                     const TripleDistances& triple_distances)
99*2d1272b8SAndroid Build Coastguard Worker   {
100*2d1272b8SAndroid Build Coastguard Worker     float from_coord = coords[0].to_float ();
101*2d1272b8SAndroid Build Coastguard Worker     float to_coord = coords[1].to_float ();
102*2d1272b8SAndroid Build Coastguard Worker 
103*2d1272b8SAndroid Build Coastguard Worker     from_coord = renormalizeValue ((double) from_coord, unmapped_range, triple_distances);
104*2d1272b8SAndroid Build Coastguard Worker     to_coord = renormalizeValue ((double) to_coord, axis_range, triple_distances);
105*2d1272b8SAndroid Build Coastguard Worker 
106*2d1272b8SAndroid Build Coastguard Worker     coords[0].set_float (from_coord);
107*2d1272b8SAndroid Build Coastguard Worker     coords[1].set_float (to_coord);
108*2d1272b8SAndroid Build Coastguard Worker   }
109*2d1272b8SAndroid Build Coastguard Worker 
cmpOT::AxisValueMap110*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL static int cmp (const void *pa, const void *pb)
111*2d1272b8SAndroid Build Coastguard Worker   {
112*2d1272b8SAndroid Build Coastguard Worker     const AxisValueMap *a = (const AxisValueMap *) pa;
113*2d1272b8SAndroid Build Coastguard Worker     const AxisValueMap *b = (const AxisValueMap *) pb;
114*2d1272b8SAndroid Build Coastguard Worker 
115*2d1272b8SAndroid Build Coastguard Worker     int a_from = a->coords[0].to_int ();
116*2d1272b8SAndroid Build Coastguard Worker     int b_from = b->coords[0].to_int ();
117*2d1272b8SAndroid Build Coastguard Worker     if (a_from != b_from)
118*2d1272b8SAndroid Build Coastguard Worker       return a_from - b_from;
119*2d1272b8SAndroid Build Coastguard Worker 
120*2d1272b8SAndroid Build Coastguard Worker     /* this should never be reached. according to the spec, all of the axis
121*2d1272b8SAndroid Build Coastguard Worker      * value map records for a given axis must have different fromCoord values
122*2d1272b8SAndroid Build Coastguard Worker      * */
123*2d1272b8SAndroid Build Coastguard Worker     int a_to = a->coords[1].to_int ();
124*2d1272b8SAndroid Build Coastguard Worker     int b_to = b->coords[1].to_int ();
125*2d1272b8SAndroid Build Coastguard Worker     return a_to - b_to;
126*2d1272b8SAndroid Build Coastguard Worker   }
127*2d1272b8SAndroid Build Coastguard Worker 
serializeOT::AxisValueMap128*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c) const
129*2d1272b8SAndroid Build Coastguard Worker   {
130*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
131*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->embed (this));
132*2d1272b8SAndroid Build Coastguard Worker   }
133*2d1272b8SAndroid Build Coastguard Worker 
134*2d1272b8SAndroid Build Coastguard Worker   public:
135*2d1272b8SAndroid Build Coastguard Worker   F2DOT14	coords[2];
136*2d1272b8SAndroid Build Coastguard Worker //   F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
137*2d1272b8SAndroid Build Coastguard Worker //				 * default normalization. */
138*2d1272b8SAndroid Build Coastguard Worker //   F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
139*2d1272b8SAndroid Build Coastguard Worker 
140*2d1272b8SAndroid Build Coastguard Worker   public:
141*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_STATIC (4);
142*2d1272b8SAndroid Build Coastguard Worker };
143*2d1272b8SAndroid Build Coastguard Worker 
144*2d1272b8SAndroid Build Coastguard Worker struct SegmentMaps : Array16Of<AxisValueMap>
145*2d1272b8SAndroid Build Coastguard Worker {
mapOT::SegmentMaps146*2d1272b8SAndroid Build Coastguard Worker   int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
147*2d1272b8SAndroid Build Coastguard Worker   {
148*2d1272b8SAndroid Build Coastguard Worker #define fromCoord coords[from_offset].to_int ()
149*2d1272b8SAndroid Build Coastguard Worker #define toCoord coords[to_offset].to_int ()
150*2d1272b8SAndroid Build Coastguard Worker     /* The following special-cases are not part of OpenType, which requires
151*2d1272b8SAndroid Build Coastguard Worker      * that at least -1, 0, and +1 must be mapped. But we include these as
152*2d1272b8SAndroid Build Coastguard Worker      * part of a better error recovery scheme. */
153*2d1272b8SAndroid Build Coastguard Worker     if (len < 2)
154*2d1272b8SAndroid Build Coastguard Worker     {
155*2d1272b8SAndroid Build Coastguard Worker       if (!len)
156*2d1272b8SAndroid Build Coastguard Worker 	return value;
157*2d1272b8SAndroid Build Coastguard Worker       else /* len == 1*/
158*2d1272b8SAndroid Build Coastguard Worker 	return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
159*2d1272b8SAndroid Build Coastguard Worker     }
160*2d1272b8SAndroid Build Coastguard Worker 
161*2d1272b8SAndroid Build Coastguard Worker     if (value <= arrayZ[0].fromCoord)
162*2d1272b8SAndroid Build Coastguard Worker       return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
163*2d1272b8SAndroid Build Coastguard Worker 
164*2d1272b8SAndroid Build Coastguard Worker     unsigned int i;
165*2d1272b8SAndroid Build Coastguard Worker     unsigned int count = len - 1;
166*2d1272b8SAndroid Build Coastguard Worker     for (i = 1; i < count && value > arrayZ[i].fromCoord; i++)
167*2d1272b8SAndroid Build Coastguard Worker       ;
168*2d1272b8SAndroid Build Coastguard Worker 
169*2d1272b8SAndroid Build Coastguard Worker     if (value >= arrayZ[i].fromCoord)
170*2d1272b8SAndroid Build Coastguard Worker       return value - arrayZ[i].fromCoord + arrayZ[i].toCoord;
171*2d1272b8SAndroid Build Coastguard Worker 
172*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (arrayZ[i-1].fromCoord == arrayZ[i].fromCoord))
173*2d1272b8SAndroid Build Coastguard Worker       return arrayZ[i-1].toCoord;
174*2d1272b8SAndroid Build Coastguard Worker 
175*2d1272b8SAndroid Build Coastguard Worker     int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
176*2d1272b8SAndroid Build Coastguard Worker     return roundf (arrayZ[i-1].toCoord + ((float) (arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
177*2d1272b8SAndroid Build Coastguard Worker 					  (value - arrayZ[i-1].fromCoord)) / denom);
178*2d1272b8SAndroid Build Coastguard Worker #undef toCoord
179*2d1272b8SAndroid Build Coastguard Worker #undef fromCoord
180*2d1272b8SAndroid Build Coastguard Worker   }
181*2d1272b8SAndroid Build Coastguard Worker 
unmapOT::SegmentMaps182*2d1272b8SAndroid Build Coastguard Worker   int unmap (int value) const { return map (value, 1, 0); }
183*2d1272b8SAndroid Build Coastguard Worker 
unmap_axis_rangeOT::SegmentMaps184*2d1272b8SAndroid Build Coastguard Worker   Triple unmap_axis_range (const Triple& axis_range) const
185*2d1272b8SAndroid Build Coastguard Worker   {
186*2d1272b8SAndroid Build Coastguard Worker     F2DOT14 val, unmapped_val;
187*2d1272b8SAndroid Build Coastguard Worker 
188*2d1272b8SAndroid Build Coastguard Worker     val.set_float (axis_range.minimum);
189*2d1272b8SAndroid Build Coastguard Worker     unmapped_val.set_int (unmap (val.to_int ()));
190*2d1272b8SAndroid Build Coastguard Worker     float unmapped_min = unmapped_val.to_float ();
191*2d1272b8SAndroid Build Coastguard Worker 
192*2d1272b8SAndroid Build Coastguard Worker     val.set_float (axis_range.middle);
193*2d1272b8SAndroid Build Coastguard Worker     unmapped_val.set_int (unmap (val.to_int ()));
194*2d1272b8SAndroid Build Coastguard Worker     float unmapped_middle = unmapped_val.to_float ();
195*2d1272b8SAndroid Build Coastguard Worker 
196*2d1272b8SAndroid Build Coastguard Worker     val.set_float (axis_range.maximum);
197*2d1272b8SAndroid Build Coastguard Worker     unmapped_val.set_int (unmap (val.to_int ()));
198*2d1272b8SAndroid Build Coastguard Worker     float unmapped_max = unmapped_val.to_float ();
199*2d1272b8SAndroid Build Coastguard Worker 
200*2d1272b8SAndroid Build Coastguard Worker     return Triple{(double) unmapped_min, (double) unmapped_middle, (double) unmapped_max};
201*2d1272b8SAndroid Build Coastguard Worker   }
202*2d1272b8SAndroid Build Coastguard Worker 
subsetOT::SegmentMaps203*2d1272b8SAndroid Build Coastguard Worker   bool subset (hb_subset_context_t *c, hb_tag_t axis_tag) const
204*2d1272b8SAndroid Build Coastguard Worker   {
205*2d1272b8SAndroid Build Coastguard Worker     TRACE_SUBSET (this);
206*2d1272b8SAndroid Build Coastguard Worker     /* avar mapped normalized axis range*/
207*2d1272b8SAndroid Build Coastguard Worker     Triple *axis_range;
208*2d1272b8SAndroid Build Coastguard Worker     if (!c->plan->axes_location.has (axis_tag, &axis_range))
209*2d1272b8SAndroid Build Coastguard Worker       return c->serializer->embed (*this);
210*2d1272b8SAndroid Build Coastguard Worker 
211*2d1272b8SAndroid Build Coastguard Worker     TripleDistances *axis_triple_distances;
212*2d1272b8SAndroid Build Coastguard Worker     if (!c->plan->axes_triple_distances.has (axis_tag, &axis_triple_distances))
213*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
214*2d1272b8SAndroid Build Coastguard Worker 
215*2d1272b8SAndroid Build Coastguard Worker     auto *out = c->serializer->start_embed (this);
216*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
217*2d1272b8SAndroid Build Coastguard Worker 
218*2d1272b8SAndroid Build Coastguard Worker     Triple unmapped_range = unmap_axis_range (*axis_range);
219*2d1272b8SAndroid Build Coastguard Worker 
220*2d1272b8SAndroid Build Coastguard Worker     /* create a vector of retained mappings and sort */
221*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<AxisValueMap> value_mappings;
222*2d1272b8SAndroid Build Coastguard Worker     for (const auto& _ : as_array ())
223*2d1272b8SAndroid Build Coastguard Worker     {
224*2d1272b8SAndroid Build Coastguard Worker       if (_.is_outside_axis_range (unmapped_range))
225*2d1272b8SAndroid Build Coastguard Worker         continue;
226*2d1272b8SAndroid Build Coastguard Worker       AxisValueMap mapping;
227*2d1272b8SAndroid Build Coastguard Worker       mapping = _;
228*2d1272b8SAndroid Build Coastguard Worker       mapping.instantiate (*axis_range, unmapped_range, *axis_triple_distances);
229*2d1272b8SAndroid Build Coastguard Worker       /* (-1, -1), (0, 0), (1, 1) mappings will be added later, so avoid
230*2d1272b8SAndroid Build Coastguard Worker        * duplicates here */
231*2d1272b8SAndroid Build Coastguard Worker       if (mapping.must_include ())
232*2d1272b8SAndroid Build Coastguard Worker         continue;
233*2d1272b8SAndroid Build Coastguard Worker       value_mappings.push (mapping);
234*2d1272b8SAndroid Build Coastguard Worker     }
235*2d1272b8SAndroid Build Coastguard Worker 
236*2d1272b8SAndroid Build Coastguard Worker     AxisValueMap m;
237*2d1272b8SAndroid Build Coastguard Worker     m.set_mapping (-1.f, -1.f);
238*2d1272b8SAndroid Build Coastguard Worker     value_mappings.push (m);
239*2d1272b8SAndroid Build Coastguard Worker 
240*2d1272b8SAndroid Build Coastguard Worker     m.set_mapping (0.f, 0.f);
241*2d1272b8SAndroid Build Coastguard Worker     value_mappings.push (m);
242*2d1272b8SAndroid Build Coastguard Worker 
243*2d1272b8SAndroid Build Coastguard Worker     m.set_mapping (1.f, 1.f);
244*2d1272b8SAndroid Build Coastguard Worker     value_mappings.push (m);
245*2d1272b8SAndroid Build Coastguard Worker 
246*2d1272b8SAndroid Build Coastguard Worker     value_mappings.qsort ();
247*2d1272b8SAndroid Build Coastguard Worker 
248*2d1272b8SAndroid Build Coastguard Worker     for (const auto& _ : value_mappings)
249*2d1272b8SAndroid Build Coastguard Worker     {
250*2d1272b8SAndroid Build Coastguard Worker       if (!_.serialize (c->serializer))
251*2d1272b8SAndroid Build Coastguard Worker         return_trace (false);
252*2d1272b8SAndroid Build Coastguard Worker     }
253*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->serializer->check_assign (out->len, value_mappings.length, HB_SERIALIZE_ERROR_INT_OVERFLOW));
254*2d1272b8SAndroid Build Coastguard Worker   }
255*2d1272b8SAndroid Build Coastguard Worker 
256*2d1272b8SAndroid Build Coastguard Worker   public:
257*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_ARRAY (2, *this);
258*2d1272b8SAndroid Build Coastguard Worker };
259*2d1272b8SAndroid Build Coastguard Worker 
260*2d1272b8SAndroid Build Coastguard Worker struct avar
261*2d1272b8SAndroid Build Coastguard Worker {
262*2d1272b8SAndroid Build Coastguard Worker   static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
263*2d1272b8SAndroid Build Coastguard Worker 
has_dataOT::avar264*2d1272b8SAndroid Build Coastguard Worker   bool has_data () const { return version.to_int (); }
265*2d1272b8SAndroid Build Coastguard Worker 
get_segment_mapsOT::avar266*2d1272b8SAndroid Build Coastguard Worker   const SegmentMaps* get_segment_maps () const
267*2d1272b8SAndroid Build Coastguard Worker   { return &firstAxisSegmentMaps; }
268*2d1272b8SAndroid Build Coastguard Worker 
get_axis_countOT::avar269*2d1272b8SAndroid Build Coastguard Worker   unsigned get_axis_count () const
270*2d1272b8SAndroid Build Coastguard Worker   { return axisCount; }
271*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::avar272*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
273*2d1272b8SAndroid Build Coastguard Worker   {
274*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
275*2d1272b8SAndroid Build Coastguard Worker     if (!(version.sanitize (c) &&
276*2d1272b8SAndroid Build Coastguard Worker 	  hb_barrier () &&
277*2d1272b8SAndroid Build Coastguard Worker 	  (version.major == 1
278*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AVAR2
279*2d1272b8SAndroid Build Coastguard Worker 	   || version.major == 2
280*2d1272b8SAndroid Build Coastguard Worker #endif
281*2d1272b8SAndroid Build Coastguard Worker 	   ) &&
282*2d1272b8SAndroid Build Coastguard Worker 	  c->check_struct (this)))
283*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
284*2d1272b8SAndroid Build Coastguard Worker 
285*2d1272b8SAndroid Build Coastguard Worker     const SegmentMaps *map = &firstAxisSegmentMaps;
286*2d1272b8SAndroid Build Coastguard Worker     unsigned int count = axisCount;
287*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < count; i++)
288*2d1272b8SAndroid Build Coastguard Worker     {
289*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!map->sanitize (c)))
290*2d1272b8SAndroid Build Coastguard Worker 	return_trace (false);
291*2d1272b8SAndroid Build Coastguard Worker       map = &StructAfter<SegmentMaps> (*map);
292*2d1272b8SAndroid Build Coastguard Worker     }
293*2d1272b8SAndroid Build Coastguard Worker 
294*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AVAR2
295*2d1272b8SAndroid Build Coastguard Worker     if (version.major < 2)
296*2d1272b8SAndroid Build Coastguard Worker       return_trace (true);
297*2d1272b8SAndroid Build Coastguard Worker     hb_barrier ();
298*2d1272b8SAndroid Build Coastguard Worker 
299*2d1272b8SAndroid Build Coastguard Worker     const auto &v2 = * (const avarV2Tail *) map;
300*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!v2.sanitize (c, this)))
301*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
302*2d1272b8SAndroid Build Coastguard Worker #endif
303*2d1272b8SAndroid Build Coastguard Worker 
304*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
305*2d1272b8SAndroid Build Coastguard Worker   }
306*2d1272b8SAndroid Build Coastguard Worker 
map_coordsOT::avar307*2d1272b8SAndroid Build Coastguard Worker   void map_coords (int *coords, unsigned int coords_length) const
308*2d1272b8SAndroid Build Coastguard Worker   {
309*2d1272b8SAndroid Build Coastguard Worker     unsigned int count = hb_min (coords_length, axisCount);
310*2d1272b8SAndroid Build Coastguard Worker 
311*2d1272b8SAndroid Build Coastguard Worker     const SegmentMaps *map = &firstAxisSegmentMaps;
312*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < count; i++)
313*2d1272b8SAndroid Build Coastguard Worker     {
314*2d1272b8SAndroid Build Coastguard Worker       coords[i] = map->map (coords[i]);
315*2d1272b8SAndroid Build Coastguard Worker       map = &StructAfter<SegmentMaps> (*map);
316*2d1272b8SAndroid Build Coastguard Worker     }
317*2d1272b8SAndroid Build Coastguard Worker 
318*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AVAR2
319*2d1272b8SAndroid Build Coastguard Worker     if (version.major < 2)
320*2d1272b8SAndroid Build Coastguard Worker       return;
321*2d1272b8SAndroid Build Coastguard Worker     hb_barrier ();
322*2d1272b8SAndroid Build Coastguard Worker 
323*2d1272b8SAndroid Build Coastguard Worker     for (; count < axisCount; count++)
324*2d1272b8SAndroid Build Coastguard Worker       map = &StructAfter<SegmentMaps> (*map);
325*2d1272b8SAndroid Build Coastguard Worker 
326*2d1272b8SAndroid Build Coastguard Worker     const auto &v2 = * (const avarV2Tail *) map;
327*2d1272b8SAndroid Build Coastguard Worker 
328*2d1272b8SAndroid Build Coastguard Worker     const auto &varidx_map = this+v2.varIdxMap;
329*2d1272b8SAndroid Build Coastguard Worker     const auto &var_store = this+v2.varStore;
330*2d1272b8SAndroid Build Coastguard Worker     auto *var_store_cache = var_store.create_cache ();
331*2d1272b8SAndroid Build Coastguard Worker 
332*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<int> out;
333*2d1272b8SAndroid Build Coastguard Worker     out.alloc (coords_length);
334*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < coords_length; i++)
335*2d1272b8SAndroid Build Coastguard Worker     {
336*2d1272b8SAndroid Build Coastguard Worker       int v = coords[i];
337*2d1272b8SAndroid Build Coastguard Worker       uint32_t varidx = varidx_map.map (i);
338*2d1272b8SAndroid Build Coastguard Worker       float delta = var_store.get_delta (varidx, coords, coords_length, var_store_cache);
339*2d1272b8SAndroid Build Coastguard Worker       v += roundf (delta);
340*2d1272b8SAndroid Build Coastguard Worker       v = hb_clamp (v, -(1<<14), +(1<<14));
341*2d1272b8SAndroid Build Coastguard Worker       out.push (v);
342*2d1272b8SAndroid Build Coastguard Worker     }
343*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < coords_length; i++)
344*2d1272b8SAndroid Build Coastguard Worker       coords[i] = out[i];
345*2d1272b8SAndroid Build Coastguard Worker 
346*2d1272b8SAndroid Build Coastguard Worker     OT::ItemVariationStore::destroy_cache (var_store_cache);
347*2d1272b8SAndroid Build Coastguard Worker #endif
348*2d1272b8SAndroid Build Coastguard Worker   }
349*2d1272b8SAndroid Build Coastguard Worker 
unmap_coordsOT::avar350*2d1272b8SAndroid Build Coastguard Worker   void unmap_coords (int *coords, unsigned int coords_length) const
351*2d1272b8SAndroid Build Coastguard Worker   {
352*2d1272b8SAndroid Build Coastguard Worker     unsigned int count = hb_min (coords_length, axisCount);
353*2d1272b8SAndroid Build Coastguard Worker 
354*2d1272b8SAndroid Build Coastguard Worker     const SegmentMaps *map = &firstAxisSegmentMaps;
355*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < count; i++)
356*2d1272b8SAndroid Build Coastguard Worker     {
357*2d1272b8SAndroid Build Coastguard Worker       coords[i] = map->unmap (coords[i]);
358*2d1272b8SAndroid Build Coastguard Worker       map = &StructAfter<SegmentMaps> (*map);
359*2d1272b8SAndroid Build Coastguard Worker     }
360*2d1272b8SAndroid Build Coastguard Worker   }
361*2d1272b8SAndroid Build Coastguard Worker 
subsetOT::avar362*2d1272b8SAndroid Build Coastguard Worker   bool subset (hb_subset_context_t *c) const
363*2d1272b8SAndroid Build Coastguard Worker   {
364*2d1272b8SAndroid Build Coastguard Worker     TRACE_SUBSET (this);
365*2d1272b8SAndroid Build Coastguard Worker     unsigned retained_axis_count = c->plan->axes_index_map.get_population ();
366*2d1272b8SAndroid Build Coastguard Worker     if (!retained_axis_count) //all axes are pinned/dropped
367*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
368*2d1272b8SAndroid Build Coastguard Worker 
369*2d1272b8SAndroid Build Coastguard Worker     avar *out = c->serializer->allocate_min<avar> ();
370*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!out)) return_trace (false);
371*2d1272b8SAndroid Build Coastguard Worker 
372*2d1272b8SAndroid Build Coastguard Worker     out->version.major = 1;
373*2d1272b8SAndroid Build Coastguard Worker     out->version.minor = 0;
374*2d1272b8SAndroid Build Coastguard Worker     if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
375*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
376*2d1272b8SAndroid Build Coastguard Worker 
377*2d1272b8SAndroid Build Coastguard Worker     const hb_map_t& axes_index_map = c->plan->axes_index_map;
378*2d1272b8SAndroid Build Coastguard Worker     const SegmentMaps *map = &firstAxisSegmentMaps;
379*2d1272b8SAndroid Build Coastguard Worker     unsigned count = axisCount;
380*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < count; i++)
381*2d1272b8SAndroid Build Coastguard Worker     {
382*2d1272b8SAndroid Build Coastguard Worker       if (axes_index_map.has (i))
383*2d1272b8SAndroid Build Coastguard Worker       {
384*2d1272b8SAndroid Build Coastguard Worker         hb_tag_t *axis_tag;
385*2d1272b8SAndroid Build Coastguard Worker         if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag))
386*2d1272b8SAndroid Build Coastguard Worker           return_trace (false);
387*2d1272b8SAndroid Build Coastguard Worker         if (!map->subset (c, *axis_tag))
388*2d1272b8SAndroid Build Coastguard Worker           return_trace (false);
389*2d1272b8SAndroid Build Coastguard Worker       }
390*2d1272b8SAndroid Build Coastguard Worker       map = &StructAfter<SegmentMaps> (*map);
391*2d1272b8SAndroid Build Coastguard Worker     }
392*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
393*2d1272b8SAndroid Build Coastguard Worker   }
394*2d1272b8SAndroid Build Coastguard Worker 
395*2d1272b8SAndroid Build Coastguard Worker   protected:
396*2d1272b8SAndroid Build Coastguard Worker   FixedVersion<>version;	/* Version of the avar table
397*2d1272b8SAndroid Build Coastguard Worker 				 * initially set to 0x00010000u */
398*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	reserved;	/* This field is permanently reserved. Set to 0. */
399*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	axisCount;	/* The number of variation axes in the font. This
400*2d1272b8SAndroid Build Coastguard Worker 				 * must be the same number as axisCount in the
401*2d1272b8SAndroid Build Coastguard Worker 				 * 'fvar' table. */
402*2d1272b8SAndroid Build Coastguard Worker   SegmentMaps	firstAxisSegmentMaps;
403*2d1272b8SAndroid Build Coastguard Worker 
404*2d1272b8SAndroid Build Coastguard Worker   public:
405*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (8);
406*2d1272b8SAndroid Build Coastguard Worker };
407*2d1272b8SAndroid Build Coastguard Worker 
408*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */
409*2d1272b8SAndroid Build Coastguard Worker 
410*2d1272b8SAndroid Build Coastguard Worker 
411*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_VAR_AVAR_TABLE_HH */
412