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