1*2d1272b8SAndroid Build Coastguard Worker /* 2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2016 Elie Roux <[email protected]> 3*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2018 Google, Inc. 4*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2018-2019 Ebrahim Byagowi 5*2d1272b8SAndroid Build Coastguard Worker * 6*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library. 7*2d1272b8SAndroid Build Coastguard Worker * 8*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without 9*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this 10*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the 11*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in 12*2d1272b8SAndroid Build Coastguard Worker * all copies of this software. 13*2d1272b8SAndroid Build Coastguard Worker * 14*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 15*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 16*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 17*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 18*2d1272b8SAndroid Build Coastguard Worker * DAMAGE. 19*2d1272b8SAndroid Build Coastguard Worker * 20*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 21*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 22*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 23*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 24*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25*2d1272b8SAndroid Build Coastguard Worker * 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_LAYOUT_BASE_TABLE_HH 30*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_LAYOUT_BASE_TABLE_HH 31*2d1272b8SAndroid Build Coastguard Worker 32*2d1272b8SAndroid Build Coastguard Worker #include "hb-open-type.hh" 33*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-layout-common.hh" 34*2d1272b8SAndroid Build Coastguard Worker 35*2d1272b8SAndroid Build Coastguard Worker namespace OT { 36*2d1272b8SAndroid Build Coastguard Worker 37*2d1272b8SAndroid Build Coastguard Worker /* 38*2d1272b8SAndroid Build Coastguard Worker * BASE -- Baseline 39*2d1272b8SAndroid Build Coastguard Worker * https://docs.microsoft.com/en-us/typography/opentype/spec/base 40*2d1272b8SAndroid Build Coastguard Worker */ 41*2d1272b8SAndroid Build Coastguard Worker 42*2d1272b8SAndroid Build Coastguard Worker struct BaseCoordFormat1 43*2d1272b8SAndroid Build Coastguard Worker { get_coordOT::BaseCoordFormat144*2d1272b8SAndroid Build Coastguard Worker hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const 45*2d1272b8SAndroid Build Coastguard Worker { 46*2d1272b8SAndroid Build Coastguard Worker return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); 47*2d1272b8SAndroid Build Coastguard Worker } 48*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseCoordFormat149*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 50*2d1272b8SAndroid Build Coastguard Worker { 51*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 52*2d1272b8SAndroid Build Coastguard Worker return_trace ((bool) c->serializer->embed (*this)); 53*2d1272b8SAndroid Build Coastguard Worker } 54*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseCoordFormat155*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 56*2d1272b8SAndroid Build Coastguard Worker { 57*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 58*2d1272b8SAndroid Build Coastguard Worker return_trace (c->check_struct (this)); 59*2d1272b8SAndroid Build Coastguard Worker } 60*2d1272b8SAndroid Build Coastguard Worker 61*2d1272b8SAndroid Build Coastguard Worker protected: 62*2d1272b8SAndroid Build Coastguard Worker HBUINT16 format; /* Format identifier--format = 1 */ 63*2d1272b8SAndroid Build Coastguard Worker FWORD coordinate; /* X or Y value, in design units */ 64*2d1272b8SAndroid Build Coastguard Worker public: 65*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (4); 66*2d1272b8SAndroid Build Coastguard Worker }; 67*2d1272b8SAndroid Build Coastguard Worker 68*2d1272b8SAndroid Build Coastguard Worker struct BaseCoordFormat2 69*2d1272b8SAndroid Build Coastguard Worker { get_coordOT::BaseCoordFormat270*2d1272b8SAndroid Build Coastguard Worker hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const 71*2d1272b8SAndroid Build Coastguard Worker { 72*2d1272b8SAndroid Build Coastguard Worker /* TODO */ 73*2d1272b8SAndroid Build Coastguard Worker return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); 74*2d1272b8SAndroid Build Coastguard Worker } 75*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseCoordFormat276*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 77*2d1272b8SAndroid Build Coastguard Worker { 78*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 79*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->embed (*this); 80*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out)) return_trace (false); 81*2d1272b8SAndroid Build Coastguard Worker 82*2d1272b8SAndroid Build Coastguard Worker return_trace (c->serializer->check_assign (out->referenceGlyph, 83*2d1272b8SAndroid Build Coastguard Worker c->plan->glyph_map->get (referenceGlyph), 84*2d1272b8SAndroid Build Coastguard Worker HB_SERIALIZE_ERROR_INT_OVERFLOW)); 85*2d1272b8SAndroid Build Coastguard Worker } 86*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseCoordFormat287*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 88*2d1272b8SAndroid Build Coastguard Worker { 89*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 90*2d1272b8SAndroid Build Coastguard Worker return_trace (c->check_struct (this)); 91*2d1272b8SAndroid Build Coastguard Worker } 92*2d1272b8SAndroid Build Coastguard Worker 93*2d1272b8SAndroid Build Coastguard Worker protected: 94*2d1272b8SAndroid Build Coastguard Worker HBUINT16 format; /* Format identifier--format = 2 */ 95*2d1272b8SAndroid Build Coastguard Worker FWORD coordinate; /* X or Y value, in design units */ 96*2d1272b8SAndroid Build Coastguard Worker HBGlyphID16 referenceGlyph; /* Glyph ID of control glyph */ 97*2d1272b8SAndroid Build Coastguard Worker HBUINT16 coordPoint; /* Index of contour point on the 98*2d1272b8SAndroid Build Coastguard Worker * reference glyph */ 99*2d1272b8SAndroid Build Coastguard Worker public: 100*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (8); 101*2d1272b8SAndroid Build Coastguard Worker }; 102*2d1272b8SAndroid Build Coastguard Worker 103*2d1272b8SAndroid Build Coastguard Worker struct BaseCoordFormat3 104*2d1272b8SAndroid Build Coastguard Worker { get_coordOT::BaseCoordFormat3105*2d1272b8SAndroid Build Coastguard Worker hb_position_t get_coord (hb_font_t *font, 106*2d1272b8SAndroid Build Coastguard Worker const ItemVariationStore &var_store, 107*2d1272b8SAndroid Build Coastguard Worker hb_direction_t direction) const 108*2d1272b8SAndroid Build Coastguard Worker { 109*2d1272b8SAndroid Build Coastguard Worker const Device &device = this+deviceTable; 110*2d1272b8SAndroid Build Coastguard Worker 111*2d1272b8SAndroid Build Coastguard Worker return HB_DIRECTION_IS_HORIZONTAL (direction) 112*2d1272b8SAndroid Build Coastguard Worker ? font->em_scale_y (coordinate) + device.get_y_delta (font, var_store) 113*2d1272b8SAndroid Build Coastguard Worker : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store); 114*2d1272b8SAndroid Build Coastguard Worker } 115*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BaseCoordFormat3116*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const 117*2d1272b8SAndroid Build Coastguard Worker { 118*2d1272b8SAndroid Build Coastguard Worker unsigned varidx = (this+deviceTable).get_variation_index (); 119*2d1272b8SAndroid Build Coastguard Worker varidx_set.add (varidx); 120*2d1272b8SAndroid Build Coastguard Worker } 121*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseCoordFormat3122*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 123*2d1272b8SAndroid Build Coastguard Worker { 124*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 125*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->embed (*this); 126*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out)) return_trace (false); 127*2d1272b8SAndroid Build Coastguard Worker 128*2d1272b8SAndroid Build Coastguard Worker if (!c->plan->pinned_at_default) 129*2d1272b8SAndroid Build Coastguard Worker { 130*2d1272b8SAndroid Build Coastguard Worker unsigned var_idx = (this+deviceTable).get_variation_index (); 131*2d1272b8SAndroid Build Coastguard Worker if (var_idx != VarIdx::NO_VARIATION) 132*2d1272b8SAndroid Build Coastguard Worker { 133*2d1272b8SAndroid Build Coastguard Worker hb_pair_t<unsigned, int> *v; 134*2d1272b8SAndroid Build Coastguard Worker if (!c->plan->base_variation_idx_map.has (var_idx, &v)) 135*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 136*2d1272b8SAndroid Build Coastguard Worker 137*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!c->serializer->check_assign (out->coordinate, coordinate + hb_second (*v), 138*2d1272b8SAndroid Build Coastguard Worker HB_SERIALIZE_ERROR_INT_OVERFLOW))) 139*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 140*2d1272b8SAndroid Build Coastguard Worker } 141*2d1272b8SAndroid Build Coastguard Worker } 142*2d1272b8SAndroid Build Coastguard Worker return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, 143*2d1272b8SAndroid Build Coastguard Worker this, 0, 144*2d1272b8SAndroid Build Coastguard Worker hb_serialize_context_t::Head, 145*2d1272b8SAndroid Build Coastguard Worker &c->plan->base_variation_idx_map)); 146*2d1272b8SAndroid Build Coastguard Worker } 147*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseCoordFormat3148*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 149*2d1272b8SAndroid Build Coastguard Worker { 150*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 151*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 152*2d1272b8SAndroid Build Coastguard Worker deviceTable.sanitize (c, this))); 153*2d1272b8SAndroid Build Coastguard Worker } 154*2d1272b8SAndroid Build Coastguard Worker 155*2d1272b8SAndroid Build Coastguard Worker protected: 156*2d1272b8SAndroid Build Coastguard Worker HBUINT16 format; /* Format identifier--format = 3 */ 157*2d1272b8SAndroid Build Coastguard Worker FWORD coordinate; /* X or Y value, in design units */ 158*2d1272b8SAndroid Build Coastguard Worker Offset16To<Device> 159*2d1272b8SAndroid Build Coastguard Worker deviceTable; /* Offset to Device table for X or 160*2d1272b8SAndroid Build Coastguard Worker * Y value, from beginning of 161*2d1272b8SAndroid Build Coastguard Worker * BaseCoord table (may be NULL). */ 162*2d1272b8SAndroid Build Coastguard Worker public: 163*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (6); 164*2d1272b8SAndroid Build Coastguard Worker }; 165*2d1272b8SAndroid Build Coastguard Worker 166*2d1272b8SAndroid Build Coastguard Worker struct BaseCoord 167*2d1272b8SAndroid Build Coastguard Worker { has_dataOT::BaseCoord168*2d1272b8SAndroid Build Coastguard Worker bool has_data () const { return u.format; } 169*2d1272b8SAndroid Build Coastguard Worker get_coordOT::BaseCoord170*2d1272b8SAndroid Build Coastguard Worker hb_position_t get_coord (hb_font_t *font, 171*2d1272b8SAndroid Build Coastguard Worker const ItemVariationStore &var_store, 172*2d1272b8SAndroid Build Coastguard Worker hb_direction_t direction) const 173*2d1272b8SAndroid Build Coastguard Worker { 174*2d1272b8SAndroid Build Coastguard Worker switch (u.format) { 175*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return u.format1.get_coord (font, direction); 176*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); return u.format2.get_coord (font, direction); 177*2d1272b8SAndroid Build Coastguard Worker case 3: hb_barrier (); return u.format3.get_coord (font, var_store, direction); 178*2d1272b8SAndroid Build Coastguard Worker default:return 0; 179*2d1272b8SAndroid Build Coastguard Worker } 180*2d1272b8SAndroid Build Coastguard Worker } 181*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BaseCoord182*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const 183*2d1272b8SAndroid Build Coastguard Worker { 184*2d1272b8SAndroid Build Coastguard Worker switch (u.format) { 185*2d1272b8SAndroid Build Coastguard Worker case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); 186*2d1272b8SAndroid Build Coastguard Worker default:return; 187*2d1272b8SAndroid Build Coastguard Worker } 188*2d1272b8SAndroid Build Coastguard Worker } 189*2d1272b8SAndroid Build Coastguard Worker 190*2d1272b8SAndroid Build Coastguard Worker template <typename context_t, typename ...Ts> dispatchOT::BaseCoord191*2d1272b8SAndroid Build Coastguard Worker typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const 192*2d1272b8SAndroid Build Coastguard Worker { 193*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); 194*2d1272b8SAndroid Build Coastguard Worker TRACE_DISPATCH (this, u.format); 195*2d1272b8SAndroid Build Coastguard Worker switch (u.format) { 196*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); 197*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); 198*2d1272b8SAndroid Build Coastguard Worker case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); 199*2d1272b8SAndroid Build Coastguard Worker default:return_trace (c->default_return_value ()); 200*2d1272b8SAndroid Build Coastguard Worker } 201*2d1272b8SAndroid Build Coastguard Worker } 202*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseCoord203*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 204*2d1272b8SAndroid Build Coastguard Worker { 205*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 206*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!u.format.sanitize (c))) return_trace (false); 207*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 208*2d1272b8SAndroid Build Coastguard Worker switch (u.format) { 209*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return_trace (u.format1.sanitize (c)); 210*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); return_trace (u.format2.sanitize (c)); 211*2d1272b8SAndroid Build Coastguard Worker case 3: hb_barrier (); return_trace (u.format3.sanitize (c)); 212*2d1272b8SAndroid Build Coastguard Worker default:return_trace (false); 213*2d1272b8SAndroid Build Coastguard Worker } 214*2d1272b8SAndroid Build Coastguard Worker } 215*2d1272b8SAndroid Build Coastguard Worker 216*2d1272b8SAndroid Build Coastguard Worker protected: 217*2d1272b8SAndroid Build Coastguard Worker union { 218*2d1272b8SAndroid Build Coastguard Worker HBUINT16 format; 219*2d1272b8SAndroid Build Coastguard Worker BaseCoordFormat1 format1; 220*2d1272b8SAndroid Build Coastguard Worker BaseCoordFormat2 format2; 221*2d1272b8SAndroid Build Coastguard Worker BaseCoordFormat3 format3; 222*2d1272b8SAndroid Build Coastguard Worker } u; 223*2d1272b8SAndroid Build Coastguard Worker public: 224*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_UNION (2, format); 225*2d1272b8SAndroid Build Coastguard Worker }; 226*2d1272b8SAndroid Build Coastguard Worker 227*2d1272b8SAndroid Build Coastguard Worker struct FeatMinMaxRecord 228*2d1272b8SAndroid Build Coastguard Worker { cmpOT::FeatMinMaxRecord229*2d1272b8SAndroid Build Coastguard Worker int cmp (hb_tag_t key) const { return tag.cmp (key); } 230*2d1272b8SAndroid Build Coastguard Worker has_dataOT::FeatMinMaxRecord231*2d1272b8SAndroid Build Coastguard Worker bool has_data () const { return tag; } 232*2d1272b8SAndroid Build Coastguard Worker get_feature_tagOT::FeatMinMaxRecord233*2d1272b8SAndroid Build Coastguard Worker hb_tag_t get_feature_tag () const { return tag; } 234*2d1272b8SAndroid Build Coastguard Worker get_min_maxOT::FeatMinMaxRecord235*2d1272b8SAndroid Build Coastguard Worker void get_min_max (const BaseCoord **min, const BaseCoord **max) const 236*2d1272b8SAndroid Build Coastguard Worker { 237*2d1272b8SAndroid Build Coastguard Worker if (likely (min)) *min = &(this+minCoord); 238*2d1272b8SAndroid Build Coastguard Worker if (likely (max)) *max = &(this+maxCoord); 239*2d1272b8SAndroid Build Coastguard Worker } 240*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::FeatMinMaxRecord241*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const hb_subset_plan_t* plan, 242*2d1272b8SAndroid Build Coastguard Worker const void *base, 243*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 244*2d1272b8SAndroid Build Coastguard Worker { 245*2d1272b8SAndroid Build Coastguard Worker if (!plan->layout_features.has (tag)) 246*2d1272b8SAndroid Build Coastguard Worker return; 247*2d1272b8SAndroid Build Coastguard Worker 248*2d1272b8SAndroid Build Coastguard Worker (base+minCoord).collect_variation_indices (varidx_set); 249*2d1272b8SAndroid Build Coastguard Worker (base+maxCoord).collect_variation_indices (varidx_set); 250*2d1272b8SAndroid Build Coastguard Worker } 251*2d1272b8SAndroid Build Coastguard Worker subsetOT::FeatMinMaxRecord252*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c, 253*2d1272b8SAndroid Build Coastguard Worker const void *base) const 254*2d1272b8SAndroid Build Coastguard Worker { 255*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 256*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->embed (*this); 257*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out)) return_trace (false); 258*2d1272b8SAndroid Build Coastguard Worker if (!(out->minCoord.serialize_subset (c, minCoord, base))) 259*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 260*2d1272b8SAndroid Build Coastguard Worker 261*2d1272b8SAndroid Build Coastguard Worker return_trace (out->maxCoord.serialize_subset (c, maxCoord, base)); 262*2d1272b8SAndroid Build Coastguard Worker } 263*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::FeatMinMaxRecord264*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c, const void *base) const 265*2d1272b8SAndroid Build Coastguard Worker { 266*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 267*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 268*2d1272b8SAndroid Build Coastguard Worker minCoord.sanitize (c, base) && 269*2d1272b8SAndroid Build Coastguard Worker maxCoord.sanitize (c, base))); 270*2d1272b8SAndroid Build Coastguard Worker } 271*2d1272b8SAndroid Build Coastguard Worker 272*2d1272b8SAndroid Build Coastguard Worker protected: 273*2d1272b8SAndroid Build Coastguard Worker Tag tag; /* 4-byte feature identification tag--must 274*2d1272b8SAndroid Build Coastguard Worker * match feature tag in FeatureList */ 275*2d1272b8SAndroid Build Coastguard Worker Offset16To<BaseCoord> 276*2d1272b8SAndroid Build Coastguard Worker minCoord; /* Offset to BaseCoord table that defines 277*2d1272b8SAndroid Build Coastguard Worker * the minimum extent value, from beginning 278*2d1272b8SAndroid Build Coastguard Worker * of MinMax table (may be NULL) */ 279*2d1272b8SAndroid Build Coastguard Worker Offset16To<BaseCoord> 280*2d1272b8SAndroid Build Coastguard Worker maxCoord; /* Offset to BaseCoord table that defines 281*2d1272b8SAndroid Build Coastguard Worker * the maximum extent value, from beginning 282*2d1272b8SAndroid Build Coastguard Worker * of MinMax table (may be NULL) */ 283*2d1272b8SAndroid Build Coastguard Worker public: 284*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (8); 285*2d1272b8SAndroid Build Coastguard Worker }; 286*2d1272b8SAndroid Build Coastguard Worker 287*2d1272b8SAndroid Build Coastguard Worker struct MinMax 288*2d1272b8SAndroid Build Coastguard Worker { get_min_maxOT::MinMax289*2d1272b8SAndroid Build Coastguard Worker void get_min_max (hb_tag_t feature_tag, 290*2d1272b8SAndroid Build Coastguard Worker const BaseCoord **min, 291*2d1272b8SAndroid Build Coastguard Worker const BaseCoord **max) const 292*2d1272b8SAndroid Build Coastguard Worker { 293*2d1272b8SAndroid Build Coastguard Worker const FeatMinMaxRecord &minMaxCoord = featMinMaxRecords.bsearch (feature_tag); 294*2d1272b8SAndroid Build Coastguard Worker if (minMaxCoord.has_data ()) 295*2d1272b8SAndroid Build Coastguard Worker minMaxCoord.get_min_max (min, max); 296*2d1272b8SAndroid Build Coastguard Worker else 297*2d1272b8SAndroid Build Coastguard Worker { 298*2d1272b8SAndroid Build Coastguard Worker if (likely (min)) *min = &(this+minCoord); 299*2d1272b8SAndroid Build Coastguard Worker if (likely (max)) *max = &(this+maxCoord); 300*2d1272b8SAndroid Build Coastguard Worker } 301*2d1272b8SAndroid Build Coastguard Worker } 302*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::MinMax303*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const hb_subset_plan_t* plan, 304*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 305*2d1272b8SAndroid Build Coastguard Worker { 306*2d1272b8SAndroid Build Coastguard Worker (this+minCoord).collect_variation_indices (varidx_set); 307*2d1272b8SAndroid Build Coastguard Worker (this+maxCoord).collect_variation_indices (varidx_set); 308*2d1272b8SAndroid Build Coastguard Worker for (const FeatMinMaxRecord& record : featMinMaxRecords) 309*2d1272b8SAndroid Build Coastguard Worker record.collect_variation_indices (plan, this, varidx_set); 310*2d1272b8SAndroid Build Coastguard Worker } 311*2d1272b8SAndroid Build Coastguard Worker subsetOT::MinMax312*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 313*2d1272b8SAndroid Build Coastguard Worker { 314*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 315*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->start_embed (*this); 316*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); 317*2d1272b8SAndroid Build Coastguard Worker 318*2d1272b8SAndroid Build Coastguard Worker if (!(out->minCoord.serialize_subset (c, minCoord, this)) || 319*2d1272b8SAndroid Build Coastguard Worker !(out->maxCoord.serialize_subset (c, maxCoord, this))) 320*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 321*2d1272b8SAndroid Build Coastguard Worker 322*2d1272b8SAndroid Build Coastguard Worker unsigned len = 0; 323*2d1272b8SAndroid Build Coastguard Worker for (const FeatMinMaxRecord& _ : featMinMaxRecords) 324*2d1272b8SAndroid Build Coastguard Worker { 325*2d1272b8SAndroid Build Coastguard Worker hb_tag_t feature_tag = _.get_feature_tag (); 326*2d1272b8SAndroid Build Coastguard Worker if (!c->plan->layout_features.has (feature_tag)) 327*2d1272b8SAndroid Build Coastguard Worker continue; 328*2d1272b8SAndroid Build Coastguard Worker 329*2d1272b8SAndroid Build Coastguard Worker if (!_.subset (c, this)) return false; 330*2d1272b8SAndroid Build Coastguard Worker len++; 331*2d1272b8SAndroid Build Coastguard Worker } 332*2d1272b8SAndroid Build Coastguard Worker return_trace (c->serializer->check_assign (out->featMinMaxRecords.len, len, 333*2d1272b8SAndroid Build Coastguard Worker HB_SERIALIZE_ERROR_INT_OVERFLOW)); 334*2d1272b8SAndroid Build Coastguard Worker } 335*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::MinMax336*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 337*2d1272b8SAndroid Build Coastguard Worker { 338*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 339*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 340*2d1272b8SAndroid Build Coastguard Worker minCoord.sanitize (c, this) && 341*2d1272b8SAndroid Build Coastguard Worker maxCoord.sanitize (c, this) && 342*2d1272b8SAndroid Build Coastguard Worker featMinMaxRecords.sanitize (c, this))); 343*2d1272b8SAndroid Build Coastguard Worker } 344*2d1272b8SAndroid Build Coastguard Worker 345*2d1272b8SAndroid Build Coastguard Worker protected: 346*2d1272b8SAndroid Build Coastguard Worker Offset16To<BaseCoord> 347*2d1272b8SAndroid Build Coastguard Worker minCoord; /* Offset to BaseCoord table that defines 348*2d1272b8SAndroid Build Coastguard Worker * minimum extent value, from the beginning 349*2d1272b8SAndroid Build Coastguard Worker * of MinMax table (may be NULL) */ 350*2d1272b8SAndroid Build Coastguard Worker Offset16To<BaseCoord> 351*2d1272b8SAndroid Build Coastguard Worker maxCoord; /* Offset to BaseCoord table that defines 352*2d1272b8SAndroid Build Coastguard Worker * maximum extent value, from the beginning 353*2d1272b8SAndroid Build Coastguard Worker * of MinMax table (may be NULL) */ 354*2d1272b8SAndroid Build Coastguard Worker SortedArray16Of<FeatMinMaxRecord> 355*2d1272b8SAndroid Build Coastguard Worker featMinMaxRecords; 356*2d1272b8SAndroid Build Coastguard Worker /* Array of FeatMinMaxRecords, in alphabetical 357*2d1272b8SAndroid Build Coastguard Worker * order by featureTableTag */ 358*2d1272b8SAndroid Build Coastguard Worker public: 359*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY (6, featMinMaxRecords); 360*2d1272b8SAndroid Build Coastguard Worker }; 361*2d1272b8SAndroid Build Coastguard Worker 362*2d1272b8SAndroid Build Coastguard Worker struct BaseValues 363*2d1272b8SAndroid Build Coastguard Worker { get_base_coordOT::BaseValues364*2d1272b8SAndroid Build Coastguard Worker const BaseCoord &get_base_coord (int baseline_tag_index) const 365*2d1272b8SAndroid Build Coastguard Worker { 366*2d1272b8SAndroid Build Coastguard Worker if (baseline_tag_index == -1) baseline_tag_index = defaultIndex; 367*2d1272b8SAndroid Build Coastguard Worker return this+baseCoords[baseline_tag_index]; 368*2d1272b8SAndroid Build Coastguard Worker } 369*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BaseValues370*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const 371*2d1272b8SAndroid Build Coastguard Worker { 372*2d1272b8SAndroid Build Coastguard Worker for (const auto& _ : baseCoords) 373*2d1272b8SAndroid Build Coastguard Worker (this+_).collect_variation_indices (varidx_set); 374*2d1272b8SAndroid Build Coastguard Worker } 375*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseValues376*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 377*2d1272b8SAndroid Build Coastguard Worker { 378*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 379*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->start_embed (*this); 380*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); 381*2d1272b8SAndroid Build Coastguard Worker out->defaultIndex = defaultIndex; 382*2d1272b8SAndroid Build Coastguard Worker 383*2d1272b8SAndroid Build Coastguard Worker for (const auto& _ : baseCoords) 384*2d1272b8SAndroid Build Coastguard Worker if (!subset_offset_array (c, out->baseCoords, this) (_)) 385*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 386*2d1272b8SAndroid Build Coastguard Worker 387*2d1272b8SAndroid Build Coastguard Worker return_trace (bool (out->baseCoords)); 388*2d1272b8SAndroid Build Coastguard Worker } 389*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseValues390*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 391*2d1272b8SAndroid Build Coastguard Worker { 392*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 393*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 394*2d1272b8SAndroid Build Coastguard Worker baseCoords.sanitize (c, this))); 395*2d1272b8SAndroid Build Coastguard Worker } 396*2d1272b8SAndroid Build Coastguard Worker 397*2d1272b8SAndroid Build Coastguard Worker protected: 398*2d1272b8SAndroid Build Coastguard Worker Index defaultIndex; /* Index number of default baseline for this 399*2d1272b8SAndroid Build Coastguard Worker * script — equals index position of baseline tag 400*2d1272b8SAndroid Build Coastguard Worker * in baselineTags array of the BaseTagList */ 401*2d1272b8SAndroid Build Coastguard Worker Array16OfOffset16To<BaseCoord> 402*2d1272b8SAndroid Build Coastguard Worker baseCoords; /* Number of BaseCoord tables defined — should equal 403*2d1272b8SAndroid Build Coastguard Worker * baseTagCount in the BaseTagList 404*2d1272b8SAndroid Build Coastguard Worker * 405*2d1272b8SAndroid Build Coastguard Worker * Array of offsets to BaseCoord tables, from beginning of 406*2d1272b8SAndroid Build Coastguard Worker * BaseValues table — order matches baselineTags array in 407*2d1272b8SAndroid Build Coastguard Worker * the BaseTagList */ 408*2d1272b8SAndroid Build Coastguard Worker public: 409*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY (4, baseCoords); 410*2d1272b8SAndroid Build Coastguard Worker }; 411*2d1272b8SAndroid Build Coastguard Worker 412*2d1272b8SAndroid Build Coastguard Worker struct BaseLangSysRecord 413*2d1272b8SAndroid Build Coastguard Worker { cmpOT::BaseLangSysRecord414*2d1272b8SAndroid Build Coastguard Worker int cmp (hb_tag_t key) const { return baseLangSysTag.cmp (key); } 415*2d1272b8SAndroid Build Coastguard Worker has_dataOT::BaseLangSysRecord416*2d1272b8SAndroid Build Coastguard Worker bool has_data () const { return baseLangSysTag; } 417*2d1272b8SAndroid Build Coastguard Worker get_min_maxOT::BaseLangSysRecord418*2d1272b8SAndroid Build Coastguard Worker const MinMax &get_min_max (const void* base) const { return base+minMax; } 419*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BaseLangSysRecord420*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const void* base, 421*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t* plan, 422*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 423*2d1272b8SAndroid Build Coastguard Worker { (base+minMax).collect_variation_indices (plan, varidx_set); } 424*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseLangSysRecord425*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c, 426*2d1272b8SAndroid Build Coastguard Worker const void *base) const 427*2d1272b8SAndroid Build Coastguard Worker { 428*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 429*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->embed (*this); 430*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out)) return_trace (false); 431*2d1272b8SAndroid Build Coastguard Worker 432*2d1272b8SAndroid Build Coastguard Worker return_trace (out->minMax.serialize_subset (c, minMax, base)); 433*2d1272b8SAndroid Build Coastguard Worker } 434*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseLangSysRecord435*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c, const void *base) const 436*2d1272b8SAndroid Build Coastguard Worker { 437*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 438*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 439*2d1272b8SAndroid Build Coastguard Worker minMax.sanitize (c, base))); 440*2d1272b8SAndroid Build Coastguard Worker } 441*2d1272b8SAndroid Build Coastguard Worker 442*2d1272b8SAndroid Build Coastguard Worker protected: 443*2d1272b8SAndroid Build Coastguard Worker Tag baseLangSysTag; /* 4-byte language system identification tag */ 444*2d1272b8SAndroid Build Coastguard Worker Offset16To<MinMax> 445*2d1272b8SAndroid Build Coastguard Worker minMax; /* Offset to MinMax table, from beginning 446*2d1272b8SAndroid Build Coastguard Worker * of BaseScript table */ 447*2d1272b8SAndroid Build Coastguard Worker public: 448*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (6); 449*2d1272b8SAndroid Build Coastguard Worker }; 450*2d1272b8SAndroid Build Coastguard Worker 451*2d1272b8SAndroid Build Coastguard Worker struct BaseScript 452*2d1272b8SAndroid Build Coastguard Worker { get_min_maxOT::BaseScript453*2d1272b8SAndroid Build Coastguard Worker const MinMax &get_min_max (hb_tag_t language_tag) const 454*2d1272b8SAndroid Build Coastguard Worker { 455*2d1272b8SAndroid Build Coastguard Worker const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag); 456*2d1272b8SAndroid Build Coastguard Worker return record.has_data () ? record.get_min_max (this) : this+defaultMinMax; 457*2d1272b8SAndroid Build Coastguard Worker } 458*2d1272b8SAndroid Build Coastguard Worker get_base_coordOT::BaseScript459*2d1272b8SAndroid Build Coastguard Worker const BaseCoord &get_base_coord (int baseline_tag_index) const 460*2d1272b8SAndroid Build Coastguard Worker { return (this+baseValues).get_base_coord (baseline_tag_index); } 461*2d1272b8SAndroid Build Coastguard Worker has_valuesOT::BaseScript462*2d1272b8SAndroid Build Coastguard Worker bool has_values () const { return baseValues; } has_min_maxOT::BaseScript463*2d1272b8SAndroid Build Coastguard Worker bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ } 464*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BaseScript465*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const hb_subset_plan_t* plan, 466*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 467*2d1272b8SAndroid Build Coastguard Worker { 468*2d1272b8SAndroid Build Coastguard Worker (this+baseValues).collect_variation_indices (varidx_set); 469*2d1272b8SAndroid Build Coastguard Worker (this+defaultMinMax).collect_variation_indices (plan, varidx_set); 470*2d1272b8SAndroid Build Coastguard Worker 471*2d1272b8SAndroid Build Coastguard Worker for (const BaseLangSysRecord& _ : baseLangSysRecords) 472*2d1272b8SAndroid Build Coastguard Worker _.collect_variation_indices (this, plan, varidx_set); 473*2d1272b8SAndroid Build Coastguard Worker } 474*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseScript475*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 476*2d1272b8SAndroid Build Coastguard Worker { 477*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 478*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->start_embed (*this); 479*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); 480*2d1272b8SAndroid Build Coastguard Worker 481*2d1272b8SAndroid Build Coastguard Worker if (baseValues && !out->baseValues.serialize_subset (c, baseValues, this)) 482*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 483*2d1272b8SAndroid Build Coastguard Worker 484*2d1272b8SAndroid Build Coastguard Worker if (defaultMinMax && !out->defaultMinMax.serialize_subset (c, defaultMinMax, this)) 485*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 486*2d1272b8SAndroid Build Coastguard Worker 487*2d1272b8SAndroid Build Coastguard Worker for (const auto& _ : baseLangSysRecords) 488*2d1272b8SAndroid Build Coastguard Worker if (!_.subset (c, this)) return_trace (false); 489*2d1272b8SAndroid Build Coastguard Worker 490*2d1272b8SAndroid Build Coastguard Worker return_trace (c->serializer->check_assign (out->baseLangSysRecords.len, baseLangSysRecords.len, 491*2d1272b8SAndroid Build Coastguard Worker HB_SERIALIZE_ERROR_INT_OVERFLOW)); 492*2d1272b8SAndroid Build Coastguard Worker } 493*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseScript494*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 495*2d1272b8SAndroid Build Coastguard Worker { 496*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 497*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 498*2d1272b8SAndroid Build Coastguard Worker baseValues.sanitize (c, this) && 499*2d1272b8SAndroid Build Coastguard Worker defaultMinMax.sanitize (c, this) && 500*2d1272b8SAndroid Build Coastguard Worker baseLangSysRecords.sanitize (c, this))); 501*2d1272b8SAndroid Build Coastguard Worker } 502*2d1272b8SAndroid Build Coastguard Worker 503*2d1272b8SAndroid Build Coastguard Worker protected: 504*2d1272b8SAndroid Build Coastguard Worker Offset16To<BaseValues> 505*2d1272b8SAndroid Build Coastguard Worker baseValues; /* Offset to BaseValues table, from beginning 506*2d1272b8SAndroid Build Coastguard Worker * of BaseScript table (may be NULL) */ 507*2d1272b8SAndroid Build Coastguard Worker Offset16To<MinMax> 508*2d1272b8SAndroid Build Coastguard Worker defaultMinMax; /* Offset to MinMax table, from beginning of 509*2d1272b8SAndroid Build Coastguard Worker * BaseScript table (may be NULL) */ 510*2d1272b8SAndroid Build Coastguard Worker SortedArray16Of<BaseLangSysRecord> 511*2d1272b8SAndroid Build Coastguard Worker baseLangSysRecords; 512*2d1272b8SAndroid Build Coastguard Worker /* Number of BaseLangSysRecords 513*2d1272b8SAndroid Build Coastguard Worker * defined — may be zero (0) */ 514*2d1272b8SAndroid Build Coastguard Worker 515*2d1272b8SAndroid Build Coastguard Worker public: 516*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY (6, baseLangSysRecords); 517*2d1272b8SAndroid Build Coastguard Worker }; 518*2d1272b8SAndroid Build Coastguard Worker 519*2d1272b8SAndroid Build Coastguard Worker struct BaseScriptList; 520*2d1272b8SAndroid Build Coastguard Worker struct BaseScriptRecord 521*2d1272b8SAndroid Build Coastguard Worker { cmpOT::BaseScriptRecord522*2d1272b8SAndroid Build Coastguard Worker int cmp (hb_tag_t key) const { return baseScriptTag.cmp (key); } 523*2d1272b8SAndroid Build Coastguard Worker has_dataOT::BaseScriptRecord524*2d1272b8SAndroid Build Coastguard Worker bool has_data () const { return baseScriptTag; } 525*2d1272b8SAndroid Build Coastguard Worker get_script_tagOT::BaseScriptRecord526*2d1272b8SAndroid Build Coastguard Worker hb_tag_t get_script_tag () const { return baseScriptTag; } 527*2d1272b8SAndroid Build Coastguard Worker get_base_scriptOT::BaseScriptRecord528*2d1272b8SAndroid Build Coastguard Worker const BaseScript &get_base_script (const BaseScriptList *list) const 529*2d1272b8SAndroid Build Coastguard Worker { return list+baseScript; } 530*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BaseScriptRecord531*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const hb_subset_plan_t* plan, 532*2d1272b8SAndroid Build Coastguard Worker const void* list, 533*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 534*2d1272b8SAndroid Build Coastguard Worker { 535*2d1272b8SAndroid Build Coastguard Worker if (!plan->layout_scripts.has (baseScriptTag)) 536*2d1272b8SAndroid Build Coastguard Worker return; 537*2d1272b8SAndroid Build Coastguard Worker 538*2d1272b8SAndroid Build Coastguard Worker (list+baseScript).collect_variation_indices (plan, varidx_set); 539*2d1272b8SAndroid Build Coastguard Worker } 540*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseScriptRecord541*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c, 542*2d1272b8SAndroid Build Coastguard Worker const void *base) const 543*2d1272b8SAndroid Build Coastguard Worker { 544*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 545*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->embed (*this); 546*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out)) return_trace (false); 547*2d1272b8SAndroid Build Coastguard Worker 548*2d1272b8SAndroid Build Coastguard Worker return_trace (out->baseScript.serialize_subset (c, baseScript, base)); 549*2d1272b8SAndroid Build Coastguard Worker } 550*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseScriptRecord551*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c, const void *base) const 552*2d1272b8SAndroid Build Coastguard Worker { 553*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 554*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 555*2d1272b8SAndroid Build Coastguard Worker baseScript.sanitize (c, base))); 556*2d1272b8SAndroid Build Coastguard Worker } 557*2d1272b8SAndroid Build Coastguard Worker 558*2d1272b8SAndroid Build Coastguard Worker protected: 559*2d1272b8SAndroid Build Coastguard Worker Tag baseScriptTag; /* 4-byte script identification tag */ 560*2d1272b8SAndroid Build Coastguard Worker Offset16To<BaseScript> 561*2d1272b8SAndroid Build Coastguard Worker baseScript; /* Offset to BaseScript table, from beginning 562*2d1272b8SAndroid Build Coastguard Worker * of BaseScriptList */ 563*2d1272b8SAndroid Build Coastguard Worker 564*2d1272b8SAndroid Build Coastguard Worker public: 565*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (6); 566*2d1272b8SAndroid Build Coastguard Worker }; 567*2d1272b8SAndroid Build Coastguard Worker 568*2d1272b8SAndroid Build Coastguard Worker struct BaseScriptList 569*2d1272b8SAndroid Build Coastguard Worker { get_base_scriptOT::BaseScriptList570*2d1272b8SAndroid Build Coastguard Worker const BaseScript &get_base_script (hb_tag_t script) const 571*2d1272b8SAndroid Build Coastguard Worker { 572*2d1272b8SAndroid Build Coastguard Worker const BaseScriptRecord *record = &baseScriptRecords.bsearch (script); 573*2d1272b8SAndroid Build Coastguard Worker if (!record->has_data ()) record = &baseScriptRecords.bsearch (HB_TAG ('D','F','L','T')); 574*2d1272b8SAndroid Build Coastguard Worker return record->has_data () ? record->get_base_script (this) : Null (BaseScript); 575*2d1272b8SAndroid Build Coastguard Worker } 576*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BaseScriptList577*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const hb_subset_plan_t* plan, 578*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 579*2d1272b8SAndroid Build Coastguard Worker { 580*2d1272b8SAndroid Build Coastguard Worker for (const BaseScriptRecord& _ : baseScriptRecords) 581*2d1272b8SAndroid Build Coastguard Worker _.collect_variation_indices (plan, this, varidx_set); 582*2d1272b8SAndroid Build Coastguard Worker } 583*2d1272b8SAndroid Build Coastguard Worker subsetOT::BaseScriptList584*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 585*2d1272b8SAndroid Build Coastguard Worker { 586*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 587*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->start_embed (*this); 588*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); 589*2d1272b8SAndroid Build Coastguard Worker 590*2d1272b8SAndroid Build Coastguard Worker unsigned len = 0; 591*2d1272b8SAndroid Build Coastguard Worker for (const BaseScriptRecord& _ : baseScriptRecords) 592*2d1272b8SAndroid Build Coastguard Worker { 593*2d1272b8SAndroid Build Coastguard Worker hb_tag_t script_tag = _.get_script_tag (); 594*2d1272b8SAndroid Build Coastguard Worker if (!c->plan->layout_scripts.has (script_tag)) 595*2d1272b8SAndroid Build Coastguard Worker continue; 596*2d1272b8SAndroid Build Coastguard Worker 597*2d1272b8SAndroid Build Coastguard Worker if (!_.subset (c, this)) return false; 598*2d1272b8SAndroid Build Coastguard Worker len++; 599*2d1272b8SAndroid Build Coastguard Worker } 600*2d1272b8SAndroid Build Coastguard Worker return_trace (c->serializer->check_assign (out->baseScriptRecords.len, len, 601*2d1272b8SAndroid Build Coastguard Worker HB_SERIALIZE_ERROR_INT_OVERFLOW)); 602*2d1272b8SAndroid Build Coastguard Worker } 603*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BaseScriptList604*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 605*2d1272b8SAndroid Build Coastguard Worker { 606*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 607*2d1272b8SAndroid Build Coastguard Worker return_trace (c->check_struct (this) && 608*2d1272b8SAndroid Build Coastguard Worker baseScriptRecords.sanitize (c, this)); 609*2d1272b8SAndroid Build Coastguard Worker } 610*2d1272b8SAndroid Build Coastguard Worker 611*2d1272b8SAndroid Build Coastguard Worker protected: 612*2d1272b8SAndroid Build Coastguard Worker SortedArray16Of<BaseScriptRecord> 613*2d1272b8SAndroid Build Coastguard Worker baseScriptRecords; 614*2d1272b8SAndroid Build Coastguard Worker 615*2d1272b8SAndroid Build Coastguard Worker public: 616*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY (2, baseScriptRecords); 617*2d1272b8SAndroid Build Coastguard Worker }; 618*2d1272b8SAndroid Build Coastguard Worker 619*2d1272b8SAndroid Build Coastguard Worker struct Axis 620*2d1272b8SAndroid Build Coastguard Worker { get_baselineOT::Axis621*2d1272b8SAndroid Build Coastguard Worker bool get_baseline (hb_tag_t baseline_tag, 622*2d1272b8SAndroid Build Coastguard Worker hb_tag_t script_tag, 623*2d1272b8SAndroid Build Coastguard Worker hb_tag_t language_tag, 624*2d1272b8SAndroid Build Coastguard Worker const BaseCoord **coord) const 625*2d1272b8SAndroid Build Coastguard Worker { 626*2d1272b8SAndroid Build Coastguard Worker const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); 627*2d1272b8SAndroid Build Coastguard Worker if (!base_script.has_values ()) 628*2d1272b8SAndroid Build Coastguard Worker { 629*2d1272b8SAndroid Build Coastguard Worker *coord = nullptr; 630*2d1272b8SAndroid Build Coastguard Worker return false; 631*2d1272b8SAndroid Build Coastguard Worker } 632*2d1272b8SAndroid Build Coastguard Worker 633*2d1272b8SAndroid Build Coastguard Worker if (likely (coord)) 634*2d1272b8SAndroid Build Coastguard Worker { 635*2d1272b8SAndroid Build Coastguard Worker unsigned int tag_index = 0; 636*2d1272b8SAndroid Build Coastguard Worker if (!(this+baseTagList).bfind (baseline_tag, &tag_index)) 637*2d1272b8SAndroid Build Coastguard Worker { 638*2d1272b8SAndroid Build Coastguard Worker *coord = nullptr; 639*2d1272b8SAndroid Build Coastguard Worker return false; 640*2d1272b8SAndroid Build Coastguard Worker } 641*2d1272b8SAndroid Build Coastguard Worker *coord = &base_script.get_base_coord (tag_index); 642*2d1272b8SAndroid Build Coastguard Worker } 643*2d1272b8SAndroid Build Coastguard Worker 644*2d1272b8SAndroid Build Coastguard Worker return true; 645*2d1272b8SAndroid Build Coastguard Worker } 646*2d1272b8SAndroid Build Coastguard Worker get_min_maxOT::Axis647*2d1272b8SAndroid Build Coastguard Worker bool get_min_max (hb_tag_t script_tag, 648*2d1272b8SAndroid Build Coastguard Worker hb_tag_t language_tag, 649*2d1272b8SAndroid Build Coastguard Worker hb_tag_t feature_tag, 650*2d1272b8SAndroid Build Coastguard Worker const BaseCoord **min_coord, 651*2d1272b8SAndroid Build Coastguard Worker const BaseCoord **max_coord) const 652*2d1272b8SAndroid Build Coastguard Worker { 653*2d1272b8SAndroid Build Coastguard Worker const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); 654*2d1272b8SAndroid Build Coastguard Worker if (!base_script.has_min_max ()) 655*2d1272b8SAndroid Build Coastguard Worker { 656*2d1272b8SAndroid Build Coastguard Worker *min_coord = *max_coord = nullptr; 657*2d1272b8SAndroid Build Coastguard Worker return false; 658*2d1272b8SAndroid Build Coastguard Worker } 659*2d1272b8SAndroid Build Coastguard Worker 660*2d1272b8SAndroid Build Coastguard Worker base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord); 661*2d1272b8SAndroid Build Coastguard Worker 662*2d1272b8SAndroid Build Coastguard Worker return true; 663*2d1272b8SAndroid Build Coastguard Worker } 664*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::Axis665*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const hb_subset_plan_t* plan, 666*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 667*2d1272b8SAndroid Build Coastguard Worker { (this+baseScriptList).collect_variation_indices (plan, varidx_set); } 668*2d1272b8SAndroid Build Coastguard Worker subsetOT::Axis669*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 670*2d1272b8SAndroid Build Coastguard Worker { 671*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 672*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->embed (*this); 673*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out)) return_trace (false); 674*2d1272b8SAndroid Build Coastguard Worker 675*2d1272b8SAndroid Build Coastguard Worker out->baseTagList.serialize_copy (c->serializer, baseTagList, this); 676*2d1272b8SAndroid Build Coastguard Worker return_trace (out->baseScriptList.serialize_subset (c, baseScriptList, this)); 677*2d1272b8SAndroid Build Coastguard Worker } 678*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::Axis679*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 680*2d1272b8SAndroid Build Coastguard Worker { 681*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 682*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 683*2d1272b8SAndroid Build Coastguard Worker baseTagList.sanitize (c, this) && 684*2d1272b8SAndroid Build Coastguard Worker baseScriptList.sanitize (c, this))); 685*2d1272b8SAndroid Build Coastguard Worker } 686*2d1272b8SAndroid Build Coastguard Worker 687*2d1272b8SAndroid Build Coastguard Worker protected: 688*2d1272b8SAndroid Build Coastguard Worker Offset16To<SortedArray16Of<Tag>> 689*2d1272b8SAndroid Build Coastguard Worker baseTagList; /* Offset to BaseTagList table, from beginning 690*2d1272b8SAndroid Build Coastguard Worker * of Axis table (may be NULL) 691*2d1272b8SAndroid Build Coastguard Worker * Array of 4-byte baseline identification tags — must 692*2d1272b8SAndroid Build Coastguard Worker * be in alphabetical order */ 693*2d1272b8SAndroid Build Coastguard Worker Offset16To<BaseScriptList> 694*2d1272b8SAndroid Build Coastguard Worker baseScriptList; /* Offset to BaseScriptList table, from beginning 695*2d1272b8SAndroid Build Coastguard Worker * of Axis table 696*2d1272b8SAndroid Build Coastguard Worker * Array of BaseScriptRecords, in alphabetical order 697*2d1272b8SAndroid Build Coastguard Worker * by baseScriptTag */ 698*2d1272b8SAndroid Build Coastguard Worker 699*2d1272b8SAndroid Build Coastguard Worker public: 700*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (4); 701*2d1272b8SAndroid Build Coastguard Worker }; 702*2d1272b8SAndroid Build Coastguard Worker 703*2d1272b8SAndroid Build Coastguard Worker struct BASE 704*2d1272b8SAndroid Build Coastguard Worker { 705*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t tableTag = HB_OT_TAG_BASE; 706*2d1272b8SAndroid Build Coastguard Worker get_axisOT::BASE707*2d1272b8SAndroid Build Coastguard Worker const Axis &get_axis (hb_direction_t direction) const 708*2d1272b8SAndroid Build Coastguard Worker { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; } 709*2d1272b8SAndroid Build Coastguard Worker has_var_storeOT::BASE710*2d1272b8SAndroid Build Coastguard Worker bool has_var_store () const 711*2d1272b8SAndroid Build Coastguard Worker { return version.to_int () >= 0x00010001u && varStore != 0; } 712*2d1272b8SAndroid Build Coastguard Worker get_var_storeOT::BASE713*2d1272b8SAndroid Build Coastguard Worker const ItemVariationStore &get_var_store () const 714*2d1272b8SAndroid Build Coastguard Worker { return version.to_int () < 0x00010001u ? Null (ItemVariationStore) : this+varStore; } 715*2d1272b8SAndroid Build Coastguard Worker collect_variation_indicesOT::BASE716*2d1272b8SAndroid Build Coastguard Worker void collect_variation_indices (const hb_subset_plan_t* plan, 717*2d1272b8SAndroid Build Coastguard Worker hb_set_t& varidx_set /* OUT */) const 718*2d1272b8SAndroid Build Coastguard Worker { 719*2d1272b8SAndroid Build Coastguard Worker (this+hAxis).collect_variation_indices (plan, varidx_set); 720*2d1272b8SAndroid Build Coastguard Worker (this+vAxis).collect_variation_indices (plan, varidx_set); 721*2d1272b8SAndroid Build Coastguard Worker } 722*2d1272b8SAndroid Build Coastguard Worker subset_varstoreOT::BASE723*2d1272b8SAndroid Build Coastguard Worker bool subset_varstore (hb_subset_context_t *c, 724*2d1272b8SAndroid Build Coastguard Worker BASE *out /* OUT */) const 725*2d1272b8SAndroid Build Coastguard Worker { 726*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 727*2d1272b8SAndroid Build Coastguard Worker if (!c->serializer->allocate_size<Offset32To<ItemVariationStore>> (Offset32To<ItemVariationStore>::static_size)) 728*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 729*2d1272b8SAndroid Build Coastguard Worker if (!c->plan->normalized_coords) 730*2d1272b8SAndroid Build Coastguard Worker return_trace (out->varStore.serialize_subset (c, varStore, this, c->plan->base_varstore_inner_maps.as_array ())); 731*2d1272b8SAndroid Build Coastguard Worker 732*2d1272b8SAndroid Build Coastguard Worker if (c->plan->all_axes_pinned) 733*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 734*2d1272b8SAndroid Build Coastguard Worker 735*2d1272b8SAndroid Build Coastguard Worker item_variations_t item_vars; 736*2d1272b8SAndroid Build Coastguard Worker if (!item_vars.instantiate (this+varStore, c->plan, true, true, 737*2d1272b8SAndroid Build Coastguard Worker c->plan->base_varstore_inner_maps.as_array ())) 738*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 739*2d1272b8SAndroid Build Coastguard Worker 740*2d1272b8SAndroid Build Coastguard Worker if (!out->varStore.serialize_serialize (c->serializer, 741*2d1272b8SAndroid Build Coastguard Worker item_vars.has_long_word (), 742*2d1272b8SAndroid Build Coastguard Worker c->plan->axis_tags, 743*2d1272b8SAndroid Build Coastguard Worker item_vars.get_region_list (), 744*2d1272b8SAndroid Build Coastguard Worker item_vars.get_vardata_encodings ())) 745*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 746*2d1272b8SAndroid Build Coastguard Worker 747*2d1272b8SAndroid Build Coastguard Worker const hb_map_t &varidx_map = item_vars.get_varidx_map (); 748*2d1272b8SAndroid Build Coastguard Worker /* base_variation_idx_map in the plan is old_varidx->(varidx, delta) 749*2d1272b8SAndroid Build Coastguard Worker * mapping, new varidx is generated for subsetting, we need to remap this 750*2d1272b8SAndroid Build Coastguard Worker * after instancing */ 751*2d1272b8SAndroid Build Coastguard Worker for (auto _ : c->plan->base_variation_idx_map.iter_ref ()) 752*2d1272b8SAndroid Build Coastguard Worker { 753*2d1272b8SAndroid Build Coastguard Worker uint32_t varidx = _.second.first; 754*2d1272b8SAndroid Build Coastguard Worker uint32_t *new_varidx; 755*2d1272b8SAndroid Build Coastguard Worker if (varidx_map.has (varidx, &new_varidx)) 756*2d1272b8SAndroid Build Coastguard Worker _.second.first = *new_varidx; 757*2d1272b8SAndroid Build Coastguard Worker else 758*2d1272b8SAndroid Build Coastguard Worker _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX; 759*2d1272b8SAndroid Build Coastguard Worker } 760*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 761*2d1272b8SAndroid Build Coastguard Worker } 762*2d1272b8SAndroid Build Coastguard Worker subsetOT::BASE763*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 764*2d1272b8SAndroid Build Coastguard Worker { 765*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 766*2d1272b8SAndroid Build Coastguard Worker auto *out = c->serializer->start_embed (*this); 767*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); 768*2d1272b8SAndroid Build Coastguard Worker 769*2d1272b8SAndroid Build Coastguard Worker out->version = version; 770*2d1272b8SAndroid Build Coastguard Worker if (has_var_store () && !subset_varstore (c, out)) 771*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 772*2d1272b8SAndroid Build Coastguard Worker 773*2d1272b8SAndroid Build Coastguard Worker if (hAxis && !out->hAxis.serialize_subset (c, hAxis, this)) 774*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 775*2d1272b8SAndroid Build Coastguard Worker 776*2d1272b8SAndroid Build Coastguard Worker if (vAxis && !out->vAxis.serialize_subset (c, vAxis, this)) 777*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 778*2d1272b8SAndroid Build Coastguard Worker 779*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 780*2d1272b8SAndroid Build Coastguard Worker } 781*2d1272b8SAndroid Build Coastguard Worker get_baselineOT::BASE782*2d1272b8SAndroid Build Coastguard Worker bool get_baseline (hb_font_t *font, 783*2d1272b8SAndroid Build Coastguard Worker hb_tag_t baseline_tag, 784*2d1272b8SAndroid Build Coastguard Worker hb_direction_t direction, 785*2d1272b8SAndroid Build Coastguard Worker hb_tag_t script_tag, 786*2d1272b8SAndroid Build Coastguard Worker hb_tag_t language_tag, 787*2d1272b8SAndroid Build Coastguard Worker hb_position_t *base) const 788*2d1272b8SAndroid Build Coastguard Worker { 789*2d1272b8SAndroid Build Coastguard Worker const BaseCoord *base_coord = nullptr; 790*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!get_axis (direction).get_baseline (baseline_tag, script_tag, language_tag, &base_coord) || 791*2d1272b8SAndroid Build Coastguard Worker !base_coord || !base_coord->has_data ())) 792*2d1272b8SAndroid Build Coastguard Worker return false; 793*2d1272b8SAndroid Build Coastguard Worker 794*2d1272b8SAndroid Build Coastguard Worker if (likely (base)) 795*2d1272b8SAndroid Build Coastguard Worker *base = base_coord->get_coord (font, get_var_store (), direction); 796*2d1272b8SAndroid Build Coastguard Worker 797*2d1272b8SAndroid Build Coastguard Worker return true; 798*2d1272b8SAndroid Build Coastguard Worker } 799*2d1272b8SAndroid Build Coastguard Worker get_min_maxOT::BASE800*2d1272b8SAndroid Build Coastguard Worker bool get_min_max (hb_font_t *font, 801*2d1272b8SAndroid Build Coastguard Worker hb_direction_t direction, 802*2d1272b8SAndroid Build Coastguard Worker hb_tag_t script_tag, 803*2d1272b8SAndroid Build Coastguard Worker hb_tag_t language_tag, 804*2d1272b8SAndroid Build Coastguard Worker hb_tag_t feature_tag, 805*2d1272b8SAndroid Build Coastguard Worker hb_position_t *min, 806*2d1272b8SAndroid Build Coastguard Worker hb_position_t *max) const 807*2d1272b8SAndroid Build Coastguard Worker { 808*2d1272b8SAndroid Build Coastguard Worker const BaseCoord *min_coord, *max_coord; 809*2d1272b8SAndroid Build Coastguard Worker if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag, 810*2d1272b8SAndroid Build Coastguard Worker &min_coord, &max_coord)) 811*2d1272b8SAndroid Build Coastguard Worker return false; 812*2d1272b8SAndroid Build Coastguard Worker 813*2d1272b8SAndroid Build Coastguard Worker const ItemVariationStore &var_store = get_var_store (); 814*2d1272b8SAndroid Build Coastguard Worker if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction); 815*2d1272b8SAndroid Build Coastguard Worker if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction); 816*2d1272b8SAndroid Build Coastguard Worker return true; 817*2d1272b8SAndroid Build Coastguard Worker } 818*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::BASE819*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 820*2d1272b8SAndroid Build Coastguard Worker { 821*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 822*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (c->check_struct (this) && 823*2d1272b8SAndroid Build Coastguard Worker hb_barrier () && 824*2d1272b8SAndroid Build Coastguard Worker likely (version.major == 1) && 825*2d1272b8SAndroid Build Coastguard Worker hAxis.sanitize (c, this) && 826*2d1272b8SAndroid Build Coastguard Worker vAxis.sanitize (c, this) && 827*2d1272b8SAndroid Build Coastguard Worker (version.to_int () < 0x00010001u || varStore.sanitize (c, this)))); 828*2d1272b8SAndroid Build Coastguard Worker } 829*2d1272b8SAndroid Build Coastguard Worker 830*2d1272b8SAndroid Build Coastguard Worker protected: 831*2d1272b8SAndroid Build Coastguard Worker FixedVersion<>version; /* Version of the BASE table */ 832*2d1272b8SAndroid Build Coastguard Worker Offset16To<Axis>hAxis; /* Offset to horizontal Axis table, from beginning 833*2d1272b8SAndroid Build Coastguard Worker * of BASE table (may be NULL) */ 834*2d1272b8SAndroid Build Coastguard Worker Offset16To<Axis>vAxis; /* Offset to vertical Axis table, from beginning 835*2d1272b8SAndroid Build Coastguard Worker * of BASE table (may be NULL) */ 836*2d1272b8SAndroid Build Coastguard Worker Offset32To<ItemVariationStore> 837*2d1272b8SAndroid Build Coastguard Worker varStore; /* Offset to the table of Item Variation 838*2d1272b8SAndroid Build Coastguard Worker * Store--from beginning of BASE 839*2d1272b8SAndroid Build Coastguard Worker * header (may be NULL). Introduced 840*2d1272b8SAndroid Build Coastguard Worker * in version 0x00010001. */ 841*2d1272b8SAndroid Build Coastguard Worker public: 842*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_MIN (8); 843*2d1272b8SAndroid Build Coastguard Worker }; 844*2d1272b8SAndroid Build Coastguard Worker 845*2d1272b8SAndroid Build Coastguard Worker 846*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 847*2d1272b8SAndroid Build Coastguard Worker 848*2d1272b8SAndroid Build Coastguard Worker 849*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_LAYOUT_BASE_TABLE_HH */ 850