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 { 50 map_count = 0; 51 outer_bit_count = 0; 52 inner_bit_count = 1; 53 max_inners.init (); 54 output_map.init (); 55 56 if (&index_map == &Null (DeltaSetIndexMap)) return; 57 58 unsigned int last_val = (unsigned int)-1; 59 hb_codepoint_t last_gid = (hb_codepoint_t)-1; 60 hb_codepoint_t gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ()); 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 for (; gid > 0; gid--) 68 { 69 hb_codepoint_t old_gid; 70 if (!plan->old_gid_for_new_gid (gid - 1, &old_gid)) 71 { 72 if (last_gid == (hb_codepoint_t) -1) 73 continue; 74 else 75 break; 76 } 77 78 unsigned int v = index_map.map (old_gid); 79 if (last_gid == (hb_codepoint_t) -1) 80 { 81 last_val = v; 82 last_gid = gid; 83 continue; 84 } 85 if (v != last_val) break; 86 87 last_gid = gid; 88 } 89 90 if (unlikely (last_gid == (hb_codepoint_t)-1)) return; 91 map_count = last_gid; 92 for (gid = 0; gid < map_count; gid++) 93 { 94 hb_codepoint_t old_gid; 95 if (plan->old_gid_for_new_gid (gid, &old_gid)) 96 { 97 unsigned int v = index_map.map (old_gid); 98 unsigned int outer = v >> 16; 99 unsigned int inner = v & 0xFFFF; 100 outer_map.add (outer); 101 if (inner > max_inners[outer]) max_inners[outer] = inner; 102 if (outer >= inner_sets.length) return; 103 inner_sets[outer]->add (inner); 104 } 105 } 106 } 107 finiOT::index_map_subset_plan_t108 void fini () 109 { 110 max_inners.fini (); 111 output_map.fini (); 112 } 113 remapOT::index_map_subset_plan_t114 void remap (const DeltaSetIndexMap *input_map, 115 const hb_inc_bimap_t &outer_map, 116 const hb_vector_t<hb_inc_bimap_t> &inner_maps, 117 const hb_subset_plan_t *plan) 118 { 119 if (input_map == &Null (DeltaSetIndexMap)) return; 120 121 for (unsigned int i = 0; i < max_inners.length; i++) 122 { 123 if (inner_maps[i].get_population () == 0) continue; 124 unsigned int bit_count = (max_inners[i]==0)? 1: hb_bit_storage (inner_maps[i][max_inners[i]]); 125 if (bit_count > inner_bit_count) inner_bit_count = bit_count; 126 } 127 128 output_map.resize (map_count); 129 for (hb_codepoint_t gid = 0; gid < output_map.length; gid++) 130 { 131 hb_codepoint_t old_gid; 132 if (plan->old_gid_for_new_gid (gid, &old_gid)) 133 { 134 uint32_t v = input_map->map (old_gid); 135 unsigned int outer = v >> 16; 136 output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]); 137 } 138 else 139 output_map[gid] = 0; /* Map unused glyph to outer/inner=0/0 */ 140 } 141 } 142 get_inner_bit_countOT::index_map_subset_plan_t143 unsigned int get_inner_bit_count () const { return inner_bit_count; } get_widthOT::index_map_subset_plan_t144 unsigned int get_width () const { return ((outer_bit_count + inner_bit_count + 7) / 8); } get_map_countOT::index_map_subset_plan_t145 unsigned int get_map_count () const { return map_count; } 146 get_sizeOT::index_map_subset_plan_t147 unsigned int get_size () const 148 { return (map_count? (DeltaSetIndexMap::min_size + get_width () * map_count): 0); } 149 is_identityOT::index_map_subset_plan_t150 bool is_identity () const { return get_output_map ().length == 0; } get_output_mapOT::index_map_subset_plan_t151 hb_array_t<const uint32_t> get_output_map () const { return output_map.as_array (); } 152 153 protected: 154 unsigned int map_count; 155 hb_vector_t<unsigned int> max_inners; 156 unsigned int outer_bit_count; 157 unsigned int inner_bit_count; 158 hb_vector_t<uint32_t> output_map; 159 }; 160 161 struct hvarvvar_subset_plan_t 162 { hvarvvar_subset_plan_tOT::hvarvvar_subset_plan_t163 hvarvvar_subset_plan_t() : inner_maps (), index_map_plans () {} ~hvarvvar_subset_plan_tOT::hvarvvar_subset_plan_t164 ~hvarvvar_subset_plan_t() { fini (); } 165 initOT::hvarvvar_subset_plan_t166 void init (const hb_array_t<const DeltaSetIndexMap *> &index_maps, 167 const VariationStore &_var_store, 168 const hb_subset_plan_t *plan) 169 { 170 index_map_plans.resize (index_maps.length); 171 172 var_store = &_var_store; 173 inner_sets.resize (var_store->get_sub_table_count ()); 174 for (unsigned int i = 0; i < inner_sets.length; i++) 175 inner_sets[i] = hb_set_create (); 176 adv_set = hb_set_create (); 177 178 inner_maps.resize (var_store->get_sub_table_count ()); 179 180 if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return; 181 182 bool retain_adv_map = false; 183 index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan); 184 if (index_maps[0] == &Null (DeltaSetIndexMap)) 185 { 186 retain_adv_map = plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS; 187 outer_map.add (0); 188 for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++) 189 { 190 hb_codepoint_t old_gid; 191 if (plan->old_gid_for_new_gid (gid, &old_gid)) 192 inner_sets[0]->add (old_gid); 193 } 194 hb_set_union (adv_set, inner_sets[0]); 195 } 196 197 for (unsigned int i = 1; i < index_maps.length; i++) 198 index_map_plans[i].init (*index_maps[i], outer_map, inner_sets, plan); 199 200 outer_map.sort (); 201 202 if (retain_adv_map) 203 { 204 for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++) 205 if (inner_sets[0]->has (gid)) 206 inner_maps[0].add (gid); 207 else 208 inner_maps[0].skip (); 209 } 210 else 211 { 212 inner_maps[0].add_set (adv_set); 213 hb_set_subtract (inner_sets[0], adv_set); 214 inner_maps[0].add_set (inner_sets[0]); 215 } 216 217 for (unsigned int i = 1; i < inner_maps.length; i++) 218 inner_maps[i].add_set (inner_sets[i]); 219 220 for (unsigned int i = 0; i < index_maps.length; i++) 221 index_map_plans[i].remap (index_maps[i], outer_map, inner_maps, plan); 222 } 223 finiOT::hvarvvar_subset_plan_t224 void fini () 225 { 226 for (unsigned int i = 0; i < inner_sets.length; i++) 227 hb_set_destroy (inner_sets[i]); 228 hb_set_destroy (adv_set); 229 inner_maps.fini (); 230 index_map_plans.fini (); 231 } 232 233 hb_inc_bimap_t outer_map; 234 hb_vector_t<hb_inc_bimap_t> inner_maps; 235 hb_vector_t<index_map_subset_plan_t> index_map_plans; 236 const VariationStore *var_store; 237 238 protected: 239 hb_vector_t<hb_set_t *> inner_sets; 240 hb_set_t *adv_set; 241 }; 242 243 /* 244 * HVAR -- Horizontal Metrics Variations 245 * https://docs.microsoft.com/en-us/typography/opentype/spec/hvar 246 * VVAR -- Vertical Metrics Variations 247 * https://docs.microsoft.com/en-us/typography/opentype/spec/vvar 248 */ 249 #define HB_OT_TAG_HVAR HB_TAG('H','V','A','R') 250 #define HB_OT_TAG_VVAR HB_TAG('V','V','A','R') 251 252 struct HVARVVAR 253 { 254 static constexpr hb_tag_t HVARTag = HB_OT_TAG_HVAR; 255 static constexpr hb_tag_t VVARTag = HB_OT_TAG_VVAR; 256 sanitizeOT::HVARVVAR257 bool sanitize (hb_sanitize_context_t *c) const 258 { 259 TRACE_SANITIZE (this); 260 return_trace (version.sanitize (c) && 261 likely (version.major == 1) && 262 varStore.sanitize (c, this) && 263 advMap.sanitize (c, this) && 264 lsbMap.sanitize (c, this) && 265 rsbMap.sanitize (c, this)); 266 } 267 listup_index_mapsOT::HVARVVAR268 void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const 269 { 270 index_maps.push (&(this+advMap)); 271 index_maps.push (&(this+lsbMap)); 272 index_maps.push (&(this+rsbMap)); 273 } 274 serialize_index_mapsOT::HVARVVAR275 bool serialize_index_maps (hb_serialize_context_t *c, 276 const hb_array_t<index_map_subset_plan_t> &im_plans) 277 { 278 TRACE_SERIALIZE (this); 279 if (im_plans[index_map_subset_plan_t::ADV_INDEX].is_identity ()) 280 advMap = 0; 281 else if (unlikely (!advMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::ADV_INDEX]))) 282 return_trace (false); 283 if (im_plans[index_map_subset_plan_t::LSB_INDEX].is_identity ()) 284 lsbMap = 0; 285 else if (unlikely (!lsbMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::LSB_INDEX]))) 286 return_trace (false); 287 if (im_plans[index_map_subset_plan_t::RSB_INDEX].is_identity ()) 288 rsbMap = 0; 289 else if (unlikely (!rsbMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::RSB_INDEX]))) 290 return_trace (false); 291 292 return_trace (true); 293 } 294 295 template <typename T> _subsetOT::HVARVVAR296 bool _subset (hb_subset_context_t *c) const 297 { 298 TRACE_SUBSET (this); 299 hvarvvar_subset_plan_t hvar_plan; 300 hb_vector_t<const DeltaSetIndexMap *> 301 index_maps; 302 303 ((T*)this)->listup_index_maps (index_maps); 304 hvar_plan.init (index_maps.as_array (), this+varStore, c->plan); 305 306 T *out = c->serializer->allocate_min<T> (); 307 if (unlikely (!out)) return_trace (false); 308 309 out->version.major = 1; 310 out->version.minor = 0; 311 312 if (unlikely (!out->varStore 313 .serialize_serialize (c->serializer, 314 hvar_plan.var_store, 315 hvar_plan.inner_maps.as_array ()))) 316 return_trace (false); 317 318 return_trace (out->T::serialize_index_maps (c->serializer, 319 hvar_plan.index_map_plans.as_array ())); 320 } 321 get_advance_delta_unscaledOT::HVARVVAR322 float get_advance_delta_unscaled (hb_codepoint_t glyph, 323 const int *coords, unsigned int coord_count, 324 VariationStore::cache_t *store_cache = nullptr) const 325 { 326 uint32_t varidx = (this+advMap).map (glyph); 327 return (this+varStore).get_delta (varidx, 328 coords, coord_count, 329 store_cache); 330 } 331 get_lsb_delta_unscaledOT::HVARVVAR332 bool get_lsb_delta_unscaled (hb_codepoint_t glyph, 333 const int *coords, unsigned int coord_count, 334 float *lsb) const 335 { 336 if (!lsbMap) return false; 337 uint32_t varidx = (this+lsbMap).map (glyph); 338 *lsb = (this+varStore).get_delta (varidx, coords, coord_count); 339 return true; 340 } 341 342 public: 343 FixedVersion<>version; /* Version of the metrics variation table 344 * initially set to 0x00010000u */ 345 Offset32To<VariationStore> 346 varStore; /* Offset to item variation store table. */ 347 Offset32To<DeltaSetIndexMap> 348 advMap; /* Offset to advance var-idx mapping. */ 349 Offset32To<DeltaSetIndexMap> 350 lsbMap; /* Offset to lsb/tsb var-idx mapping. */ 351 Offset32To<DeltaSetIndexMap> 352 rsbMap; /* Offset to rsb/bsb var-idx mapping. */ 353 354 public: 355 DEFINE_SIZE_STATIC (20); 356 }; 357 358 struct HVAR : HVARVVAR { 359 static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR; subsetOT::HVAR360 bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<HVAR> (c); } 361 }; 362 struct VVAR : HVARVVAR { 363 static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR; 364 sanitizeOT::VVAR365 bool sanitize (hb_sanitize_context_t *c) const 366 { 367 TRACE_SANITIZE (this); 368 return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) && 369 vorgMap.sanitize (c, this)); 370 } 371 listup_index_mapsOT::VVAR372 void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const 373 { 374 HVARVVAR::listup_index_maps (index_maps); 375 index_maps.push (&(this+vorgMap)); 376 } 377 serialize_index_mapsOT::VVAR378 bool serialize_index_maps (hb_serialize_context_t *c, 379 const hb_array_t<index_map_subset_plan_t> &im_plans) 380 { 381 TRACE_SERIALIZE (this); 382 if (unlikely (!HVARVVAR::serialize_index_maps (c, im_plans))) 383 return_trace (false); 384 if (!im_plans[index_map_subset_plan_t::VORG_INDEX].get_map_count ()) 385 vorgMap = 0; 386 else if (unlikely (!vorgMap.serialize_serialize (c, im_plans[index_map_subset_plan_t::VORG_INDEX]))) 387 return_trace (false); 388 389 return_trace (true); 390 } 391 subsetOT::VVAR392 bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); } 393 get_vorg_delta_unscaledOT::VVAR394 bool get_vorg_delta_unscaled (hb_codepoint_t glyph, 395 const int *coords, unsigned int coord_count, 396 float *delta) const 397 { 398 if (!vorgMap) return false; 399 uint32_t varidx = (this+vorgMap).map (glyph); 400 *delta = (this+varStore).get_delta (varidx, coords, coord_count); 401 return true; 402 } 403 404 protected: 405 Offset32To<DeltaSetIndexMap> 406 vorgMap; /* Offset to vertical-origin var-idx mapping. */ 407 408 public: 409 DEFINE_SIZE_STATIC (24); 410 }; 411 412 } /* namespace OT */ 413 414 415 #endif /* HB_OT_VAR_HVAR_TABLE_HH */ 416