/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 */ |