tor-browser

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

LigatureSubstFormat1.hh (6725B)


      1 #ifndef OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
      2 #define OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
      3 
      4 #include "Common.hh"
      5 #include "LigatureSet.hh"
      6 
      7 namespace OT {
      8 namespace Layout {
      9 namespace GSUB_impl {
     10 
     11 template <typename Types>
     12 struct LigatureSubstFormat1_2
     13 {
     14  protected:
     15  HBUINT16      format;                 /* Format identifier--format = 1 */
     16  typename Types::template OffsetTo<Coverage>
     17                coverage;               /* Offset to Coverage table--from
     18                                         * beginning of Substitution table */
     19  Array16Of<typename Types::template OffsetTo<LigatureSet<Types>>>
     20                ligatureSet;            /* Array LigatureSet tables
     21                                         * ordered by Coverage Index */
     22  public:
     23  DEFINE_SIZE_ARRAY (4 + Types::size, ligatureSet);
     24 
     25  bool sanitize (hb_sanitize_context_t *c) const
     26  {
     27    TRACE_SANITIZE (this);
     28    return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
     29  }
     30 
     31  bool intersects (const hb_set_t *glyphs) const
     32  {
     33    return
     34    + hb_zip (this+coverage, ligatureSet)
     35    | hb_filter (*glyphs, hb_first)
     36    | hb_map (hb_second)
     37    | hb_map ([this, glyphs] (const typename Types::template OffsetTo<LigatureSet<Types>> &_)
     38              { return (this+_).intersects (glyphs); })
     39    | hb_any
     40    ;
     41  }
     42 
     43  bool may_have_non_1to1 () const
     44  { return true; }
     45 
     46  void closure (hb_closure_context_t *c) const
     47  {
     48    + hb_zip (this+coverage, ligatureSet)
     49    | hb_filter (c->parent_active_glyphs (), hb_first)
     50    | hb_map (hb_second)
     51    | hb_map (hb_add (this))
     52    | hb_apply ([c] (const LigatureSet<Types> &_) { _.closure (c); })
     53    ;
     54 
     55  }
     56 
     57  void closure_lookups (hb_closure_lookups_context_t *c) const {}
     58 
     59  void collect_glyphs (hb_collect_glyphs_context_t *c) const
     60  {
     61    if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
     62 
     63    + hb_zip (this+coverage, ligatureSet)
     64    | hb_map (hb_second)
     65    | hb_map (hb_add (this))
     66    | hb_apply ([c] (const LigatureSet<Types> &_) { _.collect_glyphs (c); })
     67    ;
     68  }
     69 
     70  const Coverage &get_coverage () const { return this+coverage; }
     71 
     72  bool would_apply (hb_would_apply_context_t *c) const
     73  {
     74    unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
     75    if (likely (index == NOT_COVERED)) return false;
     76 
     77    const auto &lig_set = this+ligatureSet[index];
     78    return lig_set.would_apply (c);
     79  }
     80 
     81  struct external_cache_t
     82  {
     83    hb_ot_layout_mapping_cache_t coverage;
     84    hb_set_digest_t seconds;
     85  };
     86  void *external_cache_create () const
     87  {
     88    external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
     89    if (likely (cache))
     90    {
     91      cache->coverage.clear ();
     92 
     93      cache->seconds.init ();
     94      + hb_iter (ligatureSet)
     95      | hb_map (hb_add (this))
     96      | hb_apply ([cache] (const LigatureSet<Types> &_) { _.collect_seconds (cache->seconds); })
     97      ;
     98    }
     99    return cache;
    100  }
    101 
    102  bool apply (hb_ot_apply_context_t *c, void *external_cache) const
    103  {
    104    TRACE_APPLY (this);
    105    hb_buffer_t *buffer = c->buffer;
    106 
    107 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
    108    external_cache_t *cache = (external_cache_t *) external_cache;
    109    const hb_set_digest_t *seconds = cache ? &cache->seconds : nullptr;
    110    unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
    111 #else
    112    const hb_set_digest_t *seconds = nullptr;
    113    unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
    114 #endif
    115    if (index == NOT_COVERED) return_trace (false);
    116 
    117    const auto &lig_set = this+ligatureSet[index];
    118    return_trace (lig_set.apply (c, seconds));
    119  }
    120 
    121  bool serialize (hb_serialize_context_t *c,
    122                  hb_sorted_array_t<const HBGlyphID16> first_glyphs,
    123                  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
    124                  hb_array_t<const HBGlyphID16> ligatures_list,
    125                  hb_array_t<const unsigned int> component_count_list,
    126                  hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
    127  {
    128    TRACE_SERIALIZE (this);
    129    if (unlikely (!c->extend_min (this))) return_trace (false);
    130    if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
    131    for (unsigned int i = 0; i < first_glyphs.length; i++)
    132    {
    133      unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
    134      if (unlikely (!ligatureSet[i]
    135                        .serialize_serialize (c,
    136                                              ligatures_list.sub_array (0, ligature_count),
    137                                              component_count_list.sub_array (0, ligature_count),
    138                                              component_list))) return_trace (false);
    139      ligatures_list += ligature_count;
    140      component_count_list += ligature_count;
    141    }
    142    return_trace (coverage.serialize_serialize (c, first_glyphs));
    143  }
    144 
    145  bool subset (hb_subset_context_t *c) const
    146  {
    147    TRACE_SUBSET (this);
    148    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
    149    const hb_map_t &glyph_map = *c->plan->glyph_map;
    150 
    151    auto *out = c->serializer->start_embed (*this);
    152    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
    153    out->format = format;
    154 
    155    // Due to a bug in some older versions of windows 7 the Coverage table must be
    156    // packed after the LigatureSet and Ligature tables, so serialize Coverage first
    157    // which places it last in the packed order.
    158    hb_set_t new_coverage;
    159    + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
    160    | hb_filter (glyphset, hb_first)
    161    | hb_filter ([&] (const LigatureSet<Types>& _) {
    162      return _.intersects_lig_glyph (&glyphset);
    163    }, hb_second)
    164    | hb_map (hb_first)
    165    | hb_sink (new_coverage);
    166 
    167    if (!c->serializer->push<Coverage> ()
    168        ->serialize (c->serializer,
    169                     + new_coverage.iter () | hb_map_retains_sorting (glyph_map)))
    170    {
    171      c->serializer->pop_discard ();
    172      return_trace (false);
    173    }
    174 
    175    unsigned coverage_idx = c->serializer->pop_pack ();
    176     c->serializer->add_link (out->coverage, coverage_idx);
    177 
    178    + hb_zip (this+coverage, ligatureSet)
    179    | hb_filter (new_coverage, hb_first)
    180    | hb_map (hb_second)
    181    // to ensure that the repacker always orders the coverage table after the LigatureSet
    182    // and LigatureSubtable's they will be linked to the Coverage table via a virtual link
    183    // the coverage table object idx is passed down to facilitate this.
    184    | hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx))
    185    ;
    186 
    187    return_trace (bool (new_coverage));
    188  }
    189 };
    190 
    191 }
    192 }
    193 }
    194 
    195 #endif  /* OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH */