tor-browser

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

SinglePosFormat2.hh (7286B)


      1 #ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
      2 #define OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
      3 
      4 #include "Common.hh"
      5 
      6 namespace OT {
      7 namespace Layout {
      8 namespace GPOS_impl {
      9 
     10 struct SinglePosFormat2 : ValueBase
     11 {
     12  protected:
     13  HBUINT16      format;                 /* Format identifier--format = 2 */
     14  Offset16To<Coverage>
     15                coverage;               /* Offset to Coverage table--from
     16                                         * beginning of subtable */
     17  ValueFormat   valueFormat;            /* Defines the types of data in the
     18                                         * ValueRecord */
     19  HBUINT16      valueCount;             /* Number of ValueRecords */
     20  ValueRecord   values;                 /* Array of ValueRecords--positioning
     21                                         * values applied to glyphs */
     22  public:
     23  DEFINE_SIZE_ARRAY (8, values);
     24 
     25  bool sanitize (hb_sanitize_context_t *c) const
     26  {
     27    TRACE_SANITIZE (this);
     28    return_trace (c->check_struct (this) &&
     29                  coverage.sanitize (c, this) &&
     30                  valueFormat.sanitize_values (c, this, values, valueCount));
     31  }
     32 
     33  bool intersects (const hb_set_t *glyphs) const
     34  { return (this+coverage).intersects (glyphs); }
     35 
     36  void closure_lookups (hb_closure_lookups_context_t *c) const {}
     37  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
     38  {
     39    if (!valueFormat.has_device ()) return;
     40 
     41    auto it =
     42    + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
     43    | hb_filter (c->glyph_set, hb_first)
     44    ;
     45 
     46    if (!it) return;
     47 
     48    unsigned sub_length = valueFormat.get_len ();
     49    const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
     50 
     51    for (unsigned i : + it
     52                      | hb_map (hb_second))
     53      valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
     54 
     55  }
     56 
     57  void collect_glyphs (hb_collect_glyphs_context_t *c) const
     58  { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
     59 
     60  const Coverage &get_coverage () const { return this+coverage; }
     61 
     62  ValueFormat get_value_format () const { return valueFormat; }
     63 
     64  bool apply (hb_ot_apply_context_t *c) const
     65  {
     66    TRACE_APPLY (this);
     67    hb_buffer_t *buffer = c->buffer;
     68    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     69    if (index == NOT_COVERED) return_trace (false);
     70 
     71    if (unlikely (index >= valueCount)) return_trace (false);
     72 
     73    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     74    {
     75      c->buffer->message (c->font,
     76 		  "positioning glyph at %u",
     77 		  c->buffer->idx);
     78    }
     79 
     80    valueFormat.apply_value (c, this,
     81                             &values[index * valueFormat.get_len ()],
     82                             buffer->cur_pos());
     83 
     84    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     85    {
     86      c->buffer->message (c->font,
     87 		  "positioned glyph at %u",
     88 		  c->buffer->idx);
     89    }
     90 
     91    buffer->idx++;
     92    return_trace (true);
     93  }
     94 
     95  bool
     96  position_single (hb_font_t           *font,
     97 	   hb_blob_t           *table_blob,
     98 	   hb_direction_t       direction,
     99 	   hb_codepoint_t       gid,
    100 	   hb_glyph_position_t &pos) const
    101  {
    102    unsigned int index = (this+coverage).get_coverage  (gid);
    103    if (likely (index == NOT_COVERED)) return false;
    104    if (unlikely (index >= valueCount)) return false;
    105 
    106    /* This is ugly... */
    107    hb_buffer_t buffer;
    108    buffer.props.direction = direction;
    109    OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
    110 
    111    valueFormat.apply_value (&c, this,
    112                             &values[index * valueFormat.get_len ()],
    113                             pos);
    114    return true;
    115  }
    116 
    117 
    118  template<typename Iterator,
    119      typename SrcLookup,
    120      hb_requires (hb_is_iterator (Iterator))>
    121  void serialize (hb_serialize_context_t *c,
    122                  const SrcLookup *src,
    123                  Iterator it,
    124                  ValueFormat newFormat,
    125                  const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
    126  {
    127    auto out = c->extend_min (this);
    128    if (unlikely (!out)) return;
    129    if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
    130    if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
    131 
    132    + it
    133    | hb_map (hb_second)
    134    | hb_apply ([&] (hb_array_t<const Value> _)
    135    { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); })
    136    ;
    137 
    138    auto glyphs =
    139    + it
    140    | hb_map_retains_sorting (hb_first)
    141    ;
    142 
    143    coverage.serialize_serialize (c, glyphs);
    144  }
    145 
    146  template<typename Iterator,
    147      hb_requires (hb_is_iterator (Iterator))>
    148  unsigned compute_effective_format (const hb_face_t *face,
    149                                     Iterator it,
    150                                     bool is_instancing, bool strip_hints,
    151                                     bool has_gdef_varstore,
    152                                     const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const
    153  {
    154    hb_blob_t* blob = hb_face_reference_table (face, HB_TAG ('f','v','a','r'));
    155    bool has_fvar = (blob != hb_blob_get_empty ());
    156    hb_blob_destroy (blob);
    157 
    158    unsigned new_format = 0;
    159    if (is_instancing)
    160    {
    161      new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), false, false, this, varidx_delta_map);
    162    }
    163    /* do not strip hints for VF */
    164    else if (strip_hints)
    165    {
    166      bool strip = !has_fvar;
    167      if (has_fvar && !has_gdef_varstore)
    168        strip = true;
    169      new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), strip, true, this, nullptr);
    170    }
    171    else
    172      new_format = valueFormat;
    173 
    174    return new_format;
    175  }
    176 
    177  bool subset (hb_subset_context_t *c) const
    178  {
    179    TRACE_SUBSET (this);
    180    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
    181    const hb_map_t &glyph_map = *c->plan->glyph_map;
    182 
    183    unsigned sub_length = valueFormat.get_len ();
    184    auto values_array = values.as_array (valueCount * sub_length);
    185 
    186    auto it =
    187    + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
    188    | hb_filter (glyphset, hb_first)
    189    | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
    190                              {
    191                                return hb_pair (glyph_map[_.first],
    192                                                values_array.sub_array (_.second * sub_length,
    193                                                                        sub_length));
    194                              })
    195    ;
    196 
    197    unsigned new_format = compute_effective_format (c->plan->source, it,
    198                                                    bool (c->plan->normalized_coords),
    199                                                    bool (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
    200                                                    c->plan->has_gdef_varstore,
    201                                                    &c->plan->layout_variation_idx_delta_map);
    202    bool ret = bool (it);
    203    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
    204    return_trace (ret);
    205  }
    206 };
    207 
    208 
    209 }
    210 }
    211 }
    212 
    213 #endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH */