tor-browser

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

PairPosFormat1.hh (8304B)


      1 #ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
      2 #define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
      3 
      4 #include "PairSet.hh"
      5 
      6 namespace OT {
      7 namespace Layout {
      8 namespace GPOS_impl {
      9 
     10 
     11 template <typename Types>
     12 struct PairPosFormat1_3
     13 {
     14  using PairSet = GPOS_impl::PairSet<Types>;
     15  using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
     16 
     17  protected:
     18  HBUINT16      format;                 /* Format identifier--format = 1 */
     19  typename Types::template OffsetTo<Coverage>
     20                coverage;               /* Offset to Coverage table--from
     21                                         * beginning of subtable */
     22  ValueFormat   valueFormat[2];         /* [0] Defines the types of data in
     23                                         * ValueRecord1--for the first glyph
     24                                         * in the pair--may be zero (0) */
     25                                        /* [1] Defines the types of data in
     26                                         * ValueRecord2--for the second glyph
     27                                         * in the pair--may be zero (0) */
     28  Array16Of<typename Types::template OffsetTo<PairSet>>
     29                pairSet;                /* Array of PairSet tables
     30                                         * ordered by Coverage Index */
     31  public:
     32  DEFINE_SIZE_ARRAY (8 + Types::size, pairSet);
     33 
     34  bool sanitize (hb_sanitize_context_t *c) const
     35  {
     36    TRACE_SANITIZE (this);
     37 
     38    if (!c->check_struct (this)) return_trace (false);
     39    hb_barrier ();
     40 
     41    unsigned int len1 = valueFormat[0].get_len ();
     42    unsigned int len2 = valueFormat[1].get_len ();
     43    typename PairSet::sanitize_closure_t closure =
     44    {
     45      valueFormat,
     46      len1,
     47      PairSet::get_size (len1, len2)
     48    };
     49 
     50    return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
     51  }
     52 
     53  bool intersects (const hb_set_t *glyphs) const
     54  {
     55    auto &cov = this+coverage;
     56 
     57    if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len))
     58    {
     59      for (hb_codepoint_t g : glyphs->iter())
     60      {
     61 unsigned i = cov.get_coverage (g);
     62 if ((this+pairSet[i]).intersects (glyphs, valueFormat))
     63   return true;
     64      }
     65      return false;
     66    }
     67 
     68    return
     69    + hb_zip (cov, pairSet)
     70    | hb_filter (*glyphs, hb_first)
     71    | hb_map (hb_second)
     72    | hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
     73              { return (this+_).intersects (glyphs, valueFormat); })
     74    | hb_any
     75    ;
     76  }
     77 
     78  void closure_lookups (hb_closure_lookups_context_t *c) const {}
     79  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
     80  {
     81    if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
     82 
     83    auto it =
     84    + hb_zip (this+coverage, pairSet)
     85    | hb_filter (c->glyph_set, hb_first)
     86    | hb_map (hb_second)
     87    ;
     88 
     89    if (!it) return;
     90    + it
     91    | hb_map (hb_add (this))
     92    | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
     93    ;
     94  }
     95 
     96  void collect_glyphs (hb_collect_glyphs_context_t *c) const
     97  {
     98    if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
     99    unsigned int count = pairSet.len;
    100    for (unsigned int i = 0; i < count; i++)
    101      (this+pairSet[i]).collect_glyphs (c, valueFormat);
    102  }
    103 
    104  const Coverage &get_coverage () const { return this+coverage; }
    105 
    106  struct external_cache_t
    107  {
    108    hb_ot_layout_mapping_cache_t coverage;
    109  };
    110  void *external_cache_create () const
    111  {
    112    external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
    113    if (likely (cache))
    114    {
    115      cache->coverage.clear ();
    116    }
    117    return cache;
    118  }
    119 
    120  bool apply (hb_ot_apply_context_t *c, void *external_cache) const
    121  {
    122    TRACE_APPLY (this);
    123 
    124    hb_buffer_t *buffer = c->buffer;
    125 
    126 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
    127    external_cache_t *cache = (external_cache_t *) external_cache;
    128    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
    129 #else
    130    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
    131 #endif
    132    if (index == NOT_COVERED) return_trace (false);
    133 
    134    auto &skippy_iter = c->iter_input;
    135    skippy_iter.reset_fast (buffer->idx);
    136    unsigned unsafe_to;
    137    if (unlikely (!skippy_iter.next (&unsafe_to)))
    138    {
    139      buffer->unsafe_to_concat (buffer->idx, unsafe_to);
    140      return_trace (false);
    141    }
    142 
    143    return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
    144  }
    145 
    146  bool subset (hb_subset_context_t *c) const
    147  {
    148    TRACE_SUBSET (this);
    149 
    150    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
    151    const hb_map_t &glyph_map = *c->plan->glyph_map;
    152 
    153    auto *out = c->serializer->start_embed (*this);
    154    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
    155    out->format = format;
    156 
    157    hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat[0], valueFormat[1]);
    158 
    159    if (c->plan->normalized_coords)
    160    {
    161      /* all device flags will be dropped when full instancing, no need to strip
    162       * hints, also do not strip emtpy cause we don't compute the new default
    163       * value during stripping */
    164      newFormats = compute_effective_value_formats (glyphset, false, false, &c->plan->layout_variation_idx_delta_map);
    165    }
    166    /* do not strip hints for VF */
    167    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
    168    {
    169      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
    170      bool has_fvar = (blob != hb_blob_get_empty ());
    171      hb_blob_destroy (blob);
    172 
    173      bool strip = !has_fvar;
    174      /* special case: strip hints when a VF has no GDEF varstore after
    175       * subsetting*/
    176      if (has_fvar && !c->plan->has_gdef_varstore)
    177        strip = true;
    178      newFormats = compute_effective_value_formats (glyphset, strip, true);
    179    }
    180 
    181    out->valueFormat[0] = newFormats.first;
    182    out->valueFormat[1] = newFormats.second;
    183 
    184    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
    185 
    186    + hb_zip (this+coverage, pairSet)
    187    | hb_filter (glyphset, hb_first)
    188    | hb_filter ([this, c, out] (const typename Types::template OffsetTo<PairSet>& _)
    189                 {
    190                   auto snap = c->serializer->snapshot ();
    191                   auto *o = out->pairSet.serialize_append (c->serializer);
    192                   if (unlikely (!o)) return false;
    193                   bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
    194                   if (!ret)
    195                   {
    196                     out->pairSet.pop ();
    197                     c->serializer->revert (snap);
    198                   }
    199                   return ret;
    200                 },
    201                 hb_second)
    202    | hb_map (hb_first)
    203    | hb_map (glyph_map)
    204    | hb_sink (new_coverage)
    205    ;
    206 
    207    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
    208 
    209    return_trace (bool (new_coverage));
    210  }
    211 
    212 
    213  hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset,
    214                                                                 bool strip_hints, bool strip_empty,
    215                                                                 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map = nullptr) const
    216  {
    217    unsigned record_size = PairSet::get_size (valueFormat);
    218 
    219    unsigned format1 = 0;
    220    unsigned format2 = 0;
    221    for (const auto & _ :
    222   + hb_zip (this+coverage, pairSet)
    223   | hb_filter (glyphset, hb_first)
    224   | hb_map (hb_second)
    225 )
    226    {
    227      const PairSet& set = (this + _);
    228      const PairValueRecord *record = &set.firstPairValueRecord;
    229 
    230      unsigned count = set.len;
    231      for (unsigned i = 0; i < count; i++)
    232      {
    233        if (record->intersects (glyphset))
    234        {
    235          format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 (), strip_hints, strip_empty, &set, varidx_delta_map);
    236          format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]), strip_hints, strip_empty, &set, varidx_delta_map);
    237        }
    238        record = &StructAtOffset<const PairValueRecord> (record, record_size);
    239      }
    240 
    241      if (format1 == valueFormat[0] && format2 == valueFormat[1])
    242        break;
    243    }
    244 
    245    return hb_pair (format1, format2);
    246  }
    247 };
    248 
    249 
    250 }
    251 }
    252 }
    253 
    254 #endif  // OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH