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_HVAR_TABLE_HH 28*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_VAR_HVAR_TABLE_HH 29*2d1272b8SAndroid Build Coastguard Worker 30*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-layout-common.hh" 31*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-var-common.hh" 32*2d1272b8SAndroid Build Coastguard Worker 33*2d1272b8SAndroid Build Coastguard Worker namespace OT { 34*2d1272b8SAndroid Build Coastguard Worker 35*2d1272b8SAndroid Build Coastguard Worker 36*2d1272b8SAndroid Build Coastguard Worker struct index_map_subset_plan_t 37*2d1272b8SAndroid Build Coastguard Worker { 38*2d1272b8SAndroid Build Coastguard Worker enum index_map_index_t { 39*2d1272b8SAndroid Build Coastguard Worker ADV_INDEX, 40*2d1272b8SAndroid Build Coastguard Worker LSB_INDEX, /* dual as TSB */ 41*2d1272b8SAndroid Build Coastguard Worker RSB_INDEX, /* dual as BSB */ 42*2d1272b8SAndroid Build Coastguard Worker VORG_INDEX 43*2d1272b8SAndroid Build Coastguard Worker }; 44*2d1272b8SAndroid Build Coastguard Worker initOT::index_map_subset_plan_t45*2d1272b8SAndroid Build Coastguard Worker void init (const DeltaSetIndexMap &index_map, 46*2d1272b8SAndroid Build Coastguard Worker hb_inc_bimap_t &outer_map, 47*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<hb_set_t *> &inner_sets, 48*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan, 49*2d1272b8SAndroid Build Coastguard Worker bool bypass_empty = true) 50*2d1272b8SAndroid Build Coastguard Worker { 51*2d1272b8SAndroid Build Coastguard Worker map_count = 0; 52*2d1272b8SAndroid Build Coastguard Worker outer_bit_count = 0; 53*2d1272b8SAndroid Build Coastguard Worker inner_bit_count = 1; 54*2d1272b8SAndroid Build Coastguard Worker max_inners.init (); 55*2d1272b8SAndroid Build Coastguard Worker output_map.init (); 56*2d1272b8SAndroid Build Coastguard Worker 57*2d1272b8SAndroid Build Coastguard Worker if (bypass_empty && !index_map.get_map_count ()) return; 58*2d1272b8SAndroid Build Coastguard Worker 59*2d1272b8SAndroid Build Coastguard Worker unsigned int last_val = (unsigned int)-1; 60*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t last_gid = HB_CODEPOINT_INVALID; 61*2d1272b8SAndroid Build Coastguard Worker 62*2d1272b8SAndroid Build Coastguard Worker outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count (); 63*2d1272b8SAndroid Build Coastguard Worker max_inners.resize (inner_sets.length); 64*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0; 65*2d1272b8SAndroid Build Coastguard Worker 66*2d1272b8SAndroid Build Coastguard Worker /* Search backwards for a map value different from the last map value */ 67*2d1272b8SAndroid Build Coastguard Worker auto &new_to_old_gid_list = plan->new_to_old_gid_list; 68*2d1272b8SAndroid Build Coastguard Worker unsigned count = new_to_old_gid_list.length; 69*2d1272b8SAndroid Build Coastguard Worker for (unsigned j = count; j; j--) 70*2d1272b8SAndroid Build Coastguard Worker { 71*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = new_to_old_gid_list.arrayZ[j - 1].first; 72*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid = new_to_old_gid_list.arrayZ[j - 1].second; 73*2d1272b8SAndroid Build Coastguard Worker 74*2d1272b8SAndroid Build Coastguard Worker unsigned int v = index_map.map (old_gid); 75*2d1272b8SAndroid Build Coastguard Worker if (last_gid == HB_CODEPOINT_INVALID) 76*2d1272b8SAndroid Build Coastguard Worker { 77*2d1272b8SAndroid Build Coastguard Worker last_val = v; 78*2d1272b8SAndroid Build Coastguard Worker last_gid = gid; 79*2d1272b8SAndroid Build Coastguard Worker continue; 80*2d1272b8SAndroid Build Coastguard Worker } 81*2d1272b8SAndroid Build Coastguard Worker if (v != last_val) 82*2d1272b8SAndroid Build Coastguard Worker break; 83*2d1272b8SAndroid Build Coastguard Worker 84*2d1272b8SAndroid Build Coastguard Worker last_gid = gid; 85*2d1272b8SAndroid Build Coastguard Worker } 86*2d1272b8SAndroid Build Coastguard Worker 87*2d1272b8SAndroid Build Coastguard Worker if (unlikely (last_gid == (hb_codepoint_t)-1)) return; 88*2d1272b8SAndroid Build Coastguard Worker map_count = last_gid + 1; 89*2d1272b8SAndroid Build Coastguard Worker for (auto _ : plan->new_to_old_gid_list) 90*2d1272b8SAndroid Build Coastguard Worker { 91*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = _.first; 92*2d1272b8SAndroid Build Coastguard Worker if (gid >= map_count) break; 93*2d1272b8SAndroid Build Coastguard Worker 94*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid = _.second; 95*2d1272b8SAndroid Build Coastguard Worker unsigned int v = index_map.map (old_gid); 96*2d1272b8SAndroid Build Coastguard Worker unsigned int outer = v >> 16; 97*2d1272b8SAndroid Build Coastguard Worker unsigned int inner = v & 0xFFFF; 98*2d1272b8SAndroid Build Coastguard Worker outer_map.add (outer); 99*2d1272b8SAndroid Build Coastguard Worker if (inner > max_inners[outer]) max_inners[outer] = inner; 100*2d1272b8SAndroid Build Coastguard Worker if (outer >= inner_sets.length) return; 101*2d1272b8SAndroid Build Coastguard Worker inner_sets[outer]->add (inner); 102*2d1272b8SAndroid Build Coastguard Worker } 103*2d1272b8SAndroid Build Coastguard Worker } 104*2d1272b8SAndroid Build Coastguard Worker finiOT::index_map_subset_plan_t105*2d1272b8SAndroid Build Coastguard Worker void fini () 106*2d1272b8SAndroid Build Coastguard Worker { 107*2d1272b8SAndroid Build Coastguard Worker max_inners.fini (); 108*2d1272b8SAndroid Build Coastguard Worker output_map.fini (); 109*2d1272b8SAndroid Build Coastguard Worker } 110*2d1272b8SAndroid Build Coastguard Worker remapOT::index_map_subset_plan_t111*2d1272b8SAndroid Build Coastguard Worker void remap (const DeltaSetIndexMap *input_map, 112*2d1272b8SAndroid Build Coastguard Worker const hb_inc_bimap_t &outer_map, 113*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<hb_inc_bimap_t> &inner_maps, 114*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan) 115*2d1272b8SAndroid Build Coastguard Worker { 116*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < max_inners.length; i++) 117*2d1272b8SAndroid Build Coastguard Worker { 118*2d1272b8SAndroid Build Coastguard Worker if (inner_maps[i].get_population () == 0) continue; 119*2d1272b8SAndroid Build Coastguard Worker unsigned int bit_count = (max_inners[i]==0)? 1: hb_bit_storage (inner_maps[i][max_inners[i]]); 120*2d1272b8SAndroid Build Coastguard Worker if (bit_count > inner_bit_count) inner_bit_count = bit_count; 121*2d1272b8SAndroid Build Coastguard Worker } 122*2d1272b8SAndroid Build Coastguard Worker 123*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!output_map.resize (map_count))) return; 124*2d1272b8SAndroid Build Coastguard Worker for (const auto &_ : plan->new_to_old_gid_list) 125*2d1272b8SAndroid Build Coastguard Worker { 126*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_gid = _.first; 127*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid = _.second; 128*2d1272b8SAndroid Build Coastguard Worker 129*2d1272b8SAndroid Build Coastguard Worker if (unlikely (new_gid >= map_count)) break; 130*2d1272b8SAndroid Build Coastguard Worker 131*2d1272b8SAndroid Build Coastguard Worker uint32_t v = input_map->map (old_gid); 132*2d1272b8SAndroid Build Coastguard Worker unsigned int outer = v >> 16; 133*2d1272b8SAndroid Build Coastguard Worker output_map.arrayZ[new_gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]); 134*2d1272b8SAndroid Build Coastguard Worker } 135*2d1272b8SAndroid Build Coastguard Worker } 136*2d1272b8SAndroid Build Coastguard Worker remap_after_instantiationOT::index_map_subset_plan_t137*2d1272b8SAndroid Build Coastguard Worker bool remap_after_instantiation (const hb_subset_plan_t *plan, 138*2d1272b8SAndroid Build Coastguard Worker const hb_map_t& varidx_map) 139*2d1272b8SAndroid Build Coastguard Worker { 140*2d1272b8SAndroid Build Coastguard Worker /* recalculate bit_count after remapping */ 141*2d1272b8SAndroid Build Coastguard Worker outer_bit_count = 1; 142*2d1272b8SAndroid Build Coastguard Worker inner_bit_count = 1; 143*2d1272b8SAndroid Build Coastguard Worker 144*2d1272b8SAndroid Build Coastguard Worker for (const auto &_ : plan->new_to_old_gid_list) 145*2d1272b8SAndroid Build Coastguard Worker { 146*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_gid = _.first; 147*2d1272b8SAndroid Build Coastguard Worker if (unlikely (new_gid >= map_count)) break; 148*2d1272b8SAndroid Build Coastguard Worker 149*2d1272b8SAndroid Build Coastguard Worker uint32_t v = output_map.arrayZ[new_gid]; 150*2d1272b8SAndroid Build Coastguard Worker uint32_t *new_varidx; 151*2d1272b8SAndroid Build Coastguard Worker if (!varidx_map.has (v, &new_varidx)) 152*2d1272b8SAndroid Build Coastguard Worker return false; 153*2d1272b8SAndroid Build Coastguard Worker 154*2d1272b8SAndroid Build Coastguard Worker output_map.arrayZ[new_gid] = *new_varidx; 155*2d1272b8SAndroid Build Coastguard Worker 156*2d1272b8SAndroid Build Coastguard Worker unsigned outer = (*new_varidx) >> 16; 157*2d1272b8SAndroid Build Coastguard Worker unsigned bit_count = (outer == 0) ? 1 : hb_bit_storage (outer); 158*2d1272b8SAndroid Build Coastguard Worker outer_bit_count = hb_max (bit_count, outer_bit_count); 159*2d1272b8SAndroid Build Coastguard Worker 160*2d1272b8SAndroid Build Coastguard Worker unsigned inner = (*new_varidx) & 0xFFFF; 161*2d1272b8SAndroid Build Coastguard Worker bit_count = (inner == 0) ? 1 : hb_bit_storage (inner); 162*2d1272b8SAndroid Build Coastguard Worker inner_bit_count = hb_max (bit_count, inner_bit_count); 163*2d1272b8SAndroid Build Coastguard Worker } 164*2d1272b8SAndroid Build Coastguard Worker return true; 165*2d1272b8SAndroid Build Coastguard Worker } 166*2d1272b8SAndroid Build Coastguard Worker get_inner_bit_countOT::index_map_subset_plan_t167*2d1272b8SAndroid Build Coastguard Worker unsigned int get_inner_bit_count () const { return inner_bit_count; } get_widthOT::index_map_subset_plan_t168*2d1272b8SAndroid Build Coastguard Worker unsigned int get_width () const { return ((outer_bit_count + inner_bit_count + 7) / 8); } get_map_countOT::index_map_subset_plan_t169*2d1272b8SAndroid Build Coastguard Worker unsigned int get_map_count () const { return map_count; } 170*2d1272b8SAndroid Build Coastguard Worker get_sizeOT::index_map_subset_plan_t171*2d1272b8SAndroid Build Coastguard Worker unsigned int get_size () const 172*2d1272b8SAndroid Build Coastguard Worker { return (map_count? (DeltaSetIndexMap::min_size + get_width () * map_count): 0); } 173*2d1272b8SAndroid Build Coastguard Worker is_identityOT::index_map_subset_plan_t174*2d1272b8SAndroid Build Coastguard Worker bool is_identity () const { return get_output_map ().length == 0; } get_output_mapOT::index_map_subset_plan_t175*2d1272b8SAndroid Build Coastguard Worker hb_array_t<const uint32_t> get_output_map () const { return output_map.as_array (); } 176*2d1272b8SAndroid Build Coastguard Worker 177*2d1272b8SAndroid Build Coastguard Worker protected: 178*2d1272b8SAndroid Build Coastguard Worker unsigned int map_count; 179*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<unsigned int> max_inners; 180*2d1272b8SAndroid Build Coastguard Worker unsigned int outer_bit_count; 181*2d1272b8SAndroid Build Coastguard Worker unsigned int inner_bit_count; 182*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<uint32_t> output_map; 183*2d1272b8SAndroid Build Coastguard Worker }; 184*2d1272b8SAndroid Build Coastguard Worker 185*2d1272b8SAndroid Build Coastguard Worker struct hvarvvar_subset_plan_t 186*2d1272b8SAndroid Build Coastguard Worker { hvarvvar_subset_plan_tOT::hvarvvar_subset_plan_t187*2d1272b8SAndroid Build Coastguard Worker hvarvvar_subset_plan_t() : inner_maps (), index_map_plans () {} ~hvarvvar_subset_plan_tOT::hvarvvar_subset_plan_t188*2d1272b8SAndroid Build Coastguard Worker ~hvarvvar_subset_plan_t() { fini (); } 189*2d1272b8SAndroid Build Coastguard Worker initOT::hvarvvar_subset_plan_t190*2d1272b8SAndroid Build Coastguard Worker void init (const hb_array_t<const DeltaSetIndexMap *> &index_maps, 191*2d1272b8SAndroid Build Coastguard Worker const ItemVariationStore &_var_store, 192*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan) 193*2d1272b8SAndroid Build Coastguard Worker { 194*2d1272b8SAndroid Build Coastguard Worker index_map_plans.resize (index_maps.length); 195*2d1272b8SAndroid Build Coastguard Worker 196*2d1272b8SAndroid Build Coastguard Worker var_store = &_var_store; 197*2d1272b8SAndroid Build Coastguard Worker inner_sets.resize (var_store->get_sub_table_count ()); 198*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < inner_sets.length; i++) 199*2d1272b8SAndroid Build Coastguard Worker inner_sets[i] = hb_set_create (); 200*2d1272b8SAndroid Build Coastguard Worker adv_set = hb_set_create (); 201*2d1272b8SAndroid Build Coastguard Worker 202*2d1272b8SAndroid Build Coastguard Worker inner_maps.resize (var_store->get_sub_table_count ()); 203*2d1272b8SAndroid Build Coastguard Worker 204*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return; 205*2d1272b8SAndroid Build Coastguard Worker 206*2d1272b8SAndroid Build Coastguard Worker bool retain_adv_map = false; 207*2d1272b8SAndroid Build Coastguard Worker index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan, false); 208*2d1272b8SAndroid Build Coastguard Worker if (index_maps[0] == &Null (DeltaSetIndexMap)) 209*2d1272b8SAndroid Build Coastguard Worker { 210*2d1272b8SAndroid Build Coastguard Worker retain_adv_map = plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS; 211*2d1272b8SAndroid Build Coastguard Worker outer_map.add (0); 212*2d1272b8SAndroid Build Coastguard Worker for (hb_codepoint_t old_gid : plan->glyphset()->iter()) 213*2d1272b8SAndroid Build Coastguard Worker inner_sets[0]->add (old_gid); 214*2d1272b8SAndroid Build Coastguard Worker hb_set_union (adv_set, inner_sets[0]); 215*2d1272b8SAndroid Build Coastguard Worker } 216*2d1272b8SAndroid Build Coastguard Worker 217*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 1; i < index_maps.length; i++) 218*2d1272b8SAndroid Build Coastguard Worker index_map_plans[i].init (*index_maps[i], outer_map, inner_sets, plan); 219*2d1272b8SAndroid Build Coastguard Worker 220*2d1272b8SAndroid Build Coastguard Worker outer_map.sort (); 221*2d1272b8SAndroid Build Coastguard Worker 222*2d1272b8SAndroid Build Coastguard Worker if (retain_adv_map) 223*2d1272b8SAndroid Build Coastguard Worker { 224*2d1272b8SAndroid Build Coastguard Worker for (const auto &_ : plan->new_to_old_gid_list) 225*2d1272b8SAndroid Build Coastguard Worker { 226*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid = _.second; 227*2d1272b8SAndroid Build Coastguard Worker inner_maps[0].add (old_gid); 228*2d1272b8SAndroid Build Coastguard Worker } 229*2d1272b8SAndroid Build Coastguard Worker } 230*2d1272b8SAndroid Build Coastguard Worker else 231*2d1272b8SAndroid Build Coastguard Worker { 232*2d1272b8SAndroid Build Coastguard Worker inner_maps[0].add_set (adv_set); 233*2d1272b8SAndroid Build Coastguard Worker hb_set_subtract (inner_sets[0], adv_set); 234*2d1272b8SAndroid Build Coastguard Worker inner_maps[0].add_set (inner_sets[0]); 235*2d1272b8SAndroid Build Coastguard Worker } 236*2d1272b8SAndroid Build Coastguard Worker 237*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 1; i < inner_maps.length; i++) 238*2d1272b8SAndroid Build Coastguard Worker inner_maps[i].add_set (inner_sets[i]); 239*2d1272b8SAndroid Build Coastguard Worker 240*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < index_maps.length; i++) 241*2d1272b8SAndroid Build Coastguard Worker index_map_plans[i].remap (index_maps[i], outer_map, inner_maps, plan); 242*2d1272b8SAndroid Build Coastguard Worker } 243*2d1272b8SAndroid Build Coastguard Worker 244*2d1272b8SAndroid Build Coastguard Worker /* remap */ remap_index_map_plansOT::hvarvvar_subset_plan_t245*2d1272b8SAndroid Build Coastguard Worker bool remap_index_map_plans (const hb_subset_plan_t *plan, 246*2d1272b8SAndroid Build Coastguard Worker const hb_map_t& varidx_map) 247*2d1272b8SAndroid Build Coastguard Worker { 248*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < index_map_plans.length; i++) 249*2d1272b8SAndroid Build Coastguard Worker if (!index_map_plans[i].remap_after_instantiation (plan, varidx_map)) 250*2d1272b8SAndroid Build Coastguard Worker return false; 251*2d1272b8SAndroid Build Coastguard Worker return true; 252*2d1272b8SAndroid Build Coastguard Worker } 253*2d1272b8SAndroid Build Coastguard Worker finiOT::hvarvvar_subset_plan_t254*2d1272b8SAndroid Build Coastguard Worker void fini () 255*2d1272b8SAndroid Build Coastguard Worker { 256*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < inner_sets.length; i++) 257*2d1272b8SAndroid Build Coastguard Worker hb_set_destroy (inner_sets[i]); 258*2d1272b8SAndroid Build Coastguard Worker hb_set_destroy (adv_set); 259*2d1272b8SAndroid Build Coastguard Worker inner_maps.fini (); 260*2d1272b8SAndroid Build Coastguard Worker index_map_plans.fini (); 261*2d1272b8SAndroid Build Coastguard Worker } 262*2d1272b8SAndroid Build Coastguard Worker 263*2d1272b8SAndroid Build Coastguard Worker hb_inc_bimap_t outer_map; 264*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<hb_inc_bimap_t> inner_maps; 265*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<index_map_subset_plan_t> index_map_plans; 266*2d1272b8SAndroid Build Coastguard Worker const ItemVariationStore *var_store; 267*2d1272b8SAndroid Build Coastguard Worker 268*2d1272b8SAndroid Build Coastguard Worker protected: 269*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<hb_set_t *> inner_sets; 270*2d1272b8SAndroid Build Coastguard Worker hb_set_t *adv_set; 271*2d1272b8SAndroid Build Coastguard Worker }; 272*2d1272b8SAndroid Build Coastguard Worker 273*2d1272b8SAndroid Build Coastguard Worker /* 274*2d1272b8SAndroid Build Coastguard Worker * HVAR -- Horizontal Metrics Variations 275*2d1272b8SAndroid Build Coastguard Worker * https://docs.microsoft.com/en-us/typography/opentype/spec/hvar 276*2d1272b8SAndroid Build Coastguard Worker * VVAR -- Vertical Metrics Variations 277*2d1272b8SAndroid Build Coastguard Worker * https://docs.microsoft.com/en-us/typography/opentype/spec/vvar 278*2d1272b8SAndroid Build Coastguard Worker */ 279*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_HVAR HB_TAG('H','V','A','R') 280*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_VVAR HB_TAG('V','V','A','R') 281*2d1272b8SAndroid Build Coastguard Worker 282*2d1272b8SAndroid Build Coastguard Worker struct HVARVVAR 283*2d1272b8SAndroid Build Coastguard Worker { 284*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t HVARTag = HB_OT_TAG_HVAR; 285*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t VVARTag = HB_OT_TAG_VVAR; 286*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::HVARVVAR287*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 288*2d1272b8SAndroid Build Coastguard Worker { 289*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 290*2d1272b8SAndroid Build Coastguard Worker return_trace (version.sanitize (c) && 291*2d1272b8SAndroid Build Coastguard Worker hb_barrier () && 292*2d1272b8SAndroid Build Coastguard Worker likely (version.major == 1) && 293*2d1272b8SAndroid Build Coastguard Worker varStore.sanitize (c, this) && 294*2d1272b8SAndroid Build Coastguard Worker advMap.sanitize (c, this) && 295*2d1272b8SAndroid Build Coastguard Worker lsbMap.sanitize (c, this) && 296*2d1272b8SAndroid Build Coastguard Worker rsbMap.sanitize (c, this)); 297*2d1272b8SAndroid Build Coastguard Worker } 298*2d1272b8SAndroid Build Coastguard Worker get_var_storeOT::HVARVVAR299*2d1272b8SAndroid Build Coastguard Worker const ItemVariationStore& get_var_store () const 300*2d1272b8SAndroid Build Coastguard Worker { return this+varStore; } 301*2d1272b8SAndroid Build Coastguard Worker listup_index_mapsOT::HVARVVAR302*2d1272b8SAndroid Build Coastguard Worker void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const 303*2d1272b8SAndroid Build Coastguard Worker { 304*2d1272b8SAndroid Build Coastguard Worker index_maps.push (&(this+advMap)); 305*2d1272b8SAndroid Build Coastguard Worker index_maps.push (&(this+lsbMap)); 306*2d1272b8SAndroid Build Coastguard Worker index_maps.push (&(this+rsbMap)); 307*2d1272b8SAndroid Build Coastguard Worker } 308*2d1272b8SAndroid Build Coastguard Worker serialize_index_mapsOT::HVARVVAR309*2d1272b8SAndroid Build Coastguard Worker bool serialize_index_maps (hb_serialize_context_t *c, 310*2d1272b8SAndroid Build Coastguard Worker const hb_array_t<index_map_subset_plan_t> &im_plans) 311*2d1272b8SAndroid Build Coastguard Worker { 312*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 313*2d1272b8SAndroid Build Coastguard Worker if (im_plans[index_map_subset_plan_t::ADV_INDEX].is_identity ()) 314*2d1272b8SAndroid Build Coastguard Worker advMap = 0; 315*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (!advMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::ADV_INDEX]))) 316*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 317*2d1272b8SAndroid Build Coastguard Worker if (im_plans[index_map_subset_plan_t::LSB_INDEX].is_identity ()) 318*2d1272b8SAndroid Build Coastguard Worker lsbMap = 0; 319*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (!lsbMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::LSB_INDEX]))) 320*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 321*2d1272b8SAndroid Build Coastguard Worker if (im_plans[index_map_subset_plan_t::RSB_INDEX].is_identity ()) 322*2d1272b8SAndroid Build Coastguard Worker rsbMap = 0; 323*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (!rsbMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::RSB_INDEX]))) 324*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 325*2d1272b8SAndroid Build Coastguard Worker 326*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 327*2d1272b8SAndroid Build Coastguard Worker } 328*2d1272b8SAndroid Build Coastguard Worker 329*2d1272b8SAndroid Build Coastguard Worker template <typename T> _subsetOT::HVARVVAR330*2d1272b8SAndroid Build Coastguard Worker bool _subset (hb_subset_context_t *c) const 331*2d1272b8SAndroid Build Coastguard Worker { 332*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 333*2d1272b8SAndroid Build Coastguard Worker if (c->plan->all_axes_pinned) 334*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 335*2d1272b8SAndroid Build Coastguard Worker 336*2d1272b8SAndroid Build Coastguard Worker hvarvvar_subset_plan_t hvar_plan; 337*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<const DeltaSetIndexMap *> 338*2d1272b8SAndroid Build Coastguard Worker index_maps; 339*2d1272b8SAndroid Build Coastguard Worker 340*2d1272b8SAndroid Build Coastguard Worker ((T*)this)->listup_index_maps (index_maps); 341*2d1272b8SAndroid Build Coastguard Worker hvar_plan.init (index_maps.as_array (), this+varStore, c->plan); 342*2d1272b8SAndroid Build Coastguard Worker 343*2d1272b8SAndroid Build Coastguard Worker T *out = c->serializer->allocate_min<T> (); 344*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out)) return_trace (false); 345*2d1272b8SAndroid Build Coastguard Worker 346*2d1272b8SAndroid Build Coastguard Worker out->version.major = 1; 347*2d1272b8SAndroid Build Coastguard Worker out->version.minor = 0; 348*2d1272b8SAndroid Build Coastguard Worker 349*2d1272b8SAndroid Build Coastguard Worker if (c->plan->normalized_coords) 350*2d1272b8SAndroid Build Coastguard Worker { 351*2d1272b8SAndroid Build Coastguard Worker item_variations_t item_vars; 352*2d1272b8SAndroid Build Coastguard Worker if (!item_vars.instantiate (this+varStore, c->plan, 353*2d1272b8SAndroid Build Coastguard Worker advMap == 0 ? false : true, 354*2d1272b8SAndroid Build Coastguard Worker false, /* use_no_variation_idx = false */ 355*2d1272b8SAndroid Build Coastguard Worker hvar_plan.inner_maps.as_array ())) 356*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 357*2d1272b8SAndroid Build Coastguard Worker 358*2d1272b8SAndroid Build Coastguard Worker if (!out->varStore.serialize_serialize (c->serializer, 359*2d1272b8SAndroid Build Coastguard Worker item_vars.has_long_word (), 360*2d1272b8SAndroid Build Coastguard Worker c->plan->axis_tags, 361*2d1272b8SAndroid Build Coastguard Worker item_vars.get_region_list (), 362*2d1272b8SAndroid Build Coastguard Worker item_vars.get_vardata_encodings ())) 363*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 364*2d1272b8SAndroid Build Coastguard Worker 365*2d1272b8SAndroid Build Coastguard Worker /* if varstore is optimized, remap output_map */ 366*2d1272b8SAndroid Build Coastguard Worker if (advMap) 367*2d1272b8SAndroid Build Coastguard Worker { 368*2d1272b8SAndroid Build Coastguard Worker if (!hvar_plan.remap_index_map_plans (c->plan, item_vars.get_varidx_map ())) 369*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 370*2d1272b8SAndroid Build Coastguard Worker } 371*2d1272b8SAndroid Build Coastguard Worker } 372*2d1272b8SAndroid Build Coastguard Worker else 373*2d1272b8SAndroid Build Coastguard Worker { 374*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!out->varStore 375*2d1272b8SAndroid Build Coastguard Worker .serialize_serialize (c->serializer, 376*2d1272b8SAndroid Build Coastguard Worker hvar_plan.var_store, 377*2d1272b8SAndroid Build Coastguard Worker hvar_plan.inner_maps.as_array ()))) 378*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 379*2d1272b8SAndroid Build Coastguard Worker } 380*2d1272b8SAndroid Build Coastguard Worker 381*2d1272b8SAndroid Build Coastguard Worker return_trace (out->T::serialize_index_maps (c->serializer, 382*2d1272b8SAndroid Build Coastguard Worker hvar_plan.index_map_plans.as_array ())); 383*2d1272b8SAndroid Build Coastguard Worker } 384*2d1272b8SAndroid Build Coastguard Worker get_advance_delta_unscaledOT::HVARVVAR385*2d1272b8SAndroid Build Coastguard Worker float get_advance_delta_unscaled (hb_codepoint_t glyph, 386*2d1272b8SAndroid Build Coastguard Worker const int *coords, unsigned int coord_count, 387*2d1272b8SAndroid Build Coastguard Worker ItemVariationStore::cache_t *store_cache = nullptr) const 388*2d1272b8SAndroid Build Coastguard Worker { 389*2d1272b8SAndroid Build Coastguard Worker uint32_t varidx = (this+advMap).map (glyph); 390*2d1272b8SAndroid Build Coastguard Worker return (this+varStore).get_delta (varidx, 391*2d1272b8SAndroid Build Coastguard Worker coords, coord_count, 392*2d1272b8SAndroid Build Coastguard Worker store_cache); 393*2d1272b8SAndroid Build Coastguard Worker } 394*2d1272b8SAndroid Build Coastguard Worker get_lsb_delta_unscaledOT::HVARVVAR395*2d1272b8SAndroid Build Coastguard Worker bool get_lsb_delta_unscaled (hb_codepoint_t glyph, 396*2d1272b8SAndroid Build Coastguard Worker const int *coords, unsigned int coord_count, 397*2d1272b8SAndroid Build Coastguard Worker float *lsb) const 398*2d1272b8SAndroid Build Coastguard Worker { 399*2d1272b8SAndroid Build Coastguard Worker if (!lsbMap) return false; 400*2d1272b8SAndroid Build Coastguard Worker uint32_t varidx = (this+lsbMap).map (glyph); 401*2d1272b8SAndroid Build Coastguard Worker *lsb = (this+varStore).get_delta (varidx, coords, coord_count); 402*2d1272b8SAndroid Build Coastguard Worker return true; 403*2d1272b8SAndroid Build Coastguard Worker } 404*2d1272b8SAndroid Build Coastguard Worker 405*2d1272b8SAndroid Build Coastguard Worker public: 406*2d1272b8SAndroid Build Coastguard Worker FixedVersion<>version; /* Version of the metrics variation table 407*2d1272b8SAndroid Build Coastguard Worker * initially set to 0x00010000u */ 408*2d1272b8SAndroid Build Coastguard Worker Offset32To<ItemVariationStore> 409*2d1272b8SAndroid Build Coastguard Worker varStore; /* Offset to item variation store table. */ 410*2d1272b8SAndroid Build Coastguard Worker Offset32To<DeltaSetIndexMap> 411*2d1272b8SAndroid Build Coastguard Worker advMap; /* Offset to advance var-idx mapping. */ 412*2d1272b8SAndroid Build Coastguard Worker Offset32To<DeltaSetIndexMap> 413*2d1272b8SAndroid Build Coastguard Worker lsbMap; /* Offset to lsb/tsb var-idx mapping. */ 414*2d1272b8SAndroid Build Coastguard Worker Offset32To<DeltaSetIndexMap> 415*2d1272b8SAndroid Build Coastguard Worker rsbMap; /* Offset to rsb/bsb var-idx mapping. */ 416*2d1272b8SAndroid Build Coastguard Worker 417*2d1272b8SAndroid Build Coastguard Worker public: 418*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (20); 419*2d1272b8SAndroid Build Coastguard Worker }; 420*2d1272b8SAndroid Build Coastguard Worker 421*2d1272b8SAndroid Build Coastguard Worker struct HVAR : HVARVVAR { 422*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR; subsetOT::HVAR423*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<HVAR> (c); } 424*2d1272b8SAndroid Build Coastguard Worker }; 425*2d1272b8SAndroid Build Coastguard Worker struct VVAR : HVARVVAR { 426*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR; 427*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::VVAR428*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 429*2d1272b8SAndroid Build Coastguard Worker { 430*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 431*2d1272b8SAndroid Build Coastguard Worker return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) && 432*2d1272b8SAndroid Build Coastguard Worker vorgMap.sanitize (c, this)); 433*2d1272b8SAndroid Build Coastguard Worker } 434*2d1272b8SAndroid Build Coastguard Worker listup_index_mapsOT::VVAR435*2d1272b8SAndroid Build Coastguard Worker void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const 436*2d1272b8SAndroid Build Coastguard Worker { 437*2d1272b8SAndroid Build Coastguard Worker HVARVVAR::listup_index_maps (index_maps); 438*2d1272b8SAndroid Build Coastguard Worker index_maps.push (&(this+vorgMap)); 439*2d1272b8SAndroid Build Coastguard Worker } 440*2d1272b8SAndroid Build Coastguard Worker serialize_index_mapsOT::VVAR441*2d1272b8SAndroid Build Coastguard Worker bool serialize_index_maps (hb_serialize_context_t *c, 442*2d1272b8SAndroid Build Coastguard Worker const hb_array_t<index_map_subset_plan_t> &im_plans) 443*2d1272b8SAndroid Build Coastguard Worker { 444*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 445*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!HVARVVAR::serialize_index_maps (c, im_plans))) 446*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 447*2d1272b8SAndroid Build Coastguard Worker if (!im_plans[index_map_subset_plan_t::VORG_INDEX].get_map_count ()) 448*2d1272b8SAndroid Build Coastguard Worker vorgMap = 0; 449*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (!vorgMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::VORG_INDEX]))) 450*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 451*2d1272b8SAndroid Build Coastguard Worker 452*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 453*2d1272b8SAndroid Build Coastguard Worker } 454*2d1272b8SAndroid Build Coastguard Worker subsetOT::VVAR455*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); } 456*2d1272b8SAndroid Build Coastguard Worker get_vorg_delta_unscaledOT::VVAR457*2d1272b8SAndroid Build Coastguard Worker bool get_vorg_delta_unscaled (hb_codepoint_t glyph, 458*2d1272b8SAndroid Build Coastguard Worker const int *coords, unsigned int coord_count, 459*2d1272b8SAndroid Build Coastguard Worker float *delta) const 460*2d1272b8SAndroid Build Coastguard Worker { 461*2d1272b8SAndroid Build Coastguard Worker if (!vorgMap) return false; 462*2d1272b8SAndroid Build Coastguard Worker uint32_t varidx = (this+vorgMap).map (glyph); 463*2d1272b8SAndroid Build Coastguard Worker *delta = (this+varStore).get_delta (varidx, coords, coord_count); 464*2d1272b8SAndroid Build Coastguard Worker return true; 465*2d1272b8SAndroid Build Coastguard Worker } 466*2d1272b8SAndroid Build Coastguard Worker 467*2d1272b8SAndroid Build Coastguard Worker protected: 468*2d1272b8SAndroid Build Coastguard Worker Offset32To<DeltaSetIndexMap> 469*2d1272b8SAndroid Build Coastguard Worker vorgMap; /* Offset to vertical-origin var-idx mapping. */ 470*2d1272b8SAndroid Build Coastguard Worker 471*2d1272b8SAndroid Build Coastguard Worker public: 472*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (24); 473*2d1272b8SAndroid Build Coastguard Worker }; 474*2d1272b8SAndroid Build Coastguard Worker 475*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 476*2d1272b8SAndroid Build Coastguard Worker 477*2d1272b8SAndroid Build Coastguard Worker 478*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_VAR_HVAR_TABLE_HH */ 479