tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hb-ot-var-hvar-table.hh (15347B)


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