/src/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
Line | Count | Source |
1 | | #ifndef OT_LAYOUT_GSUB_SEQUENCE_HH |
2 | | #define OT_LAYOUT_GSUB_SEQUENCE_HH |
3 | | |
4 | | #include "Common.hh" |
5 | | |
6 | | namespace OT { |
7 | | namespace Layout { |
8 | | namespace GSUB_impl { |
9 | | |
10 | | template <typename Types> |
11 | | struct Sequence |
12 | | { |
13 | | protected: |
14 | | Array16Of<typename Types::HBGlyphID> |
15 | | substitute; /* String of GlyphIDs to substitute */ |
16 | | public: |
17 | | DEFINE_SIZE_ARRAY (2, substitute); |
18 | | |
19 | | bool sanitize (hb_sanitize_context_t *c) const |
20 | 48.1k | { |
21 | 48.1k | TRACE_SANITIZE (this); |
22 | 48.1k | return_trace (substitute.sanitize (c)); |
23 | 48.1k | } OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 20 | 47.8k | { | 21 | 47.8k | TRACE_SANITIZE (this); | 22 | 47.8k | return_trace (substitute.sanitize (c)); | 23 | 47.8k | } |
OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 20 | 385 | { | 21 | 385 | TRACE_SANITIZE (this); | 22 | 385 | return_trace (substitute.sanitize (c)); | 23 | 385 | } |
|
24 | | |
25 | | bool intersects (const hb_set_t *glyphs) const |
26 | 0 | { return hb_all (substitute, glyphs); }Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>::intersects(hb_set_t const*) const Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>::intersects(hb_set_t const*) const |
27 | | |
28 | | void closure (hb_closure_context_t *c) const |
29 | 0 | { |
30 | 0 | if (unlikely (!c->spend_budget (HB_BUDGET_1, substitute.len))) return; |
31 | 0 | c->output->add_array (substitute.arrayZ, substitute.len); |
32 | 0 | } Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>::closure(OT::hb_closure_context_t*) const Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>::closure(OT::hb_closure_context_t*) const |
33 | | |
34 | | void depend (hb_depend_context_t *c, hb_codepoint_t source) const |
35 | 0 | { |
36 | 0 | + hb_iter (substitute) |
37 | 0 | | hb_apply ([&] (const hb_codepoint_t &target) { c->depend_data->add_gsub_lookup (source, c->lookup_index, target); }) |
38 | 0 | ; |
39 | 0 | } Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>::depend(OT::hb_depend_context_t*, unsigned int) const Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>::depend(OT::hb_depend_context_t*, unsigned int) const |
40 | | |
41 | | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
42 | 0 | { c->output->add_array (substitute.arrayZ, substitute.len); }Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>::collect_glyphs(OT::hb_collect_glyphs_context_t*) const Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>::collect_glyphs(OT::hb_collect_glyphs_context_t*) const |
43 | | |
44 | | bool apply (hb_ot_apply_context_t *c) const |
45 | 4.51M | { |
46 | 4.51M | TRACE_APPLY (this); |
47 | 4.51M | unsigned int count = substitute.len; |
48 | | |
49 | | /* Special-case to make it in-place and not consider this |
50 | | * as a "multiplied" substitution. */ |
51 | 4.51M | if (unlikely (count == 1)) |
52 | 1.67k | { |
53 | 1.67k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) |
54 | 0 | { |
55 | 0 | c->buffer->sync_so_far (); |
56 | 0 | c->buffer->message (c->font, |
57 | 0 | "replacing glyph at %u (multiple substitution)", |
58 | 0 | c->buffer->idx); |
59 | 0 | } |
60 | | |
61 | 1.67k | c->replace_glyph (substitute.arrayZ[0]); |
62 | | |
63 | 1.67k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) |
64 | 0 | { |
65 | 0 | c->buffer->message (c->font, |
66 | 0 | "replaced glyph at %u (multiple substitution)", |
67 | 0 | c->buffer->idx - 1u); |
68 | 0 | } |
69 | | |
70 | 1.67k | return_trace (true); |
71 | 1.67k | } |
72 | | /* Spec disallows this, but Uniscribe allows it. |
73 | | * https://github.com/harfbuzz/harfbuzz/issues/253 */ |
74 | 4.51M | else if (unlikely (count == 0)) |
75 | 1.77M | { |
76 | 1.77M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) |
77 | 0 | { |
78 | 0 | c->buffer->sync_so_far (); |
79 | 0 | c->buffer->message (c->font, |
80 | 0 | "deleting glyph at %u (multiple substitution)", |
81 | 0 | c->buffer->idx); |
82 | 0 | } |
83 | | |
84 | 1.77M | c->buffer->delete_glyph (); |
85 | | |
86 | 1.77M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) |
87 | 0 | { |
88 | 0 | c->buffer->sync_so_far (); |
89 | 0 | c->buffer->message (c->font, |
90 | 0 | "deleted glyph at %u (multiple substitution)", |
91 | 0 | c->buffer->idx); |
92 | 0 | } |
93 | | |
94 | 1.77M | return_trace (true); |
95 | 1.77M | } |
96 | | |
97 | 2.73M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) |
98 | 0 | { |
99 | 0 | c->buffer->sync_so_far (); |
100 | 0 | c->buffer->message (c->font, |
101 | 0 | "multiplying glyph at %u", |
102 | 0 | c->buffer->idx); |
103 | 0 | } |
104 | | |
105 | 2.73M | unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? |
106 | 2.71M | HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; |
107 | 2.73M | unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur()); |
108 | | |
109 | 72.9M | for (unsigned int i = 0; i < count; i++) |
110 | 70.1M | { |
111 | | /* If is attached to a ligature, don't disturb that. |
112 | | * https://github.com/harfbuzz/harfbuzz/issues/3069 */ |
113 | 70.1M | if (!lig_id) |
114 | 68.8M | _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); |
115 | 70.1M | c->output_glyph_for_component (substitute.arrayZ[i], klass); |
116 | 70.1M | } |
117 | 2.73M | c->buffer->skip_glyph (); |
118 | | |
119 | 2.73M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) |
120 | 0 | { |
121 | 0 | c->buffer->sync_so_far (); |
122 | |
|
123 | 0 | char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0}; |
124 | 0 | char *p = buf; |
125 | |
|
126 | 0 | for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++) |
127 | 0 | { |
128 | 0 | if (buf < p && sizeof(buf) - 1u > unsigned (p - buf)) |
129 | 0 | *p++ = ','; |
130 | 0 | snprintf (p, sizeof(buf) - (p - buf), "%u", i); |
131 | 0 | p += strlen(p); |
132 | 0 | } |
133 | |
|
134 | 0 | c->buffer->message (c->font, |
135 | 0 | "multiplied glyphs at %s", |
136 | 0 | buf); |
137 | 0 | } |
138 | | |
139 | 2.73M | return_trace (true); |
140 | 4.51M | } OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>::apply(OT::hb_ot_apply_context_t*) const Line | Count | Source | 45 | 4.50M | { | 46 | 4.50M | TRACE_APPLY (this); | 47 | 4.50M | unsigned int count = substitute.len; | 48 | | | 49 | | /* Special-case to make it in-place and not consider this | 50 | | * as a "multiplied" substitution. */ | 51 | 4.50M | if (unlikely (count == 1)) | 52 | 666 | { | 53 | 666 | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 54 | 0 | { | 55 | 0 | c->buffer->sync_so_far (); | 56 | 0 | c->buffer->message (c->font, | 57 | 0 | "replacing glyph at %u (multiple substitution)", | 58 | 0 | c->buffer->idx); | 59 | 0 | } | 60 | | | 61 | 666 | c->replace_glyph (substitute.arrayZ[0]); | 62 | | | 63 | 666 | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 64 | 0 | { | 65 | 0 | c->buffer->message (c->font, | 66 | 0 | "replaced glyph at %u (multiple substitution)", | 67 | 0 | c->buffer->idx - 1u); | 68 | 0 | } | 69 | | | 70 | 666 | return_trace (true); | 71 | 666 | } | 72 | | /* Spec disallows this, but Uniscribe allows it. | 73 | | * https://github.com/harfbuzz/harfbuzz/issues/253 */ | 74 | 4.50M | else if (unlikely (count == 0)) | 75 | 1.77M | { | 76 | 1.77M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 77 | 0 | { | 78 | 0 | c->buffer->sync_so_far (); | 79 | 0 | c->buffer->message (c->font, | 80 | 0 | "deleting glyph at %u (multiple substitution)", | 81 | 0 | c->buffer->idx); | 82 | 0 | } | 83 | | | 84 | 1.77M | c->buffer->delete_glyph (); | 85 | | | 86 | 1.77M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 87 | 0 | { | 88 | 0 | c->buffer->sync_so_far (); | 89 | 0 | c->buffer->message (c->font, | 90 | 0 | "deleted glyph at %u (multiple substitution)", | 91 | 0 | c->buffer->idx); | 92 | 0 | } | 93 | | | 94 | 1.77M | return_trace (true); | 95 | 1.77M | } | 96 | | | 97 | 2.73M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 98 | 0 | { | 99 | 0 | c->buffer->sync_so_far (); | 100 | 0 | c->buffer->message (c->font, | 101 | 0 | "multiplying glyph at %u", | 102 | 0 | c->buffer->idx); | 103 | 0 | } | 104 | | | 105 | 2.73M | unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? | 106 | 2.70M | HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; | 107 | 2.73M | unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur()); | 108 | | | 109 | 72.1M | for (unsigned int i = 0; i < count; i++) | 110 | 69.3M | { | 111 | | /* If is attached to a ligature, don't disturb that. | 112 | | * https://github.com/harfbuzz/harfbuzz/issues/3069 */ | 113 | 69.3M | if (!lig_id) | 114 | 68.0M | _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); | 115 | 69.3M | c->output_glyph_for_component (substitute.arrayZ[i], klass); | 116 | 69.3M | } | 117 | 2.73M | c->buffer->skip_glyph (); | 118 | | | 119 | 2.73M | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 120 | 0 | { | 121 | 0 | c->buffer->sync_so_far (); | 122 | |
| 123 | 0 | char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0}; | 124 | 0 | char *p = buf; | 125 | |
| 126 | 0 | for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++) | 127 | 0 | { | 128 | 0 | if (buf < p && sizeof(buf) - 1u > unsigned (p - buf)) | 129 | 0 | *p++ = ','; | 130 | 0 | snprintf (p, sizeof(buf) - (p - buf), "%u", i); | 131 | 0 | p += strlen(p); | 132 | 0 | } | 133 | |
| 134 | 0 | c->buffer->message (c->font, | 135 | 0 | "multiplied glyphs at %s", | 136 | 0 | buf); | 137 | 0 | } | 138 | | | 139 | 2.73M | return_trace (true); | 140 | 4.50M | } |
OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>::apply(OT::hb_ot_apply_context_t*) const Line | Count | Source | 45 | 7.11k | { | 46 | 7.11k | TRACE_APPLY (this); | 47 | 7.11k | unsigned int count = substitute.len; | 48 | | | 49 | | /* Special-case to make it in-place and not consider this | 50 | | * as a "multiplied" substitution. */ | 51 | 7.11k | if (unlikely (count == 1)) | 52 | 1.00k | { | 53 | 1.00k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 54 | 0 | { | 55 | 0 | c->buffer->sync_so_far (); | 56 | 0 | c->buffer->message (c->font, | 57 | 0 | "replacing glyph at %u (multiple substitution)", | 58 | 0 | c->buffer->idx); | 59 | 0 | } | 60 | | | 61 | 1.00k | c->replace_glyph (substitute.arrayZ[0]); | 62 | | | 63 | 1.00k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 64 | 0 | { | 65 | 0 | c->buffer->message (c->font, | 66 | 0 | "replaced glyph at %u (multiple substitution)", | 67 | 0 | c->buffer->idx - 1u); | 68 | 0 | } | 69 | | | 70 | 1.00k | return_trace (true); | 71 | 1.00k | } | 72 | | /* Spec disallows this, but Uniscribe allows it. | 73 | | * https://github.com/harfbuzz/harfbuzz/issues/253 */ | 74 | 6.11k | else if (unlikely (count == 0)) | 75 | 2.43k | { | 76 | 2.43k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 77 | 0 | { | 78 | 0 | c->buffer->sync_so_far (); | 79 | 0 | c->buffer->message (c->font, | 80 | 0 | "deleting glyph at %u (multiple substitution)", | 81 | 0 | c->buffer->idx); | 82 | 0 | } | 83 | | | 84 | 2.43k | c->buffer->delete_glyph (); | 85 | | | 86 | 2.43k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 87 | 0 | { | 88 | 0 | c->buffer->sync_so_far (); | 89 | 0 | c->buffer->message (c->font, | 90 | 0 | "deleted glyph at %u (multiple substitution)", | 91 | 0 | c->buffer->idx); | 92 | 0 | } | 93 | | | 94 | 2.43k | return_trace (true); | 95 | 2.43k | } | 96 | | | 97 | 3.67k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 98 | 0 | { | 99 | 0 | c->buffer->sync_so_far (); | 100 | 0 | c->buffer->message (c->font, | 101 | 0 | "multiplying glyph at %u", | 102 | 0 | c->buffer->idx); | 103 | 0 | } | 104 | | | 105 | 3.67k | unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? | 106 | 3.67k | HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; | 107 | 3.67k | unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur()); | 108 | | | 109 | 818k | for (unsigned int i = 0; i < count; i++) | 110 | 814k | { | 111 | | /* If is attached to a ligature, don't disturb that. | 112 | | * https://github.com/harfbuzz/harfbuzz/issues/3069 */ | 113 | 814k | if (!lig_id) | 114 | 791k | _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); | 115 | 814k | c->output_glyph_for_component (substitute.arrayZ[i], klass); | 116 | 814k | } | 117 | 3.67k | c->buffer->skip_glyph (); | 118 | | | 119 | 3.67k | if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) | 120 | 0 | { | 121 | 0 | c->buffer->sync_so_far (); | 122 | |
| 123 | 0 | char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0}; | 124 | 0 | char *p = buf; | 125 | |
| 126 | 0 | for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++) | 127 | 0 | { | 128 | 0 | if (buf < p && sizeof(buf) - 1u > unsigned (p - buf)) | 129 | 0 | *p++ = ','; | 130 | 0 | snprintf (p, sizeof(buf) - (p - buf), "%u", i); | 131 | 0 | p += strlen(p); | 132 | 0 | } | 133 | |
| 134 | 0 | c->buffer->message (c->font, | 135 | 0 | "multiplied glyphs at %s", | 136 | 0 | buf); | 137 | 0 | } | 138 | | | 139 | 3.67k | return_trace (true); | 140 | 7.11k | } |
|
141 | | |
142 | | template <typename Iterator, |
143 | | hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))> |
144 | | bool serialize (hb_serialize_context_t *c, |
145 | | Iterator subst) |
146 | 0 | { |
147 | 0 | TRACE_SERIALIZE (this); |
148 | 0 | return_trace (substitute.serialize (c, subst)); |
149 | 0 | } Unexecuted instantiation: _ZN2OT6Layout9GSUB_impl8SequenceINS0_10SmallTypesEE9serializeI13hb_map_iter_tI10hb_array_tIKNS_11HBGlyphID16EERK8hb_map_tL24hb_function_sortedness_t0ELPv0EETnPNSt3__19enable_ifIXsr15hb_is_source_ofIT_jEE5valueEvE4typeELSF_0EEEbP22hb_serialize_context_tSJ_ Unexecuted instantiation: _ZN2OT6Layout9GSUB_impl8SequenceINS0_11MediumTypesEE9serializeI13hb_map_iter_tI10hb_array_tIKNS_11HBGlyphID24EERK8hb_map_tL24hb_function_sortedness_t0ELPv0EETnPNSt3__19enable_ifIXsr15hb_is_source_ofIT_jEE5valueEvE4typeELSF_0EEEbP22hb_serialize_context_tSJ_ |
150 | | |
151 | | bool subset (hb_subset_context_t *c) const |
152 | 0 | { |
153 | 0 | TRACE_SUBSET (this); |
154 | 0 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
155 | 0 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
156 | 0 |
|
157 | 0 | if (!intersects (&glyphset)) return_trace (false); |
158 | 0 |
|
159 | 0 | auto it = |
160 | 0 | + hb_iter (substitute) |
161 | 0 | | hb_map (glyph_map) |
162 | 0 | ; |
163 | 0 |
|
164 | 0 | auto *out = c->serializer->start_embed (*this); |
165 | 0 | return_trace (out->serialize (c->serializer, it)); |
166 | 0 | } Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>::subset(hb_subset_context_t*) const Unexecuted instantiation: OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>::subset(hb_subset_context_t*) const |
167 | | }; |
168 | | |
169 | | |
170 | | } |
171 | | } |
172 | | } |
173 | | |
174 | | |
175 | | #endif /* OT_LAYOUT_GSUB_SEQUENCE_HH */ |