Coverage Report

Created: 2025-12-04 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh
Line
Count
Source
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
209
  {
15
209
    TRACE_SANITIZE (this);
16
209
    return_trace (Array16Of<MarkRecord>::sanitize (c, this));
17
209
  }
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.attach_chain() = (int) glyph_pos - (int) buffer->idx;
51
0
    if (o.attach_chain() != (int) glyph_pos - (int) buffer->idx)
52
0
    {
53
0
      o.attach_chain() = 0;
54
0
      goto overflow;
55
0
    }
56
0
    o.attach_type() = ATTACH_TYPE_MARK;
57
0
    o.x_offset = roundf (base_x - mark_x);
58
0
    o.y_offset = roundf (base_y - mark_y);
59
0
    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
60
61
0
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
62
0
    {
63
0
      c->buffer->message (c->font,
64
0
        "attached mark glyph at %u to glyph at %u",
65
0
        c->buffer->idx, glyph_pos);
66
0
    }
67
68
0
  overflow:
69
0
    buffer->idx++;
70
0
    return_trace (true);
71
0
  }
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
0
  {
79
0
    TRACE_SUBSET (this);
80
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
81
0
82
0
    auto* out = c->serializer->start_embed (this);
83
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
84
0
85
0
    auto mark_iter =
86
0
    + hb_zip (coverage, this->iter ())
87
0
    | hb_filter (glyphset, hb_first)
88
0
    | hb_map (hb_second)
89
0
    ;
90
0
91
0
    bool ret = false;
92
0
    unsigned new_length = 0;
93
0
    for (const auto& mark_record : mark_iter) {
94
0
      ret |= mark_record.subset (c, this, klass_mapping);
95
0
      new_length++;
96
0
    }
97
0
98
0
    if (unlikely (!c->serializer->check_assign (out->len, new_length,
99
0
                                                HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
100
0
      return_trace (false);
101
0
102
0
    return_trace (ret);
103
0
  }
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
0
{
112
0
  hb_set_t orig_classes;
113
0
114
0
  + hb_zip (mark_coverage, mark_array)
115
0
  | hb_filter (glyphset, hb_first)
116
0
  | hb_map (hb_second)
117
0
  | hb_map (&MarkRecord::get_class)
118
0
  | hb_sink (orig_classes)
119
0
  ;
120
0
121
0
  unsigned idx = 0;
122
0
  for (auto klass : orig_classes.iter ())
123
0
  {
124
0
    if (klass_mapping->has (klass)) continue;
125
0
    klass_mapping->set (klass, idx);
126
0
    idx++;
127
0
  }
128
0
}
129
130
}
131
}
132
}
133
134
#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */