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