tor-browser

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

MarkArray.hh (4044B)


      1 #ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
      2 #define OT_LAYOUT_GPOS_MARKARRAY_HH
      3 
      4 #include "AnchorMatrix.hh"
      5 #include "MarkRecord.hh"
      6 
      7 namespace OT {
      8 namespace Layout {
      9 namespace GPOS_impl {
     10 
     11 struct MarkArray : Array16Of<MarkRecord>        /* Array of MarkRecords--in Coverage order */
     12 {
     13  bool sanitize (hb_sanitize_context_t *c) const
     14  {
     15    TRACE_SANITIZE (this);
     16    return_trace (Array16Of<MarkRecord>::sanitize (c, this));
     17  }
     18 
     19  bool apply (hb_ot_apply_context_t *c,
     20              unsigned int mark_index, unsigned int glyph_index,
     21              const AnchorMatrix &anchors, unsigned int class_count,
     22              unsigned int glyph_pos) const
     23  {
     24    TRACE_APPLY (this);
     25    hb_buffer_t *buffer = c->buffer;
     26    const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
     27    unsigned int mark_class = record.klass;
     28 
     29    const Anchor& mark_anchor = this + record.markAnchor;
     30    bool found;
     31    const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found);
     32    /* If this subtable doesn't have an anchor for this base and this class,
     33     * return false such that the subsequent subtables have a chance at it. */
     34    if (unlikely (!found)) return_trace (false);
     35 
     36    float mark_x, mark_y, base_x, base_y;
     37 
     38    buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
     39    mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
     40    glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
     41 
     42    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     43    {
     44      c->buffer->message (c->font,
     45 		  "attaching mark glyph at %u to glyph at %u",
     46 		  c->buffer->idx, glyph_pos);
     47    }
     48 
     49    hb_glyph_position_t &o = buffer->cur_pos();
     50    o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
     51    if (o.attach_chain() != (int) glyph_pos - (int) buffer->idx)
     52    {
     53      o.attach_chain() = 0;
     54      goto overflow;
     55    }
     56    o.attach_type() = ATTACH_TYPE_MARK;
     57    o.x_offset = roundf (base_x - mark_x);
     58    o.y_offset = roundf (base_y - mark_y);
     59    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
     60 
     61    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     62    {
     63      c->buffer->message (c->font,
     64 		  "attached mark glyph at %u to glyph at %u",
     65 		  c->buffer->idx, glyph_pos);
     66    }
     67 
     68  overflow:
     69    buffer->idx++;
     70    return_trace (true);
     71  }
     72 
     73  template <typename Iterator,
     74      hb_requires (hb_is_iterator (Iterator))>
     75  bool subset (hb_subset_context_t *c,
     76               Iterator             coverage,
     77               const hb_map_t      *klass_mapping) const
     78  {
     79    TRACE_SUBSET (this);
     80    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
     81 
     82    auto* out = c->serializer->start_embed (this);
     83    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
     84 
     85    auto mark_iter =
     86    + hb_zip (coverage, this->iter ())
     87    | hb_filter (glyphset, hb_first)
     88    | hb_map (hb_second)
     89    ;
     90 
     91    bool ret = false;
     92    unsigned new_length = 0;
     93    for (const auto& mark_record : mark_iter) {
     94      ret |= mark_record.subset (c, this, klass_mapping);
     95      new_length++;
     96    }
     97 
     98    if (unlikely (!c->serializer->check_assign (out->len, new_length,
     99                                                HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
    100      return_trace (false);
    101 
    102    return_trace (ret);
    103  }
    104 };
    105 
    106 HB_INTERNAL inline
    107 void Markclass_closure_and_remap_indexes (const Coverage  &mark_coverage,
    108                                          const MarkArray &mark_array,
    109                                          const hb_set_t  &glyphset,
    110                                          hb_map_t*        klass_mapping /* INOUT */)
    111 {
    112  hb_set_t orig_classes;
    113 
    114  + hb_zip (mark_coverage, mark_array)
    115  | hb_filter (glyphset, hb_first)
    116  | hb_map (hb_second)
    117  | hb_map (&MarkRecord::get_class)
    118  | hb_sink (orig_classes)
    119  ;
    120 
    121  unsigned idx = 0;
    122  for (auto klass : orig_classes.iter ())
    123  {
    124    if (klass_mapping->has (klass)) continue;
    125    klass_mapping->set (klass, idx);
    126    idx++;
    127  }
    128 }
    129 
    130 }
    131 }
    132 }
    133 
    134 #endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */