tor-browser

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

PairSet.hh (6370B)


      1 #ifndef OT_LAYOUT_GPOS_PAIRSET_HH
      2 #define OT_LAYOUT_GPOS_PAIRSET_HH
      3 
      4 #include "PairValueRecord.hh"
      5 
      6 namespace OT {
      7 namespace Layout {
      8 namespace GPOS_impl {
      9 
     10 
     11 template <typename Types>
     12 struct PairSet : ValueBase
     13 {
     14  template <typename Types2>
     15  friend struct PairPosFormat1_3;
     16 
     17  using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
     18 
     19  protected:
     20  HBUINT16              len;    /* Number of PairValueRecords */
     21  PairValueRecord       firstPairValueRecord;
     22                                /* Array of PairValueRecords--ordered
     23                                 * by GlyphID of the second glyph */
     24  public:
     25  DEFINE_SIZE_MIN (2);
     26 
     27  static unsigned get_size (unsigned len1, unsigned len2)
     28  {
     29    return Types::HBGlyphID::static_size + Value::static_size * (len1 + len2);
     30  }
     31  static unsigned get_size (const ValueFormat valueFormats[2])
     32  {
     33    unsigned len1 = valueFormats[0].get_len ();
     34    unsigned len2 = valueFormats[1].get_len ();
     35    return get_size (len1, len2);
     36  }
     37 
     38  struct sanitize_closure_t
     39  {
     40    const ValueFormat *valueFormats;
     41    unsigned int len1; /* valueFormats[0].get_len() */
     42    unsigned int stride; /* bytes */
     43  };
     44 
     45  bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
     46  {
     47    TRACE_SANITIZE (this);
     48    if (!(c->check_struct (this) &&
     49   hb_barrier () &&
     50          c->check_range (&firstPairValueRecord,
     51                          len,
     52                          closure->stride))) return_trace (false);
     53    hb_barrier ();
     54 
     55    unsigned int count = len;
     56    const PairValueRecord *record = &firstPairValueRecord;
     57    return_trace (c->lazy_some_gpos ||
     58 	  (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
     59                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)));
     60  }
     61 
     62  bool intersects (const hb_set_t *glyphs,
     63                   const ValueFormat *valueFormats) const
     64  {
     65    unsigned record_size = get_size (valueFormats);
     66 
     67    const PairValueRecord *record = &firstPairValueRecord;
     68    unsigned int count = len;
     69    for (unsigned int i = 0; i < count; i++)
     70    {
     71      if (glyphs->has (record->secondGlyph))
     72        return true;
     73      record = &StructAtOffset<const PairValueRecord> (record, record_size);
     74    }
     75    return false;
     76  }
     77 
     78  void collect_glyphs (hb_collect_glyphs_context_t *c,
     79                       const ValueFormat *valueFormats) const
     80  {
     81    unsigned record_size = get_size (valueFormats);
     82 
     83    const PairValueRecord *record = &firstPairValueRecord;
     84    c->input->add_array (&record->secondGlyph, len, record_size);
     85  }
     86 
     87  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
     88                                  const ValueFormat *valueFormats) const
     89  {
     90    unsigned record_size = get_size (valueFormats);
     91 
     92    const PairValueRecord *record = &firstPairValueRecord;
     93    unsigned count = len;
     94    for (unsigned i = 0; i < count; i++)
     95    {
     96      if (c->glyph_set->has (record->secondGlyph))
     97      { record->collect_variation_indices (c, valueFormats, this); }
     98 
     99      record = &StructAtOffset<const PairValueRecord> (record, record_size);
    100    }
    101  }
    102 
    103  bool apply (hb_ot_apply_context_t *c,
    104              const ValueFormat *valueFormats,
    105              unsigned int pos) const
    106  {
    107    TRACE_APPLY (this);
    108    hb_buffer_t *buffer = c->buffer;
    109    unsigned int len1 = valueFormats[0].get_len ();
    110    unsigned int len2 = valueFormats[1].get_len ();
    111    unsigned record_size = get_size (len1, len2);
    112 
    113    const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
    114                                                &firstPairValueRecord,
    115                                                len,
    116                                                record_size);
    117    if (record)
    118    {
    119      if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
    120      {
    121 c->buffer->message (c->font,
    122 		    "try kerning glyphs at %u,%u",
    123 		    c->buffer->idx, pos);
    124      }
    125 
    126      bool applied_first = len1 && valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
    127      bool applied_second = len2 && valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
    128 
    129      if (applied_first || applied_second)
    130 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
    131 {
    132   c->buffer->message (c->font,
    133 		      "kerned glyphs at %u,%u",
    134 		      c->buffer->idx, pos);
    135 }
    136 
    137      if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
    138      {
    139 c->buffer->message (c->font,
    140 		    "tried kerning glyphs at %u,%u",
    141 		    c->buffer->idx, pos);
    142      }
    143 
    144      if (applied_first || applied_second)
    145        buffer->unsafe_to_break (buffer->idx, pos + 1);
    146 
    147      if (len2)
    148      {
    149 pos++;
    150      // https://github.com/harfbuzz/harfbuzz/issues/3824
    151      // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
    152      buffer->unsafe_to_break (buffer->idx, pos + 1);
    153      }
    154 
    155      buffer->idx = pos;
    156      return_trace (true);
    157    }
    158    buffer->unsafe_to_concat (buffer->idx, pos + 1);
    159    return_trace (false);
    160  }
    161 
    162  bool subset (hb_subset_context_t *c,
    163               const ValueFormat valueFormats[2],
    164               const ValueFormat newFormats[2]) const
    165  {
    166    TRACE_SUBSET (this);
    167    auto snap = c->serializer->snapshot ();
    168 
    169    auto *out = c->serializer->start_embed (*this);
    170    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
    171    out->len = 0;
    172 
    173    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
    174    const hb_map_t &glyph_map = *c->plan->glyph_map;
    175 
    176    unsigned len1 = valueFormats[0].get_len ();
    177    unsigned len2 = valueFormats[1].get_len ();
    178    unsigned record_size = get_size (len1, len2);
    179 
    180    typename PairValueRecord::context_t context =
    181    {
    182      this,
    183      valueFormats,
    184      newFormats,
    185      len1,
    186      &glyph_map,
    187      &c->plan->layout_variation_idx_delta_map
    188    };
    189 
    190    const PairValueRecord *record = &firstPairValueRecord;
    191    unsigned count = len, num = 0;
    192    for (unsigned i = 0; i < count; i++)
    193    {
    194      if (glyphset.has (record->secondGlyph)
    195         && record->subset (c, &context)) num++;
    196      record = &StructAtOffset<const PairValueRecord> (record, record_size);
    197    }
    198 
    199    out->len = num;
    200    if (!num) c->serializer->revert (snap);
    201    return_trace (num);
    202  }
    203 };
    204 
    205 
    206 }
    207 }
    208 }
    209 
    210 #endif  // OT_LAYOUT_GPOS_PAIRSET_HH