• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
sanitizeOT::Layout::GPOS_impl::MarkArray13   bool sanitize (hb_sanitize_context_t *c) const
14   {
15     TRACE_SANITIZE (this);
16     return_trace (Array16Of<MarkRecord>::sanitize (c, this));
17   }
18 
applyOT::Layout::GPOS_impl::MarkArray19   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 (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 %d to glyph at %d",
46 			  c->buffer->idx, glyph_pos);
47     }
48 
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;
55 
56     if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
57     {
58       c->buffer->message (c->font,
59 			  "attached mark glyph at %d to glyph at %d",
60 			  c->buffer->idx, glyph_pos);
61     }
62 
63     buffer->idx++;
64     return_trace (true);
65   }
66 
67   template <typename Iterator,
68       hb_requires (hb_is_iterator (Iterator))>
subsetOT::Layout::GPOS_impl::MarkArray69   bool subset (hb_subset_context_t *c,
70                Iterator             coverage,
71                const hb_map_t      *klass_mapping) const
72   {
73     TRACE_SUBSET (this);
74     const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
75 
76     auto* out = c->serializer->start_embed (this);
77     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
78 
79     auto mark_iter =
80     + hb_zip (coverage, this->iter ())
81     | hb_filter (glyphset, hb_first)
82     | hb_map (hb_second)
83     ;
84 
85     unsigned new_length = 0;
86     for (const auto& mark_record : mark_iter) {
87       if (unlikely (!mark_record.subset (c, this, klass_mapping)))
88         return_trace (false);
89       new_length++;
90     }
91 
92     if (unlikely (!c->serializer->check_assign (out->len, new_length,
93                                                 HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
94       return_trace (false);
95 
96     return_trace (true);
97   }
98 };
99 
100 HB_INTERNAL inline
Markclass_closure_and_remap_indexes(const Coverage & mark_coverage,const MarkArray & mark_array,const hb_set_t & glyphset,hb_map_t * klass_mapping)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 {
106   hb_set_t orig_classes;
107 
108   + hb_zip (mark_coverage, mark_array)
109   | hb_filter (glyphset, hb_first)
110   | hb_map (hb_second)
111   | hb_map (&MarkRecord::get_class)
112   | hb_sink (orig_classes)
113   ;
114 
115   unsigned idx = 0;
116   for (auto klass : orig_classes.iter ())
117   {
118     if (klass_mapping->has (klass)) continue;
119     klass_mapping->set (klass, idx);
120     idx++;
121   }
122 }
123 
124 }
125 }
126 }
127 
128 #endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */
129