Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 | |
| 45 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 | |
| 108 void fini () | |
| 109 { | |
| 110 max_inners.fini (); | |
| 111 output_map.fini (); | |
| 112 } | |
| 113 | |
| 114 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 | |
| 143 unsigned int get_inner_bit_count () const { return inner_bit_count; } | |
| 144 unsigned int get_width () const { return ((outer_bit_count + inner_bit_count + 7) / 8); } | |
| 145 unsigned int get_map_count () const { return map_count; } | |
| 146 | |
| 147 unsigned int get_size () const | |
| 148 { return (map_count? (DeltaSetIndexMap::min_size + get_width () * map_count): 0); } | |
| 149 | |
| 150 bool is_identity () const { return get_output_map ().length == 0; } | |
| 151 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 { | |
| 163 hvarvvar_subset_plan_t() : inner_maps (), index_map_plans () {} | |
| 164 ~hvarvvar_subset_plan_t() { fini (); } | |
| 165 | |
| 166 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 | |
| 224 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 | |
| 257 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 | |
| 268 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 | |
| 275 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> | |
| 296 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 | |
| 322 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 | |
| 332 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; | |
| 360 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 | |
| 365 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 | |
| 372 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 | |
| 378 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 | |
| 392 bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); } | |
| 393 | |
| 394 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 */ |
