tor-browser

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

SingleSubstFormat2.hh (5291B)


      1 #ifndef OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
      2 #define OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
      3 
      4 #include "Common.hh"
      5 
      6 namespace OT {
      7 namespace Layout {
      8 namespace GSUB_impl {
      9 
     10 template <typename Types>
     11 struct SingleSubstFormat2_4
     12 {
     13  protected:
     14  HBUINT16      format;                 /* Format identifier--format = 2 */
     15  typename Types::template OffsetTo<Coverage>
     16                coverage;               /* Offset to Coverage table--from
     17                                         * beginning of Substitution table */
     18  Array16Of<typename Types::HBGlyphID>
     19                substitute;             /* Array of substitute
     20                                         * GlyphIDs--ordered by Coverage Index */
     21 
     22  public:
     23  DEFINE_SIZE_ARRAY (4 + Types::size, substitute);
     24 
     25  bool sanitize (hb_sanitize_context_t *c) const
     26  {
     27    TRACE_SANITIZE (this);
     28    return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
     29  }
     30 
     31  bool intersects (const hb_set_t *glyphs) const
     32  { return (this+coverage).intersects (glyphs); }
     33 
     34  bool may_have_non_1to1 () const
     35  { return false; }
     36 
     37  void closure (hb_closure_context_t *c) const
     38  {
     39    auto &cov = this+coverage;
     40    auto &glyph_set = c->parent_active_glyphs ();
     41 
     42    if (substitute.len > glyph_set.get_population () * 4)
     43    {
     44      for (auto g : glyph_set)
     45      {
     46 unsigned i = cov.get_coverage (g);
     47 if (i == NOT_COVERED || i >= substitute.len)
     48   continue;
     49 c->output->add (substitute.arrayZ[i]);
     50      }
     51 
     52      return;
     53    }
     54 
     55    + hb_zip (cov, substitute)
     56    | hb_filter (glyph_set, hb_first)
     57    | hb_map (hb_second)
     58    | hb_sink (c->output)
     59    ;
     60  }
     61 
     62  void closure_lookups (hb_closure_lookups_context_t *c) const {}
     63 
     64  void collect_glyphs (hb_collect_glyphs_context_t *c) const
     65  {
     66    if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
     67    + hb_zip (this+coverage, substitute)
     68    | hb_map (hb_second)
     69    | hb_sink (c->output)
     70    ;
     71  }
     72 
     73  const Coverage &get_coverage () const { return this+coverage; }
     74 
     75  bool would_apply (hb_would_apply_context_t *c) const
     76  { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
     77 
     78  unsigned
     79  get_glyph_alternates (hb_codepoint_t  glyph_id,
     80                        unsigned        start_offset,
     81                        unsigned       *alternate_count  /* IN/OUT.  May be NULL. */,
     82                        hb_codepoint_t *alternate_glyphs /* OUT.     May be NULL. */) const
     83  {
     84    unsigned int index = (this+coverage).get_coverage (glyph_id);
     85    if (likely (index == NOT_COVERED))
     86    {
     87      if (alternate_count)
     88        *alternate_count = 0;
     89      return 0;
     90    }
     91 
     92    if (alternate_count && *alternate_count)
     93    {
     94      glyph_id = substitute[index];
     95 
     96      *alternate_glyphs = glyph_id;
     97      *alternate_count = 1;
     98    }
     99 
    100    return 1;
    101  }
    102 
    103  void
    104  collect_glyph_alternates (hb_map_t  *alternate_count /* IN/OUT */,
    105 		    hb_map_t  *alternate_glyphs /* IN/OUT */) const
    106  {
    107    + hb_zip (this+coverage, substitute)
    108    | hb_apply ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> &p) -> void
    109 	{ _hb_collect_glyph_alternates_add (p.first, p.second,
    110 					    alternate_count, alternate_glyphs); })
    111    ;
    112  }
    113 
    114  bool apply (hb_ot_apply_context_t *c) const
    115  {
    116    TRACE_APPLY (this);
    117    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
    118    if (index == NOT_COVERED) return_trace (false);
    119 
    120    if (unlikely (index >= substitute.len)) return_trace (false);
    121 
    122    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
    123    {
    124      c->buffer->sync_so_far ();
    125      c->buffer->message (c->font,
    126 		  "replacing glyph at %u (single substitution)",
    127 		  c->buffer->idx);
    128    }
    129 
    130    c->replace_glyph (substitute[index]);
    131 
    132    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
    133    {
    134      c->buffer->message (c->font,
    135 		  "replaced glyph at %u (single substitution)",
    136 		  c->buffer->idx - 1u);
    137    }
    138 
    139    return_trace (true);
    140  }
    141 
    142  template<typename Iterator,
    143           hb_requires (hb_is_sorted_source_of (Iterator,
    144                                                hb_codepoint_pair_t))>
    145  bool serialize (hb_serialize_context_t *c,
    146                  Iterator it)
    147  {
    148    TRACE_SERIALIZE (this);
    149    auto substitutes =
    150      + it
    151      | hb_map (hb_second)
    152      ;
    153    auto glyphs =
    154      + it
    155      | hb_map_retains_sorting (hb_first)
    156      ;
    157    if (unlikely (!c->extend_min (this))) return_trace (false);
    158    if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
    159    if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
    160    return_trace (true);
    161  }
    162 
    163  bool subset (hb_subset_context_t *c) const
    164  {
    165    TRACE_SUBSET (this);
    166    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
    167    const hb_map_t &glyph_map = *c->plan->glyph_map;
    168 
    169    auto it =
    170    + hb_zip (this+coverage, substitute)
    171    | hb_filter (glyphset, hb_first)
    172    | hb_filter (glyphset, hb_second)
    173    | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const typename Types::HBGlyphID &> p) -> hb_codepoint_pair_t
    174                              { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
    175    ;
    176 
    177    bool ret = bool (it);
    178    SingleSubst_serialize (c->serializer, it);
    179    return_trace (ret);
    180  }
    181 };
    182 
    183 }
    184 }
    185 }
    186 
    187 #endif /* OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH */