/src/harfbuzz/src/hb-aat-layout-morx-table.hh
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright © 2017 Google, Inc. |
3 | | * |
4 | | * This is part of HarfBuzz, a text shaping library. |
5 | | * |
6 | | * Permission is hereby granted, without written agreement and without |
7 | | * license or royalty fees, to use, copy, modify, and distribute this |
8 | | * software and its documentation for any purpose, provided that the |
9 | | * above copyright notice and the following two paragraphs appear in |
10 | | * all copies of this software. |
11 | | * |
12 | | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
13 | | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
14 | | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
15 | | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
16 | | * DAMAGE. |
17 | | * |
18 | | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
19 | | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
20 | | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
21 | | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
22 | | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 | | * |
24 | | * Google Author(s): Behdad Esfahbod |
25 | | */ |
26 | | |
27 | | #ifndef HB_AAT_LAYOUT_MORX_TABLE_HH |
28 | | #define HB_AAT_LAYOUT_MORX_TABLE_HH |
29 | | |
30 | | #include "hb-open-type.hh" |
31 | | #include "hb-aat-layout-common.hh" |
32 | | #include "hb-ot-layout-common.hh" |
33 | | #include "hb-ot-layout-gdef-table.hh" |
34 | | #include "hb-aat-map.hh" |
35 | | |
36 | | /* |
37 | | * morx -- Extended Glyph Metamorphosis |
38 | | * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html |
39 | | * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html |
40 | | */ |
41 | | #define HB_AAT_TAG_morx HB_TAG('m','o','r','x') |
42 | | #define HB_AAT_TAG_mort HB_TAG('m','o','r','t') |
43 | | |
44 | | |
45 | | namespace AAT { |
46 | | |
47 | | using namespace OT; |
48 | | |
49 | | template <typename Types> |
50 | | struct RearrangementSubtable |
51 | | { |
52 | | typedef typename Types::HBUINT HBUINT; |
53 | | |
54 | | typedef void EntryData; |
55 | | |
56 | | struct driver_context_t |
57 | | { |
58 | | static constexpr bool in_place = true; |
59 | | enum Flags |
60 | | { |
61 | | MarkFirst = 0x8000, /* If set, make the current glyph the first |
62 | | * glyph to be rearranged. */ |
63 | | DontAdvance = 0x4000, /* If set, don't advance to the next glyph |
64 | | * before going to the new state. This means |
65 | | * that the glyph index doesn't change, even |
66 | | * if the glyph at that index has changed. */ |
67 | | MarkLast = 0x2000, /* If set, make the current glyph the last |
68 | | * glyph to be rearranged. */ |
69 | | Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */ |
70 | | Verb = 0x000F, /* The type of rearrangement specified. */ |
71 | | }; |
72 | | |
73 | | driver_context_t (const RearrangementSubtable *table HB_UNUSED) : |
74 | | ret (false), |
75 | 25.2k | start (0), end (0) {} AAT::RearrangementSubtable<AAT::ExtendedTypes>::driver_context_t::driver_context_t(AAT::RearrangementSubtable<AAT::ExtendedTypes> const*) Line | Count | Source | 75 | 12.1k | start (0), end (0) {} |
AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t::driver_context_t(AAT::RearrangementSubtable<AAT::ObsoleteTypes> const*) Line | Count | Source | 75 | 13.1k | start (0), end (0) {} |
|
76 | | |
77 | | bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, |
78 | | const Entry<EntryData> &entry) |
79 | 66.5M | { |
80 | 66.5M | return (entry.flags & Verb) && start < end; |
81 | 66.5M | } AAT::RearrangementSubtable<AAT::ExtendedTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ExtendedTypes, void>*, AAT::Entry<void> const&) Line | Count | Source | 79 | 21.4M | { | 80 | 21.4M | return (entry.flags & Verb) && start < end; | 81 | 21.4M | } |
AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ObsoleteTypes, void>*, AAT::Entry<void> const&) Line | Count | Source | 79 | 45.1M | { | 80 | 45.1M | return (entry.flags & Verb) && start < end; | 81 | 45.1M | } |
|
82 | | void transition (StateTableDriver<Types, EntryData> *driver, |
83 | | const Entry<EntryData> &entry) |
84 | 47.8M | { |
85 | 47.8M | hb_buffer_t *buffer = driver->buffer; |
86 | 47.8M | unsigned int flags = entry.flags; |
87 | | |
88 | 47.8M | if (flags & MarkFirst) |
89 | 21.4M | start = buffer->idx; |
90 | | |
91 | 47.8M | if (flags & MarkLast) |
92 | 28.9M | end = hb_min (buffer->idx + 1, buffer->len); |
93 | | |
94 | 47.8M | if ((flags & Verb) && start < end) |
95 | 30.3M | { |
96 | | /* The following map has two nibbles, for start-side |
97 | | * and end-side. Values of 0,1,2 mean move that many |
98 | | * to the other side. Value of 3 means move 2 and |
99 | | * flip them. */ |
100 | 30.3M | const unsigned char map[16] = |
101 | 30.3M | { |
102 | 30.3M | 0x00, /* 0 no change */ |
103 | 30.3M | 0x10, /* 1 Ax => xA */ |
104 | 30.3M | 0x01, /* 2 xD => Dx */ |
105 | 30.3M | 0x11, /* 3 AxD => DxA */ |
106 | 30.3M | 0x20, /* 4 ABx => xAB */ |
107 | 30.3M | 0x30, /* 5 ABx => xBA */ |
108 | 30.3M | 0x02, /* 6 xCD => CDx */ |
109 | 30.3M | 0x03, /* 7 xCD => DCx */ |
110 | 30.3M | 0x12, /* 8 AxCD => CDxA */ |
111 | 30.3M | 0x13, /* 9 AxCD => DCxA */ |
112 | 30.3M | 0x21, /* 10 ABxD => DxAB */ |
113 | 30.3M | 0x31, /* 11 ABxD => DxBA */ |
114 | 30.3M | 0x22, /* 12 ABxCD => CDxAB */ |
115 | 30.3M | 0x32, /* 13 ABxCD => CDxBA */ |
116 | 30.3M | 0x23, /* 14 ABxCD => DCxAB */ |
117 | 30.3M | 0x33, /* 15 ABxCD => DCxBA */ |
118 | 30.3M | }; |
119 | | |
120 | 30.3M | unsigned int m = map[flags & Verb]; |
121 | 30.3M | unsigned int l = hb_min (2u, m >> 4); |
122 | 30.3M | unsigned int r = hb_min (2u, m & 0x0F); |
123 | 30.3M | bool reverse_l = 3 == (m >> 4); |
124 | 30.3M | bool reverse_r = 3 == (m & 0x0F); |
125 | | |
126 | 30.3M | if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH) |
127 | 8.77M | { |
128 | 8.77M | buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len)); |
129 | 8.77M | buffer->merge_clusters (start, end); |
130 | | |
131 | 8.77M | hb_glyph_info_t *info = buffer->info; |
132 | 8.77M | hb_glyph_info_t buf[4]; |
133 | | |
134 | 8.77M | hb_memcpy (buf, info + start, l * sizeof (buf[0])); |
135 | 8.77M | hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0])); |
136 | | |
137 | 8.77M | if (l != r) |
138 | 7.41M | memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0])); |
139 | | |
140 | 8.77M | hb_memcpy (info + start, buf + 2, r * sizeof (buf[0])); |
141 | 8.77M | hb_memcpy (info + end - l, buf, l * sizeof (buf[0])); |
142 | 8.77M | if (reverse_l) |
143 | 1.37M | { |
144 | 1.37M | buf[0] = info[end - 1]; |
145 | 1.37M | info[end - 1] = info[end - 2]; |
146 | 1.37M | info[end - 2] = buf[0]; |
147 | 1.37M | } |
148 | 8.77M | if (reverse_r) |
149 | 388k | { |
150 | 388k | buf[0] = info[start]; |
151 | 388k | info[start] = info[start + 1]; |
152 | 388k | info[start + 1] = buf[0]; |
153 | 388k | } |
154 | 8.77M | } |
155 | 30.3M | } |
156 | 47.8M | } AAT::RearrangementSubtable<AAT::ExtendedTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ExtendedTypes, void>*, AAT::Entry<void> const&) Line | Count | Source | 84 | 12.2M | { | 85 | 12.2M | hb_buffer_t *buffer = driver->buffer; | 86 | 12.2M | unsigned int flags = entry.flags; | 87 | | | 88 | 12.2M | if (flags & MarkFirst) | 89 | 9.05M | start = buffer->idx; | 90 | | | 91 | 12.2M | if (flags & MarkLast) | 92 | 8.63M | end = hb_min (buffer->idx + 1, buffer->len); | 93 | | | 94 | 12.2M | if ((flags & Verb) && start < end) | 95 | 4.18M | { | 96 | | /* The following map has two nibbles, for start-side | 97 | | * and end-side. Values of 0,1,2 mean move that many | 98 | | * to the other side. Value of 3 means move 2 and | 99 | | * flip them. */ | 100 | 4.18M | const unsigned char map[16] = | 101 | 4.18M | { | 102 | 4.18M | 0x00, /* 0 no change */ | 103 | 4.18M | 0x10, /* 1 Ax => xA */ | 104 | 4.18M | 0x01, /* 2 xD => Dx */ | 105 | 4.18M | 0x11, /* 3 AxD => DxA */ | 106 | 4.18M | 0x20, /* 4 ABx => xAB */ | 107 | 4.18M | 0x30, /* 5 ABx => xBA */ | 108 | 4.18M | 0x02, /* 6 xCD => CDx */ | 109 | 4.18M | 0x03, /* 7 xCD => DCx */ | 110 | 4.18M | 0x12, /* 8 AxCD => CDxA */ | 111 | 4.18M | 0x13, /* 9 AxCD => DCxA */ | 112 | 4.18M | 0x21, /* 10 ABxD => DxAB */ | 113 | 4.18M | 0x31, /* 11 ABxD => DxBA */ | 114 | 4.18M | 0x22, /* 12 ABxCD => CDxAB */ | 115 | 4.18M | 0x32, /* 13 ABxCD => CDxBA */ | 116 | 4.18M | 0x23, /* 14 ABxCD => DCxAB */ | 117 | 4.18M | 0x33, /* 15 ABxCD => DCxBA */ | 118 | 4.18M | }; | 119 | | | 120 | 4.18M | unsigned int m = map[flags & Verb]; | 121 | 4.18M | unsigned int l = hb_min (2u, m >> 4); | 122 | 4.18M | unsigned int r = hb_min (2u, m & 0x0F); | 123 | 4.18M | bool reverse_l = 3 == (m >> 4); | 124 | 4.18M | bool reverse_r = 3 == (m & 0x0F); | 125 | | | 126 | 4.18M | if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH) | 127 | 1.54M | { | 128 | 1.54M | buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len)); | 129 | 1.54M | buffer->merge_clusters (start, end); | 130 | | | 131 | 1.54M | hb_glyph_info_t *info = buffer->info; | 132 | 1.54M | hb_glyph_info_t buf[4]; | 133 | | | 134 | 1.54M | hb_memcpy (buf, info + start, l * sizeof (buf[0])); | 135 | 1.54M | hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0])); | 136 | | | 137 | 1.54M | if (l != r) | 138 | 1.54M | memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0])); | 139 | | | 140 | 1.54M | hb_memcpy (info + start, buf + 2, r * sizeof (buf[0])); | 141 | 1.54M | hb_memcpy (info + end - l, buf, l * sizeof (buf[0])); | 142 | 1.54M | if (reverse_l) | 143 | 560 | { | 144 | 560 | buf[0] = info[end - 1]; | 145 | 560 | info[end - 1] = info[end - 2]; | 146 | 560 | info[end - 2] = buf[0]; | 147 | 560 | } | 148 | 1.54M | if (reverse_r) | 149 | 776 | { | 150 | 776 | buf[0] = info[start]; | 151 | 776 | info[start] = info[start + 1]; | 152 | 776 | info[start + 1] = buf[0]; | 153 | 776 | } | 154 | 1.54M | } | 155 | 4.18M | } | 156 | 12.2M | } |
AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ObsoleteTypes, void>*, AAT::Entry<void> const&) Line | Count | Source | 84 | 35.5M | { | 85 | 35.5M | hb_buffer_t *buffer = driver->buffer; | 86 | 35.5M | unsigned int flags = entry.flags; | 87 | | | 88 | 35.5M | if (flags & MarkFirst) | 89 | 12.3M | start = buffer->idx; | 90 | | | 91 | 35.5M | if (flags & MarkLast) | 92 | 20.3M | end = hb_min (buffer->idx + 1, buffer->len); | 93 | | | 94 | 35.5M | if ((flags & Verb) && start < end) | 95 | 26.1M | { | 96 | | /* The following map has two nibbles, for start-side | 97 | | * and end-side. Values of 0,1,2 mean move that many | 98 | | * to the other side. Value of 3 means move 2 and | 99 | | * flip them. */ | 100 | 26.1M | const unsigned char map[16] = | 101 | 26.1M | { | 102 | 26.1M | 0x00, /* 0 no change */ | 103 | 26.1M | 0x10, /* 1 Ax => xA */ | 104 | 26.1M | 0x01, /* 2 xD => Dx */ | 105 | 26.1M | 0x11, /* 3 AxD => DxA */ | 106 | 26.1M | 0x20, /* 4 ABx => xAB */ | 107 | 26.1M | 0x30, /* 5 ABx => xBA */ | 108 | 26.1M | 0x02, /* 6 xCD => CDx */ | 109 | 26.1M | 0x03, /* 7 xCD => DCx */ | 110 | 26.1M | 0x12, /* 8 AxCD => CDxA */ | 111 | 26.1M | 0x13, /* 9 AxCD => DCxA */ | 112 | 26.1M | 0x21, /* 10 ABxD => DxAB */ | 113 | 26.1M | 0x31, /* 11 ABxD => DxBA */ | 114 | 26.1M | 0x22, /* 12 ABxCD => CDxAB */ | 115 | 26.1M | 0x32, /* 13 ABxCD => CDxBA */ | 116 | 26.1M | 0x23, /* 14 ABxCD => DCxAB */ | 117 | 26.1M | 0x33, /* 15 ABxCD => DCxBA */ | 118 | 26.1M | }; | 119 | | | 120 | 26.1M | unsigned int m = map[flags & Verb]; | 121 | 26.1M | unsigned int l = hb_min (2u, m >> 4); | 122 | 26.1M | unsigned int r = hb_min (2u, m & 0x0F); | 123 | 26.1M | bool reverse_l = 3 == (m >> 4); | 124 | 26.1M | bool reverse_r = 3 == (m & 0x0F); | 125 | | | 126 | 26.1M | if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH) | 127 | 7.23M | { | 128 | 7.23M | buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len)); | 129 | 7.23M | buffer->merge_clusters (start, end); | 130 | | | 131 | 7.23M | hb_glyph_info_t *info = buffer->info; | 132 | 7.23M | hb_glyph_info_t buf[4]; | 133 | | | 134 | 7.23M | hb_memcpy (buf, info + start, l * sizeof (buf[0])); | 135 | 7.23M | hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0])); | 136 | | | 137 | 7.23M | if (l != r) | 138 | 5.87M | memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0])); | 139 | | | 140 | 7.23M | hb_memcpy (info + start, buf + 2, r * sizeof (buf[0])); | 141 | 7.23M | hb_memcpy (info + end - l, buf, l * sizeof (buf[0])); | 142 | 7.23M | if (reverse_l) | 143 | 1.37M | { | 144 | 1.37M | buf[0] = info[end - 1]; | 145 | 1.37M | info[end - 1] = info[end - 2]; | 146 | 1.37M | info[end - 2] = buf[0]; | 147 | 1.37M | } | 148 | 7.23M | if (reverse_r) | 149 | 388k | { | 150 | 388k | buf[0] = info[start]; | 151 | 388k | info[start] = info[start + 1]; | 152 | 388k | info[start + 1] = buf[0]; | 153 | 388k | } | 154 | 7.23M | } | 155 | 26.1M | } | 156 | 35.5M | } |
|
157 | | |
158 | | public: |
159 | | bool ret; |
160 | | private: |
161 | | unsigned int start; |
162 | | unsigned int end; |
163 | | }; |
164 | | |
165 | | bool apply (hb_aat_apply_context_t *c) const |
166 | 25.2k | { |
167 | 25.2k | TRACE_APPLY (this); |
168 | | |
169 | 25.2k | driver_context_t dc (this); |
170 | | |
171 | 25.2k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); |
172 | 25.2k | driver.drive (&dc, c); |
173 | | |
174 | 25.2k | return_trace (dc.ret); |
175 | 25.2k | } AAT::RearrangementSubtable<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 166 | 12.1k | { | 167 | 12.1k | TRACE_APPLY (this); | 168 | | | 169 | 12.1k | driver_context_t dc (this); | 170 | | | 171 | 12.1k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 172 | 12.1k | driver.drive (&dc, c); | 173 | | | 174 | 12.1k | return_trace (dc.ret); | 175 | 12.1k | } |
AAT::RearrangementSubtable<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 166 | 13.1k | { | 167 | 13.1k | TRACE_APPLY (this); | 168 | | | 169 | 13.1k | driver_context_t dc (this); | 170 | | | 171 | 13.1k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 172 | 13.1k | driver.drive (&dc, c); | 173 | | | 174 | 13.1k | return_trace (dc.ret); | 175 | 13.1k | } |
|
176 | | |
177 | | bool sanitize (hb_sanitize_context_t *c) const |
178 | 5.92k | { |
179 | 5.92k | TRACE_SANITIZE (this); |
180 | 5.92k | return_trace (machine.sanitize (c)); |
181 | 5.92k | } AAT::RearrangementSubtable<AAT::ExtendedTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 178 | 1.47k | { | 179 | 1.47k | TRACE_SANITIZE (this); | 180 | 1.47k | return_trace (machine.sanitize (c)); | 181 | 1.47k | } |
AAT::RearrangementSubtable<AAT::ObsoleteTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 178 | 4.45k | { | 179 | 4.45k | TRACE_SANITIZE (this); | 180 | 4.45k | return_trace (machine.sanitize (c)); | 181 | 4.45k | } |
|
182 | | |
183 | | protected: |
184 | | StateTable<Types, EntryData> machine; |
185 | | public: |
186 | | DEFINE_SIZE_STATIC (16); |
187 | | }; |
188 | | |
189 | | template <typename Types> |
190 | | struct ContextualSubtable |
191 | | { |
192 | | typedef typename Types::HBUINT HBUINT; |
193 | | |
194 | | struct EntryData |
195 | | { |
196 | | HBUINT16 markIndex; /* Index of the substitution table for the |
197 | | * marked glyph (use 0xFFFF for none). */ |
198 | | HBUINT16 currentIndex; /* Index of the substitution table for the |
199 | | * current glyph (use 0xFFFF for none). */ |
200 | | public: |
201 | | DEFINE_SIZE_STATIC (4); |
202 | | }; |
203 | | |
204 | | struct driver_context_t |
205 | | { |
206 | | static constexpr bool in_place = true; |
207 | | enum Flags |
208 | | { |
209 | | SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */ |
210 | | DontAdvance = 0x4000, /* If set, don't advance to the next glyph before |
211 | | * going to the new state. */ |
212 | | Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ |
213 | | }; |
214 | | |
215 | | driver_context_t (const ContextualSubtable *table_, |
216 | | hb_aat_apply_context_t *c_) : |
217 | | ret (false), |
218 | | c (c_), |
219 | | gdef (*c->gdef_table), |
220 | | mark_set (false), |
221 | | has_glyph_classes (gdef.has_glyph_classes ()), |
222 | | mark (0), |
223 | | table (table_), |
224 | 24.3k | subs (table+table->substitutionTables) {} AAT::ContextualSubtable<AAT::ExtendedTypes>::driver_context_t::driver_context_t(AAT::ContextualSubtable<AAT::ExtendedTypes> const*, AAT::hb_aat_apply_context_t*) Line | Count | Source | 224 | 20.7k | subs (table+table->substitutionTables) {} |
AAT::ContextualSubtable<AAT::ObsoleteTypes>::driver_context_t::driver_context_t(AAT::ContextualSubtable<AAT::ObsoleteTypes> const*, AAT::hb_aat_apply_context_t*) Line | Count | Source | 224 | 3.55k | subs (table+table->substitutionTables) {} |
|
225 | | |
226 | | bool is_actionable (StateTableDriver<Types, EntryData> *driver, |
227 | | const Entry<EntryData> &entry) |
228 | 35.9M | { |
229 | 35.9M | hb_buffer_t *buffer = driver->buffer; |
230 | | |
231 | 35.9M | if (buffer->idx == buffer->len && !mark_set) |
232 | 43.9k | return false; |
233 | | |
234 | 35.9M | return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF; |
235 | 35.9M | } AAT::ContextualSubtable<AAT::ExtendedTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>*, AAT::Entry<AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData> const&) Line | Count | Source | 228 | 20.1M | { | 229 | 20.1M | hb_buffer_t *buffer = driver->buffer; | 230 | | | 231 | 20.1M | if (buffer->idx == buffer->len && !mark_set) | 232 | 38.3k | return false; | 233 | | | 234 | 20.1M | return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF; | 235 | 20.1M | } |
AAT::ContextualSubtable<AAT::ObsoleteTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>*, AAT::Entry<AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData> const&) Line | Count | Source | 228 | 15.7M | { | 229 | 15.7M | hb_buffer_t *buffer = driver->buffer; | 230 | | | 231 | 15.7M | if (buffer->idx == buffer->len && !mark_set) | 232 | 5.59k | return false; | 233 | | | 234 | 15.7M | return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF; | 235 | 15.7M | } |
|
236 | | void transition (StateTableDriver<Types, EntryData> *driver, |
237 | | const Entry<EntryData> &entry) |
238 | 27.0M | { |
239 | 27.0M | hb_buffer_t *buffer = driver->buffer; |
240 | | |
241 | | /* Looks like CoreText applies neither mark nor current substitution for |
242 | | * end-of-text if mark was not explicitly set. */ |
243 | 27.0M | if (buffer->idx == buffer->len && !mark_set) |
244 | 21.5k | return; |
245 | | |
246 | 27.0M | const HBGlyphID16 *replacement; |
247 | | |
248 | 27.0M | replacement = nullptr; |
249 | 27.0M | if (Types::extended) |
250 | 12.9M | { |
251 | 12.9M | if (entry.data.markIndex != 0xFFFF) |
252 | 2.96M | { |
253 | 2.96M | const Lookup<HBGlyphID16> &lookup = subs[entry.data.markIndex]; |
254 | 2.96M | replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs); |
255 | 2.96M | } |
256 | 12.9M | } |
257 | 14.0M | else |
258 | 14.0M | { |
259 | 14.0M | unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint; |
260 | 14.0M | const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; |
261 | 14.0M | replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; |
262 | 14.0M | if (!replacement->sanitize (&c->sanitizer) || !*replacement) |
263 | 14.0M | replacement = nullptr; |
264 | 14.0M | } |
265 | 27.0M | if (replacement) |
266 | 797k | { |
267 | 797k | buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); |
268 | 797k | buffer->info[mark].codepoint = *replacement; |
269 | 797k | if (has_glyph_classes) |
270 | 466 | _hb_glyph_info_set_glyph_props (&buffer->info[mark], |
271 | 466 | gdef.get_glyph_props (*replacement)); |
272 | 797k | ret = true; |
273 | 797k | } |
274 | | |
275 | 27.0M | replacement = nullptr; |
276 | 27.0M | unsigned int idx = hb_min (buffer->idx, buffer->len - 1); |
277 | 27.0M | if (Types::extended) |
278 | 12.9M | { |
279 | 12.9M | if (entry.data.currentIndex != 0xFFFF) |
280 | 3.68M | { |
281 | 3.68M | const Lookup<HBGlyphID16> &lookup = subs[entry.data.currentIndex]; |
282 | 3.68M | replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs); |
283 | 3.68M | } |
284 | 12.9M | } |
285 | 14.0M | else |
286 | 14.0M | { |
287 | 14.0M | unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint; |
288 | 14.0M | const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; |
289 | 14.0M | replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; |
290 | 14.0M | if (!replacement->sanitize (&c->sanitizer) || !*replacement) |
291 | 13.8M | replacement = nullptr; |
292 | 14.0M | } |
293 | 27.0M | if (replacement) |
294 | 1.79M | { |
295 | 1.79M | buffer->info[idx].codepoint = *replacement; |
296 | 1.79M | if (has_glyph_classes) |
297 | 413 | _hb_glyph_info_set_glyph_props (&buffer->info[idx], |
298 | 413 | gdef.get_glyph_props (*replacement)); |
299 | 1.79M | ret = true; |
300 | 1.79M | } |
301 | | |
302 | 27.0M | if (entry.flags & SetMark) |
303 | 20.0M | { |
304 | 20.0M | mark_set = true; |
305 | 20.0M | mark = buffer->idx; |
306 | 20.0M | } |
307 | 27.0M | } AAT::ContextualSubtable<AAT::ExtendedTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>*, AAT::Entry<AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData> const&) Line | Count | Source | 238 | 12.9M | { | 239 | 12.9M | hb_buffer_t *buffer = driver->buffer; | 240 | | | 241 | | /* Looks like CoreText applies neither mark nor current substitution for | 242 | | * end-of-text if mark was not explicitly set. */ | 243 | 12.9M | if (buffer->idx == buffer->len && !mark_set) | 244 | 19.0k | return; | 245 | | | 246 | 12.9M | const HBGlyphID16 *replacement; | 247 | | | 248 | 12.9M | replacement = nullptr; | 249 | 12.9M | if (Types::extended) | 250 | 12.9M | { | 251 | 12.9M | if (entry.data.markIndex != 0xFFFF) | 252 | 2.96M | { | 253 | 2.96M | const Lookup<HBGlyphID16> &lookup = subs[entry.data.markIndex]; | 254 | 2.96M | replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs); | 255 | 2.96M | } | 256 | 12.9M | } | 257 | 0 | else | 258 | 0 | { | 259 | 0 | unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint; | 260 | 0 | const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; | 261 | 0 | replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; | 262 | 0 | if (!replacement->sanitize (&c->sanitizer) || !*replacement) | 263 | 0 | replacement = nullptr; | 264 | 0 | } | 265 | 12.9M | if (replacement) | 266 | 751k | { | 267 | 751k | buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); | 268 | 751k | buffer->info[mark].codepoint = *replacement; | 269 | 751k | if (has_glyph_classes) | 270 | 81 | _hb_glyph_info_set_glyph_props (&buffer->info[mark], | 271 | 81 | gdef.get_glyph_props (*replacement)); | 272 | 751k | ret = true; | 273 | 751k | } | 274 | | | 275 | 12.9M | replacement = nullptr; | 276 | 12.9M | unsigned int idx = hb_min (buffer->idx, buffer->len - 1); | 277 | 12.9M | if (Types::extended) | 278 | 12.9M | { | 279 | 12.9M | if (entry.data.currentIndex != 0xFFFF) | 280 | 3.68M | { | 281 | 3.68M | const Lookup<HBGlyphID16> &lookup = subs[entry.data.currentIndex]; | 282 | 3.68M | replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs); | 283 | 3.68M | } | 284 | 12.9M | } | 285 | 0 | else | 286 | 0 | { | 287 | 0 | unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint; | 288 | 0 | const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; | 289 | 0 | replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; | 290 | 0 | if (!replacement->sanitize (&c->sanitizer) || !*replacement) | 291 | 0 | replacement = nullptr; | 292 | 0 | } | 293 | 12.9M | if (replacement) | 294 | 1.62M | { | 295 | 1.62M | buffer->info[idx].codepoint = *replacement; | 296 | 1.62M | if (has_glyph_classes) | 297 | 66 | _hb_glyph_info_set_glyph_props (&buffer->info[idx], | 298 | 66 | gdef.get_glyph_props (*replacement)); | 299 | 1.62M | ret = true; | 300 | 1.62M | } | 301 | | | 302 | 12.9M | if (entry.flags & SetMark) | 303 | 7.62M | { | 304 | 7.62M | mark_set = true; | 305 | 7.62M | mark = buffer->idx; | 306 | 7.62M | } | 307 | 12.9M | } |
AAT::ContextualSubtable<AAT::ObsoleteTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>*, AAT::Entry<AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData> const&) Line | Count | Source | 238 | 14.0M | { | 239 | 14.0M | hb_buffer_t *buffer = driver->buffer; | 240 | | | 241 | | /* Looks like CoreText applies neither mark nor current substitution for | 242 | | * end-of-text if mark was not explicitly set. */ | 243 | 14.0M | if (buffer->idx == buffer->len && !mark_set) | 244 | 2.55k | return; | 245 | | | 246 | 14.0M | const HBGlyphID16 *replacement; | 247 | | | 248 | 14.0M | replacement = nullptr; | 249 | 14.0M | if (Types::extended) | 250 | 0 | { | 251 | 0 | if (entry.data.markIndex != 0xFFFF) | 252 | 0 | { | 253 | 0 | const Lookup<HBGlyphID16> &lookup = subs[entry.data.markIndex]; | 254 | 0 | replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs); | 255 | 0 | } | 256 | 0 | } | 257 | 14.0M | else | 258 | 14.0M | { | 259 | 14.0M | unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint; | 260 | 14.0M | const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; | 261 | 14.0M | replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; | 262 | 14.0M | if (!replacement->sanitize (&c->sanitizer) || !*replacement) | 263 | 14.0M | replacement = nullptr; | 264 | 14.0M | } | 265 | 14.0M | if (replacement) | 266 | 45.4k | { | 267 | 45.4k | buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); | 268 | 45.4k | buffer->info[mark].codepoint = *replacement; | 269 | 45.4k | if (has_glyph_classes) | 270 | 385 | _hb_glyph_info_set_glyph_props (&buffer->info[mark], | 271 | 385 | gdef.get_glyph_props (*replacement)); | 272 | 45.4k | ret = true; | 273 | 45.4k | } | 274 | | | 275 | 14.0M | replacement = nullptr; | 276 | 14.0M | unsigned int idx = hb_min (buffer->idx, buffer->len - 1); | 277 | 14.0M | if (Types::extended) | 278 | 0 | { | 279 | 0 | if (entry.data.currentIndex != 0xFFFF) | 280 | 0 | { | 281 | 0 | const Lookup<HBGlyphID16> &lookup = subs[entry.data.currentIndex]; | 282 | 0 | replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs); | 283 | 0 | } | 284 | 0 | } | 285 | 14.0M | else | 286 | 14.0M | { | 287 | 14.0M | unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint; | 288 | 14.0M | const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; | 289 | 14.0M | replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; | 290 | 14.0M | if (!replacement->sanitize (&c->sanitizer) || !*replacement) | 291 | 13.8M | replacement = nullptr; | 292 | 14.0M | } | 293 | 14.0M | if (replacement) | 294 | 169k | { | 295 | 169k | buffer->info[idx].codepoint = *replacement; | 296 | 169k | if (has_glyph_classes) | 297 | 347 | _hb_glyph_info_set_glyph_props (&buffer->info[idx], | 298 | 347 | gdef.get_glyph_props (*replacement)); | 299 | 169k | ret = true; | 300 | 169k | } | 301 | | | 302 | 14.0M | if (entry.flags & SetMark) | 303 | 12.4M | { | 304 | 12.4M | mark_set = true; | 305 | 12.4M | mark = buffer->idx; | 306 | 12.4M | } | 307 | 14.0M | } |
|
308 | | |
309 | | public: |
310 | | bool ret; |
311 | | private: |
312 | | hb_aat_apply_context_t *c; |
313 | | const OT::GDEF &gdef; |
314 | | bool mark_set; |
315 | | bool has_glyph_classes; |
316 | | unsigned int mark; |
317 | | const ContextualSubtable *table; |
318 | | const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false> &subs; |
319 | | }; |
320 | | |
321 | | bool apply (hb_aat_apply_context_t *c) const |
322 | 24.3k | { |
323 | 24.3k | TRACE_APPLY (this); |
324 | | |
325 | 24.3k | driver_context_t dc (this, c); |
326 | | |
327 | 24.3k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); |
328 | 24.3k | driver.drive (&dc, c); |
329 | | |
330 | 24.3k | return_trace (dc.ret); |
331 | 24.3k | } AAT::ContextualSubtable<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 322 | 20.7k | { | 323 | 20.7k | TRACE_APPLY (this); | 324 | | | 325 | 20.7k | driver_context_t dc (this, c); | 326 | | | 327 | 20.7k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 328 | 20.7k | driver.drive (&dc, c); | 329 | | | 330 | 20.7k | return_trace (dc.ret); | 331 | 20.7k | } |
AAT::ContextualSubtable<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 322 | 3.55k | { | 323 | 3.55k | TRACE_APPLY (this); | 324 | | | 325 | 3.55k | driver_context_t dc (this, c); | 326 | | | 327 | 3.55k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 328 | 3.55k | driver.drive (&dc, c); | 329 | | | 330 | 3.55k | return_trace (dc.ret); | 331 | 3.55k | } |
|
332 | | |
333 | | bool sanitize (hb_sanitize_context_t *c) const |
334 | 3.65k | { |
335 | 3.65k | TRACE_SANITIZE (this); |
336 | | |
337 | 3.65k | unsigned int num_entries = 0; |
338 | 3.65k | if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false); |
339 | | |
340 | 3.31k | if (!Types::extended) |
341 | 1.06k | return_trace (substitutionTables.sanitize (c, this, 0)); |
342 | | |
343 | 2.25k | unsigned int num_lookups = 0; |
344 | | |
345 | 2.25k | const Entry<EntryData> *entries = machine.get_entries (); |
346 | 8.76k | for (unsigned int i = 0; i < num_entries; i++) |
347 | 6.51k | { |
348 | 6.51k | const EntryData &data = entries[i].data; |
349 | | |
350 | 6.51k | if (data.markIndex != 0xFFFF) |
351 | 2.13k | num_lookups = hb_max (num_lookups, 1u + data.markIndex); |
352 | 6.51k | if (data.currentIndex != 0xFFFF) |
353 | 1.25k | num_lookups = hb_max (num_lookups, 1u + data.currentIndex); |
354 | 6.51k | } |
355 | | |
356 | 2.25k | return_trace (substitutionTables.sanitize (c, this, num_lookups)); |
357 | 3.31k | } AAT::ContextualSubtable<AAT::ExtendedTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 334 | 2.42k | { | 335 | 2.42k | TRACE_SANITIZE (this); | 336 | | | 337 | 2.42k | unsigned int num_entries = 0; | 338 | 2.42k | if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false); | 339 | | | 340 | 2.25k | if (!Types::extended) | 341 | 0 | return_trace (substitutionTables.sanitize (c, this, 0)); | 342 | | | 343 | 2.25k | unsigned int num_lookups = 0; | 344 | | | 345 | 2.25k | const Entry<EntryData> *entries = machine.get_entries (); | 346 | 8.76k | for (unsigned int i = 0; i < num_entries; i++) | 347 | 6.51k | { | 348 | 6.51k | const EntryData &data = entries[i].data; | 349 | | | 350 | 6.51k | if (data.markIndex != 0xFFFF) | 351 | 2.13k | num_lookups = hb_max (num_lookups, 1u + data.markIndex); | 352 | 6.51k | if (data.currentIndex != 0xFFFF) | 353 | 1.25k | num_lookups = hb_max (num_lookups, 1u + data.currentIndex); | 354 | 6.51k | } | 355 | | | 356 | 2.25k | return_trace (substitutionTables.sanitize (c, this, num_lookups)); | 357 | 2.25k | } |
AAT::ContextualSubtable<AAT::ObsoleteTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 334 | 1.23k | { | 335 | 1.23k | TRACE_SANITIZE (this); | 336 | | | 337 | 1.23k | unsigned int num_entries = 0; | 338 | 1.23k | if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false); | 339 | | | 340 | 1.06k | if (!Types::extended) | 341 | 1.06k | return_trace (substitutionTables.sanitize (c, this, 0)); | 342 | | | 343 | 0 | unsigned int num_lookups = 0; | 344 | |
| 345 | 0 | const Entry<EntryData> *entries = machine.get_entries (); | 346 | 0 | for (unsigned int i = 0; i < num_entries; i++) | 347 | 0 | { | 348 | 0 | const EntryData &data = entries[i].data; | 349 | |
| 350 | 0 | if (data.markIndex != 0xFFFF) | 351 | 0 | num_lookups = hb_max (num_lookups, 1u + data.markIndex); | 352 | 0 | if (data.currentIndex != 0xFFFF) | 353 | 0 | num_lookups = hb_max (num_lookups, 1u + data.currentIndex); | 354 | 0 | } | 355 | |
| 356 | 0 | return_trace (substitutionTables.sanitize (c, this, num_lookups)); | 357 | 1.06k | } |
|
358 | | |
359 | | protected: |
360 | | StateTable<Types, EntryData> |
361 | | machine; |
362 | | NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false>, HBUINT> |
363 | | substitutionTables; |
364 | | public: |
365 | | DEFINE_SIZE_STATIC (20); |
366 | | }; |
367 | | |
368 | | |
369 | | template <bool extended> |
370 | | struct LigatureEntry; |
371 | | |
372 | | template <> |
373 | | struct LigatureEntry<true> |
374 | | { |
375 | | enum Flags |
376 | | { |
377 | | SetComponent = 0x8000, /* Push this glyph onto the component stack for |
378 | | * eventual processing. */ |
379 | | DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the |
380 | | next iteration. */ |
381 | | PerformAction = 0x2000, /* Use the ligActionIndex to process a ligature |
382 | | * group. */ |
383 | | Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */ |
384 | | }; |
385 | | |
386 | | struct EntryData |
387 | | { |
388 | | HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry |
389 | | * for processing this group, if indicated |
390 | | * by the flags. */ |
391 | | public: |
392 | | DEFINE_SIZE_STATIC (2); |
393 | | }; |
394 | | |
395 | | static bool performAction (const Entry<EntryData> &entry) |
396 | 14.4M | { return entry.flags & PerformAction; } |
397 | | |
398 | | static unsigned int ligActionIndex (const Entry<EntryData> &entry) |
399 | 4.01M | { return entry.data.ligActionIndex; } |
400 | | }; |
401 | | template <> |
402 | | struct LigatureEntry<false> |
403 | | { |
404 | | enum Flags |
405 | | { |
406 | | SetComponent = 0x8000, /* Push this glyph onto the component stack for |
407 | | * eventual processing. */ |
408 | | DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the |
409 | | next iteration. */ |
410 | | Offset = 0x3FFF, /* Byte offset from beginning of subtable to the |
411 | | * ligature action list. This value must be a |
412 | | * multiple of 4. */ |
413 | | }; |
414 | | |
415 | | typedef void EntryData; |
416 | | |
417 | | static bool performAction (const Entry<EntryData> &entry) |
418 | 16.2M | { return entry.flags & Offset; } |
419 | | |
420 | | static unsigned int ligActionIndex (const Entry<EntryData> &entry) |
421 | 5.92M | { return entry.flags & Offset; } |
422 | | }; |
423 | | |
424 | | |
425 | | template <typename Types> |
426 | | struct LigatureSubtable |
427 | | { |
428 | | typedef typename Types::HBUINT HBUINT; |
429 | | |
430 | | typedef LigatureEntry<Types::extended> LigatureEntryT; |
431 | | typedef typename LigatureEntryT::EntryData EntryData; |
432 | | |
433 | | struct driver_context_t |
434 | | { |
435 | | static constexpr bool in_place = false; |
436 | | enum |
437 | | { |
438 | | DontAdvance = LigatureEntryT::DontAdvance, |
439 | | }; |
440 | | enum LigActionFlags |
441 | | { |
442 | | LigActionLast = 0x80000000, /* This is the last action in the list. This also |
443 | | * implies storage. */ |
444 | | LigActionStore = 0x40000000, /* Store the ligature at the current cumulated index |
445 | | * in the ligature table in place of the marked |
446 | | * (i.e. currently-popped) glyph. */ |
447 | | LigActionOffset = 0x3FFFFFFF, /* A 30-bit value which is sign-extended to 32-bits |
448 | | * and added to the glyph ID, resulting in an index |
449 | | * into the component table. */ |
450 | | }; |
451 | | |
452 | | driver_context_t (const LigatureSubtable *table_, |
453 | | hb_aat_apply_context_t *c_) : |
454 | | ret (false), |
455 | | c (c_), |
456 | | table (table_), |
457 | | ligAction (table+table->ligAction), |
458 | | component (table+table->component), |
459 | | ligature (table+table->ligature), |
460 | 17.4k | match_length (0) {} AAT::LigatureSubtable<AAT::ExtendedTypes>::driver_context_t::driver_context_t(AAT::LigatureSubtable<AAT::ExtendedTypes> const*, AAT::hb_aat_apply_context_t*) Line | Count | Source | 460 | 14.5k | match_length (0) {} |
AAT::LigatureSubtable<AAT::ObsoleteTypes>::driver_context_t::driver_context_t(AAT::LigatureSubtable<AAT::ObsoleteTypes> const*, AAT::hb_aat_apply_context_t*) Line | Count | Source | 460 | 2.92k | match_length (0) {} |
|
461 | | |
462 | | bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, |
463 | | const Entry<EntryData> &entry) |
464 | 16.3M | { |
465 | 16.3M | return LigatureEntryT::performAction (entry); |
466 | 16.3M | } AAT::LigatureSubtable<AAT::ExtendedTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>*, AAT::Entry<AAT::LigatureEntry<true>::EntryData> const&) Line | Count | Source | 464 | 8.09M | { | 465 | 8.09M | return LigatureEntryT::performAction (entry); | 466 | 8.09M | } |
AAT::LigatureSubtable<AAT::ObsoleteTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ObsoleteTypes, void>*, AAT::Entry<void> const&) Line | Count | Source | 464 | 8.27M | { | 465 | 8.27M | return LigatureEntryT::performAction (entry); | 466 | 8.27M | } |
|
467 | | void transition (StateTableDriver<Types, EntryData> *driver, |
468 | | const Entry<EntryData> &entry) |
469 | 14.2M | { |
470 | 14.2M | hb_buffer_t *buffer = driver->buffer; |
471 | | |
472 | 14.2M | DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx); |
473 | 14.2M | if (entry.flags & LigatureEntryT::SetComponent) |
474 | 9.79M | { |
475 | | /* Never mark same index twice, in case DontAdvance was used... */ |
476 | 9.79M | if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len) |
477 | 9.27M | match_length--; |
478 | | |
479 | 9.79M | match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len; |
480 | 9.79M | DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len); |
481 | 9.79M | } |
482 | | |
483 | 14.2M | if (LigatureEntryT::performAction (entry)) |
484 | 12.4M | { |
485 | 12.4M | DEBUG_MSG (APPLY, nullptr, "Perform action with %u", match_length); |
486 | 12.4M | unsigned int end = buffer->out_len; |
487 | | |
488 | 12.4M | if (unlikely (!match_length)) |
489 | 2.54M | return; |
490 | | |
491 | 9.93M | if (buffer->idx >= buffer->len) |
492 | 1.19k | return; /* TODO Work on previous instead? */ |
493 | | |
494 | 9.93M | unsigned int cursor = match_length; |
495 | | |
496 | 9.93M | unsigned int action_idx = LigatureEntryT::ligActionIndex (entry); |
497 | 9.93M | action_idx = Types::offsetToIndex (action_idx, table, ligAction.arrayZ); |
498 | 9.93M | const HBUINT32 *actionData = &ligAction[action_idx]; |
499 | | |
500 | 9.93M | unsigned int ligature_idx = 0; |
501 | 9.93M | unsigned int action; |
502 | 9.93M | do |
503 | 10.9M | { |
504 | 10.9M | if (unlikely (!cursor)) |
505 | 238k | { |
506 | | /* Stack underflow. Clear the stack. */ |
507 | 238k | DEBUG_MSG (APPLY, nullptr, "Stack underflow"); |
508 | 238k | match_length = 0; |
509 | 238k | break; |
510 | 238k | } |
511 | | |
512 | 10.7M | DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1); |
513 | 10.7M | if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return; |
514 | | |
515 | 10.7M | if (unlikely (!actionData->sanitize (&c->sanitizer))) break; |
516 | 4.07M | action = *actionData; |
517 | | |
518 | 4.07M | uint32_t uoffset = action & LigActionOffset; |
519 | 4.07M | if (uoffset & 0x20000000) |
520 | 3.30M | uoffset |= 0xC0000000; /* Sign-extend. */ |
521 | 4.07M | int32_t offset = (int32_t) uoffset; |
522 | 4.07M | unsigned int component_idx = buffer->cur().codepoint + offset; |
523 | 4.07M | component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ); |
524 | 4.07M | const HBUINT16 &componentData = component[component_idx]; |
525 | 4.07M | if (unlikely (!componentData.sanitize (&c->sanitizer))) break; |
526 | 1.17M | ligature_idx += componentData; |
527 | | |
528 | 1.17M | DEBUG_MSG (APPLY, nullptr, "Action store %d last %d", |
529 | 1.17M | bool (action & LigActionStore), |
530 | 1.17M | bool (action & LigActionLast)); |
531 | 1.17M | if (action & (LigActionStore | LigActionLast)) |
532 | 228k | { |
533 | 228k | ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ); |
534 | 228k | const HBGlyphID16 &ligatureData = ligature[ligature_idx]; |
535 | 228k | if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break; |
536 | 111k | hb_codepoint_t lig = ligatureData; |
537 | | |
538 | 111k | DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig); |
539 | 111k | if (unlikely (!buffer->replace_glyph (lig))) return; |
540 | | |
541 | 111k | unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u; |
542 | | /* Now go and delete all subsequent components. */ |
543 | 111k | while (match_length - 1u > cursor) |
544 | 173 | { |
545 | 173 | DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); |
546 | 173 | if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; |
547 | 173 | if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; |
548 | 173 | } |
549 | | |
550 | 111k | if (unlikely (!buffer->move_to (lig_end))) return; |
551 | 111k | buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len); |
552 | 111k | } |
553 | | |
554 | 1.05M | actionData++; |
555 | 1.05M | } |
556 | 9.93M | while (!(action & LigActionLast)); |
557 | 9.93M | if (unlikely (!buffer->move_to (end))) return; |
558 | 9.93M | } |
559 | 14.2M | } AAT::LigatureSubtable<AAT::ExtendedTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>*, AAT::Entry<AAT::LigatureEntry<true>::EntryData> const&) Line | Count | Source | 469 | 6.30M | { | 470 | 6.30M | hb_buffer_t *buffer = driver->buffer; | 471 | | | 472 | 6.30M | DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx); | 473 | 6.30M | if (entry.flags & LigatureEntryT::SetComponent) | 474 | 4.52M | { | 475 | | /* Never mark same index twice, in case DontAdvance was used... */ | 476 | 4.52M | if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len) | 477 | 4.29M | match_length--; | 478 | | | 479 | 4.52M | match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len; | 480 | 4.52M | DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len); | 481 | 4.52M | } | 482 | | | 483 | 6.30M | if (LigatureEntryT::performAction (entry)) | 484 | 4.85M | { | 485 | 4.85M | DEBUG_MSG (APPLY, nullptr, "Perform action with %u", match_length); | 486 | 4.85M | unsigned int end = buffer->out_len; | 487 | | | 488 | 4.85M | if (unlikely (!match_length)) | 489 | 846k | return; | 490 | | | 491 | 4.01M | if (buffer->idx >= buffer->len) | 492 | 384 | return; /* TODO Work on previous instead? */ | 493 | | | 494 | 4.01M | unsigned int cursor = match_length; | 495 | | | 496 | 4.01M | unsigned int action_idx = LigatureEntryT::ligActionIndex (entry); | 497 | 4.01M | action_idx = Types::offsetToIndex (action_idx, table, ligAction.arrayZ); | 498 | 4.01M | const HBUINT32 *actionData = &ligAction[action_idx]; | 499 | | | 500 | 4.01M | unsigned int ligature_idx = 0; | 501 | 4.01M | unsigned int action; | 502 | 4.01M | do | 503 | 5.04M | { | 504 | 5.04M | if (unlikely (!cursor)) | 505 | 221k | { | 506 | | /* Stack underflow. Clear the stack. */ | 507 | 221k | DEBUG_MSG (APPLY, nullptr, "Stack underflow"); | 508 | 221k | match_length = 0; | 509 | 221k | break; | 510 | 221k | } | 511 | | | 512 | 4.82M | DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1); | 513 | 4.82M | if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return; | 514 | | | 515 | 4.82M | if (unlikely (!actionData->sanitize (&c->sanitizer))) break; | 516 | 4.00M | action = *actionData; | 517 | | | 518 | 4.00M | uint32_t uoffset = action & LigActionOffset; | 519 | 4.00M | if (uoffset & 0x20000000) | 520 | 3.30M | uoffset |= 0xC0000000; /* Sign-extend. */ | 521 | 4.00M | int32_t offset = (int32_t) uoffset; | 522 | 4.00M | unsigned int component_idx = buffer->cur().codepoint + offset; | 523 | 4.00M | component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ); | 524 | 4.00M | const HBUINT16 &componentData = component[component_idx]; | 525 | 4.00M | if (unlikely (!componentData.sanitize (&c->sanitizer))) break; | 526 | 1.15M | ligature_idx += componentData; | 527 | | | 528 | 1.15M | DEBUG_MSG (APPLY, nullptr, "Action store %d last %d", | 529 | 1.15M | bool (action & LigActionStore), | 530 | 1.15M | bool (action & LigActionLast)); | 531 | 1.15M | if (action & (LigActionStore | LigActionLast)) | 532 | 228k | { | 533 | 228k | ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ); | 534 | 228k | const HBGlyphID16 &ligatureData = ligature[ligature_idx]; | 535 | 228k | if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break; | 536 | 111k | hb_codepoint_t lig = ligatureData; | 537 | | | 538 | 111k | DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig); | 539 | 111k | if (unlikely (!buffer->replace_glyph (lig))) return; | 540 | | | 541 | 111k | unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u; | 542 | | /* Now go and delete all subsequent components. */ | 543 | 111k | while (match_length - 1u > cursor) | 544 | 173 | { | 545 | 173 | DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); | 546 | 173 | if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; | 547 | 173 | if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; | 548 | 173 | } | 549 | | | 550 | 111k | if (unlikely (!buffer->move_to (lig_end))) return; | 551 | 111k | buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len); | 552 | 111k | } | 553 | | | 554 | 1.03M | actionData++; | 555 | 1.03M | } | 556 | 4.01M | while (!(action & LigActionLast)); | 557 | 4.01M | if (unlikely (!buffer->move_to (end))) return; | 558 | 4.01M | } | 559 | 6.30M | } |
AAT::LigatureSubtable<AAT::ObsoleteTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ObsoleteTypes, void>*, AAT::Entry<void> const&) Line | Count | Source | 469 | 7.95M | { | 470 | 7.95M | hb_buffer_t *buffer = driver->buffer; | 471 | | | 472 | 7.95M | DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx); | 473 | 7.95M | if (entry.flags & LigatureEntryT::SetComponent) | 474 | 5.26M | { | 475 | | /* Never mark same index twice, in case DontAdvance was used... */ | 476 | 5.26M | if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len) | 477 | 4.97M | match_length--; | 478 | | | 479 | 5.26M | match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len; | 480 | 5.26M | DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len); | 481 | 5.26M | } | 482 | | | 483 | 7.95M | if (LigatureEntryT::performAction (entry)) | 484 | 7.62M | { | 485 | 7.62M | DEBUG_MSG (APPLY, nullptr, "Perform action with %u", match_length); | 486 | 7.62M | unsigned int end = buffer->out_len; | 487 | | | 488 | 7.62M | if (unlikely (!match_length)) | 489 | 1.70M | return; | 490 | | | 491 | 5.92M | if (buffer->idx >= buffer->len) | 492 | 815 | return; /* TODO Work on previous instead? */ | 493 | | | 494 | 5.92M | unsigned int cursor = match_length; | 495 | | | 496 | 5.92M | unsigned int action_idx = LigatureEntryT::ligActionIndex (entry); | 497 | 5.92M | action_idx = Types::offsetToIndex (action_idx, table, ligAction.arrayZ); | 498 | 5.92M | const HBUINT32 *actionData = &ligAction[action_idx]; | 499 | | | 500 | 5.92M | unsigned int ligature_idx = 0; | 501 | 5.92M | unsigned int action; | 502 | 5.92M | do | 503 | 5.94M | { | 504 | 5.94M | if (unlikely (!cursor)) | 505 | 16.8k | { | 506 | | /* Stack underflow. Clear the stack. */ | 507 | 16.8k | DEBUG_MSG (APPLY, nullptr, "Stack underflow"); | 508 | 16.8k | match_length = 0; | 509 | 16.8k | break; | 510 | 16.8k | } | 511 | | | 512 | 5.92M | DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1); | 513 | 5.92M | if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return; | 514 | | | 515 | 5.92M | if (unlikely (!actionData->sanitize (&c->sanitizer))) break; | 516 | 69.7k | action = *actionData; | 517 | | | 518 | 69.7k | uint32_t uoffset = action & LigActionOffset; | 519 | 69.7k | if (uoffset & 0x20000000) | 520 | 203 | uoffset |= 0xC0000000; /* Sign-extend. */ | 521 | 69.7k | int32_t offset = (int32_t) uoffset; | 522 | 69.7k | unsigned int component_idx = buffer->cur().codepoint + offset; | 523 | 69.7k | component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ); | 524 | 69.7k | const HBUINT16 &componentData = component[component_idx]; | 525 | 69.7k | if (unlikely (!componentData.sanitize (&c->sanitizer))) break; | 526 | 16.8k | ligature_idx += componentData; | 527 | | | 528 | 16.8k | DEBUG_MSG (APPLY, nullptr, "Action store %d last %d", | 529 | 16.8k | bool (action & LigActionStore), | 530 | 16.8k | bool (action & LigActionLast)); | 531 | 16.8k | if (action & (LigActionStore | LigActionLast)) | 532 | 57 | { | 533 | 57 | ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ); | 534 | 57 | const HBGlyphID16 &ligatureData = ligature[ligature_idx]; | 535 | 57 | if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break; | 536 | 0 | hb_codepoint_t lig = ligatureData; | 537 | |
| 538 | 0 | DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig); | 539 | 0 | if (unlikely (!buffer->replace_glyph (lig))) return; | 540 | | | 541 | 0 | unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u; | 542 | | /* Now go and delete all subsequent components. */ | 543 | 0 | while (match_length - 1u > cursor) | 544 | 0 | { | 545 | 0 | DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); | 546 | 0 | if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; | 547 | 0 | if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; | 548 | 0 | } | 549 | | | 550 | 0 | if (unlikely (!buffer->move_to (lig_end))) return; | 551 | 0 | buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len); | 552 | 0 | } | 553 | | | 554 | 16.8k | actionData++; | 555 | 16.8k | } | 556 | 5.92M | while (!(action & LigActionLast)); | 557 | 5.92M | if (unlikely (!buffer->move_to (end))) return; | 558 | 5.92M | } | 559 | 7.95M | } |
|
560 | | |
561 | | public: |
562 | | bool ret; |
563 | | private: |
564 | | hb_aat_apply_context_t *c; |
565 | | const LigatureSubtable *table; |
566 | | const UnsizedArrayOf<HBUINT32> &ligAction; |
567 | | const UnsizedArrayOf<HBUINT16> &component; |
568 | | const UnsizedArrayOf<HBGlyphID16> &ligature; |
569 | | unsigned int match_length; |
570 | | unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; |
571 | | }; |
572 | | |
573 | | bool apply (hb_aat_apply_context_t *c) const |
574 | 17.4k | { |
575 | 17.4k | TRACE_APPLY (this); |
576 | | |
577 | 17.4k | driver_context_t dc (this, c); |
578 | | |
579 | 17.4k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); |
580 | 17.4k | driver.drive (&dc, c); |
581 | | |
582 | 17.4k | return_trace (dc.ret); |
583 | 17.4k | } AAT::LigatureSubtable<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 574 | 14.5k | { | 575 | 14.5k | TRACE_APPLY (this); | 576 | | | 577 | 14.5k | driver_context_t dc (this, c); | 578 | | | 579 | 14.5k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 580 | 14.5k | driver.drive (&dc, c); | 581 | | | 582 | 14.5k | return_trace (dc.ret); | 583 | 14.5k | } |
AAT::LigatureSubtable<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 574 | 2.92k | { | 575 | 2.92k | TRACE_APPLY (this); | 576 | | | 577 | 2.92k | driver_context_t dc (this, c); | 578 | | | 579 | 2.92k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 580 | 2.92k | driver.drive (&dc, c); | 581 | | | 582 | 2.92k | return_trace (dc.ret); | 583 | 2.92k | } |
|
584 | | |
585 | | bool sanitize (hb_sanitize_context_t *c) const |
586 | 2.95k | { |
587 | 2.95k | TRACE_SANITIZE (this); |
588 | | /* The rest of array sanitizations are done at run-time. */ |
589 | 2.95k | return_trace (c->check_struct (this) && machine.sanitize (c) && |
590 | 2.95k | ligAction && component && ligature); |
591 | 2.95k | } AAT::LigatureSubtable<AAT::ExtendedTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 586 | 2.00k | { | 587 | 2.00k | TRACE_SANITIZE (this); | 588 | | /* The rest of array sanitizations are done at run-time. */ | 589 | 2.00k | return_trace (c->check_struct (this) && machine.sanitize (c) && | 590 | 2.00k | ligAction && component && ligature); | 591 | 2.00k | } |
AAT::LigatureSubtable<AAT::ObsoleteTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 586 | 949 | { | 587 | 949 | TRACE_SANITIZE (this); | 588 | | /* The rest of array sanitizations are done at run-time. */ | 589 | 949 | return_trace (c->check_struct (this) && machine.sanitize (c) && | 590 | 949 | ligAction && component && ligature); | 591 | 949 | } |
|
592 | | |
593 | | protected: |
594 | | StateTable<Types, EntryData> |
595 | | machine; |
596 | | NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT> |
597 | | ligAction; /* Offset to the ligature action table. */ |
598 | | NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT> |
599 | | component; /* Offset to the component table. */ |
600 | | NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT> |
601 | | ligature; /* Offset to the actual ligature lists. */ |
602 | | public: |
603 | | DEFINE_SIZE_STATIC (28); |
604 | | }; |
605 | | |
606 | | template <typename Types> |
607 | | struct NoncontextualSubtable |
608 | | { |
609 | | bool apply (hb_aat_apply_context_t *c) const |
610 | 7.32k | { |
611 | 7.32k | TRACE_APPLY (this); |
612 | | |
613 | 7.32k | const OT::GDEF &gdef (*c->gdef_table); |
614 | 7.32k | bool has_glyph_classes = gdef.has_glyph_classes (); |
615 | | |
616 | 7.32k | bool ret = false; |
617 | 7.32k | unsigned int num_glyphs = c->face->get_num_glyphs (); |
618 | | |
619 | 7.32k | hb_glyph_info_t *info = c->buffer->info; |
620 | 7.32k | unsigned int count = c->buffer->len; |
621 | | // If there's only one range, we already checked the flag. |
622 | 7.32k | auto *last_range = c->range_flags && (c->range_flags->length > 1) ? &(*c->range_flags)[0] : nullptr; |
623 | 1.17M | for (unsigned int i = 0; i < count; i++) |
624 | 1.17M | { |
625 | | /* This block copied from StateTableDriver::drive. Keep in sync. */ |
626 | 1.17M | if (last_range) |
627 | 0 | { |
628 | 0 | auto *range = last_range; |
629 | 0 | { |
630 | 0 | unsigned cluster = info[i].cluster; |
631 | 0 | while (cluster < range->cluster_first) |
632 | 0 | range--; |
633 | 0 | while (cluster > range->cluster_last) |
634 | 0 | range++; |
635 | |
|
636 | 0 | last_range = range; |
637 | 0 | } |
638 | 0 | if (!(range->flags & c->subtable_flags)) |
639 | 0 | continue; |
640 | 0 | } |
641 | | |
642 | 1.17M | const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs); |
643 | 1.17M | if (replacement) |
644 | 775k | { |
645 | 775k | info[i].codepoint = *replacement; |
646 | 775k | if (has_glyph_classes) |
647 | 59.1k | _hb_glyph_info_set_glyph_props (&info[i], |
648 | 59.1k | gdef.get_glyph_props (*replacement)); |
649 | 775k | ret = true; |
650 | 775k | } |
651 | 1.17M | } |
652 | | |
653 | 7.32k | return_trace (ret); |
654 | 7.32k | } AAT::NoncontextualSubtable<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 610 | 4.59k | { | 611 | 4.59k | TRACE_APPLY (this); | 612 | | | 613 | 4.59k | const OT::GDEF &gdef (*c->gdef_table); | 614 | 4.59k | bool has_glyph_classes = gdef.has_glyph_classes (); | 615 | | | 616 | 4.59k | bool ret = false; | 617 | 4.59k | unsigned int num_glyphs = c->face->get_num_glyphs (); | 618 | | | 619 | 4.59k | hb_glyph_info_t *info = c->buffer->info; | 620 | 4.59k | unsigned int count = c->buffer->len; | 621 | | // If there's only one range, we already checked the flag. | 622 | 4.59k | auto *last_range = c->range_flags && (c->range_flags->length > 1) ? &(*c->range_flags)[0] : nullptr; | 623 | 759k | for (unsigned int i = 0; i < count; i++) | 624 | 754k | { | 625 | | /* This block copied from StateTableDriver::drive. Keep in sync. */ | 626 | 754k | if (last_range) | 627 | 0 | { | 628 | 0 | auto *range = last_range; | 629 | 0 | { | 630 | 0 | unsigned cluster = info[i].cluster; | 631 | 0 | while (cluster < range->cluster_first) | 632 | 0 | range--; | 633 | 0 | while (cluster > range->cluster_last) | 634 | 0 | range++; | 635 | |
| 636 | 0 | last_range = range; | 637 | 0 | } | 638 | 0 | if (!(range->flags & c->subtable_flags)) | 639 | 0 | continue; | 640 | 0 | } | 641 | | | 642 | 754k | const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs); | 643 | 754k | if (replacement) | 644 | 649k | { | 645 | 649k | info[i].codepoint = *replacement; | 646 | 649k | if (has_glyph_classes) | 647 | 1.12k | _hb_glyph_info_set_glyph_props (&info[i], | 648 | 1.12k | gdef.get_glyph_props (*replacement)); | 649 | 649k | ret = true; | 650 | 649k | } | 651 | 754k | } | 652 | | | 653 | 4.59k | return_trace (ret); | 654 | 4.59k | } |
AAT::NoncontextualSubtable<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 610 | 2.72k | { | 611 | 2.72k | TRACE_APPLY (this); | 612 | | | 613 | 2.72k | const OT::GDEF &gdef (*c->gdef_table); | 614 | 2.72k | bool has_glyph_classes = gdef.has_glyph_classes (); | 615 | | | 616 | 2.72k | bool ret = false; | 617 | 2.72k | unsigned int num_glyphs = c->face->get_num_glyphs (); | 618 | | | 619 | 2.72k | hb_glyph_info_t *info = c->buffer->info; | 620 | 2.72k | unsigned int count = c->buffer->len; | 621 | | // If there's only one range, we already checked the flag. | 622 | 2.72k | auto *last_range = c->range_flags && (c->range_flags->length > 1) ? &(*c->range_flags)[0] : nullptr; | 623 | 418k | for (unsigned int i = 0; i < count; i++) | 624 | 415k | { | 625 | | /* This block copied from StateTableDriver::drive. Keep in sync. */ | 626 | 415k | if (last_range) | 627 | 0 | { | 628 | 0 | auto *range = last_range; | 629 | 0 | { | 630 | 0 | unsigned cluster = info[i].cluster; | 631 | 0 | while (cluster < range->cluster_first) | 632 | 0 | range--; | 633 | 0 | while (cluster > range->cluster_last) | 634 | 0 | range++; | 635 | |
| 636 | 0 | last_range = range; | 637 | 0 | } | 638 | 0 | if (!(range->flags & c->subtable_flags)) | 639 | 0 | continue; | 640 | 0 | } | 641 | | | 642 | 415k | const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs); | 643 | 415k | if (replacement) | 644 | 126k | { | 645 | 126k | info[i].codepoint = *replacement; | 646 | 126k | if (has_glyph_classes) | 647 | 58.0k | _hb_glyph_info_set_glyph_props (&info[i], | 648 | 58.0k | gdef.get_glyph_props (*replacement)); | 649 | 126k | ret = true; | 650 | 126k | } | 651 | 415k | } | 652 | | | 653 | 2.72k | return_trace (ret); | 654 | 2.72k | } |
|
655 | | |
656 | | bool sanitize (hb_sanitize_context_t *c) const |
657 | 1.23k | { |
658 | 1.23k | TRACE_SANITIZE (this); |
659 | 1.23k | return_trace (substitute.sanitize (c)); |
660 | 1.23k | } AAT::NoncontextualSubtable<AAT::ExtendedTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 657 | 684 | { | 658 | 684 | TRACE_SANITIZE (this); | 659 | 684 | return_trace (substitute.sanitize (c)); | 660 | 684 | } |
AAT::NoncontextualSubtable<AAT::ObsoleteTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 657 | 555 | { | 658 | 555 | TRACE_SANITIZE (this); | 659 | 555 | return_trace (substitute.sanitize (c)); | 660 | 555 | } |
|
661 | | |
662 | | protected: |
663 | | Lookup<HBGlyphID16> substitute; |
664 | | public: |
665 | | DEFINE_SIZE_MIN (2); |
666 | | }; |
667 | | |
668 | | template <typename Types> |
669 | | struct InsertionSubtable |
670 | | { |
671 | | typedef typename Types::HBUINT HBUINT; |
672 | | |
673 | | struct EntryData |
674 | | { |
675 | | HBUINT16 currentInsertIndex; /* Zero-based index into the insertion glyph table. |
676 | | * The number of glyphs to be inserted is contained |
677 | | * in the currentInsertCount field in the flags. |
678 | | * A value of 0xFFFF indicates no insertion is to |
679 | | * be done. */ |
680 | | HBUINT16 markedInsertIndex; /* Zero-based index into the insertion glyph table. |
681 | | * The number of glyphs to be inserted is contained |
682 | | * in the markedInsertCount field in the flags. |
683 | | * A value of 0xFFFF indicates no insertion is to |
684 | | * be done. */ |
685 | | public: |
686 | | DEFINE_SIZE_STATIC (4); |
687 | | }; |
688 | | |
689 | | struct driver_context_t |
690 | | { |
691 | | static constexpr bool in_place = false; |
692 | | enum Flags |
693 | | { |
694 | | SetMark = 0x8000, /* If set, mark the current glyph. */ |
695 | | DontAdvance = 0x4000, /* If set, don't advance to the next glyph before |
696 | | * going to the new state. This does not mean |
697 | | * that the glyph pointed to is the same one as |
698 | | * before. If you've made insertions immediately |
699 | | * downstream of the current glyph, the next glyph |
700 | | * processed would in fact be the first one |
701 | | * inserted. */ |
702 | | CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero, |
703 | | * then the specified glyph list will be inserted |
704 | | * as a kashida-like insertion, either before or |
705 | | * after the current glyph (depending on the state |
706 | | * of the currentInsertBefore flag). If clear, and |
707 | | * the currentInsertList is nonzero, then the |
708 | | * specified glyph list will be inserted as a |
709 | | * split-vowel-like insertion, either before or |
710 | | * after the current glyph (depending on the state |
711 | | * of the currentInsertBefore flag). */ |
712 | | MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero, |
713 | | * then the specified glyph list will be inserted |
714 | | * as a kashida-like insertion, either before or |
715 | | * after the marked glyph (depending on the state |
716 | | * of the markedInsertBefore flag). If clear, and |
717 | | * the markedInsertList is nonzero, then the |
718 | | * specified glyph list will be inserted as a |
719 | | * split-vowel-like insertion, either before or |
720 | | * after the marked glyph (depending on the state |
721 | | * of the markedInsertBefore flag). */ |
722 | | CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made |
723 | | * to the left of the current glyph. If clear, |
724 | | * they're made to the right of the current glyph. */ |
725 | | MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be |
726 | | * made to the left of the marked glyph. If clear, |
727 | | * they're made to the right of the marked glyph. */ |
728 | | CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the |
729 | | * number of glyphs to insert at the current |
730 | | * position. Since zero means no insertions, the |
731 | | * largest number of insertions at any given |
732 | | * current location is 31 glyphs. */ |
733 | | MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the |
734 | | * number of glyphs to insert at the marked |
735 | | * position. Since zero means no insertions, the |
736 | | * largest number of insertions at any given |
737 | | * marked location is 31 glyphs. */ |
738 | | }; |
739 | | |
740 | | driver_context_t (const InsertionSubtable *table, |
741 | | hb_aat_apply_context_t *c_) : |
742 | | ret (false), |
743 | | c (c_), |
744 | | mark (0), |
745 | 36.8k | insertionAction (table+table->insertionAction) {} AAT::InsertionSubtable<AAT::ExtendedTypes>::driver_context_t::driver_context_t(AAT::InsertionSubtable<AAT::ExtendedTypes> const*, AAT::hb_aat_apply_context_t*) Line | Count | Source | 745 | 28.1k | insertionAction (table+table->insertionAction) {} |
AAT::InsertionSubtable<AAT::ObsoleteTypes>::driver_context_t::driver_context_t(AAT::InsertionSubtable<AAT::ObsoleteTypes> const*, AAT::hb_aat_apply_context_t*) Line | Count | Source | 745 | 8.69k | insertionAction (table+table->insertionAction) {} |
|
746 | | |
747 | | bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, |
748 | | const Entry<EntryData> &entry) |
749 | 40.3M | { |
750 | 40.3M | return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) && |
751 | 40.3M | (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF); |
752 | 40.3M | } AAT::InsertionSubtable<AAT::ExtendedTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>*, AAT::Entry<AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData> const&) Line | Count | Source | 749 | 26.5M | { | 750 | 26.5M | return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) && | 751 | 26.5M | (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF); | 752 | 26.5M | } |
AAT::InsertionSubtable<AAT::ObsoleteTypes>::driver_context_t::is_actionable(AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>*, AAT::Entry<AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData> const&) Line | Count | Source | 749 | 13.8M | { | 750 | 13.8M | return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) && | 751 | 13.8M | (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF); | 752 | 13.8M | } |
|
753 | | void transition (StateTableDriver<Types, EntryData> *driver, |
754 | | const Entry<EntryData> &entry) |
755 | 27.3M | { |
756 | 27.3M | hb_buffer_t *buffer = driver->buffer; |
757 | 27.3M | unsigned int flags = entry.flags; |
758 | | |
759 | 27.3M | unsigned mark_loc = buffer->out_len; |
760 | | |
761 | 27.3M | if (entry.data.markedInsertIndex != 0xFFFF) |
762 | 12.0M | { |
763 | 12.0M | unsigned int count = (flags & MarkedInsertCount); |
764 | 12.0M | if (unlikely ((buffer->max_ops -= count) <= 0)) return; |
765 | 7.38M | unsigned int start = entry.data.markedInsertIndex; |
766 | 7.38M | const HBGlyphID16 *glyphs = &insertionAction[start]; |
767 | 7.38M | if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; |
768 | | |
769 | 7.38M | bool before = flags & MarkedInsertBefore; |
770 | | |
771 | 7.38M | unsigned int end = buffer->out_len; |
772 | 7.38M | if (unlikely (!buffer->move_to (mark))) return; |
773 | | |
774 | 7.38M | if (buffer->idx < buffer->len && !before) |
775 | 6.25M | if (unlikely (!buffer->copy_glyph ())) return; |
776 | | /* TODO We ignore KashidaLike setting. */ |
777 | 7.38M | if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; |
778 | 7.38M | if (buffer->idx < buffer->len && !before) |
779 | 6.25M | buffer->skip_glyph (); |
780 | | |
781 | 7.38M | if (unlikely (!buffer->move_to (end + count))) return; |
782 | | |
783 | 7.38M | buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len)); |
784 | 7.38M | } |
785 | | |
786 | 22.7M | if (flags & SetMark) |
787 | 12.9M | mark = mark_loc; |
788 | | |
789 | 22.7M | if (entry.data.currentInsertIndex != 0xFFFF) |
790 | 11.8M | { |
791 | 11.8M | unsigned int count = (flags & CurrentInsertCount) >> 5; |
792 | 11.8M | if (unlikely ((buffer->max_ops -= count) <= 0)) return; |
793 | 10.6M | unsigned int start = entry.data.currentInsertIndex; |
794 | 10.6M | const HBGlyphID16 *glyphs = &insertionAction[start]; |
795 | 10.6M | if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; |
796 | | |
797 | 10.6M | bool before = flags & CurrentInsertBefore; |
798 | | |
799 | 10.6M | unsigned int end = buffer->out_len; |
800 | | |
801 | 10.6M | if (buffer->idx < buffer->len && !before) |
802 | 3.82M | if (unlikely (!buffer->copy_glyph ())) return; |
803 | | /* TODO We ignore KashidaLike setting. */ |
804 | 10.6M | if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; |
805 | 10.6M | if (buffer->idx < buffer->len && !before) |
806 | 3.82M | buffer->skip_glyph (); |
807 | | |
808 | | /* Humm. Not sure where to move to. There's this wording under |
809 | | * DontAdvance flag: |
810 | | * |
811 | | * "If set, don't update the glyph index before going to the new state. |
812 | | * This does not mean that the glyph pointed to is the same one as |
813 | | * before. If you've made insertions immediately downstream of the |
814 | | * current glyph, the next glyph processed would in fact be the first |
815 | | * one inserted." |
816 | | * |
817 | | * This suggests that if DontAdvance is NOT set, we should move to |
818 | | * end+count. If it *was*, then move to end, such that newly inserted |
819 | | * glyphs are now visible. |
820 | | * |
821 | | * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417 |
822 | | */ |
823 | 10.6M | if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return; |
824 | 10.6M | } |
825 | 22.7M | } AAT::InsertionSubtable<AAT::ExtendedTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>*, AAT::Entry<AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData> const&) Line | Count | Source | 755 | 15.6M | { | 756 | 15.6M | hb_buffer_t *buffer = driver->buffer; | 757 | 15.6M | unsigned int flags = entry.flags; | 758 | | | 759 | 15.6M | unsigned mark_loc = buffer->out_len; | 760 | | | 761 | 15.6M | if (entry.data.markedInsertIndex != 0xFFFF) | 762 | 1.64M | { | 763 | 1.64M | unsigned int count = (flags & MarkedInsertCount); | 764 | 1.64M | if (unlikely ((buffer->max_ops -= count) <= 0)) return; | 765 | 987k | unsigned int start = entry.data.markedInsertIndex; | 766 | 987k | const HBGlyphID16 *glyphs = &insertionAction[start]; | 767 | 987k | if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; | 768 | | | 769 | 987k | bool before = flags & MarkedInsertBefore; | 770 | | | 771 | 987k | unsigned int end = buffer->out_len; | 772 | 987k | if (unlikely (!buffer->move_to (mark))) return; | 773 | | | 774 | 987k | if (buffer->idx < buffer->len && !before) | 775 | 657k | if (unlikely (!buffer->copy_glyph ())) return; | 776 | | /* TODO We ignore KashidaLike setting. */ | 777 | 987k | if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; | 778 | 987k | if (buffer->idx < buffer->len && !before) | 779 | 657k | buffer->skip_glyph (); | 780 | | | 781 | 987k | if (unlikely (!buffer->move_to (end + count))) return; | 782 | | | 783 | 987k | buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len)); | 784 | 987k | } | 785 | | | 786 | 14.9M | if (flags & SetMark) | 787 | 6.03M | mark = mark_loc; | 788 | | | 789 | 14.9M | if (entry.data.currentInsertIndex != 0xFFFF) | 790 | 4.66M | { | 791 | 4.66M | unsigned int count = (flags & CurrentInsertCount) >> 5; | 792 | 4.66M | if (unlikely ((buffer->max_ops -= count) <= 0)) return; | 793 | 3.54M | unsigned int start = entry.data.currentInsertIndex; | 794 | 3.54M | const HBGlyphID16 *glyphs = &insertionAction[start]; | 795 | 3.54M | if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; | 796 | | | 797 | 3.54M | bool before = flags & CurrentInsertBefore; | 798 | | | 799 | 3.54M | unsigned int end = buffer->out_len; | 800 | | | 801 | 3.54M | if (buffer->idx < buffer->len && !before) | 802 | 2.90M | if (unlikely (!buffer->copy_glyph ())) return; | 803 | | /* TODO We ignore KashidaLike setting. */ | 804 | 3.54M | if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; | 805 | 3.54M | if (buffer->idx < buffer->len && !before) | 806 | 2.90M | buffer->skip_glyph (); | 807 | | | 808 | | /* Humm. Not sure where to move to. There's this wording under | 809 | | * DontAdvance flag: | 810 | | * | 811 | | * "If set, don't update the glyph index before going to the new state. | 812 | | * This does not mean that the glyph pointed to is the same one as | 813 | | * before. If you've made insertions immediately downstream of the | 814 | | * current glyph, the next glyph processed would in fact be the first | 815 | | * one inserted." | 816 | | * | 817 | | * This suggests that if DontAdvance is NOT set, we should move to | 818 | | * end+count. If it *was*, then move to end, such that newly inserted | 819 | | * glyphs are now visible. | 820 | | * | 821 | | * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417 | 822 | | */ | 823 | 3.54M | if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return; | 824 | 3.54M | } | 825 | 14.9M | } |
AAT::InsertionSubtable<AAT::ObsoleteTypes>::driver_context_t::transition(AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>*, AAT::Entry<AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData> const&) Line | Count | Source | 755 | 11.7M | { | 756 | 11.7M | hb_buffer_t *buffer = driver->buffer; | 757 | 11.7M | unsigned int flags = entry.flags; | 758 | | | 759 | 11.7M | unsigned mark_loc = buffer->out_len; | 760 | | | 761 | 11.7M | if (entry.data.markedInsertIndex != 0xFFFF) | 762 | 10.3M | { | 763 | 10.3M | unsigned int count = (flags & MarkedInsertCount); | 764 | 10.3M | if (unlikely ((buffer->max_ops -= count) <= 0)) return; | 765 | 6.40M | unsigned int start = entry.data.markedInsertIndex; | 766 | 6.40M | const HBGlyphID16 *glyphs = &insertionAction[start]; | 767 | 6.40M | if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; | 768 | | | 769 | 6.40M | bool before = flags & MarkedInsertBefore; | 770 | | | 771 | 6.40M | unsigned int end = buffer->out_len; | 772 | 6.40M | if (unlikely (!buffer->move_to (mark))) return; | 773 | | | 774 | 6.40M | if (buffer->idx < buffer->len && !before) | 775 | 5.59M | if (unlikely (!buffer->copy_glyph ())) return; | 776 | | /* TODO We ignore KashidaLike setting. */ | 777 | 6.40M | if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; | 778 | 6.40M | if (buffer->idx < buffer->len && !before) | 779 | 5.59M | buffer->skip_glyph (); | 780 | | | 781 | 6.40M | if (unlikely (!buffer->move_to (end + count))) return; | 782 | | | 783 | 6.40M | buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len)); | 784 | 6.40M | } | 785 | | | 786 | 7.77M | if (flags & SetMark) | 787 | 6.87M | mark = mark_loc; | 788 | | | 789 | 7.77M | if (entry.data.currentInsertIndex != 0xFFFF) | 790 | 7.16M | { | 791 | 7.16M | unsigned int count = (flags & CurrentInsertCount) >> 5; | 792 | 7.16M | if (unlikely ((buffer->max_ops -= count) <= 0)) return; | 793 | 7.06M | unsigned int start = entry.data.currentInsertIndex; | 794 | 7.06M | const HBGlyphID16 *glyphs = &insertionAction[start]; | 795 | 7.06M | if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; | 796 | | | 797 | 7.06M | bool before = flags & CurrentInsertBefore; | 798 | | | 799 | 7.06M | unsigned int end = buffer->out_len; | 800 | | | 801 | 7.06M | if (buffer->idx < buffer->len && !before) | 802 | 925k | if (unlikely (!buffer->copy_glyph ())) return; | 803 | | /* TODO We ignore KashidaLike setting. */ | 804 | 7.06M | if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; | 805 | 7.06M | if (buffer->idx < buffer->len && !before) | 806 | 925k | buffer->skip_glyph (); | 807 | | | 808 | | /* Humm. Not sure where to move to. There's this wording under | 809 | | * DontAdvance flag: | 810 | | * | 811 | | * "If set, don't update the glyph index before going to the new state. | 812 | | * This does not mean that the glyph pointed to is the same one as | 813 | | * before. If you've made insertions immediately downstream of the | 814 | | * current glyph, the next glyph processed would in fact be the first | 815 | | * one inserted." | 816 | | * | 817 | | * This suggests that if DontAdvance is NOT set, we should move to | 818 | | * end+count. If it *was*, then move to end, such that newly inserted | 819 | | * glyphs are now visible. | 820 | | * | 821 | | * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417 | 822 | | */ | 823 | 7.06M | if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return; | 824 | 7.06M | } | 825 | 7.77M | } |
|
826 | | |
827 | | public: |
828 | | bool ret; |
829 | | private: |
830 | | hb_aat_apply_context_t *c; |
831 | | unsigned int mark; |
832 | | const UnsizedArrayOf<HBGlyphID16> &insertionAction; |
833 | | }; |
834 | | |
835 | | bool apply (hb_aat_apply_context_t *c) const |
836 | 36.8k | { |
837 | 36.8k | TRACE_APPLY (this); |
838 | | |
839 | 36.8k | driver_context_t dc (this, c); |
840 | | |
841 | 36.8k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); |
842 | 36.8k | driver.drive (&dc, c); |
843 | | |
844 | 36.8k | return_trace (dc.ret); |
845 | 36.8k | } AAT::InsertionSubtable<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 836 | 28.1k | { | 837 | 28.1k | TRACE_APPLY (this); | 838 | | | 839 | 28.1k | driver_context_t dc (this, c); | 840 | | | 841 | 28.1k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 842 | 28.1k | driver.drive (&dc, c); | 843 | | | 844 | 28.1k | return_trace (dc.ret); | 845 | 28.1k | } |
AAT::InsertionSubtable<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 836 | 8.69k | { | 837 | 8.69k | TRACE_APPLY (this); | 838 | | | 839 | 8.69k | driver_context_t dc (this, c); | 840 | | | 841 | 8.69k | StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); | 842 | 8.69k | driver.drive (&dc, c); | 843 | | | 844 | 8.69k | return_trace (dc.ret); | 845 | 8.69k | } |
|
846 | | |
847 | | bool sanitize (hb_sanitize_context_t *c) const |
848 | 6.95k | { |
849 | 6.95k | TRACE_SANITIZE (this); |
850 | | /* The rest of array sanitizations are done at run-time. */ |
851 | 6.95k | return_trace (c->check_struct (this) && machine.sanitize (c) && |
852 | 6.95k | insertionAction); |
853 | 6.95k | } AAT::InsertionSubtable<AAT::ExtendedTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 848 | 3.97k | { | 849 | 3.97k | TRACE_SANITIZE (this); | 850 | | /* The rest of array sanitizations are done at run-time. */ | 851 | 3.97k | return_trace (c->check_struct (this) && machine.sanitize (c) && | 852 | 3.97k | insertionAction); | 853 | 3.97k | } |
AAT::InsertionSubtable<AAT::ObsoleteTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 848 | 2.98k | { | 849 | 2.98k | TRACE_SANITIZE (this); | 850 | | /* The rest of array sanitizations are done at run-time. */ | 851 | 2.98k | return_trace (c->check_struct (this) && machine.sanitize (c) && | 852 | 2.98k | insertionAction); | 853 | 2.98k | } |
|
854 | | |
855 | | protected: |
856 | | StateTable<Types, EntryData> |
857 | | machine; |
858 | | NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT> |
859 | | insertionAction; /* Byte offset from stateHeader to the start of |
860 | | * the insertion glyph table. */ |
861 | | public: |
862 | | DEFINE_SIZE_STATIC (20); |
863 | | }; |
864 | | |
865 | | |
866 | | struct Feature |
867 | | { |
868 | | bool sanitize (hb_sanitize_context_t *c) const |
869 | 0 | { |
870 | 0 | TRACE_SANITIZE (this); |
871 | 0 | return_trace (c->check_struct (this)); |
872 | 0 | } |
873 | | |
874 | | public: |
875 | | HBUINT16 featureType; /* The type of feature. */ |
876 | | HBUINT16 featureSetting; /* The feature's setting (aka selector). */ |
877 | | HBUINT32 enableFlags; /* Flags for the settings that this feature |
878 | | * and setting enables. */ |
879 | | HBUINT32 disableFlags; /* Complement of flags for the settings that this |
880 | | * feature and setting disable. */ |
881 | | |
882 | | public: |
883 | | DEFINE_SIZE_STATIC (12); |
884 | | }; |
885 | | |
886 | | template <typename Types> |
887 | | struct ChainSubtable |
888 | | { |
889 | | typedef typename Types::HBUINT HBUINT; |
890 | | |
891 | | template <typename T> |
892 | | friend struct Chain; |
893 | | |
894 | 322k | unsigned int get_size () const { return length; } AAT::ChainSubtable<AAT::ExtendedTypes>::get_size() const Line | Count | Source | 894 | 188k | unsigned int get_size () const { return length; } |
AAT::ChainSubtable<AAT::ObsoleteTypes>::get_size() const Line | Count | Source | 894 | 134k | unsigned int get_size () const { return length; } |
|
895 | 148k | unsigned int get_type () const { return coverage & 0xFF; } AAT::ChainSubtable<AAT::ExtendedTypes>::get_type() const Line | Count | Source | 895 | 92.2k | unsigned int get_type () const { return coverage & 0xFF; } |
AAT::ChainSubtable<AAT::ObsoleteTypes>::get_type() const Line | Count | Source | 895 | 56.7k | unsigned int get_type () const { return coverage & 0xFF; } |
|
896 | 377k | unsigned int get_coverage () const { return coverage >> (sizeof (HBUINT) * 8 - 8); } AAT::ChainSubtable<AAT::ExtendedTypes>::get_coverage() const Line | Count | Source | 896 | 246k | unsigned int get_coverage () const { return coverage >> (sizeof (HBUINT) * 8 - 8); } |
AAT::ChainSubtable<AAT::ObsoleteTypes>::get_coverage() const Line | Count | Source | 896 | 130k | unsigned int get_coverage () const { return coverage >> (sizeof (HBUINT) * 8 - 8); } |
|
897 | | |
898 | | enum Coverage |
899 | | { |
900 | | Vertical = 0x80, /* If set, this subtable will only be applied |
901 | | * to vertical text. If clear, this subtable |
902 | | * will only be applied to horizontal text. */ |
903 | | Backwards = 0x40, /* If set, this subtable will process glyphs |
904 | | * in descending order. If clear, it will |
905 | | * process the glyphs in ascending order. */ |
906 | | AllDirections = 0x20, /* If set, this subtable will be applied to |
907 | | * both horizontal and vertical text (i.e. |
908 | | * the state of bit 0x80000000 is ignored). */ |
909 | | Logical = 0x10, /* If set, this subtable will process glyphs |
910 | | * in logical order (or reverse logical order, |
911 | | * depending on the value of bit 0x80000000). */ |
912 | | }; |
913 | | enum Type |
914 | | { |
915 | | Rearrangement = 0, |
916 | | Contextual = 1, |
917 | | Ligature = 2, |
918 | | Noncontextual = 4, |
919 | | Insertion = 5 |
920 | | }; |
921 | | |
922 | | template <typename context_t, typename ...Ts> |
923 | | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
924 | 148k | { |
925 | 148k | unsigned int subtable_type = get_type (); |
926 | 148k | TRACE_DISPATCH (this, subtable_type); |
927 | 148k | switch (subtable_type) { |
928 | 31.2k | case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...)); |
929 | 27.9k | case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...)); |
930 | 20.4k | case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...)); |
931 | 8.56k | case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...)); |
932 | 43.7k | case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...)); |
933 | 16.9k | default: return_trace (c->default_return_value ()); |
934 | 148k | } |
935 | 148k | } hb_sanitize_context_t::return_t AAT::ChainSubtable<AAT::ExtendedTypes>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const Line | Count | Source | 924 | 10.8k | { | 925 | 10.8k | unsigned int subtable_type = get_type (); | 926 | 10.8k | TRACE_DISPATCH (this, subtable_type); | 927 | 10.8k | switch (subtable_type) { | 928 | 1.47k | case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...)); | 929 | 2.42k | case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...)); | 930 | 2.00k | case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...)); | 931 | 684 | case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...)); | 932 | 3.97k | case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...)); | 933 | 331 | default: return_trace (c->default_return_value ()); | 934 | 10.8k | } | 935 | 10.8k | } |
hb_sanitize_context_t::return_t AAT::ChainSubtable<AAT::ObsoleteTypes>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const Line | Count | Source | 924 | 16.0k | { | 925 | 16.0k | unsigned int subtable_type = get_type (); | 926 | 16.0k | TRACE_DISPATCH (this, subtable_type); | 927 | 16.0k | switch (subtable_type) { | 928 | 4.45k | case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...)); | 929 | 1.23k | case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...)); | 930 | 949 | case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...)); | 931 | 555 | case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...)); | 932 | 2.98k | case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...)); | 933 | 5.91k | default: return_trace (c->default_return_value ()); | 934 | 16.0k | } | 935 | 16.0k | } |
AAT::hb_aat_apply_context_t::return_t AAT::ChainSubtable<AAT::ExtendedTypes>::dispatch<AAT::hb_aat_apply_context_t>(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 924 | 81.3k | { | 925 | 81.3k | unsigned int subtable_type = get_type (); | 926 | 81.3k | TRACE_DISPATCH (this, subtable_type); | 927 | 81.3k | switch (subtable_type) { | 928 | 12.1k | case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...)); | 929 | 20.7k | case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...)); | 930 | 14.5k | case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...)); | 931 | 4.59k | case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...)); | 932 | 28.1k | case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...)); | 933 | 1.17k | default: return_trace (c->default_return_value ()); | 934 | 81.3k | } | 935 | 81.3k | } |
AAT::hb_aat_apply_context_t::return_t AAT::ChainSubtable<AAT::ObsoleteTypes>::dispatch<AAT::hb_aat_apply_context_t>(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 924 | 40.6k | { | 925 | 40.6k | unsigned int subtable_type = get_type (); | 926 | 40.6k | TRACE_DISPATCH (this, subtable_type); | 927 | 40.6k | switch (subtable_type) { | 928 | 13.1k | case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...)); | 929 | 3.55k | case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...)); | 930 | 2.92k | case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...)); | 931 | 2.72k | case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...)); | 932 | 8.69k | case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...)); | 933 | 9.54k | default: return_trace (c->default_return_value ()); | 934 | 40.6k | } | 935 | 40.6k | } |
|
936 | | |
937 | | bool apply (hb_aat_apply_context_t *c) const |
938 | 121k | { |
939 | 121k | TRACE_APPLY (this); |
940 | 121k | hb_sanitize_with_object_t with (&c->sanitizer, this); |
941 | 121k | return_trace (dispatch (c)); |
942 | 121k | } AAT::ChainSubtable<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 938 | 81.3k | { | 939 | 81.3k | TRACE_APPLY (this); | 940 | 81.3k | hb_sanitize_with_object_t with (&c->sanitizer, this); | 941 | 81.3k | return_trace (dispatch (c)); | 942 | 81.3k | } |
AAT::ChainSubtable<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 938 | 40.6k | { | 939 | 40.6k | TRACE_APPLY (this); | 940 | 40.6k | hb_sanitize_with_object_t with (&c->sanitizer, this); | 941 | 40.6k | return_trace (dispatch (c)); | 942 | 40.6k | } |
|
943 | | |
944 | | bool sanitize (hb_sanitize_context_t *c) const |
945 | 27.1k | { |
946 | 27.1k | TRACE_SANITIZE (this); |
947 | 27.1k | if (!length.sanitize (c) || |
948 | 27.1k | length <= min_size || |
949 | 27.1k | !c->check_range (this, length)) |
950 | 161 | return_trace (false); |
951 | | |
952 | 26.9k | hb_sanitize_with_object_t with (c, this); |
953 | 26.9k | return_trace (dispatch (c)); |
954 | 27.1k | } AAT::ChainSubtable<AAT::ExtendedTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 945 | 10.9k | { | 946 | 10.9k | TRACE_SANITIZE (this); | 947 | 10.9k | if (!length.sanitize (c) || | 948 | 10.9k | length <= min_size || | 949 | 10.9k | !c->check_range (this, length)) | 950 | 97 | return_trace (false); | 951 | | | 952 | 10.8k | hb_sanitize_with_object_t with (c, this); | 953 | 10.8k | return_trace (dispatch (c)); | 954 | 10.9k | } |
AAT::ChainSubtable<AAT::ObsoleteTypes>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 945 | 16.1k | { | 946 | 16.1k | TRACE_SANITIZE (this); | 947 | 16.1k | if (!length.sanitize (c) || | 948 | 16.1k | length <= min_size || | 949 | 16.1k | !c->check_range (this, length)) | 950 | 64 | return_trace (false); | 951 | | | 952 | 16.0k | hb_sanitize_with_object_t with (c, this); | 953 | 16.0k | return_trace (dispatch (c)); | 954 | 16.1k | } |
|
955 | | |
956 | | protected: |
957 | | HBUINT length; /* Total subtable length, including this header. */ |
958 | | HBUINT coverage; /* Coverage flags and subtable type. */ |
959 | | HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */ |
960 | | union { |
961 | | RearrangementSubtable<Types> rearrangement; |
962 | | ContextualSubtable<Types> contextual; |
963 | | LigatureSubtable<Types> ligature; |
964 | | NoncontextualSubtable<Types> noncontextual; |
965 | | InsertionSubtable<Types> insertion; |
966 | | } u; |
967 | | public: |
968 | | DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4); |
969 | | }; |
970 | | |
971 | | template <typename Types> |
972 | | struct Chain |
973 | | { |
974 | | typedef typename Types::HBUINT HBUINT; |
975 | | |
976 | | hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const |
977 | 104k | { |
978 | 104k | hb_mask_t flags = defaultFlags; |
979 | 104k | { |
980 | 104k | unsigned int count = featureCount; |
981 | 963k | for (unsigned i = 0; i < count; i++) |
982 | 858k | { |
983 | 858k | const Feature &feature = featureZ[i]; |
984 | 858k | hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType; |
985 | 858k | hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting; |
986 | 858k | retry: |
987 | | // Check whether this type/setting pair was requested in the map, and if so, apply its flags. |
988 | | // (The search here only looks at the type and setting fields of feature_info_t.) |
989 | 858k | hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 }; |
990 | 858k | if (map->current_features.bsearch (info)) |
991 | 0 | { |
992 | 0 | flags &= feature.disableFlags; |
993 | 0 | flags |= feature.enableFlags; |
994 | 0 | } |
995 | 858k | else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE && setting == HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS) |
996 | 41 | { |
997 | | /* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */ |
998 | 41 | type = HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE; |
999 | 41 | setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS; |
1000 | 41 | goto retry; |
1001 | 41 | } |
1002 | 858k | #ifndef HB_NO_AAT |
1003 | 858k | else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting && |
1004 | | /* TODO: Rudimentary language matching. */ |
1005 | 858k | hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language)) |
1006 | 0 | { |
1007 | 0 | flags &= feature.disableFlags; |
1008 | 0 | flags |= feature.enableFlags; |
1009 | 0 | } |
1010 | 858k | #endif |
1011 | 858k | } |
1012 | 104k | } |
1013 | 104k | return flags; |
1014 | 104k | } AAT::Chain<AAT::ExtendedTypes>::compile_flags(hb_aat_map_builder_t const*) const Line | Count | Source | 977 | 46.2k | { | 978 | 46.2k | hb_mask_t flags = defaultFlags; | 979 | 46.2k | { | 980 | 46.2k | unsigned int count = featureCount; | 981 | 146k | for (unsigned i = 0; i < count; i++) | 982 | 99.8k | { | 983 | 99.8k | const Feature &feature = featureZ[i]; | 984 | 99.8k | hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType; | 985 | 99.8k | hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting; | 986 | 99.8k | retry: | 987 | | // Check whether this type/setting pair was requested in the map, and if so, apply its flags. | 988 | | // (The search here only looks at the type and setting fields of feature_info_t.) | 989 | 99.8k | hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 }; | 990 | 99.8k | if (map->current_features.bsearch (info)) | 991 | 0 | { | 992 | 0 | flags &= feature.disableFlags; | 993 | 0 | flags |= feature.enableFlags; | 994 | 0 | } | 995 | 99.8k | else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE && setting == HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS) | 996 | 0 | { | 997 | | /* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */ | 998 | 0 | type = HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE; | 999 | 0 | setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS; | 1000 | 0 | goto retry; | 1001 | 0 | } | 1002 | 99.8k | #ifndef HB_NO_AAT | 1003 | 99.8k | else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting && | 1004 | | /* TODO: Rudimentary language matching. */ | 1005 | 99.8k | hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language)) | 1006 | 0 | { | 1007 | 0 | flags &= feature.disableFlags; | 1008 | 0 | flags |= feature.enableFlags; | 1009 | 0 | } | 1010 | 99.8k | #endif | 1011 | 99.8k | } | 1012 | 46.2k | } | 1013 | 46.2k | return flags; | 1014 | 46.2k | } |
AAT::Chain<AAT::ObsoleteTypes>::compile_flags(hb_aat_map_builder_t const*) const Line | Count | Source | 977 | 58.3k | { | 978 | 58.3k | hb_mask_t flags = defaultFlags; | 979 | 58.3k | { | 980 | 58.3k | unsigned int count = featureCount; | 981 | 817k | for (unsigned i = 0; i < count; i++) | 982 | 758k | { | 983 | 758k | const Feature &feature = featureZ[i]; | 984 | 758k | hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType; | 985 | 758k | hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting; | 986 | 758k | retry: | 987 | | // Check whether this type/setting pair was requested in the map, and if so, apply its flags. | 988 | | // (The search here only looks at the type and setting fields of feature_info_t.) | 989 | 758k | hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 }; | 990 | 758k | if (map->current_features.bsearch (info)) | 991 | 0 | { | 992 | 0 | flags &= feature.disableFlags; | 993 | 0 | flags |= feature.enableFlags; | 994 | 0 | } | 995 | 758k | else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE && setting == HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS) | 996 | 41 | { | 997 | | /* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */ | 998 | 41 | type = HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE; | 999 | 41 | setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS; | 1000 | 41 | goto retry; | 1001 | 41 | } | 1002 | 758k | #ifndef HB_NO_AAT | 1003 | 758k | else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting && | 1004 | | /* TODO: Rudimentary language matching. */ | 1005 | 758k | hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language)) | 1006 | 0 | { | 1007 | 0 | flags &= feature.disableFlags; | 1008 | 0 | flags |= feature.enableFlags; | 1009 | 0 | } | 1010 | 758k | #endif | 1011 | 758k | } | 1012 | 58.3k | } | 1013 | 58.3k | return flags; | 1014 | 58.3k | } |
|
1015 | | |
1016 | | void apply (hb_aat_apply_context_t *c) const |
1017 | 109k | { |
1018 | 109k | const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); |
1019 | 109k | unsigned int count = subtableCount; |
1020 | 258k | for (unsigned int i = 0; i < count; i++) |
1021 | 149k | { |
1022 | 149k | bool reverse; |
1023 | | |
1024 | 149k | if (hb_none (hb_iter (c->range_flags) | |
1025 | 149k | hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); }))) AAT::Chain<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const::{lambda(hb_aat_map_t::range_flags_t)#1}::operator()(hb_aat_map_t::range_flags_t) const Line | Count | Source | 1025 | 83.5k | hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); }))) |
AAT::Chain<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const::{lambda(hb_aat_map_t::range_flags_t)#1}::operator()(hb_aat_map_t::range_flags_t) const Line | Count | Source | 1025 | 56.0k | hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); }))) |
|
1026 | 26.7k | goto skip; |
1027 | 122k | c->subtable_flags = subtable->subFeatureFlags; |
1028 | | |
1029 | 122k | if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) && |
1030 | 122k | HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != |
1031 | 10.9k | bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical)) |
1032 | 712 | goto skip; |
1033 | | |
1034 | | /* Buffer contents is always in logical direction. Determine if |
1035 | | * we need to reverse before applying this subtable. We reverse |
1036 | | * back after if we did reverse indeed. |
1037 | | * |
1038 | | * Quoting the spac: |
1039 | | * """ |
1040 | | * Bits 28 and 30 of the coverage field control the order in which |
1041 | | * glyphs are processed when the subtable is run by the layout engine. |
1042 | | * Bit 28 is used to indicate if the glyph processing direction is |
1043 | | * the same as logical order or layout order. Bit 30 is used to |
1044 | | * indicate whether glyphs are processed forwards or backwards within |
1045 | | * that order. |
1046 | | |
1047 | | Bit 30 Bit 28 Interpretation for Horizontal Text |
1048 | | 0 0 The subtable is processed in layout order |
1049 | | (the same order as the glyphs, which is |
1050 | | always left-to-right). |
1051 | | 1 0 The subtable is processed in reverse layout order |
1052 | | (the order opposite that of the glyphs, which is |
1053 | | always right-to-left). |
1054 | | 0 1 The subtable is processed in logical order |
1055 | | (the same order as the characters, which may be |
1056 | | left-to-right or right-to-left). |
1057 | | 1 1 The subtable is processed in reverse logical order |
1058 | | (the order opposite that of the characters, which |
1059 | | may be right-to-left or left-to-right). |
1060 | | */ |
1061 | 121k | reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ? |
1062 | 24.1k | bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) : |
1063 | 121k | bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) != |
1064 | 97.8k | HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); |
1065 | | |
1066 | 121k | if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index)) |
1067 | 0 | goto skip; |
1068 | | |
1069 | 121k | if (reverse) |
1070 | 34.1k | c->buffer->reverse (); |
1071 | | |
1072 | 121k | subtable->apply (c); |
1073 | | |
1074 | 121k | if (reverse) |
1075 | 34.1k | c->buffer->reverse (); |
1076 | | |
1077 | 121k | (void) c->buffer->message (c->font, "end chainsubtable %u", c->lookup_index); |
1078 | | |
1079 | 121k | if (unlikely (!c->buffer->successful)) return; |
1080 | | |
1081 | 148k | skip: |
1082 | 148k | subtable = &StructAfter<ChainSubtable<Types>> (*subtable); |
1083 | 148k | c->set_lookup_index (c->lookup_index + 1); |
1084 | 148k | } |
1085 | 109k | } AAT::Chain<AAT::ExtendedTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 1017 | 47.2k | { | 1018 | 47.2k | const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); | 1019 | 47.2k | unsigned int count = subtableCount; | 1020 | 133k | for (unsigned int i = 0; i < count; i++) | 1021 | 85.9k | { | 1022 | 85.9k | bool reverse; | 1023 | | | 1024 | 85.9k | if (hb_none (hb_iter (c->range_flags) | | 1025 | 85.9k | hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); }))) | 1026 | 4.29k | goto skip; | 1027 | 81.6k | c->subtable_flags = subtable->subFeatureFlags; | 1028 | | | 1029 | 81.6k | if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) && | 1030 | 81.6k | HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != | 1031 | 2.32k | bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical)) | 1032 | 327 | goto skip; | 1033 | | | 1034 | | /* Buffer contents is always in logical direction. Determine if | 1035 | | * we need to reverse before applying this subtable. We reverse | 1036 | | * back after if we did reverse indeed. | 1037 | | * | 1038 | | * Quoting the spac: | 1039 | | * """ | 1040 | | * Bits 28 and 30 of the coverage field control the order in which | 1041 | | * glyphs are processed when the subtable is run by the layout engine. | 1042 | | * Bit 28 is used to indicate if the glyph processing direction is | 1043 | | * the same as logical order or layout order. Bit 30 is used to | 1044 | | * indicate whether glyphs are processed forwards or backwards within | 1045 | | * that order. | 1046 | | | 1047 | | Bit 30 Bit 28 Interpretation for Horizontal Text | 1048 | | 0 0 The subtable is processed in layout order | 1049 | | (the same order as the glyphs, which is | 1050 | | always left-to-right). | 1051 | | 1 0 The subtable is processed in reverse layout order | 1052 | | (the order opposite that of the glyphs, which is | 1053 | | always right-to-left). | 1054 | | 0 1 The subtable is processed in logical order | 1055 | | (the same order as the characters, which may be | 1056 | | left-to-right or right-to-left). | 1057 | | 1 1 The subtable is processed in reverse logical order | 1058 | | (the order opposite that of the characters, which | 1059 | | may be right-to-left or left-to-right). | 1060 | | */ | 1061 | 81.3k | reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ? | 1062 | 2.41k | bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) : | 1063 | 81.3k | bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) != | 1064 | 78.9k | HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); | 1065 | | | 1066 | 81.3k | if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index)) | 1067 | 0 | goto skip; | 1068 | | | 1069 | 81.3k | if (reverse) | 1070 | 3.54k | c->buffer->reverse (); | 1071 | | | 1072 | 81.3k | subtable->apply (c); | 1073 | | | 1074 | 81.3k | if (reverse) | 1075 | 3.54k | c->buffer->reverse (); | 1076 | | | 1077 | 81.3k | (void) c->buffer->message (c->font, "end chainsubtable %u", c->lookup_index); | 1078 | | | 1079 | 81.3k | if (unlikely (!c->buffer->successful)) return; | 1080 | | | 1081 | 85.7k | skip: | 1082 | 85.7k | subtable = &StructAfter<ChainSubtable<Types>> (*subtable); | 1083 | 85.7k | c->set_lookup_index (c->lookup_index + 1); | 1084 | 85.7k | } | 1085 | 47.2k | } |
AAT::Chain<AAT::ObsoleteTypes>::apply(AAT::hb_aat_apply_context_t*) const Line | Count | Source | 1017 | 62.6k | { | 1018 | 62.6k | const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); | 1019 | 62.6k | unsigned int count = subtableCount; | 1020 | 125k | for (unsigned int i = 0; i < count; i++) | 1021 | 63.4k | { | 1022 | 63.4k | bool reverse; | 1023 | | | 1024 | 63.4k | if (hb_none (hb_iter (c->range_flags) | | 1025 | 63.4k | hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); }))) | 1026 | 22.4k | goto skip; | 1027 | 41.0k | c->subtable_flags = subtable->subFeatureFlags; | 1028 | | | 1029 | 41.0k | if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) && | 1030 | 41.0k | HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != | 1031 | 8.59k | bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical)) | 1032 | 385 | goto skip; | 1033 | | | 1034 | | /* Buffer contents is always in logical direction. Determine if | 1035 | | * we need to reverse before applying this subtable. We reverse | 1036 | | * back after if we did reverse indeed. | 1037 | | * | 1038 | | * Quoting the spac: | 1039 | | * """ | 1040 | | * Bits 28 and 30 of the coverage field control the order in which | 1041 | | * glyphs are processed when the subtable is run by the layout engine. | 1042 | | * Bit 28 is used to indicate if the glyph processing direction is | 1043 | | * the same as logical order or layout order. Bit 30 is used to | 1044 | | * indicate whether glyphs are processed forwards or backwards within | 1045 | | * that order. | 1046 | | | 1047 | | Bit 30 Bit 28 Interpretation for Horizontal Text | 1048 | | 0 0 The subtable is processed in layout order | 1049 | | (the same order as the glyphs, which is | 1050 | | always left-to-right). | 1051 | | 1 0 The subtable is processed in reverse layout order | 1052 | | (the order opposite that of the glyphs, which is | 1053 | | always right-to-left). | 1054 | | 0 1 The subtable is processed in logical order | 1055 | | (the same order as the characters, which may be | 1056 | | left-to-right or right-to-left). | 1057 | | 1 1 The subtable is processed in reverse logical order | 1058 | | (the order opposite that of the characters, which | 1059 | | may be right-to-left or left-to-right). | 1060 | | */ | 1061 | 40.6k | reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ? | 1062 | 21.7k | bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) : | 1063 | 40.6k | bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) != | 1064 | 18.8k | HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); | 1065 | | | 1066 | 40.6k | if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index)) | 1067 | 0 | goto skip; | 1068 | | | 1069 | 40.6k | if (reverse) | 1070 | 30.5k | c->buffer->reverse (); | 1071 | | | 1072 | 40.6k | subtable->apply (c); | 1073 | | | 1074 | 40.6k | if (reverse) | 1075 | 30.5k | c->buffer->reverse (); | 1076 | | | 1077 | 40.6k | (void) c->buffer->message (c->font, "end chainsubtable %u", c->lookup_index); | 1078 | | | 1079 | 40.6k | if (unlikely (!c->buffer->successful)) return; | 1080 | | | 1081 | 62.5k | skip: | 1082 | 62.5k | subtable = &StructAfter<ChainSubtable<Types>> (*subtable); | 1083 | 62.5k | c->set_lookup_index (c->lookup_index + 1); | 1084 | 62.5k | } | 1085 | 62.6k | } |
|
1086 | | |
1087 | 232k | unsigned int get_size () const { return length; } AAT::Chain<AAT::ExtendedTypes>::get_size() const Line | Count | Source | 1087 | 97.9k | unsigned int get_size () const { return length; } |
AAT::Chain<AAT::ObsoleteTypes>::get_size() const Line | Count | Source | 1087 | 134k | unsigned int get_size () const { return length; } |
|
1088 | | |
1089 | | bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const |
1090 | 22.0k | { |
1091 | 22.0k | TRACE_SANITIZE (this); |
1092 | 22.0k | if (!length.sanitize (c) || |
1093 | 22.0k | length < min_size || |
1094 | 22.0k | !c->check_range (this, length)) |
1095 | 1.39k | return_trace (false); |
1096 | | |
1097 | 20.6k | if (!c->check_array (featureZ.arrayZ, featureCount)) |
1098 | 37 | return_trace (false); |
1099 | | |
1100 | 20.6k | const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); |
1101 | 20.6k | unsigned int count = subtableCount; |
1102 | 46.1k | for (unsigned int i = 0; i < count; i++) |
1103 | 27.1k | { |
1104 | 27.1k | if (!subtable->sanitize (c)) |
1105 | 1.58k | return_trace (false); |
1106 | 25.5k | subtable = &StructAfter<ChainSubtable<Types>> (*subtable); |
1107 | 25.5k | } |
1108 | | |
1109 | 20.6k | return_trace (true); |
1110 | 20.6k | } AAT::Chain<AAT::ExtendedTypes>::sanitize(hb_sanitize_context_t*, unsigned int) const Line | Count | Source | 1090 | 6.89k | { | 1091 | 6.89k | TRACE_SANITIZE (this); | 1092 | 6.89k | if (!length.sanitize (c) || | 1093 | 6.89k | length < min_size || | 1094 | 6.89k | !c->check_range (this, length)) | 1095 | 1.32k | return_trace (false); | 1096 | | | 1097 | 5.57k | if (!c->check_array (featureZ.arrayZ, featureCount)) | 1098 | 15 | return_trace (false); | 1099 | | | 1100 | 5.56k | const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); | 1101 | 5.56k | unsigned int count = subtableCount; | 1102 | 15.6k | for (unsigned int i = 0; i < count; i++) | 1103 | 10.9k | { | 1104 | 10.9k | if (!subtable->sanitize (c)) | 1105 | 950 | return_trace (false); | 1106 | 10.0k | subtable = &StructAfter<ChainSubtable<Types>> (*subtable); | 1107 | 10.0k | } | 1108 | | | 1109 | 4.61k | return_trace (true); | 1110 | 5.56k | } |
AAT::Chain<AAT::ObsoleteTypes>::sanitize(hb_sanitize_context_t*, unsigned int) const Line | Count | Source | 1090 | 15.1k | { | 1091 | 15.1k | TRACE_SANITIZE (this); | 1092 | 15.1k | if (!length.sanitize (c) || | 1093 | 15.1k | length < min_size || | 1094 | 15.1k | !c->check_range (this, length)) | 1095 | 74 | return_trace (false); | 1096 | | | 1097 | 15.0k | if (!c->check_array (featureZ.arrayZ, featureCount)) | 1098 | 22 | return_trace (false); | 1099 | | | 1100 | 15.0k | const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); | 1101 | 15.0k | unsigned int count = subtableCount; | 1102 | 30.5k | for (unsigned int i = 0; i < count; i++) | 1103 | 16.1k | { | 1104 | 16.1k | if (!subtable->sanitize (c)) | 1105 | 636 | return_trace (false); | 1106 | 15.5k | subtable = &StructAfter<ChainSubtable<Types>> (*subtable); | 1107 | 15.5k | } | 1108 | | | 1109 | 14.4k | return_trace (true); | 1110 | 15.0k | } |
|
1111 | | |
1112 | | protected: |
1113 | | HBUINT32 defaultFlags; /* The default specification for subtables. */ |
1114 | | HBUINT32 length; /* Total byte count, including this header. */ |
1115 | | HBUINT featureCount; /* Number of feature subtable entries. */ |
1116 | | HBUINT subtableCount; /* The number of subtables in the chain. */ |
1117 | | |
1118 | | UnsizedArrayOf<Feature> featureZ; /* Features. */ |
1119 | | /*ChainSubtable firstSubtable;*//* Subtables. */ |
1120 | | /*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */ |
1121 | | |
1122 | | public: |
1123 | | DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT)); |
1124 | | }; |
1125 | | |
1126 | | |
1127 | | /* |
1128 | | * The 'mort'/'morx' Table |
1129 | | */ |
1130 | | |
1131 | | template <typename Types, hb_tag_t TAG> |
1132 | | struct mortmorx |
1133 | | { |
1134 | | static constexpr hb_tag_t tableTag = TAG; |
1135 | | |
1136 | 515k | bool has_data () const { return version != 0; } AAT::mortmorx<AAT::ExtendedTypes, 1836020344u>::has_data() const Line | Count | Source | 1136 | 324k | bool has_data () const { return version != 0; } |
AAT::mortmorx<AAT::ObsoleteTypes, 1836020340u>::has_data() const Line | Count | Source | 1136 | 191k | bool has_data () const { return version != 0; } |
|
1137 | | |
1138 | | void compile_flags (const hb_aat_map_builder_t *mapper, |
1139 | | hb_aat_map_t *map) const |
1140 | 80.7k | { |
1141 | 80.7k | const Chain<Types> *chain = &firstChain; |
1142 | 80.7k | unsigned int count = chainCount; |
1143 | 80.7k | if (unlikely (!map->chain_flags.resize (count))) |
1144 | 1.24k | return; |
1145 | 184k | for (unsigned int i = 0; i < count; i++) |
1146 | 104k | { |
1147 | 104k | map->chain_flags[i].push (hb_aat_map_t::range_flags_t {chain->compile_flags (mapper), |
1148 | 104k | mapper->range_first, |
1149 | 104k | mapper->range_last}); |
1150 | 104k | chain = &StructAfter<Chain<Types>> (*chain); |
1151 | 104k | } |
1152 | 79.5k | } AAT::mortmorx<AAT::ExtendedTypes, 1836020344u>::compile_flags(hb_aat_map_builder_t const*, hb_aat_map_t*) const Line | Count | Source | 1140 | 62.9k | { | 1141 | 62.9k | const Chain<Types> *chain = &firstChain; | 1142 | 62.9k | unsigned int count = chainCount; | 1143 | 62.9k | if (unlikely (!map->chain_flags.resize (count))) | 1144 | 491 | return; | 1145 | 108k | for (unsigned int i = 0; i < count; i++) | 1146 | 46.2k | { | 1147 | 46.2k | map->chain_flags[i].push (hb_aat_map_t::range_flags_t {chain->compile_flags (mapper), | 1148 | 46.2k | mapper->range_first, | 1149 | 46.2k | mapper->range_last}); | 1150 | 46.2k | chain = &StructAfter<Chain<Types>> (*chain); | 1151 | 46.2k | } | 1152 | 62.4k | } |
AAT::mortmorx<AAT::ObsoleteTypes, 1836020340u>::compile_flags(hb_aat_map_builder_t const*, hb_aat_map_t*) const Line | Count | Source | 1140 | 17.8k | { | 1141 | 17.8k | const Chain<Types> *chain = &firstChain; | 1142 | 17.8k | unsigned int count = chainCount; | 1143 | 17.8k | if (unlikely (!map->chain_flags.resize (count))) | 1144 | 749 | return; | 1145 | 75.4k | for (unsigned int i = 0; i < count; i++) | 1146 | 58.3k | { | 1147 | 58.3k | map->chain_flags[i].push (hb_aat_map_t::range_flags_t {chain->compile_flags (mapper), | 1148 | 58.3k | mapper->range_first, | 1149 | 58.3k | mapper->range_last}); | 1150 | 58.3k | chain = &StructAfter<Chain<Types>> (*chain); | 1151 | 58.3k | } | 1152 | 17.0k | } |
|
1153 | | |
1154 | | void apply (hb_aat_apply_context_t *c, |
1155 | | const hb_aat_map_t &map) const |
1156 | 82.2k | { |
1157 | 82.2k | if (unlikely (!c->buffer->successful)) return; |
1158 | | |
1159 | 82.2k | c->buffer->unsafe_to_concat (); |
1160 | | |
1161 | 82.2k | c->set_lookup_index (0); |
1162 | 82.2k | const Chain<Types> *chain = &firstChain; |
1163 | 82.2k | unsigned int count = chainCount; |
1164 | 191k | for (unsigned int i = 0; i < count; i++) |
1165 | 109k | { |
1166 | 109k | c->range_flags = &map.chain_flags[i]; |
1167 | 109k | chain->apply (c); |
1168 | 109k | if (unlikely (!c->buffer->successful)) return; |
1169 | 108k | chain = &StructAfter<Chain<Types>> (*chain); |
1170 | 108k | } |
1171 | 82.2k | } AAT::mortmorx<AAT::ExtendedTypes, 1836020344u>::apply(AAT::hb_aat_apply_context_t*, hb_aat_map_t const&) const Line | Count | Source | 1156 | 63.6k | { | 1157 | 63.6k | if (unlikely (!c->buffer->successful)) return; | 1158 | | | 1159 | 63.6k | c->buffer->unsafe_to_concat (); | 1160 | | | 1161 | 63.6k | c->set_lookup_index (0); | 1162 | 63.6k | const Chain<Types> *chain = &firstChain; | 1163 | 63.6k | unsigned int count = chainCount; | 1164 | 110k | for (unsigned int i = 0; i < count; i++) | 1165 | 47.2k | { | 1166 | 47.2k | c->range_flags = &map.chain_flags[i]; | 1167 | 47.2k | chain->apply (c); | 1168 | 47.2k | if (unlikely (!c->buffer->successful)) return; | 1169 | 47.0k | chain = &StructAfter<Chain<Types>> (*chain); | 1170 | 47.0k | } | 1171 | 63.6k | } |
AAT::mortmorx<AAT::ObsoleteTypes, 1836020340u>::apply(AAT::hb_aat_apply_context_t*, hb_aat_map_t const&) const Line | Count | Source | 1156 | 18.6k | { | 1157 | 18.6k | if (unlikely (!c->buffer->successful)) return; | 1158 | | | 1159 | 18.6k | c->buffer->unsafe_to_concat (); | 1160 | | | 1161 | 18.6k | c->set_lookup_index (0); | 1162 | 18.6k | const Chain<Types> *chain = &firstChain; | 1163 | 18.6k | unsigned int count = chainCount; | 1164 | 80.3k | for (unsigned int i = 0; i < count; i++) | 1165 | 62.6k | { | 1166 | 62.6k | c->range_flags = &map.chain_flags[i]; | 1167 | 62.6k | chain->apply (c); | 1168 | 62.6k | if (unlikely (!c->buffer->successful)) return; | 1169 | 61.7k | chain = &StructAfter<Chain<Types>> (*chain); | 1170 | 61.7k | } | 1171 | 18.6k | } |
|
1172 | | |
1173 | | bool sanitize (hb_sanitize_context_t *c) const |
1174 | 12.6k | { |
1175 | 12.6k | TRACE_SANITIZE (this); |
1176 | 12.6k | if (!version.sanitize (c) || !version || !chainCount.sanitize (c)) |
1177 | 526 | return_trace (false); |
1178 | | |
1179 | 12.1k | const Chain<Types> *chain = &firstChain; |
1180 | 12.1k | unsigned int count = chainCount; |
1181 | 31.1k | for (unsigned int i = 0; i < count; i++) |
1182 | 22.0k | { |
1183 | 22.0k | if (!chain->sanitize (c, version)) |
1184 | 3.01k | return_trace (false); |
1185 | 19.0k | chain = &StructAfter<Chain<Types>> (*chain); |
1186 | 19.0k | } |
1187 | | |
1188 | 9.12k | return_trace (true); |
1189 | 12.1k | } AAT::mortmorx<AAT::ExtendedTypes, 1836020344u>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 1174 | 8.19k | { | 1175 | 8.19k | TRACE_SANITIZE (this); | 1176 | 8.19k | if (!version.sanitize (c) || !version || !chainCount.sanitize (c)) | 1177 | 494 | return_trace (false); | 1178 | | | 1179 | 7.69k | const Chain<Types> *chain = &firstChain; | 1180 | 7.69k | unsigned int count = chainCount; | 1181 | 12.3k | for (unsigned int i = 0; i < count; i++) | 1182 | 6.89k | { | 1183 | 6.89k | if (!chain->sanitize (c, version)) | 1184 | 2.28k | return_trace (false); | 1185 | 4.61k | chain = &StructAfter<Chain<Types>> (*chain); | 1186 | 4.61k | } | 1187 | | | 1188 | 5.41k | return_trace (true); | 1189 | 7.69k | } |
AAT::mortmorx<AAT::ObsoleteTypes, 1836020340u>::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 1174 | 4.47k | { | 1175 | 4.47k | TRACE_SANITIZE (this); | 1176 | 4.47k | if (!version.sanitize (c) || !version || !chainCount.sanitize (c)) | 1177 | 32 | return_trace (false); | 1178 | | | 1179 | 4.44k | const Chain<Types> *chain = &firstChain; | 1180 | 4.44k | unsigned int count = chainCount; | 1181 | 18.8k | for (unsigned int i = 0; i < count; i++) | 1182 | 15.1k | { | 1183 | 15.1k | if (!chain->sanitize (c, version)) | 1184 | 732 | return_trace (false); | 1185 | 14.4k | chain = &StructAfter<Chain<Types>> (*chain); | 1186 | 14.4k | } | 1187 | | | 1188 | 3.70k | return_trace (true); | 1189 | 4.44k | } |
|
1190 | | |
1191 | | protected: |
1192 | | HBUINT16 version; /* Version number of the glyph metamorphosis table. |
1193 | | * 1, 2, or 3. */ |
1194 | | HBUINT16 unused; /* Set to 0. */ |
1195 | | HBUINT32 chainCount; /* Number of metamorphosis chains contained in this |
1196 | | * table. */ |
1197 | | Chain<Types> firstChain; /* Chains. */ |
1198 | | |
1199 | | public: |
1200 | | DEFINE_SIZE_MIN (8); |
1201 | | }; |
1202 | | |
1203 | | struct morx : mortmorx<ExtendedTypes, HB_AAT_TAG_morx> {}; |
1204 | | struct mort : mortmorx<ObsoleteTypes, HB_AAT_TAG_mort> {}; |
1205 | | |
1206 | | |
1207 | | } /* namespace AAT */ |
1208 | | |
1209 | | |
1210 | | #endif /* HB_AAT_LAYOUT_MORX_TABLE_HH */ |