1 #ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
2 #define OT_LAYOUT_GPOS_MARKARRAY_HH
4 #include "AnchorMatrix.hh"
5 #include "MarkRecord.hh"
11 struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
13 bool sanitize (hb_sanitize_context_t *c) const
15 TRACE_SANITIZE (this);
16 return_trace (Array16Of<MarkRecord>::sanitize (c, this));
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
25 hb_buffer_t *buffer = c->buffer;
26 const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
27 unsigned int mark_class = record.klass;
29 const Anchor& mark_anchor = this + record.markAnchor;
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);
36 float mark_x, mark_y, base_x, base_y;
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);
42 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
44 c->buffer->message (c->font,
45 "attaching mark glyph at %u to glyph at %u",
46 c->buffer->idx, glyph_pos);
49 hb_glyph_position_t &o = buffer->cur_pos();
50 o.x_offset = roundf (base_x - mark_x);
51 o.y_offset = roundf (base_y - mark_y);
52 o.attach_type() = ATTACH_TYPE_MARK;
53 o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
54 buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
56 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
58 c->buffer->message (c->font,
59 "attached mark glyph at %u to glyph at %u",
60 c->buffer->idx, glyph_pos);
67 template <typename Iterator,
68 hb_requires (hb_is_iterator (Iterator))>
69 bool subset (hb_subset_context_t *c,
71 const hb_map_t *klass_mapping) const
74 const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
76 auto* out = c->serializer->start_embed (this);
77 if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
80 + hb_zip (coverage, this->iter ())
81 | hb_filter (glyphset, hb_first)
86 unsigned new_length = 0;
87 for (const auto& mark_record : mark_iter) {
88 ret |= mark_record.subset (c, this, klass_mapping);
92 if (unlikely (!c->serializer->check_assign (out->len, new_length,
93 HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
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 */)
106 hb_set_t orig_classes;
108 + hb_zip (mark_coverage, mark_array)
109 | hb_filter (glyphset, hb_first)
111 | hb_map (&MarkRecord::get_class)
112 | hb_sink (orig_classes)
116 for (auto klass : orig_classes.iter ())
118 if (klass_mapping->has (klass)) continue;
119 klass_mapping->set (klass, idx);
128 #endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */