tor-browser

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

SinglePosFormat1.hh (6283B)


      1 #ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
      2 #define OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
      3 
      4 #include "Common.hh"
      5 #include "ValueFormat.hh"
      6 
      7 namespace OT {
      8 namespace Layout {
      9 namespace GPOS_impl {
     10 
     11 struct SinglePosFormat1 : ValueBase
     12 {
     13  protected:
     14  HBUINT16      format;                 /* Format identifier--format = 1 */
     15  Offset16To<Coverage>
     16                coverage;               /* Offset to Coverage table--from
     17                                         * beginning of subtable */
     18  ValueFormat   valueFormat;            /* Defines the types of data in the
     19                                         * ValueRecord */
     20  ValueRecord   values;                 /* Defines positioning
     21                                         * value(s)--applied to all glyphs in
     22                                         * the Coverage table */
     23  public:
     24  DEFINE_SIZE_ARRAY (6, values);
     25 
     26  bool sanitize (hb_sanitize_context_t *c) const
     27  {
     28    TRACE_SANITIZE (this);
     29    return_trace (c->check_struct (this) &&
     30                  coverage.sanitize (c, this) &&
     31 	  hb_barrier () &&
     32                  /* The coverage  table may use a range to represent a set
     33                   * of glyphs, which means a small number of bytes can
     34                   * generate a large glyph set. Manually modify the
     35                   * sanitizer max ops to take this into account.
     36                   *
     37                   * Note: This check *must* be right after coverage sanitize. */
     38                  c->check_ops ((this + coverage).get_population () >> 1) &&
     39                  valueFormat.sanitize_value (c, this, values));
     40 
     41  }
     42 
     43  bool intersects (const hb_set_t *glyphs) const
     44  { return (this+coverage).intersects (glyphs); }
     45 
     46  void closure_lookups (hb_closure_lookups_context_t *c) const {}
     47  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
     48  {
     49    if (!valueFormat.has_device ()) return;
     50 
     51    hb_set_t intersection;
     52    (this+coverage).intersect_set (*c->glyph_set, intersection);
     53    if (!intersection) return;
     54 
     55    valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
     56  }
     57 
     58  void collect_glyphs (hb_collect_glyphs_context_t *c) const
     59  { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
     60 
     61  const Coverage &get_coverage () const { return this+coverage; }
     62 
     63  ValueFormat get_value_format () const { return valueFormat; }
     64 
     65  bool apply (hb_ot_apply_context_t *c) const
     66  {
     67    TRACE_APPLY (this);
     68    hb_buffer_t *buffer = c->buffer;
     69    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     70    if (index == NOT_COVERED) return_trace (false);
     71 
     72    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     73    {
     74      c->buffer->message (c->font,
     75 		  "positioning glyph at %u",
     76 		  c->buffer->idx);
     77    }
     78 
     79    valueFormat.apply_value (c, this, values, buffer->cur_pos());
     80 
     81    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     82    {
     83      c->buffer->message (c->font,
     84 		  "positioned glyph at %u",
     85 		  c->buffer->idx);
     86    }
     87 
     88    buffer->idx++;
     89    return_trace (true);
     90  }
     91 
     92  bool
     93  position_single (hb_font_t           *font,
     94 	   hb_blob_t           *table_blob,
     95 	   hb_direction_t       direction,
     96 	   hb_codepoint_t       gid,
     97 	   hb_glyph_position_t &pos) const
     98  {
     99    unsigned int index = (this+coverage).get_coverage  (gid);
    100    if (likely (index == NOT_COVERED)) return false;
    101 
    102    /* This is ugly... */
    103    hb_buffer_t buffer;
    104    buffer.props.direction = direction;
    105    OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
    106 
    107    valueFormat.apply_value (&c, this, values, pos);
    108    return true;
    109  }
    110 
    111  template<typename Iterator,
    112      typename SrcLookup,
    113      hb_requires (hb_is_iterator (Iterator))>
    114  void serialize (hb_serialize_context_t *c,
    115                  const SrcLookup *src,
    116                  Iterator it,
    117                  ValueFormat newFormat,
    118                  const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
    119  {
    120    if (unlikely (!c->extend_min (this))) return;
    121    if (unlikely (!c->check_assign (valueFormat,
    122                                    newFormat,
    123                                    HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
    124 
    125    for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
    126    {
    127      src->get_value_format ().copy_values (c, newFormat, src,  &_, layout_variation_idx_delta_map);
    128      // Only serialize the first entry in the iterator, the rest are assumed to
    129      // be the same.
    130      break;
    131    }
    132 
    133    auto glyphs =
    134    + it
    135    | hb_map_retains_sorting (hb_first)
    136    ;
    137 
    138    coverage.serialize_serialize (c, glyphs);
    139  }
    140 
    141  bool subset (hb_subset_context_t *c) const
    142  {
    143    TRACE_SUBSET (this);
    144    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
    145    const hb_map_t &glyph_map = *c->plan->glyph_map;
    146 
    147    hb_set_t intersection;
    148    (this+coverage).intersect_set (glyphset, intersection);
    149 
    150    unsigned new_format = valueFormat;
    151 
    152    if (c->plan->normalized_coords)
    153    {
    154      new_format = valueFormat.get_effective_format (values.arrayZ, false, false, this, &c->plan->layout_variation_idx_delta_map);
    155    }
    156    /* do not strip hints for VF */
    157    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
    158    {
    159      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
    160      bool has_fvar = (blob != hb_blob_get_empty ());
    161      hb_blob_destroy (blob);
    162 
    163      bool strip = !has_fvar;
    164      /* special case: strip hints when a VF has no GDEF varstore after
    165       * subsetting*/
    166      if (has_fvar && !c->plan->has_gdef_varstore)
    167        strip = true;
    168      new_format = valueFormat.get_effective_format (values.arrayZ,
    169                                                     strip, /* strip hints */
    170                                                     true, /* strip empty */
    171                                                     this, nullptr);
    172    }
    173 
    174    auto it =
    175    + hb_iter (intersection)
    176    | hb_map_retains_sorting (glyph_map)
    177    | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
    178    ;
    179 
    180    bool ret = bool (it);
    181    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
    182    return_trace (ret);
    183  }
    184 };
    185 
    186 }
    187 }
    188 }
    189 
    190 #endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH */