/src/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
Line | Count | Source |
1 | | #ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH |
2 | | #define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH |
3 | | |
4 | | #include "MarkMarkPosFormat1.hh" |
5 | | |
6 | | namespace OT { |
7 | | namespace Layout { |
8 | | namespace GPOS_impl { |
9 | | |
10 | | template <typename Types> |
11 | | struct MarkMarkPosFormat1_2 |
12 | | { |
13 | | protected: |
14 | | HBUINT16 format; /* Format identifier--format = 1 */ |
15 | | typename Types::template LOffsetTo<Coverage> |
16 | | mark1Coverage; /* Offset to Combining Mark1 Coverage |
17 | | * table--from beginning of MarkMarkPos |
18 | | * subtable */ |
19 | | typename Types::template LOffsetTo<Coverage> |
20 | | mark2Coverage; /* Offset to Combining Mark2 Coverage |
21 | | * table--from beginning of MarkMarkPos |
22 | | * subtable */ |
23 | | HBUINT16 classCount; /* Number of defined mark classes */ |
24 | | typename Types::template LOffsetTo<MarkArray<Types>> |
25 | | mark1Array; /* Offset to Mark1Array table--from |
26 | | * beginning of MarkMarkPos subtable */ |
27 | | typename Types::template LOffsetTo<AnchorMatrix<Types, HBUINT16>> |
28 | | mark2Array; /* Offset to Mark2Array table--from |
29 | | * beginning of MarkMarkPos subtable */ |
30 | | public: |
31 | | DEFINE_SIZE_STATIC (4 + 4 * Types::LOffset::static_size); |
32 | | |
33 | | bool sanitize (hb_sanitize_context_t *c) const |
34 | 0 | { |
35 | 0 | TRACE_SANITIZE (this); |
36 | 0 | return_trace (c->check_struct (this) && |
37 | 0 | mark1Coverage.sanitize (c, this) && |
38 | 0 | mark2Coverage.sanitize (c, this) && |
39 | 0 | mark1Array.sanitize (c, this) && |
40 | 0 | hb_barrier () && |
41 | 0 | mark2Array.sanitize (c, this, (unsigned int) classCount)); |
42 | 0 | } Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::sanitize(hb_sanitize_context_t*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::sanitize(hb_sanitize_context_t*) const |
43 | | |
44 | | bool intersects (const hb_set_t *glyphs) const |
45 | 0 | { |
46 | 0 | return (this+mark1Coverage).intersects (glyphs) && |
47 | 0 | (this+mark2Coverage).intersects (glyphs); |
48 | 0 | } Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::intersects(hb_set_t const*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::intersects(hb_set_t const*) const |
49 | | |
50 | 0 | void closure_lookups (hb_closure_lookups_context_t *c) const {}Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::closure_lookups(OT::hb_closure_lookups_context_t*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::closure_lookups(OT::hb_closure_lookups_context_t*) const |
51 | | |
52 | | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
53 | 0 | { |
54 | 0 | (this+mark1Array).collect_variation_indices (c, this+mark1Coverage); |
55 | |
|
56 | 0 | hb_map_t klass_mapping; |
57 | 0 | Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping); |
58 | |
|
59 | 0 | hb_sorted_vector_t<unsigned> mark2_indexes; |
60 | 0 | collect_anchor_indexes (this+mark2Coverage, (this+mark2Array).rows, |
61 | 0 | classCount, *c->glyph_set, klass_mapping, |
62 | 0 | mark2_indexes); |
63 | 0 | (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ()); |
64 | 0 | } Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const |
65 | | |
66 | | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
67 | 0 | { |
68 | 0 | if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return; |
69 | 0 | if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return; |
70 | 0 | } Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::collect_glyphs(OT::hb_collect_glyphs_context_t*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::collect_glyphs(OT::hb_collect_glyphs_context_t*) const |
71 | | |
72 | | void collect_second_glyphs (hb_set_digest_t *digest) const |
73 | 0 | { (this+mark2Coverage).collect_coverage (digest); }Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::collect_second_glyphs(hb_set_digest_t*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::collect_second_glyphs(hb_set_digest_t*) const |
74 | | |
75 | 0 | const Coverage &get_coverage () const { return this+mark1Coverage; }Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::get_coverage() const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::get_coverage() const |
76 | | |
77 | | bool apply (hb_ot_apply_context_t *c) const |
78 | 0 | { |
79 | 0 | TRACE_APPLY (this); |
80 | 0 | hb_buffer_t *buffer = c->buffer; |
81 | 0 | unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint); |
82 | 0 | if (likely (mark1_index == NOT_COVERED)) return_trace (false); |
83 | | |
84 | | /* now we search backwards for a suitable mark glyph until a non-mark glyph */ |
85 | 0 | auto &skippy_iter = c->iter_input; |
86 | 0 | skippy_iter.reset_fast (buffer->idx); |
87 | 0 | skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags); |
88 | 0 | unsigned unsafe_from; |
89 | 0 | if (unlikely (!skippy_iter.prev (&unsafe_from))) |
90 | 0 | { |
91 | 0 | buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); |
92 | 0 | return_trace (false); |
93 | 0 | } |
94 | | |
95 | 0 | if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))) |
96 | 0 | { |
97 | 0 | buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); |
98 | 0 | return_trace (false); |
99 | 0 | } |
100 | | |
101 | 0 | unsigned int j = skippy_iter.idx; |
102 | |
|
103 | 0 | unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur()); |
104 | 0 | unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]); |
105 | 0 | unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur()); |
106 | 0 | unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]); |
107 | |
|
108 | 0 | if (likely (id1 == id2)) |
109 | 0 | { |
110 | 0 | if (id1 == 0) /* Marks belonging to the same base. */ |
111 | 0 | goto good; |
112 | 0 | else if (comp1 == comp2) /* Marks belonging to the same ligature component. */ |
113 | 0 | goto good; |
114 | 0 | } |
115 | 0 | else |
116 | 0 | { |
117 | | /* If ligature ids don't match, it may be the case that one of the marks |
118 | | * itself is a ligature. In which case match. */ |
119 | 0 | if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2)) |
120 | 0 | goto good; |
121 | 0 | } |
122 | | |
123 | | /* Didn't match. */ |
124 | 0 | buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); |
125 | 0 | return_trace (false); |
126 | | |
127 | 0 | good: |
128 | 0 | unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint); |
129 | 0 | if (mark2_index == NOT_COVERED) |
130 | 0 | { |
131 | 0 | buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); |
132 | 0 | return_trace (false); |
133 | 0 | } |
134 | | |
135 | 0 | return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); |
136 | 0 | } Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::apply(OT::hb_ot_apply_context_t*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::apply(OT::hb_ot_apply_context_t*) const |
137 | | |
138 | | bool subset (hb_subset_context_t *c) const |
139 | 0 | { |
140 | 0 | TRACE_SUBSET (this); |
141 | 0 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
142 | 0 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
143 | |
|
144 | 0 | auto *out = c->serializer->start_embed (*this); |
145 | 0 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
146 | 0 | out->format = format; |
147 | |
|
148 | 0 | hb_map_t klass_mapping; |
149 | 0 | Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping); |
150 | |
|
151 | 0 | if (!klass_mapping.get_population ()) return_trace (false); |
152 | 0 | out->classCount = klass_mapping.get_population (); |
153 | |
|
154 | 0 | auto mark1_iter = |
155 | 0 | + hb_zip (this+mark1Coverage, this+mark1Array) |
156 | 0 | | hb_filter (glyphset, hb_first) |
157 | 0 | ; |
158 | |
|
159 | 0 | hb_sorted_vector_t<hb_codepoint_t> new_coverage; |
160 | 0 | + mark1_iter |
161 | 0 | | hb_map (hb_first) |
162 | 0 | | hb_map (glyph_map) |
163 | 0 | | hb_sink (new_coverage) |
164 | 0 | ; |
165 | |
|
166 | 0 | if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) |
167 | 0 | return_trace (false); |
168 | | |
169 | 0 | if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this, |
170 | 0 | (this+mark1Coverage).iter (), |
171 | 0 | &klass_mapping))) |
172 | 0 | return_trace (false); |
173 | | |
174 | 0 | new_coverage.reset (); |
175 | 0 | hb_sorted_vector_t<unsigned> mark2_indexes; |
176 | 0 | const auto &mark2_array = this+mark2Array; |
177 | 0 | collect_subset_anchor_indexes (this+mark2Coverage, mark2_array.rows, |
178 | 0 | classCount, mark2_array.matrixZ.arrayZ, |
179 | 0 | glyphset, glyph_map, klass_mapping, |
180 | 0 | new_coverage, mark2_indexes); |
181 | |
|
182 | 0 | if (!new_coverage) return_trace (false); |
183 | 0 | if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) |
184 | 0 | return_trace (false); |
185 | | |
186 | 0 | return_trace (out->mark2Array.serialize_subset (c, mark2Array, this, |
187 | 0 | new_coverage.length, |
188 | 0 | mark2_indexes.iter ())); |
189 | |
|
190 | 0 | } Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::subset(hb_subset_context_t*) const Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::subset(hb_subset_context_t*) const |
191 | | }; |
192 | | |
193 | | |
194 | | } |
195 | | } |
196 | | } |
197 | | |
198 | | #endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */ |