Coverage Report

Created: 2025-07-12 07:03

/src/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh
Line
Count
Source (jump to first uncovered line)
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
382
  {
15
382
    TRACE_SANITIZE (this);
16
382
    return_trace (Array16Of<MarkRecord>::sanitize (c, this));
17
382
  }
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
0
  {
24
0
    TRACE_APPLY (this);
25
0
    hb_buffer_t *buffer = c->buffer;
26
0
    const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
27
0
    unsigned int mark_class = record.klass;
28
29
0
    const Anchor& mark_anchor = this + record.markAnchor;
30
0
    bool found;
31
0
    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
0
    if (unlikely (!found)) return_trace (false);
35
36
0
    float mark_x, mark_y, base_x, base_y;
37
38
0
    buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
39
0
    mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
40
0
    glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
41
42
0
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
43
0
    {
44
0
      c->buffer->message (c->font,
45
0
        "attaching mark glyph at %u to glyph at %u",
46
0
        c->buffer->idx, glyph_pos);
47
0
    }
48
49
0
    hb_glyph_position_t &o = buffer->cur_pos();
50
0
    o.x_offset = roundf (base_x - mark_x);
51
0
    o.y_offset = roundf (base_y - mark_y);
52
0
    o.attach_type() = ATTACH_TYPE_MARK;
53
0
    o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
54
0
    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
55
56
0
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
57
0
    {
58
0
      c->buffer->message (c->font,
59
0
        "attached mark glyph at %u to glyph at %u",
60
0
        c->buffer->idx, glyph_pos);
61
0
    }
62
63
0
    buffer->idx++;
64
0
    return_trace (true);
65
0
  }
66
67
  template <typename Iterator,
68
      hb_requires (hb_is_iterator (Iterator))>
69
  bool subset (hb_subset_context_t *c,
70
               Iterator             coverage,
71
               const hb_map_t      *klass_mapping) const
72
0
  {
73
0
    TRACE_SUBSET (this);
74
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
75
0
76
0
    auto* out = c->serializer->start_embed (this);
77
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
78
0
79
0
    auto mark_iter =
80
0
    + hb_zip (coverage, this->iter ())
81
0
    | hb_filter (glyphset, hb_first)
82
0
    | hb_map (hb_second)
83
0
    ;
84
0
85
0
    bool ret = false;
86
0
    unsigned new_length = 0;
87
0
    for (const auto& mark_record : mark_iter) {
88
0
      ret |= mark_record.subset (c, this, klass_mapping);
89
0
      new_length++;
90
0
    }
91
0
92
0
    if (unlikely (!c->serializer->check_assign (out->len, new_length,
93
0
                                                HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
94
0
      return_trace (false);
95
0
96
0
    return_trace (ret);
97
0
  }
98
};
99
100
HB_INTERNAL inline
101
void Markclass_closure_and_remap_indexes (const Coverage  &mark_coverage,
102
                                          const MarkArray &mark_array,
103
                                          const hb_set_t  &glyphset,
104
                                          hb_map_t*        klass_mapping /* INOUT */)
105
0
{
106
0
  hb_set_t orig_classes;
107
0
108
0
  + hb_zip (mark_coverage, mark_array)
109
0
  | hb_filter (glyphset, hb_first)
110
0
  | hb_map (hb_second)
111
0
  | hb_map (&MarkRecord::get_class)
112
0
  | hb_sink (orig_classes)
113
0
  ;
114
0
115
0
  unsigned idx = 0;
116
0
  for (auto klass : orig_classes.iter ())
117
0
  {
118
0
    if (klass_mapping->has (klass)) continue;
119
0
    klass_mapping->set (klass, idx);
120
0
    idx++;
121
0
  }
122
0
}
123
124
}
125
}
126
}
127
128
#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */