tor-browser

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

coverage-graph.hh (6711B)


      1 /*
      2 * Copyright © 2022  Google, Inc.
      3 *
      4 *  This is part of HarfBuzz, a text shaping library.
      5 *
      6 * Permission is hereby granted, without written agreement and without
      7 * license or royalty fees, to use, copy, modify, and distribute this
      8 * software and its documentation for any purpose, provided that the
      9 * above copyright notice and the following two paragraphs appear in
     10 * all copies of this software.
     11 *
     12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16 * DAMAGE.
     17 *
     18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23 *
     24 * Google Author(s): Garret Rieger
     25 */
     26 
     27 #include "graph.hh"
     28 #include "../OT/Layout/Common/Coverage.hh"
     29 
     30 #ifndef GRAPH_COVERAGE_GRAPH_HH
     31 #define GRAPH_COVERAGE_GRAPH_HH
     32 
     33 namespace graph {
     34 
     35 static bool sanitize (
     36  const OT::Layout::Common::CoverageFormat1_3<OT::Layout::SmallTypes>* thiz,
     37  graph_t::vertex_t& vertex
     38 ) {
     39  int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     40  constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<OT::Layout::SmallTypes>::min_size;
     41  if (vertex_len < min_size) return false;
     42  hb_barrier ();
     43  return vertex_len >= min_size + thiz->glyphArray.get_size () - thiz->glyphArray.len.get_size ();
     44 }
     45 
     46 static bool sanitize (
     47  const OT::Layout::Common::CoverageFormat2_4<OT::Layout::SmallTypes>* thiz,
     48  graph_t::vertex_t& vertex
     49 ) {
     50  int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     51  constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<OT::Layout::SmallTypes>::min_size;
     52  if (vertex_len < min_size) return false;
     53  hb_barrier ();
     54  return vertex_len >= min_size + thiz->rangeRecord.get_size () - thiz->rangeRecord.len.get_size ();
     55 }
     56 
     57 struct Coverage : public OT::Layout::Common::Coverage
     58 {
     59  static Coverage* clone_coverage (gsubgpos_graph_context_t& c,
     60                                   unsigned coverage_id,
     61                                   unsigned new_parent_id,
     62                                   unsigned link_position,
     63                                   unsigned start, unsigned end)
     64 
     65  {
     66    unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
     67    auto& coverage_v = c.graph.vertices_[coverage_id];
     68    Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
     69    if (!coverage_table || !coverage_table->sanitize (coverage_v))
     70      return nullptr;
     71 
     72    auto new_coverage =
     73        + hb_zip (coverage_table->iter (), hb_range ())
     74        | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
     75          return p.second >= start && p.second < end;
     76        })
     77        | hb_map_retains_sorting (hb_first)
     78        ;
     79 
     80    return add_coverage (c, new_parent_id, link_position, new_coverage, coverage_size);
     81  }
     82 
     83  template<typename It>
     84  static Coverage* add_coverage (gsubgpos_graph_context_t& c,
     85                                 unsigned parent_id,
     86                                 unsigned link_position,
     87                                 It glyphs,
     88                                 unsigned max_size)
     89  {
     90    unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr);
     91    auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
     92    if (!make_coverage (c, glyphs, coverage_prime_id, max_size))
     93      return nullptr;
     94 
     95    auto* coverage_link = c.graph.vertices_[parent_id].obj.real_links.push ();
     96    coverage_link->width = SmallTypes::size;
     97    coverage_link->objidx = coverage_prime_id;
     98    coverage_link->position = link_position;
     99    coverage_prime_vertex.add_parent (parent_id, false);
    100 
    101    return (Coverage*) coverage_prime_vertex.obj.head;
    102  }
    103 
    104  // Filter an existing coverage table to glyphs at indices [start, end) and replace it with the filtered version.
    105  static bool filter_coverage (gsubgpos_graph_context_t& c,
    106                               unsigned existing_coverage,
    107                               unsigned start, unsigned end) {
    108    unsigned coverage_size = c.graph.vertices_[existing_coverage].table_size ();
    109    auto& coverage_v = c.graph.vertices_[existing_coverage];
    110    Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
    111    if (!coverage_table || !coverage_table->sanitize (coverage_v))
    112      return false;
    113 
    114    auto new_coverage =
    115        + hb_zip (coverage_table->iter (), hb_range ())
    116        | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
    117          return p.second >= start && p.second < end;
    118        })
    119        | hb_map_retains_sorting (hb_first)
    120        ;
    121 
    122    return make_coverage (c, new_coverage, existing_coverage, coverage_size * 2 + 100);
    123  }
    124 
    125  // Replace the coverage table at dest obj with one covering 'glyphs'.
    126  template<typename It>
    127  static bool make_coverage (gsubgpos_graph_context_t& c,
    128                             It glyphs,
    129                             unsigned dest_obj,
    130                             unsigned max_size)
    131  {
    132    char* buffer = (char*) hb_calloc (1, max_size);
    133    hb_serialize_context_t serializer (buffer, max_size);
    134    OT::Layout::Common::Coverage_serialize (&serializer, glyphs);
    135    serializer.end_serialize ();
    136    if (serializer.in_error ())
    137    {
    138      hb_free (buffer);
    139      return false;
    140    }
    141 
    142    hb_bytes_t coverage_copy = serializer.copy_bytes ();
    143    if (!coverage_copy.arrayZ) return false;
    144    // Give ownership to the context, it will cleanup the buffer.
    145    if (!c.add_buffer ((char *) coverage_copy.arrayZ))
    146    {
    147      hb_free ((char *) coverage_copy.arrayZ);
    148      return false;
    149    }
    150 
    151    auto& obj = c.graph.vertices_[dest_obj].obj;
    152    obj.head = (char *) coverage_copy.arrayZ;
    153    obj.tail = obj.head + coverage_copy.length;
    154 
    155    hb_free (buffer);
    156    return true;
    157  }
    158 
    159  bool sanitize (graph_t::vertex_t& vertex) const
    160  {
    161    int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
    162    if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
    163    hb_barrier ();
    164    switch (u.format.v)
    165    {
    166    case 1: return graph::sanitize ((const OT::Layout::Common::CoverageFormat1_3<OT::Layout::SmallTypes>*) this, vertex);
    167    case 2: return graph::sanitize ((const OT::Layout::Common::CoverageFormat2_4<OT::Layout::SmallTypes>*) this, vertex);
    168 #ifndef HB_NO_BEYOND_64K
    169    // Not currently supported
    170    case 3:
    171    case 4:
    172 #endif
    173    default: return false;
    174    }
    175  }
    176 };
    177 
    178 
    179 }
    180 
    181 #endif  // GRAPH_COVERAGE_GRAPH_HH