tor-browser

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

CoverageFormat2.hh (6766B)


      1 /*
      2 * Copyright © 2007,2008,2009  Red Hat, Inc.
      3 * Copyright © 2010,2012  Google, Inc.
      4 *
      5 *  This is part of HarfBuzz, a text shaping library.
      6 *
      7 * Permission is hereby granted, without written agreement and without
      8 * license or royalty fees, to use, copy, modify, and distribute this
      9 * software and its documentation for any purpose, provided that the
     10 * above copyright notice and the following two paragraphs appear in
     11 * all copies of this software.
     12 *
     13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     17 * DAMAGE.
     18 *
     19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     21 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     24 *
     25 * Red Hat Author(s): Behdad Esfahbod
     26 * Google Author(s): Behdad Esfahbod, Garret Rieger
     27 */
     28 
     29 #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
     30 #define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
     31 
     32 #include "RangeRecord.hh"
     33 
     34 namespace OT {
     35 namespace Layout {
     36 namespace Common {
     37 
     38 template <typename Types>
     39 struct CoverageFormat2_4
     40 {
     41  friend struct Coverage;
     42 
     43  public:
     44  HBUINT16      coverageFormat; /* Format identifier--format = 2 */
     45  SortedArray16Of<RangeRecord<Types>>
     46                rangeRecord;    /* Array of glyph ranges--ordered by
     47                                 * Start GlyphID. rangeCount entries
     48                                 * long */
     49  public:
     50  DEFINE_SIZE_ARRAY (4, rangeRecord);
     51 
     52  private:
     53 
     54  bool sanitize (hb_sanitize_context_t *c) const
     55  {
     56    TRACE_SANITIZE (this);
     57    return_trace (rangeRecord.sanitize (c));
     58  }
     59 
     60  unsigned int get_coverage (hb_codepoint_t glyph_id) const
     61  {
     62    const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
     63    return likely (range.first <= range.last)
     64         ? (unsigned int) range.value + (glyph_id - range.first)
     65         : NOT_COVERED;
     66  }
     67 
     68  unsigned get_population () const
     69  {
     70    typename Types::large_int ret = 0;
     71    for (const auto &r : rangeRecord)
     72      ret += r.get_population ();
     73    return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
     74  }
     75 
     76  template <typename Iterator,
     77      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
     78  bool serialize (hb_serialize_context_t *c, Iterator glyphs)
     79  {
     80    TRACE_SERIALIZE (this);
     81    if (unlikely (!c->extend_min (this))) return_trace (false);
     82 
     83    unsigned num_ranges = 0;
     84    hb_codepoint_t last = (hb_codepoint_t) -2;
     85    for (auto g: glyphs)
     86    {
     87      if (last + 1 != g)
     88        num_ranges++;
     89      last = g;
     90    }
     91 
     92    if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
     93    if (!num_ranges) return_trace (true);
     94 
     95    unsigned count = 0;
     96    unsigned range = (unsigned) -1;
     97    last = (hb_codepoint_t) -2;
     98    unsigned unsorted = false;
     99    for (auto g: glyphs)
    100    {
    101      if (last + 1 != g)
    102      {
    103 if (unlikely (last != (hb_codepoint_t) -2 && last + 1 > g))
    104   unsorted = true;
    105 
    106        range++;
    107        rangeRecord.arrayZ[range].first = g;
    108        rangeRecord.arrayZ[range].value = count;
    109      }
    110      rangeRecord.arrayZ[range].last = g;
    111      last = g;
    112      count++;
    113    }
    114 
    115    if (unlikely (unsorted))
    116      rangeRecord.as_array ().qsort (RangeRecord<Types>::cmp_range);
    117 
    118    return_trace (true);
    119  }
    120 
    121  bool intersects (const hb_set_t *glyphs) const
    122  {
    123    if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
    124    {
    125      for (auto g : *glyphs)
    126        if (get_coverage (g) != NOT_COVERED)
    127   return true;
    128      return false;
    129    }
    130 
    131    return hb_any (+ hb_iter (rangeRecord)
    132                   | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
    133  }
    134  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
    135  {
    136    auto *range = rangeRecord.as_array ().bsearch (index);
    137    if (range)
    138      return range->intersects (*glyphs);
    139    return false;
    140  }
    141 
    142  template <typename IterableOut,
    143     hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
    144  void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
    145  {
    146    /* Break out of loop for overlapping, broken, tables,
    147     * to avoid fuzzer timouts. */
    148    hb_codepoint_t last = 0;
    149    for (const auto& range : rangeRecord)
    150    {
    151      if (unlikely (range.first < last))
    152        break;
    153      last = range.last;
    154      for (hb_codepoint_t g = range.first - 1;
    155    glyphs.next (&g) && g <= last;)
    156 intersect_glyphs << g;
    157    }
    158  }
    159 
    160  unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
    161 
    162  template <typename set_t>
    163  bool collect_coverage (set_t *glyphs) const
    164  {
    165    for (const auto& range: rangeRecord)
    166      if (unlikely (!range.collect_coverage (glyphs)))
    167        return false;
    168    return true;
    169  }
    170 
    171  public:
    172  /* Older compilers need this to be public. */
    173  struct iter_t
    174  {
    175    void init (const CoverageFormat2_4 &c_)
    176    {
    177      c = &c_;
    178      coverage = 0;
    179      i = 0;
    180      j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
    181      if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
    182      {
    183        /* Broken table. Skip. */
    184        i = c->rangeRecord.len;
    185        j = 0;
    186      }
    187    }
    188    bool __more__ () const { return i < c->rangeRecord.len; }
    189    void __next__ ()
    190    {
    191      if (j >= c->rangeRecord[i].last)
    192      {
    193        i++;
    194        if (__more__ ())
    195        {
    196          unsigned int old = coverage;
    197          j = c->rangeRecord.arrayZ[i].first;
    198          coverage = c->rangeRecord.arrayZ[i].value;
    199          if (unlikely (coverage != old + 1))
    200          {
    201            /* Broken table. Skip. Important to avoid DoS.
    202             * Also, our callers depend on coverage being
    203             * consecutive and monotonically increasing,
    204             * ie. iota(). */
    205           i = c->rangeRecord.len;
    206           j = 0;
    207           return;
    208          }
    209        }
    210        else
    211          j = 0;
    212        return;
    213      }
    214      coverage++;
    215      j++;
    216    }
    217    hb_codepoint_t get_glyph () const { return j; }
    218    bool operator != (const iter_t& o) const
    219    { return i != o.i || j != o.j; }
    220    iter_t __end__ () const
    221    {
    222      iter_t it;
    223      it.init (*c);
    224      it.i = c->rangeRecord.len;
    225      it.j = 0;
    226      return it;
    227    }
    228 
    229    private:
    230    const struct CoverageFormat2_4 *c;
    231    unsigned int i, coverage;
    232    hb_codepoint_t j;
    233  };
    234  private:
    235 };
    236 
    237 }
    238 }
    239 }
    240 
    241 #endif  // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH