OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
3 * Copyright © 2010,2012 Google, Inc. | 3 * Copyright © 2010,2012 Google, Inc. |
4 * | 4 * |
5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
6 * | 6 * |
7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
(...skipping 14 matching lines...) Expand all Loading... |
25 * Red Hat Author(s): Behdad Esfahbod | 25 * Red Hat Author(s): Behdad Esfahbod |
26 * Google Author(s): Behdad Esfahbod | 26 * Google Author(s): Behdad Esfahbod |
27 */ | 27 */ |
28 | 28 |
29 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH | 29 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH |
30 #define HB_OT_LAYOUT_GSUB_TABLE_HH | 30 #define HB_OT_LAYOUT_GSUB_TABLE_HH |
31 | 31 |
32 #include "hb-ot-layout-gsubgpos-private.hh" | 32 #include "hb-ot-layout-gsubgpos-private.hh" |
33 | 33 |
34 | 34 |
| 35 namespace OT { |
| 36 |
35 | 37 |
36 struct SingleSubstFormat1 | 38 struct SingleSubstFormat1 |
37 { | 39 { |
38 friend struct SingleSubst; | 40 friend struct SingleSubst; |
39 | 41 |
40 private: | 42 private: |
41 | 43 |
42 inline void closure (hb_closure_context_t *c) const | 44 inline void closure (hb_closure_context_t *c) const |
43 { | 45 { |
44 TRACE_CLOSURE (); | 46 TRACE_CLOSURE (); |
45 Coverage::Iter iter; | 47 Coverage::Iter iter; |
46 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 48 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
47 hb_codepoint_t glyph_id = iter.get_glyph (); | 49 hb_codepoint_t glyph_id = iter.get_glyph (); |
48 if (c->glyphs->has (glyph_id)) | 50 if (c->glyphs->has (glyph_id)) |
49 c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF); | 51 c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF); |
50 } | 52 } |
51 } | 53 } |
52 | 54 |
53 inline bool would_apply (hb_codepoint_t glyph_id) const | 55 inline const Coverage &get_coverage (void) const |
54 { | 56 { |
55 return (this+coverage) (glyph_id) != NOT_COVERED; | 57 return this+coverage; |
56 } | 58 } |
57 | 59 |
58 inline bool apply (hb_apply_context_t *c) const | 60 inline bool apply (hb_apply_context_t *c) const |
59 { | 61 { |
60 TRACE_APPLY (); | 62 TRACE_APPLY (); |
61 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; | 63 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; |
62 unsigned int index = (this+coverage) (glyph_id); | 64 unsigned int index = (this+coverage) (glyph_id); |
63 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 65 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
64 | 66 |
65 /* According to the Adobe Annotated OpenType Suite, result is always | 67 /* According to the Adobe Annotated OpenType Suite, result is always |
66 * limited to 16bit. */ | 68 * limited to 16bit. */ |
67 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF; | 69 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF; |
68 c->replace_glyph (glyph_id); | 70 c->replace_glyph (glyph_id); |
69 | 71 |
70 return TRACE_RETURN (true); | 72 return TRACE_RETURN (true); |
71 } | 73 } |
72 | 74 |
| 75 inline bool serialize (hb_serialize_context_t *c, |
| 76 Supplier<GlyphID> &glyphs, |
| 77 unsigned int num_glyphs, |
| 78 int delta) |
| 79 { |
| 80 TRACE_SERIALIZE (); |
| 81 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 82 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs
))) return TRACE_RETURN (false); |
| 83 deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */ |
| 84 return TRACE_RETURN (true); |
| 85 } |
| 86 |
73 inline bool sanitize (hb_sanitize_context_t *c) { | 87 inline bool sanitize (hb_sanitize_context_t *c) { |
74 TRACE_SANITIZE (); | 88 TRACE_SANITIZE (); |
75 return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c
)); | 89 return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c
)); |
76 } | 90 } |
77 | 91 |
78 private: | 92 protected: |
79 USHORT format; /* Format identifier--format = 1 */ | 93 USHORT format; /* Format identifier--format = 1 */ |
80 OffsetTo<Coverage> | 94 OffsetTo<Coverage> |
81 coverage; /* Offset to Coverage table--from | 95 coverage; /* Offset to Coverage table--from |
82 * beginning of Substitution table */ | 96 * beginning of Substitution table */ |
83 SHORT deltaGlyphID; /* Add to original GlyphID to get | 97 SHORT deltaGlyphID; /* Add to original GlyphID to get |
84 * substitute GlyphID */ | 98 * substitute GlyphID */ |
85 public: | 99 public: |
86 DEFINE_SIZE_STATIC (6); | 100 DEFINE_SIZE_STATIC (6); |
87 }; | 101 }; |
88 | 102 |
89 struct SingleSubstFormat2 | 103 struct SingleSubstFormat2 |
90 { | 104 { |
91 friend struct SingleSubst; | 105 friend struct SingleSubst; |
92 | 106 |
93 private: | 107 private: |
94 | 108 |
95 inline void closure (hb_closure_context_t *c) const | 109 inline void closure (hb_closure_context_t *c) const |
96 { | 110 { |
97 TRACE_CLOSURE (); | 111 TRACE_CLOSURE (); |
98 Coverage::Iter iter; | 112 Coverage::Iter iter; |
99 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 113 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
100 if (c->glyphs->has (iter.get_glyph ())) | 114 if (c->glyphs->has (iter.get_glyph ())) |
101 c->glyphs->add (substitute[iter.get_coverage ()]); | 115 c->glyphs->add (substitute[iter.get_coverage ()]); |
102 } | 116 } |
103 } | 117 } |
104 | 118 |
105 inline bool would_apply (hb_codepoint_t glyph_id) const | 119 inline const Coverage &get_coverage (void) const |
106 { | 120 { |
107 return (this+coverage) (glyph_id) != NOT_COVERED; | 121 return this+coverage; |
108 } | 122 } |
109 | 123 |
110 inline bool apply (hb_apply_context_t *c) const | 124 inline bool apply (hb_apply_context_t *c) const |
111 { | 125 { |
112 TRACE_APPLY (); | 126 TRACE_APPLY (); |
113 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; | 127 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; |
114 unsigned int index = (this+coverage) (glyph_id); | 128 unsigned int index = (this+coverage) (glyph_id); |
115 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 129 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
116 | 130 |
117 if (unlikely (index >= substitute.len)) return TRACE_RETURN (false); | 131 if (unlikely (index >= substitute.len)) return TRACE_RETURN (false); |
118 | 132 |
119 glyph_id = substitute[index]; | 133 glyph_id = substitute[index]; |
120 c->replace_glyph (glyph_id); | 134 c->replace_glyph (glyph_id); |
121 | 135 |
122 return TRACE_RETURN (true); | 136 return TRACE_RETURN (true); |
123 } | 137 } |
124 | 138 |
| 139 inline bool serialize (hb_serialize_context_t *c, |
| 140 Supplier<GlyphID> &glyphs, |
| 141 Supplier<GlyphID> &substitutes, |
| 142 unsigned int num_glyphs) |
| 143 { |
| 144 TRACE_SERIALIZE (); |
| 145 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 146 if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TR
ACE_RETURN (false); |
| 147 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs
))) return TRACE_RETURN (false); |
| 148 return TRACE_RETURN (true); |
| 149 } |
| 150 |
125 inline bool sanitize (hb_sanitize_context_t *c) { | 151 inline bool sanitize (hb_sanitize_context_t *c) { |
126 TRACE_SANITIZE (); | 152 TRACE_SANITIZE (); |
127 return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c))
; | 153 return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c))
; |
128 } | 154 } |
129 | 155 |
130 private: | 156 protected: |
131 USHORT format; /* Format identifier--format = 2 */ | 157 USHORT format; /* Format identifier--format = 2 */ |
132 OffsetTo<Coverage> | 158 OffsetTo<Coverage> |
133 coverage; /* Offset to Coverage table--from | 159 coverage; /* Offset to Coverage table--from |
134 * beginning of Substitution table */ | 160 * beginning of Substitution table */ |
135 ArrayOf<GlyphID> | 161 ArrayOf<GlyphID> |
136 substitute; /* Array of substitute | 162 substitute; /* Array of substitute |
137 * GlyphIDs--ordered by Coverage Index *
/ | 163 * GlyphIDs--ordered by Coverage Index *
/ |
138 public: | 164 public: |
139 DEFINE_SIZE_ARRAY (6, substitute); | 165 DEFINE_SIZE_ARRAY (6, substitute); |
140 }; | 166 }; |
141 | 167 |
142 struct SingleSubst | 168 struct SingleSubst |
143 { | 169 { |
144 friend struct SubstLookupSubTable; | 170 friend struct SubstLookupSubTable; |
| 171 friend struct SubstLookup; |
145 | 172 |
146 private: | 173 private: |
147 | 174 |
148 inline void closure (hb_closure_context_t *c) const | 175 inline void closure (hb_closure_context_t *c) const |
149 { | 176 { |
150 TRACE_CLOSURE (); | 177 TRACE_CLOSURE (); |
151 switch (u.format) { | 178 switch (u.format) { |
152 case 1: u.format1.closure (c); break; | 179 case 1: u.format1.closure (c); break; |
153 case 2: u.format2.closure (c); break; | 180 case 2: u.format2.closure (c); break; |
154 default: break; | 181 default: break; |
155 } | 182 } |
156 } | 183 } |
157 | 184 |
158 inline bool would_apply (hb_codepoint_t glyph_id) const | 185 inline const Coverage &get_coverage (void) const |
159 { | 186 { |
160 switch (u.format) { | 187 switch (u.format) { |
161 case 1: return u.format1.would_apply (glyph_id); | 188 case 1: return u.format1.get_coverage (); |
162 case 2: return u.format2.would_apply (glyph_id); | 189 case 2: return u.format2.get_coverage (); |
163 default:return false; | 190 default:return Null(Coverage); |
164 } | 191 } |
165 } | 192 } |
166 | 193 |
167 inline bool apply (hb_apply_context_t *c) const | 194 inline bool apply (hb_apply_context_t *c) const |
168 { | 195 { |
169 TRACE_APPLY (); | 196 TRACE_APPLY (); |
170 switch (u.format) { | 197 switch (u.format) { |
171 case 1: return TRACE_RETURN (u.format1.apply (c)); | 198 case 1: return TRACE_RETURN (u.format1.apply (c)); |
172 case 2: return TRACE_RETURN (u.format2.apply (c)); | 199 case 2: return TRACE_RETURN (u.format2.apply (c)); |
173 default:return TRACE_RETURN (false); | 200 default:return TRACE_RETURN (false); |
174 } | 201 } |
175 } | 202 } |
176 | 203 |
| 204 inline bool serialize (hb_serialize_context_t *c, |
| 205 Supplier<GlyphID> &glyphs, |
| 206 Supplier<GlyphID> &substitutes, |
| 207 unsigned int num_glyphs) |
| 208 { |
| 209 TRACE_SERIALIZE (); |
| 210 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); |
| 211 unsigned int format = 2; |
| 212 int delta; |
| 213 if (num_glyphs) { |
| 214 format = 1; |
| 215 /* TODO(serialize) check for wrap-around */ |
| 216 delta = substitutes[0] - glyphs[0]; |
| 217 for (unsigned int i = 1; i < num_glyphs; i++) |
| 218 if (delta != substitutes[i] - glyphs[i]) { |
| 219 format = 2; |
| 220 break; |
| 221 } |
| 222 } |
| 223 u.format.set (format); |
| 224 switch (u.format) { |
| 225 case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs, del
ta)); |
| 226 case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, substitutes, nu
m_glyphs)); |
| 227 default:return TRACE_RETURN (false); |
| 228 } |
| 229 } |
| 230 |
177 inline bool sanitize (hb_sanitize_context_t *c) { | 231 inline bool sanitize (hb_sanitize_context_t *c) { |
178 TRACE_SANITIZE (); | 232 TRACE_SANITIZE (); |
179 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 233 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
180 switch (u.format) { | 234 switch (u.format) { |
181 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 235 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
182 case 2: return TRACE_RETURN (u.format2.sanitize (c)); | 236 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
183 default:return TRACE_RETURN (true); | 237 default:return TRACE_RETURN (true); |
184 } | 238 } |
185 } | 239 } |
186 | 240 |
187 private: | 241 protected: |
188 union { | 242 union { |
189 USHORT format; /* Format identifier */ | 243 USHORT format; /* Format identifier */ |
190 SingleSubstFormat1 format1; | 244 SingleSubstFormat1 format1; |
191 SingleSubstFormat2 format2; | 245 SingleSubstFormat2 format2; |
192 } u; | 246 } u; |
193 }; | 247 }; |
194 | 248 |
195 | 249 |
196 struct Sequence | 250 struct Sequence |
197 { | 251 { |
198 friend struct MultipleSubstFormat1; | 252 friend struct MultipleSubstFormat1; |
199 | 253 |
200 private: | 254 private: |
201 | 255 |
202 inline void closure (hb_closure_context_t *c) const | 256 inline void closure (hb_closure_context_t *c) const |
203 { | 257 { |
204 TRACE_CLOSURE (); | 258 TRACE_CLOSURE (); |
205 unsigned int count = substitute.len; | 259 unsigned int count = substitute.len; |
206 for (unsigned int i = 0; i < count; i++) | 260 for (unsigned int i = 0; i < count; i++) |
207 c->glyphs->add (substitute[i]); | 261 c->glyphs->add (substitute[i]); |
208 } | 262 } |
209 | 263 |
210 inline bool apply (hb_apply_context_t *c) const | 264 inline bool apply (hb_apply_context_t *c) const |
211 { | 265 { |
212 TRACE_APPLY (); | 266 TRACE_APPLY (); |
213 if (unlikely (!substitute.len)) return TRACE_RETURN (false); | 267 if (unlikely (!substitute.len)) return TRACE_RETURN (false); |
214 | 268 |
215 unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ? HB_OT
_LAYOUT_GLYPH_CLASS_BASE_GLYPH : 0; | 269 unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ? HB_OT
_LAYOUT_GLYPH_CLASS_BASE_GLYPH : 0; |
216 c->replace_glyphs_be16 (1, substitute.len, (const char *) substitute.array,
klass); | 270 unsigned int count = substitute.len; |
| 271 for (unsigned int i = 0; i < count; i++) { |
| 272 set_lig_props_for_component (c->buffer->cur(), i); |
| 273 c->output_glyph (substitute.array[i], klass); |
| 274 } |
| 275 c->buffer->skip_glyph (); |
217 | 276 |
218 return TRACE_RETURN (true); | 277 return TRACE_RETURN (true); |
219 } | 278 } |
220 | 279 |
| 280 inline bool serialize (hb_serialize_context_t *c, |
| 281 Supplier<GlyphID> &glyphs, |
| 282 unsigned int num_glyphs) |
| 283 { |
| 284 TRACE_SERIALIZE (); |
| 285 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 286 if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_R
ETURN (false); |
| 287 return TRACE_RETURN (true); |
| 288 } |
| 289 |
221 public: | 290 public: |
222 inline bool sanitize (hb_sanitize_context_t *c) { | 291 inline bool sanitize (hb_sanitize_context_t *c) { |
223 TRACE_SANITIZE (); | 292 TRACE_SANITIZE (); |
224 return TRACE_RETURN (substitute.sanitize (c)); | 293 return TRACE_RETURN (substitute.sanitize (c)); |
225 } | 294 } |
226 | 295 |
227 private: | 296 protected: |
228 ArrayOf<GlyphID> | 297 ArrayOf<GlyphID> |
229 substitute; /* String of GlyphIDs to substitute */ | 298 substitute; /* String of GlyphIDs to substitute */ |
230 public: | 299 public: |
231 DEFINE_SIZE_ARRAY (2, substitute); | 300 DEFINE_SIZE_ARRAY (2, substitute); |
232 }; | 301 }; |
233 | 302 |
234 struct MultipleSubstFormat1 | 303 struct MultipleSubstFormat1 |
235 { | 304 { |
236 friend struct MultipleSubst; | 305 friend struct MultipleSubst; |
237 | 306 |
238 private: | 307 private: |
239 | 308 |
240 inline void closure (hb_closure_context_t *c) const | 309 inline void closure (hb_closure_context_t *c) const |
241 { | 310 { |
242 TRACE_CLOSURE (); | 311 TRACE_CLOSURE (); |
243 Coverage::Iter iter; | 312 Coverage::Iter iter; |
244 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 313 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
245 if (c->glyphs->has (iter.get_glyph ())) | 314 if (c->glyphs->has (iter.get_glyph ())) |
246 (this+sequence[iter.get_coverage ()]).closure (c); | 315 (this+sequence[iter.get_coverage ()]).closure (c); |
247 } | 316 } |
248 } | 317 } |
249 | 318 |
250 inline bool would_apply (hb_codepoint_t glyph_id) const | 319 inline const Coverage &get_coverage (void) const |
251 { | 320 { |
252 return (this+coverage) (glyph_id) != NOT_COVERED; | 321 return this+coverage; |
253 } | 322 } |
254 | 323 |
255 inline bool apply (hb_apply_context_t *c) const | 324 inline bool apply (hb_apply_context_t *c) const |
256 { | 325 { |
257 TRACE_APPLY (); | 326 TRACE_APPLY (); |
258 | 327 |
259 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); | 328 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); |
260 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 329 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
261 | 330 |
262 return TRACE_RETURN ((this+sequence[index]).apply (c)); | 331 return TRACE_RETURN ((this+sequence[index]).apply (c)); |
263 } | 332 } |
264 | 333 |
| 334 inline bool serialize (hb_serialize_context_t *c, |
| 335 Supplier<GlyphID> &glyphs, |
| 336 Supplier<unsigned int> &substitute_len_list, |
| 337 unsigned int num_glyphs, |
| 338 Supplier<GlyphID> &substitute_glyphs_list) |
| 339 { |
| 340 TRACE_SERIALIZE (); |
| 341 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 342 if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (fal
se); |
| 343 for (unsigned int i = 0; i < num_glyphs; i++) |
| 344 if (unlikely (!sequence[i].serialize (c, this).serialize (c, |
| 345 substitute_glyph
s_list, |
| 346 substitute_len_l
ist[i]))) return TRACE_RETURN (false); |
| 347 substitute_len_list.advance (num_glyphs); |
| 348 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs
))) return TRACE_RETURN (false); |
| 349 return TRACE_RETURN (true); |
| 350 } |
| 351 |
265 inline bool sanitize (hb_sanitize_context_t *c) { | 352 inline bool sanitize (hb_sanitize_context_t *c) { |
266 TRACE_SANITIZE (); | 353 TRACE_SANITIZE (); |
267 return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, th
is)); | 354 return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, th
is)); |
268 } | 355 } |
269 | 356 |
270 private: | 357 protected: |
271 USHORT format; /* Format identifier--format = 1 */ | 358 USHORT format; /* Format identifier--format = 1 */ |
272 OffsetTo<Coverage> | 359 OffsetTo<Coverage> |
273 coverage; /* Offset to Coverage table--from | 360 coverage; /* Offset to Coverage table--from |
274 * beginning of Substitution table */ | 361 * beginning of Substitution table */ |
275 OffsetArrayOf<Sequence> | 362 OffsetArrayOf<Sequence> |
276 sequence; /* Array of Sequence tables | 363 sequence; /* Array of Sequence tables |
277 * ordered by Coverage Index */ | 364 * ordered by Coverage Index */ |
278 public: | 365 public: |
279 DEFINE_SIZE_ARRAY (6, sequence); | 366 DEFINE_SIZE_ARRAY (6, sequence); |
280 }; | 367 }; |
281 | 368 |
282 struct MultipleSubst | 369 struct MultipleSubst |
283 { | 370 { |
284 friend struct SubstLookupSubTable; | 371 friend struct SubstLookupSubTable; |
| 372 friend struct SubstLookup; |
285 | 373 |
286 private: | 374 private: |
287 | 375 |
288 inline void closure (hb_closure_context_t *c) const | 376 inline void closure (hb_closure_context_t *c) const |
289 { | 377 { |
290 TRACE_CLOSURE (); | 378 TRACE_CLOSURE (); |
291 switch (u.format) { | 379 switch (u.format) { |
292 case 1: u.format1.closure (c); break; | 380 case 1: u.format1.closure (c); break; |
293 default: break; | 381 default: break; |
294 } | 382 } |
295 } | 383 } |
296 | 384 |
297 inline bool would_apply (hb_codepoint_t glyph_id) const | 385 inline const Coverage &get_coverage (void) const |
298 { | 386 { |
299 switch (u.format) { | 387 switch (u.format) { |
300 case 1: return u.format1.would_apply (glyph_id); | 388 case 1: return u.format1.get_coverage (); |
301 default:return false; | 389 default:return Null(Coverage); |
302 } | 390 } |
303 } | 391 } |
304 | 392 |
305 inline bool apply (hb_apply_context_t *c) const | 393 inline bool apply (hb_apply_context_t *c) const |
306 { | 394 { |
307 TRACE_APPLY (); | 395 TRACE_APPLY (); |
308 switch (u.format) { | 396 switch (u.format) { |
309 case 1: return TRACE_RETURN (u.format1.apply (c)); | 397 case 1: return TRACE_RETURN (u.format1.apply (c)); |
310 default:return TRACE_RETURN (false); | 398 default:return TRACE_RETURN (false); |
311 } | 399 } |
312 } | 400 } |
313 | 401 |
| 402 inline bool serialize (hb_serialize_context_t *c, |
| 403 Supplier<GlyphID> &glyphs, |
| 404 Supplier<unsigned int> &substitute_len_list, |
| 405 unsigned int num_glyphs, |
| 406 Supplier<GlyphID> &substitute_glyphs_list) |
| 407 { |
| 408 TRACE_SERIALIZE (); |
| 409 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); |
| 410 unsigned int format = 1; |
| 411 u.format.set (format); |
| 412 switch (u.format) { |
| 413 case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, substitute_len_
list, num_glyphs, substitute_glyphs_list)); |
| 414 default:return TRACE_RETURN (false); |
| 415 } |
| 416 } |
| 417 |
314 inline bool sanitize (hb_sanitize_context_t *c) { | 418 inline bool sanitize (hb_sanitize_context_t *c) { |
315 TRACE_SANITIZE (); | 419 TRACE_SANITIZE (); |
316 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 420 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
317 switch (u.format) { | 421 switch (u.format) { |
318 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 422 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
319 default:return TRACE_RETURN (true); | 423 default:return TRACE_RETURN (true); |
320 } | 424 } |
321 } | 425 } |
322 | 426 |
323 private: | 427 protected: |
324 union { | 428 union { |
325 USHORT format; /* Format identifier */ | 429 USHORT format; /* Format identifier */ |
326 MultipleSubstFormat1 format1; | 430 MultipleSubstFormat1 format1; |
327 } u; | 431 } u; |
328 }; | 432 }; |
329 | 433 |
330 | 434 |
331 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in | 435 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in |
332 * arbitrary order */ | 436 * arbitrary order */ |
333 | 437 |
(...skipping 10 matching lines...) Expand all Loading... |
344 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 448 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
345 if (c->glyphs->has (iter.get_glyph ())) { | 449 if (c->glyphs->has (iter.get_glyph ())) { |
346 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; | 450 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; |
347 unsigned int count = alt_set.len; | 451 unsigned int count = alt_set.len; |
348 for (unsigned int i = 0; i < count; i++) | 452 for (unsigned int i = 0; i < count; i++) |
349 c->glyphs->add (alt_set[i]); | 453 c->glyphs->add (alt_set[i]); |
350 } | 454 } |
351 } | 455 } |
352 } | 456 } |
353 | 457 |
354 inline bool would_apply (hb_codepoint_t glyph_id) const | 458 inline const Coverage &get_coverage (void) const |
355 { | 459 { |
356 return (this+coverage) (glyph_id) != NOT_COVERED; | 460 return this+coverage; |
357 } | 461 } |
358 | 462 |
359 inline bool apply (hb_apply_context_t *c) const | 463 inline bool apply (hb_apply_context_t *c) const |
360 { | 464 { |
361 TRACE_APPLY (); | 465 TRACE_APPLY (); |
362 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; | 466 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; |
363 | 467 |
364 unsigned int index = (this+coverage) (glyph_id); | 468 unsigned int index = (this+coverage) (glyph_id); |
365 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 469 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
366 | 470 |
(...skipping 10 matching lines...) Expand all Loading... |
377 | 481 |
378 if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETUR
N (false); | 482 if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETUR
N (false); |
379 | 483 |
380 glyph_id = alt_set[alt_index - 1]; | 484 glyph_id = alt_set[alt_index - 1]; |
381 | 485 |
382 c->replace_glyph (glyph_id); | 486 c->replace_glyph (glyph_id); |
383 | 487 |
384 return TRACE_RETURN (true); | 488 return TRACE_RETURN (true); |
385 } | 489 } |
386 | 490 |
| 491 inline bool serialize (hb_serialize_context_t *c, |
| 492 Supplier<GlyphID> &glyphs, |
| 493 Supplier<unsigned int> &alternate_len_list, |
| 494 unsigned int num_glyphs, |
| 495 Supplier<GlyphID> &alternate_glyphs_list) |
| 496 { |
| 497 TRACE_SERIALIZE (); |
| 498 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 499 if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN
(false); |
| 500 for (unsigned int i = 0; i < num_glyphs; i++) |
| 501 if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, |
| 502 alternate_gl
yphs_list, |
| 503 alternate_le
n_list[i]))) return TRACE_RETURN (false); |
| 504 alternate_len_list.advance (num_glyphs); |
| 505 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs
))) return TRACE_RETURN (false); |
| 506 return TRACE_RETURN (true); |
| 507 } |
| 508 |
387 inline bool sanitize (hb_sanitize_context_t *c) { | 509 inline bool sanitize (hb_sanitize_context_t *c) { |
388 TRACE_SANITIZE (); | 510 TRACE_SANITIZE (); |
389 return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c
, this)); | 511 return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c
, this)); |
390 } | 512 } |
391 | 513 |
392 private: | 514 protected: |
393 USHORT format; /* Format identifier--format = 1 */ | 515 USHORT format; /* Format identifier--format = 1 */ |
394 OffsetTo<Coverage> | 516 OffsetTo<Coverage> |
395 coverage; /* Offset to Coverage table--from | 517 coverage; /* Offset to Coverage table--from |
396 * beginning of Substitution table */ | 518 * beginning of Substitution table */ |
397 OffsetArrayOf<AlternateSet> | 519 OffsetArrayOf<AlternateSet> |
398 alternateSet; /* Array of AlternateSet tables | 520 alternateSet; /* Array of AlternateSet tables |
399 * ordered by Coverage Index */ | 521 * ordered by Coverage Index */ |
400 public: | 522 public: |
401 DEFINE_SIZE_ARRAY (6, alternateSet); | 523 DEFINE_SIZE_ARRAY (6, alternateSet); |
402 }; | 524 }; |
403 | 525 |
404 struct AlternateSubst | 526 struct AlternateSubst |
405 { | 527 { |
406 friend struct SubstLookupSubTable; | 528 friend struct SubstLookupSubTable; |
| 529 friend struct SubstLookup; |
407 | 530 |
408 private: | 531 private: |
409 | 532 |
410 inline void closure (hb_closure_context_t *c) const | 533 inline void closure (hb_closure_context_t *c) const |
411 { | 534 { |
412 TRACE_CLOSURE (); | 535 TRACE_CLOSURE (); |
413 switch (u.format) { | 536 switch (u.format) { |
414 case 1: u.format1.closure (c); break; | 537 case 1: u.format1.closure (c); break; |
415 default: break; | 538 default: break; |
416 } | 539 } |
417 } | 540 } |
418 | 541 |
419 inline bool would_apply (hb_codepoint_t glyph_id) const | 542 inline const Coverage &get_coverage (void) const |
420 { | 543 { |
421 switch (u.format) { | 544 switch (u.format) { |
422 case 1: return u.format1.would_apply (glyph_id); | 545 case 1: return u.format1.get_coverage (); |
423 default:return false; | 546 default:return Null(Coverage); |
424 } | 547 } |
425 } | 548 } |
426 | 549 |
427 inline bool apply (hb_apply_context_t *c) const | 550 inline bool apply (hb_apply_context_t *c) const |
428 { | 551 { |
429 TRACE_APPLY (); | 552 TRACE_APPLY (); |
430 switch (u.format) { | 553 switch (u.format) { |
431 case 1: return TRACE_RETURN (u.format1.apply (c)); | 554 case 1: return TRACE_RETURN (u.format1.apply (c)); |
432 default:return TRACE_RETURN (false); | 555 default:return TRACE_RETURN (false); |
433 } | 556 } |
434 } | 557 } |
435 | 558 |
| 559 inline bool serialize (hb_serialize_context_t *c, |
| 560 Supplier<GlyphID> &glyphs, |
| 561 Supplier<unsigned int> &alternate_len_list, |
| 562 unsigned int num_glyphs, |
| 563 Supplier<GlyphID> &alternate_glyphs_list) |
| 564 { |
| 565 TRACE_SERIALIZE (); |
| 566 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); |
| 567 unsigned int format = 1; |
| 568 u.format.set (format); |
| 569 switch (u.format) { |
| 570 case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, alternate_len_l
ist, num_glyphs, alternate_glyphs_list)); |
| 571 default:return TRACE_RETURN (false); |
| 572 } |
| 573 } |
| 574 |
436 inline bool sanitize (hb_sanitize_context_t *c) { | 575 inline bool sanitize (hb_sanitize_context_t *c) { |
437 TRACE_SANITIZE (); | 576 TRACE_SANITIZE (); |
438 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 577 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
439 switch (u.format) { | 578 switch (u.format) { |
440 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 579 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
441 default:return TRACE_RETURN (true); | 580 default:return TRACE_RETURN (true); |
442 } | 581 } |
443 } | 582 } |
444 | 583 |
445 private: | 584 protected: |
446 union { | 585 union { |
447 USHORT format; /* Format identifier */ | 586 USHORT format; /* Format identifier */ |
448 AlternateSubstFormat1 format1; | 587 AlternateSubstFormat1 format1; |
449 } u; | 588 } u; |
450 }; | 589 }; |
451 | 590 |
452 | 591 |
453 struct Ligature | 592 struct Ligature |
454 { | 593 { |
455 friend struct LigatureSet; | 594 friend struct LigatureSet; |
456 | 595 |
457 private: | 596 private: |
458 | 597 |
459 inline void closure (hb_closure_context_t *c) const | 598 inline void closure (hb_closure_context_t *c) const |
460 { | 599 { |
461 TRACE_CLOSURE (); | 600 TRACE_CLOSURE (); |
462 unsigned int count = component.len; | 601 unsigned int count = component.len; |
463 for (unsigned int i = 1; i < count; i++) | 602 for (unsigned int i = 1; i < count; i++) |
464 if (!c->glyphs->has (component[i])) | 603 if (!c->glyphs->has (component[i])) |
465 return; | 604 return; |
466 c->glyphs->add (ligGlyph); | 605 c->glyphs->add (ligGlyph); |
467 } | 606 } |
468 | 607 |
469 inline bool would_apply (hb_codepoint_t second) const | 608 inline bool would_apply (hb_would_apply_context_t *c) const |
470 { | 609 { |
471 return component.len == 2 && component[1] == second; | 610 if (c->len != component.len) |
| 611 return false; |
| 612 |
| 613 for (unsigned int i = 1; i < c->len; i++) |
| 614 if (likely (c->glyphs[i] != component[i])) |
| 615 » return false; |
| 616 |
| 617 return true; |
472 } | 618 } |
473 | 619 |
474 inline bool apply (hb_apply_context_t *c) const | 620 inline bool apply (hb_apply_context_t *c) const |
475 { | 621 { |
476 TRACE_APPLY (); | 622 TRACE_APPLY (); |
477 unsigned int count = component.len; | 623 unsigned int count = component.len; |
478 if (unlikely (count < 2)) return TRACE_RETURN (false); | 624 if (unlikely (count < 1)) return TRACE_RETURN (false); |
479 | 625 |
480 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, count - 1); | 626 unsigned int end_offset; |
481 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); | 627 bool is_mark_ligature; |
| 628 unsigned int total_component_count; |
482 | 629 |
483 bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); | 630 if (likely (!match_input (c, count, |
484 bool found_non_mark = false; | 631 » » » &component[1], |
| 632 » » » match_glyph, |
| 633 » » » NULL, |
| 634 » » » &end_offset, |
| 635 » » » &is_mark_ligature, |
| 636 » » » &total_component_count))) |
| 637 return TRACE_RETURN (false); |
485 | 638 |
486 for (unsigned int i = 1; i < count; i++) | 639 /* Deal, we are forming the ligature. */ |
487 { | 640 c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + end_offset); |
488 unsigned int property; | |
489 | 641 |
490 if (!skippy_iter.next (&property)) return TRACE_RETURN (false); | 642 ligate_input (c, |
491 | 643 » » count, |
492 found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); | 644 » » &component[1], |
493 | 645 » » ligGlyph, |
494 if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) r
eturn TRACE_RETURN (false); | 646 » » match_glyph, |
495 } | 647 » » NULL, |
496 | 648 » » is_mark_ligature, |
497 unsigned int klass = first_was_mark && found_non_mark ? HB_OT_LAYOUT_GLYPH_C
LASS_LIGATURE : 0; | 649 » » total_component_count); |
498 | |
499 /* Allocate new ligature id */ | |
500 unsigned int lig_id = allocate_lig_id (c->buffer); | |
501 set_lig_props (c->buffer->cur(), lig_id, 0); | |
502 | |
503 if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */ | |
504 { | |
505 c->replace_glyphs_be16 (count, 1, (const char *) &ligGlyph, klass); | |
506 } | |
507 else | |
508 { | |
509 c->replace_glyph (ligGlyph); | |
510 | |
511 /* Now we must do a second loop to copy the skipped glyphs to | |
512 » `out' and assign component values to it. We start with the | |
513 » glyph after the first component. Glyphs between component | |
514 » i and i+1 belong to component i. Together with the lig_id | |
515 » value it is later possible to check whether a specific | |
516 » component value really belongs to a given ligature. */ | |
517 | |
518 for (unsigned int i = 1; i < count; i++) | |
519 { | |
520 » while (c->should_mark_skip_current_glyph ()) | |
521 » { | |
522 » set_lig_props (c->buffer->cur(), lig_id, i); | |
523 » c->replace_glyph (c->buffer->cur().codepoint); | |
524 » } | |
525 | |
526 » /* Skip the base glyph */ | |
527 » c->buffer->idx++; | |
528 } | |
529 } | |
530 | 650 |
531 return TRACE_RETURN (true); | 651 return TRACE_RETURN (true); |
532 } | 652 } |
533 | 653 |
| 654 inline bool serialize (hb_serialize_context_t *c, |
| 655 GlyphID ligature, |
| 656 Supplier<GlyphID> &components, /* Starting from second
*/ |
| 657 unsigned int num_components /* Including first componen
t */) |
| 658 { |
| 659 TRACE_SERIALIZE (); |
| 660 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 661 ligGlyph = ligature; |
| 662 if (unlikely (!component.serialize (c, components, num_components))) return
TRACE_RETURN (false); |
| 663 return TRACE_RETURN (true); |
| 664 } |
| 665 |
534 public: | 666 public: |
535 inline bool sanitize (hb_sanitize_context_t *c) { | 667 inline bool sanitize (hb_sanitize_context_t *c) { |
536 TRACE_SANITIZE (); | 668 TRACE_SANITIZE (); |
537 return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c)); | 669 return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c)); |
538 } | 670 } |
539 | 671 |
540 private: | 672 protected: |
541 GlyphID ligGlyph; /* GlyphID of ligature to substitute */ | 673 GlyphID ligGlyph; /* GlyphID of ligature to substitute */ |
542 HeadlessArrayOf<GlyphID> | 674 HeadlessArrayOf<GlyphID> |
543 component; /* Array of component GlyphIDs--start | 675 component; /* Array of component GlyphIDs--start |
544 * with the second component--ordered | 676 * with the second component--ordered |
545 * in writing direction */ | 677 * in writing direction */ |
546 public: | 678 public: |
547 DEFINE_SIZE_ARRAY (4, component); | 679 DEFINE_SIZE_ARRAY (4, component); |
548 }; | 680 }; |
549 | 681 |
550 struct LigatureSet | 682 struct LigatureSet |
551 { | 683 { |
552 friend struct LigatureSubstFormat1; | 684 friend struct LigatureSubstFormat1; |
553 | 685 |
554 private: | 686 private: |
555 | 687 |
556 inline void closure (hb_closure_context_t *c) const | 688 inline void closure (hb_closure_context_t *c) const |
557 { | 689 { |
558 TRACE_CLOSURE (); | 690 TRACE_CLOSURE (); |
559 unsigned int num_ligs = ligature.len; | 691 unsigned int num_ligs = ligature.len; |
560 for (unsigned int i = 0; i < num_ligs; i++) | 692 for (unsigned int i = 0; i < num_ligs; i++) |
561 (this+ligature[i]).closure (c); | 693 (this+ligature[i]).closure (c); |
562 } | 694 } |
563 | 695 |
564 inline bool would_apply (hb_codepoint_t second) const | 696 inline bool would_apply (hb_would_apply_context_t *c) const |
565 { | 697 { |
566 unsigned int num_ligs = ligature.len; | 698 unsigned int num_ligs = ligature.len; |
567 for (unsigned int i = 0; i < num_ligs; i++) | 699 for (unsigned int i = 0; i < num_ligs; i++) |
568 { | 700 { |
569 const Ligature &lig = this+ligature[i]; | 701 const Ligature &lig = this+ligature[i]; |
570 if (lig.would_apply (second)) | 702 if (lig.would_apply (c)) |
571 return true; | 703 return true; |
572 } | 704 } |
573 return false; | 705 return false; |
574 } | 706 } |
575 | 707 |
576 inline bool apply (hb_apply_context_t *c) const | 708 inline bool apply (hb_apply_context_t *c) const |
577 { | 709 { |
578 TRACE_APPLY (); | 710 TRACE_APPLY (); |
579 unsigned int num_ligs = ligature.len; | 711 unsigned int num_ligs = ligature.len; |
580 for (unsigned int i = 0; i < num_ligs; i++) | 712 for (unsigned int i = 0; i < num_ligs; i++) |
581 { | 713 { |
582 const Ligature &lig = this+ligature[i]; | 714 const Ligature &lig = this+ligature[i]; |
583 if (lig.apply (c)) return TRACE_RETURN (true); | 715 if (lig.apply (c)) return TRACE_RETURN (true); |
584 } | 716 } |
585 | 717 |
586 return TRACE_RETURN (false); | 718 return TRACE_RETURN (false); |
587 } | 719 } |
588 | 720 |
| 721 inline bool serialize (hb_serialize_context_t *c, |
| 722 Supplier<GlyphID> &ligatures, |
| 723 Supplier<unsigned int> &component_count_list, |
| 724 unsigned int num_ligatures, |
| 725 Supplier<GlyphID> &component_list /* Starting from seco
nd for each ligature */) |
| 726 { |
| 727 TRACE_SERIALIZE (); |
| 728 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 729 if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (
false); |
| 730 for (unsigned int i = 0; i < num_ligatures; i++) |
| 731 if (unlikely (!ligature[i].serialize (c, this).serialize (c, |
| 732 ligatures[i], |
| 733 component_list, |
| 734 component_count_
list[i]))) return TRACE_RETURN (false); |
| 735 ligatures.advance (num_ligatures); |
| 736 component_count_list.advance (num_ligatures); |
| 737 return TRACE_RETURN (true); |
| 738 } |
| 739 |
589 public: | 740 public: |
590 inline bool sanitize (hb_sanitize_context_t *c) { | 741 inline bool sanitize (hb_sanitize_context_t *c) { |
591 TRACE_SANITIZE (); | 742 TRACE_SANITIZE (); |
592 return TRACE_RETURN (ligature.sanitize (c, this)); | 743 return TRACE_RETURN (ligature.sanitize (c, this)); |
593 } | 744 } |
594 | 745 |
595 private: | 746 protected: |
596 OffsetArrayOf<Ligature> | 747 OffsetArrayOf<Ligature> |
597 ligature; /* Array LigatureSet tables | 748 ligature; /* Array LigatureSet tables |
598 * ordered by preference */ | 749 * ordered by preference */ |
599 public: | 750 public: |
600 DEFINE_SIZE_ARRAY (2, ligature); | 751 DEFINE_SIZE_ARRAY (2, ligature); |
601 }; | 752 }; |
602 | 753 |
603 struct LigatureSubstFormat1 | 754 struct LigatureSubstFormat1 |
604 { | 755 { |
605 friend struct LigatureSubst; | 756 friend struct LigatureSubst; |
606 | 757 |
607 private: | 758 private: |
608 | 759 |
609 inline void closure (hb_closure_context_t *c) const | 760 inline void closure (hb_closure_context_t *c) const |
610 { | 761 { |
611 TRACE_CLOSURE (); | 762 TRACE_CLOSURE (); |
612 Coverage::Iter iter; | 763 Coverage::Iter iter; |
613 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 764 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
614 if (c->glyphs->has (iter.get_glyph ())) | 765 if (c->glyphs->has (iter.get_glyph ())) |
615 (this+ligatureSet[iter.get_coverage ()]).closure (c); | 766 (this+ligatureSet[iter.get_coverage ()]).closure (c); |
616 } | 767 } |
617 } | 768 } |
618 | 769 |
619 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const | 770 inline const Coverage &get_coverage (void) const |
620 { | 771 { |
621 unsigned int index; | 772 return this+coverage; |
622 return (index = (this+coverage) (first)) != NOT_COVERED && | 773 } |
623 » (this+ligatureSet[index]).would_apply (second); | 774 |
| 775 inline bool would_apply (hb_would_apply_context_t *c) const |
| 776 { |
| 777 return (this+ligatureSet[(this+coverage) (c->glyphs[0])]).would_apply (c); |
624 } | 778 } |
625 | 779 |
626 inline bool apply (hb_apply_context_t *c) const | 780 inline bool apply (hb_apply_context_t *c) const |
627 { | 781 { |
628 TRACE_APPLY (); | 782 TRACE_APPLY (); |
629 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; | 783 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; |
630 | 784 |
631 unsigned int index = (this+coverage) (glyph_id); | 785 unsigned int index = (this+coverage) (glyph_id); |
632 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 786 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
633 | 787 |
634 const LigatureSet &lig_set = this+ligatureSet[index]; | 788 const LigatureSet &lig_set = this+ligatureSet[index]; |
635 return TRACE_RETURN (lig_set.apply (c)); | 789 return TRACE_RETURN (lig_set.apply (c)); |
636 } | 790 } |
637 | 791 |
| 792 inline bool serialize (hb_serialize_context_t *c, |
| 793 Supplier<GlyphID> &first_glyphs, |
| 794 Supplier<unsigned int> &ligature_per_first_glyph_count_
list, |
| 795 unsigned int num_first_glyphs, |
| 796 Supplier<GlyphID> &ligatures_list, |
| 797 Supplier<unsigned int> &component_count_list, |
| 798 Supplier<GlyphID> &component_list /* Starting from seco
nd for each ligature */) |
| 799 { |
| 800 TRACE_SERIALIZE (); |
| 801 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
| 802 if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RE
TURN (false); |
| 803 for (unsigned int i = 0; i < num_first_glyphs; i++) |
| 804 if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c, |
| 805 ligatures_lis
t, |
| 806 component_cou
nt_list, |
| 807 ligature_per_
first_glyph_count_list[i], |
| 808 component_lis
t))) return TRACE_RETURN (false); |
| 809 ligature_per_first_glyph_count_list.advance (num_first_glyphs); |
| 810 if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_
first_glyphs))) return TRACE_RETURN (false); |
| 811 return TRACE_RETURN (true); |
| 812 } |
| 813 |
638 inline bool sanitize (hb_sanitize_context_t *c) { | 814 inline bool sanitize (hb_sanitize_context_t *c) { |
639 TRACE_SANITIZE (); | 815 TRACE_SANITIZE (); |
640 return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c,
this)); | 816 return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c,
this)); |
641 } | 817 } |
642 | 818 |
643 private: | 819 protected: |
644 USHORT format; /* Format identifier--format = 1 */ | 820 USHORT format; /* Format identifier--format = 1 */ |
645 OffsetTo<Coverage> | 821 OffsetTo<Coverage> |
646 coverage; /* Offset to Coverage table--from | 822 coverage; /* Offset to Coverage table--from |
647 * beginning of Substitution table */ | 823 * beginning of Substitution table */ |
648 OffsetArrayOf<LigatureSet> | 824 OffsetArrayOf<LigatureSet> |
649 ligatureSet; /* Array LigatureSet tables | 825 ligatureSet; /* Array LigatureSet tables |
650 * ordered by Coverage Index */ | 826 * ordered by Coverage Index */ |
651 public: | 827 public: |
652 DEFINE_SIZE_ARRAY (6, ligatureSet); | 828 DEFINE_SIZE_ARRAY (6, ligatureSet); |
653 }; | 829 }; |
654 | 830 |
655 struct LigatureSubst | 831 struct LigatureSubst |
656 { | 832 { |
657 friend struct SubstLookupSubTable; | 833 friend struct SubstLookupSubTable; |
| 834 friend struct SubstLookup; |
658 | 835 |
659 private: | 836 private: |
660 | 837 |
661 inline void closure (hb_closure_context_t *c) const | 838 inline void closure (hb_closure_context_t *c) const |
662 { | 839 { |
663 TRACE_CLOSURE (); | 840 TRACE_CLOSURE (); |
664 switch (u.format) { | 841 switch (u.format) { |
665 case 1: u.format1.closure (c); break; | 842 case 1: u.format1.closure (c); break; |
666 default: break; | 843 default: break; |
667 } | 844 } |
668 } | 845 } |
669 | 846 |
670 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const | 847 inline const Coverage &get_coverage (void) const |
671 { | 848 { |
672 switch (u.format) { | 849 switch (u.format) { |
673 case 1: return u.format1.would_apply (first, second); | 850 case 1: return u.format1.get_coverage (); |
| 851 default:return Null(Coverage); |
| 852 } |
| 853 } |
| 854 |
| 855 inline bool would_apply (hb_would_apply_context_t *c) const |
| 856 { |
| 857 switch (u.format) { |
| 858 case 1: return u.format1.would_apply (c); |
674 default:return false; | 859 default:return false; |
675 } | 860 } |
676 } | 861 } |
677 | 862 |
678 inline bool apply (hb_apply_context_t *c) const | 863 inline bool apply (hb_apply_context_t *c) const |
679 { | 864 { |
680 TRACE_APPLY (); | 865 TRACE_APPLY (); |
681 switch (u.format) { | 866 switch (u.format) { |
682 case 1: return TRACE_RETURN (u.format1.apply (c)); | 867 case 1: return TRACE_RETURN (u.format1.apply (c)); |
683 default:return TRACE_RETURN (false); | 868 default:return TRACE_RETURN (false); |
684 } | 869 } |
685 } | 870 } |
686 | 871 |
| 872 inline bool serialize (hb_serialize_context_t *c, |
| 873 Supplier<GlyphID> &first_glyphs, |
| 874 Supplier<unsigned int> &ligature_per_first_glyph_count_
list, |
| 875 unsigned int num_first_glyphs, |
| 876 Supplier<GlyphID> &ligatures_list, |
| 877 Supplier<unsigned int> &component_count_list, |
| 878 Supplier<GlyphID> &component_list /* Starting from seco
nd for each ligature */) |
| 879 { |
| 880 TRACE_SERIALIZE (); |
| 881 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); |
| 882 unsigned int format = 1; |
| 883 u.format.set (format); |
| 884 switch (u.format) { |
| 885 case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_
per_first_glyph_count_list, num_first_glyphs, |
| 886 ligatures_list, component_
count_list, component_list)); |
| 887 default:return TRACE_RETURN (false); |
| 888 } |
| 889 } |
| 890 |
687 inline bool sanitize (hb_sanitize_context_t *c) { | 891 inline bool sanitize (hb_sanitize_context_t *c) { |
688 TRACE_SANITIZE (); | 892 TRACE_SANITIZE (); |
689 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 893 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
690 switch (u.format) { | 894 switch (u.format) { |
691 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 895 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
692 default:return TRACE_RETURN (true); | 896 default:return TRACE_RETURN (true); |
693 } | 897 } |
694 } | 898 } |
695 | 899 |
696 private: | 900 protected: |
697 union { | 901 union { |
698 USHORT format; /* Format identifier */ | 902 USHORT format; /* Format identifier */ |
699 LigatureSubstFormat1 format1; | 903 LigatureSubstFormat1 format1; |
700 } u; | 904 } u; |
701 }; | 905 }; |
702 | 906 |
703 | 907 |
704 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index); | 908 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index); |
705 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_
index); | 909 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_
index); |
706 | 910 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 | 954 |
751 private: | 955 private: |
752 inline const struct SubstLookupSubTable& get_subtable (void) const | 956 inline const struct SubstLookupSubTable& get_subtable (void) const |
753 { | 957 { |
754 unsigned int offset = get_offset (); | 958 unsigned int offset = get_offset (); |
755 if (unlikely (!offset)) return Null(SubstLookupSubTable); | 959 if (unlikely (!offset)) return Null(SubstLookupSubTable); |
756 return StructAtOffset<SubstLookupSubTable> (this, offset); | 960 return StructAtOffset<SubstLookupSubTable> (this, offset); |
757 } | 961 } |
758 | 962 |
759 inline void closure (hb_closure_context_t *c) const; | 963 inline void closure (hb_closure_context_t *c) const; |
760 inline bool would_apply (hb_codepoint_t glyph_id) const; | 964 |
761 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const; | 965 inline const Coverage &get_coverage (void) const; |
| 966 |
| 967 inline bool would_apply (hb_would_apply_context_t *c) const; |
762 | 968 |
763 inline bool apply (hb_apply_context_t *c) const; | 969 inline bool apply (hb_apply_context_t *c) const; |
764 | 970 |
765 inline bool sanitize (hb_sanitize_context_t *c); | 971 inline bool sanitize (hb_sanitize_context_t *c); |
766 | 972 |
767 inline bool is_reverse (void) const; | 973 inline bool is_reverse (void) const; |
768 }; | 974 }; |
769 | 975 |
770 | 976 |
771 struct ReverseChainSingleSubstFormat1 | 977 struct ReverseChainSingleSubstFormat1 |
(...skipping 20 matching lines...) Expand all Loading... |
792 return; | 998 return; |
793 | 999 |
794 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); | 1000 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); |
795 Coverage::Iter iter; | 1001 Coverage::Iter iter; |
796 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 1002 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
797 if (c->glyphs->has (iter.get_glyph ())) | 1003 if (c->glyphs->has (iter.get_glyph ())) |
798 c->glyphs->add (substitute[iter.get_coverage ()]); | 1004 c->glyphs->add (substitute[iter.get_coverage ()]); |
799 } | 1005 } |
800 } | 1006 } |
801 | 1007 |
| 1008 inline const Coverage &get_coverage (void) const |
| 1009 { |
| 1010 return this+coverage; |
| 1011 } |
| 1012 |
802 inline bool apply (hb_apply_context_t *c) const | 1013 inline bool apply (hb_apply_context_t *c) const |
803 { | 1014 { |
804 TRACE_APPLY (); | 1015 TRACE_APPLY (); |
805 if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL)) | 1016 if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL)) |
806 return TRACE_RETURN (false); /* No chaining to this type */ | 1017 return TRACE_RETURN (false); /* No chaining to this type */ |
807 | 1018 |
808 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); | 1019 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); |
809 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 1020 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
810 | 1021 |
811 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag
e> > (backtrack); | 1022 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag
e> > (backtrack); |
812 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); | 1023 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); |
813 | 1024 |
814 if (match_backtrack (c, | 1025 if (match_backtrack (c, |
815 backtrack.len, (USHORT *) backtrack.array, | 1026 backtrack.len, (USHORT *) backtrack.array, |
816 match_coverage, this) && | 1027 match_coverage, this) && |
817 match_lookahead (c, | 1028 match_lookahead (c, |
818 lookahead.len, (USHORT *) lookahead.array, | 1029 lookahead.len, (USHORT *) lookahead.array, |
819 match_coverage, this, | 1030 match_coverage, this, |
820 1)) | 1031 1)) |
821 { | 1032 { |
822 c->buffer->cur().codepoint = substitute[index]; | 1033 c->replace_glyph_inplace (substitute[index]); |
823 c->buffer->idx--; /* Reverse! */ | 1034 c->buffer->idx--; /* Reverse! */ |
824 return TRACE_RETURN (true); | 1035 return TRACE_RETURN (true); |
825 } | 1036 } |
826 | 1037 |
827 return TRACE_RETURN (false); | 1038 return TRACE_RETURN (false); |
828 } | 1039 } |
829 | 1040 |
830 inline bool sanitize (hb_sanitize_context_t *c) { | 1041 inline bool sanitize (hb_sanitize_context_t *c) { |
831 TRACE_SANITIZE (); | 1042 TRACE_SANITIZE (); |
832 if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) | 1043 if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) |
833 return TRACE_RETURN (false); | 1044 return TRACE_RETURN (false); |
834 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (
backtrack); | 1045 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (
backtrack); |
835 if (!lookahead.sanitize (c, this)) | 1046 if (!lookahead.sanitize (c, this)) |
836 return TRACE_RETURN (false); | 1047 return TRACE_RETURN (false); |
837 ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); | 1048 ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); |
838 return TRACE_RETURN (substitute.sanitize (c)); | 1049 return TRACE_RETURN (substitute.sanitize (c)); |
839 } | 1050 } |
840 | 1051 |
841 private: | 1052 protected: |
842 USHORT format; /* Format identifier--format = 1 */ | 1053 USHORT format; /* Format identifier--format = 1 */ |
843 OffsetTo<Coverage> | 1054 OffsetTo<Coverage> |
844 coverage; /* Offset to Coverage table--from | 1055 coverage; /* Offset to Coverage table--from |
845 * beginning of table */ | 1056 * beginning of table */ |
846 OffsetArrayOf<Coverage> | 1057 OffsetArrayOf<Coverage> |
847 backtrack; /* Array of coverage tables | 1058 backtrack; /* Array of coverage tables |
848 * in backtracking sequence, in glyph | 1059 * in backtracking sequence, in glyph |
849 * sequence order */ | 1060 * sequence order */ |
850 OffsetArrayOf<Coverage> | 1061 OffsetArrayOf<Coverage> |
851 lookaheadX; /* Array of coverage tables | 1062 lookaheadX; /* Array of coverage tables |
(...skipping 14 matching lines...) Expand all Loading... |
866 | 1077 |
867 inline void closure (hb_closure_context_t *c) const | 1078 inline void closure (hb_closure_context_t *c) const |
868 { | 1079 { |
869 TRACE_CLOSURE (); | 1080 TRACE_CLOSURE (); |
870 switch (u.format) { | 1081 switch (u.format) { |
871 case 1: u.format1.closure (c); break; | 1082 case 1: u.format1.closure (c); break; |
872 default: break; | 1083 default: break; |
873 } | 1084 } |
874 } | 1085 } |
875 | 1086 |
| 1087 inline const Coverage &get_coverage (void) const |
| 1088 { |
| 1089 switch (u.format) { |
| 1090 case 1: return u.format1.get_coverage (); |
| 1091 default:return Null(Coverage); |
| 1092 } |
| 1093 } |
| 1094 |
876 inline bool apply (hb_apply_context_t *c) const | 1095 inline bool apply (hb_apply_context_t *c) const |
877 { | 1096 { |
878 TRACE_APPLY (); | 1097 TRACE_APPLY (); |
879 switch (u.format) { | 1098 switch (u.format) { |
880 case 1: return TRACE_RETURN (u.format1.apply (c)); | 1099 case 1: return TRACE_RETURN (u.format1.apply (c)); |
881 default:return TRACE_RETURN (false); | 1100 default:return TRACE_RETURN (false); |
882 } | 1101 } |
883 } | 1102 } |
884 | 1103 |
885 inline bool sanitize (hb_sanitize_context_t *c) { | 1104 inline bool sanitize (hb_sanitize_context_t *c) { |
886 TRACE_SANITIZE (); | 1105 TRACE_SANITIZE (); |
887 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 1106 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
888 switch (u.format) { | 1107 switch (u.format) { |
889 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 1108 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
890 default:return TRACE_RETURN (true); | 1109 default:return TRACE_RETURN (true); |
891 } | 1110 } |
892 } | 1111 } |
893 | 1112 |
894 private: | 1113 protected: |
895 union { | 1114 union { |
896 USHORT format; /* Format identifier */ | 1115 USHORT format; /* Format identifier */ |
897 ReverseChainSingleSubstFormat1 format1; | 1116 ReverseChainSingleSubstFormat1 format1; |
898 } u; | 1117 } u; |
899 }; | 1118 }; |
900 | 1119 |
901 | 1120 |
902 | 1121 |
903 /* | 1122 /* |
904 * SubstLookup | 1123 * SubstLookup |
(...skipping 16 matching lines...) Expand all Loading... |
921 | 1140 |
922 inline void closure (hb_closure_context_t *c, | 1141 inline void closure (hb_closure_context_t *c, |
923 unsigned int lookup_type) const | 1142 unsigned int lookup_type) const |
924 { | 1143 { |
925 TRACE_CLOSURE (); | 1144 TRACE_CLOSURE (); |
926 switch (lookup_type) { | 1145 switch (lookup_type) { |
927 case Single: u.single.closure (c); break; | 1146 case Single: u.single.closure (c); break; |
928 case Multiple: u.multiple.closure (c); break; | 1147 case Multiple: u.multiple.closure (c); break; |
929 case Alternate: u.alternate.closure (c); break; | 1148 case Alternate: u.alternate.closure (c); break; |
930 case Ligature: u.ligature.closure (c); break; | 1149 case Ligature: u.ligature.closure (c); break; |
931 case Context:» » u.c.closure (c); break; | 1150 case Context:» » u.context.closure (c); break; |
932 case ChainContext: u.chainContext.closure (c); break; | 1151 case ChainContext: u.chainContext.closure (c); break; |
933 case Extension: u.extension.closure (c); break; | 1152 case Extension: u.extension.closure (c); break; |
934 case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break; | 1153 case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break; |
935 default: break; | 1154 default: break; |
936 } | 1155 } |
937 } | 1156 } |
938 | 1157 |
939 inline bool would_apply (hb_codepoint_t glyph_id, | 1158 inline const Coverage &get_coverage (unsigned int lookup_type) const |
| 1159 { |
| 1160 switch (lookup_type) { |
| 1161 case Single:» » return u.single.get_coverage (); |
| 1162 case Multiple:» » return u.multiple.get_coverage (); |
| 1163 case Alternate:» » return u.alternate.get_coverage (); |
| 1164 case Ligature:» » return u.ligature.get_coverage (); |
| 1165 case Context:» » return u.context.get_coverage (); |
| 1166 case ChainContext:» » return u.chainContext.get_coverage (); |
| 1167 case Extension:» » return u.extension.get_coverage (); |
| 1168 case ReverseChainSingle:» return u.reverseChainContextSingle.get_coverage
(); |
| 1169 default:» » » return Null(Coverage); |
| 1170 } |
| 1171 } |
| 1172 |
| 1173 inline bool would_apply (hb_would_apply_context_t *c, |
940 unsigned int lookup_type) const | 1174 unsigned int lookup_type) const |
941 { | 1175 { |
| 1176 TRACE_WOULD_APPLY (); |
| 1177 if (get_coverage (lookup_type).get_coverage (c->glyphs[0]) == NOT_COVERED) r
eturn false; |
| 1178 if (c->len == 1) { |
| 1179 switch (lookup_type) { |
| 1180 case Single: |
| 1181 case Multiple: |
| 1182 case Alternate: |
| 1183 case ReverseChainSingle: |
| 1184 return true; |
| 1185 } |
| 1186 } |
| 1187 |
| 1188 /* Only need to look further for lookups that support substitutions |
| 1189 * of input longer than 1. */ |
942 switch (lookup_type) { | 1190 switch (lookup_type) { |
943 case Single:» » return u.single.would_apply (glyph_id); | 1191 case Ligature:» » return u.ligature.would_apply (c); |
944 case Multiple:» » return u.multiple.would_apply (glyph_id); | 1192 case Context:» » return u.context.would_apply (c); |
945 case Alternate:» » return u.alternate.would_apply (glyph_id); | 1193 case ChainContext:» » return u.chainContext.would_apply (c); |
946 case Extension:» » return u.extension.would_apply (glyph_id); | 1194 case Extension:» » return u.extension.would_apply (c); |
947 default: return false; | 1195 default: return false; |
948 } | 1196 } |
949 } | 1197 } |
950 inline bool would_apply (hb_codepoint_t first, | |
951 hb_codepoint_t second, | |
952 unsigned int lookup_type) const | |
953 { | |
954 switch (lookup_type) { | |
955 case Ligature: return u.ligature.would_apply (first, second); | |
956 case Extension: return u.extension.would_apply (first, second); | |
957 default: return false; | |
958 } | |
959 } | |
960 | 1198 |
961 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const | 1199 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const |
962 { | 1200 { |
963 TRACE_APPLY (); | 1201 TRACE_APPLY (); |
964 switch (lookup_type) { | 1202 switch (lookup_type) { |
965 case Single: return TRACE_RETURN (u.single.apply (c)); | 1203 case Single: return TRACE_RETURN (u.single.apply (c)); |
966 case Multiple: return TRACE_RETURN (u.multiple.apply (c)); | 1204 case Multiple: return TRACE_RETURN (u.multiple.apply (c)); |
967 case Alternate: return TRACE_RETURN (u.alternate.apply (c)); | 1205 case Alternate: return TRACE_RETURN (u.alternate.apply (c)); |
968 case Ligature: return TRACE_RETURN (u.ligature.apply (c)); | 1206 case Ligature: return TRACE_RETURN (u.ligature.apply (c)); |
969 case Context:» » return TRACE_RETURN (u.c.apply (c)); | 1207 case Context:» » return TRACE_RETURN (u.context.apply (c)); |
970 case ChainContext: return TRACE_RETURN (u.chainContext.apply (c)); | 1208 case ChainContext: return TRACE_RETURN (u.chainContext.apply (c)); |
971 case Extension: return TRACE_RETURN (u.extension.apply (c)); | 1209 case Extension: return TRACE_RETURN (u.extension.apply (c)); |
972 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle
.apply (c)); | 1210 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle
.apply (c)); |
973 default: return TRACE_RETURN (false); | 1211 default: return TRACE_RETURN (false); |
974 } | 1212 } |
975 } | 1213 } |
976 | 1214 |
977 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { | 1215 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { |
978 TRACE_SANITIZE (); | 1216 TRACE_SANITIZE (); |
| 1217 if (!u.header.sub_format.sanitize (c)) |
| 1218 return TRACE_RETURN (false); |
979 switch (lookup_type) { | 1219 switch (lookup_type) { |
980 case Single: return TRACE_RETURN (u.single.sanitize (c)); | 1220 case Single: return TRACE_RETURN (u.single.sanitize (c)); |
981 case Multiple: return TRACE_RETURN (u.multiple.sanitize (c)); | 1221 case Multiple: return TRACE_RETURN (u.multiple.sanitize (c)); |
982 case Alternate: return TRACE_RETURN (u.alternate.sanitize (c)); | 1222 case Alternate: return TRACE_RETURN (u.alternate.sanitize (c)); |
983 case Ligature: return TRACE_RETURN (u.ligature.sanitize (c)); | 1223 case Ligature: return TRACE_RETURN (u.ligature.sanitize (c)); |
984 case Context:» » return TRACE_RETURN (u.c.sanitize (c)); | 1224 case Context:» » return TRACE_RETURN (u.context.sanitize (c)); |
985 case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c)
); | 1225 case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c)
); |
986 case Extension: return TRACE_RETURN (u.extension.sanitize (c)); | 1226 case Extension: return TRACE_RETURN (u.extension.sanitize (c)); |
987 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle
.sanitize (c)); | 1227 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle
.sanitize (c)); |
988 default: return TRACE_RETURN (true); | 1228 default: return TRACE_RETURN (true); |
989 } | 1229 } |
990 } | 1230 } |
991 | 1231 |
992 private: | 1232 protected: |
993 union { | 1233 union { |
994 USHORT» » » sub_format; | 1234 struct { |
| 1235 USHORT» » » sub_format; |
| 1236 } header; |
995 SingleSubst single; | 1237 SingleSubst single; |
996 MultipleSubst multiple; | 1238 MultipleSubst multiple; |
997 AlternateSubst alternate; | 1239 AlternateSubst alternate; |
998 LigatureSubst ligature; | 1240 LigatureSubst ligature; |
999 ContextSubst» » » c; | 1241 ContextSubst» » » context; |
1000 ChainContextSubst chainContext; | 1242 ChainContextSubst chainContext; |
1001 ExtensionSubst extension; | 1243 ExtensionSubst extension; |
1002 ReverseChainSingleSubst reverseChainContextSingle; | 1244 ReverseChainSingleSubst reverseChainContextSingle; |
1003 } u; | 1245 } u; |
1004 public: | 1246 public: |
1005 DEFINE_SIZE_UNION (2, sub_format); | 1247 DEFINE_SIZE_UNION (2, header.sub_format); |
1006 }; | 1248 }; |
1007 | 1249 |
1008 | 1250 |
1009 struct SubstLookup : Lookup | 1251 struct SubstLookup : Lookup |
1010 { | 1252 { |
1011 inline const SubstLookupSubTable& get_subtable (unsigned int i) const | 1253 inline const SubstLookupSubTable& get_subtable (unsigned int i) const |
1012 { return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; } | 1254 { return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; } |
1013 | 1255 |
1014 inline static bool lookup_type_is_reverse (unsigned int lookup_type) | 1256 inline static bool lookup_type_is_reverse (unsigned int lookup_type) |
1015 { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } | 1257 { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } |
1016 | 1258 |
1017 inline bool is_reverse (void) const | 1259 inline bool is_reverse (void) const |
1018 { | 1260 { |
1019 unsigned int type = get_type (); | 1261 unsigned int type = get_type (); |
1020 if (unlikely (type == SubstLookupSubTable::Extension)) | 1262 if (unlikely (type == SubstLookupSubTable::Extension)) |
1021 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse (); | 1263 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse (); |
1022 return lookup_type_is_reverse (type); | 1264 return lookup_type_is_reverse (type); |
1023 } | 1265 } |
1024 | 1266 |
1025 inline void closure (hb_closure_context_t *c) const | 1267 inline void closure (hb_closure_context_t *c) const |
1026 { | 1268 { |
1027 unsigned int lookup_type = get_type (); | 1269 unsigned int lookup_type = get_type (); |
1028 unsigned int count = get_subtable_count (); | 1270 unsigned int count = get_subtable_count (); |
1029 for (unsigned int i = 0; i < count; i++) | 1271 for (unsigned int i = 0; i < count; i++) |
1030 get_subtable (i).closure (c, lookup_type); | 1272 get_subtable (i).closure (c, lookup_type); |
1031 } | 1273 } |
1032 | 1274 |
1033 inline bool would_apply (hb_codepoint_t glyph_id) const | 1275 template <typename set_t> |
| 1276 inline void add_coverage (set_t *glyphs) const |
1034 { | 1277 { |
| 1278 const Coverage *last = NULL; |
| 1279 unsigned int count = get_subtable_count (); |
| 1280 for (unsigned int i = 0; i < count; i++) { |
| 1281 const Coverage *c = &get_subtable (i).get_coverage (get_type ()); |
| 1282 if (c != last) { |
| 1283 c->add_coverage (glyphs); |
| 1284 last = c; |
| 1285 } |
| 1286 } |
| 1287 } |
| 1288 |
| 1289 inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *d
igest) const |
| 1290 { |
| 1291 if (unlikely (!c->len)) return false; |
| 1292 if (!digest->may_have (c->glyphs[0])) return false; |
1035 unsigned int lookup_type = get_type (); | 1293 unsigned int lookup_type = get_type (); |
1036 unsigned int count = get_subtable_count (); | 1294 unsigned int count = get_subtable_count (); |
1037 for (unsigned int i = 0; i < count; i++) | 1295 for (unsigned int i = 0; i < count; i++) |
1038 if (get_subtable (i).would_apply (glyph_id, lookup_type)) | 1296 if (get_subtable (i).would_apply (c, lookup_type)) |
1039 return true; | 1297 return true; |
1040 return false; | 1298 return false; |
1041 } | 1299 } |
1042 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const | |
1043 { | |
1044 unsigned int lookup_type = get_type (); | |
1045 unsigned int count = get_subtable_count (); | |
1046 for (unsigned int i = 0; i < count; i++) | |
1047 if (get_subtable (i).would_apply (first, second, lookup_type)) | |
1048 return true; | |
1049 return false; | |
1050 } | |
1051 | 1300 |
1052 inline bool apply_once (hb_apply_context_t *c) const | 1301 inline bool apply_once (hb_apply_context_t *c) const |
1053 { | 1302 { |
1054 unsigned int lookup_type = get_type (); | 1303 unsigned int lookup_type = get_type (); |
1055 | 1304 |
1056 if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->look
up_props, &c->property)) | 1305 if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->proper
ty)) |
1057 return false; | 1306 return false; |
1058 | 1307 |
1059 if (unlikely (lookup_type == SubstLookupSubTable::Extension)) | |
1060 { | |
1061 /* The spec says all subtables should have the same type. | |
1062 * This is specially important if one has a reverse type! | |
1063 * | |
1064 * This is rather slow to do this here for every glyph, | |
1065 * but it's easiest, and who uses extension lookups anyway?!*/ | |
1066 unsigned int type = get_subtable(0).u.extension.get_type (); | |
1067 unsigned int count = get_subtable_count (); | |
1068 for (unsigned int i = 1; i < count; i++) | |
1069 if (get_subtable(i).u.extension.get_type () != type) | |
1070 return false; | |
1071 } | |
1072 | |
1073 unsigned int count = get_subtable_count (); | 1308 unsigned int count = get_subtable_count (); |
1074 for (unsigned int i = 0; i < count; i++) | 1309 for (unsigned int i = 0; i < count; i++) |
1075 if (get_subtable (i).apply (c, lookup_type)) | 1310 if (get_subtable (i).apply (c, lookup_type)) |
1076 return true; | 1311 return true; |
1077 | 1312 |
1078 return false; | 1313 return false; |
1079 } | 1314 } |
1080 | 1315 |
1081 inline bool apply_string (hb_apply_context_t *c) const | 1316 inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest
) const |
1082 { | 1317 { |
1083 bool ret = false; | 1318 bool ret = false; |
1084 | 1319 |
1085 if (unlikely (!c->buffer->len)) | 1320 if (unlikely (!c->buffer->len || !c->lookup_mask)) |
1086 return false; | 1321 return false; |
1087 | 1322 |
1088 c->set_lookup (*this); | 1323 c->set_lookup (*this); |
1089 | 1324 |
1090 if (likely (!is_reverse ())) | 1325 if (likely (!is_reverse ())) |
1091 { | 1326 { |
1092 /* in/out forward substitution */ | 1327 /* in/out forward substitution */ |
1093 c->buffer->clear_output (); | 1328 c->buffer->clear_output (); |
1094 c->buffer->idx = 0; | 1329 c->buffer->idx = 0; |
| 1330 |
1095 while (c->buffer->idx < c->buffer->len) | 1331 while (c->buffer->idx < c->buffer->len) |
1096 { | 1332 { |
1097 » if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c)) | 1333 » if ((c->buffer->cur().mask & c->lookup_mask) && |
| 1334 » digest->may_have (c->buffer->cur().codepoint) && |
| 1335 » apply_once (c)) |
1098 ret = true; | 1336 ret = true; |
1099 else | 1337 else |
1100 c->buffer->next_glyph (); | 1338 c->buffer->next_glyph (); |
1101 | |
1102 } | 1339 } |
1103 if (ret) | 1340 if (ret) |
1104 c->buffer->swap_buffers (); | 1341 c->buffer->swap_buffers (); |
1105 } | 1342 } |
1106 else | 1343 else |
1107 { | 1344 { |
1108 /* in-place backward substitution */ | 1345 /* in-place backward substitution */ |
1109 c->buffer->idx = c->buffer->len - 1; | 1346 c->buffer->idx = c->buffer->len - 1; |
1110 do | 1347 do |
1111 { | 1348 { |
1112 » if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c)) | 1349 » if ((c->buffer->cur().mask & c->lookup_mask) && |
| 1350 » digest->may_have (c->buffer->cur().codepoint) && |
| 1351 » apply_once (c)) |
1113 ret = true; | 1352 ret = true; |
1114 else | 1353 else |
1115 c->buffer->idx--; | 1354 c->buffer->idx--; |
1116 | 1355 |
1117 } | 1356 } |
1118 while ((int) c->buffer->idx >= 0); | 1357 while ((int) c->buffer->idx >= 0); |
1119 } | 1358 } |
1120 | 1359 |
1121 return ret; | 1360 return ret; |
1122 } | 1361 } |
1123 | 1362 |
1124 inline bool sanitize (hb_sanitize_context_t *c) { | 1363 private: |
| 1364 inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c, |
| 1365 » » » » » » unsigned int i) |
| 1366 { return CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i].serialize (c
, this); } |
| 1367 public: |
| 1368 |
| 1369 inline bool serialize_single (hb_serialize_context_t *c, |
| 1370 » » » » uint32_t lookup_props, |
| 1371 » » » Supplier<GlyphID> &glyphs, |
| 1372 » » » Supplier<GlyphID> &substitutes, |
| 1373 » » » unsigned int num_glyphs) |
| 1374 { |
| 1375 TRACE_SERIALIZE (); |
| 1376 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_pro
ps, 1))) return TRACE_RETURN (false); |
| 1377 return TRACE_RETURN (serialize_subtable (c, 0).u.single.serialize (c, glyphs
, substitutes, num_glyphs)); |
| 1378 } |
| 1379 |
| 1380 inline bool serialize_multiple (hb_serialize_context_t *c, |
| 1381 » » » » uint32_t lookup_props, |
| 1382 » » » » Supplier<GlyphID> &glyphs, |
| 1383 » » » » Supplier<unsigned int> &substitute_len_list, |
| 1384 » » » » unsigned int num_glyphs, |
| 1385 » » » » Supplier<GlyphID> &substitute_glyphs_list) |
| 1386 { |
| 1387 TRACE_SERIALIZE (); |
| 1388 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_p
rops, 1))) return TRACE_RETURN (false); |
| 1389 return TRACE_RETURN (serialize_subtable (c, 0).u.multiple.serialize (c, glyp
hs, substitute_len_list, num_glyphs, |
| 1390 » » » » » » » » » substit
ute_glyphs_list)); |
| 1391 } |
| 1392 |
| 1393 inline bool serialize_alternate (hb_serialize_context_t *c, |
| 1394 » » » » uint32_t lookup_props, |
| 1395 » » » » Supplier<GlyphID> &glyphs, |
| 1396 » » » » Supplier<unsigned int> &alternate_len_list, |
| 1397 » » » » unsigned int num_glyphs, |
| 1398 » » » » Supplier<GlyphID> &alternate_glyphs_list) |
| 1399 { |
| 1400 TRACE_SERIALIZE (); |
| 1401 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_
props, 1))) return TRACE_RETURN (false); |
| 1402 return TRACE_RETURN (serialize_subtable (c, 0).u.alternate.serialize (c, gly
phs, alternate_len_list, num_glyphs, |
| 1403 » » » » » » » » » altern
ate_glyphs_list)); |
| 1404 } |
| 1405 |
| 1406 inline bool serialize_ligature (hb_serialize_context_t *c, |
| 1407 » » » » uint32_t lookup_props, |
| 1408 » » » » Supplier<GlyphID> &first_glyphs, |
| 1409 » » » » Supplier<unsigned int> &ligature_per_first_gly
ph_count_list, |
| 1410 » » » » unsigned int num_first_glyphs, |
| 1411 » » » » Supplier<GlyphID> &ligatures_list, |
| 1412 » » » » Supplier<unsigned int> &component_count_list, |
| 1413 » » » » Supplier<GlyphID> &component_list /* Starting
from second for each ligature */) |
| 1414 { |
| 1415 TRACE_SERIALIZE (); |
| 1416 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_p
rops, 1))) return TRACE_RETURN (false); |
| 1417 return TRACE_RETURN (serialize_subtable (c, 0).u.ligature.serialize (c, firs
t_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs, |
| 1418 » » » » » » » » » ligatur
es_list, component_count_list, component_list)); |
| 1419 } |
| 1420 |
| 1421 inline bool sanitize (hb_sanitize_context_t *c) |
| 1422 { |
1125 TRACE_SANITIZE (); | 1423 TRACE_SANITIZE (); |
1126 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); | 1424 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); |
1127 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu
bTable> > (subTable); | 1425 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu
bTable> > (subTable); |
1128 return TRACE_RETURN (list.sanitize (c, this, get_type ())); | 1426 if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (f
alse); |
| 1427 |
| 1428 if (unlikely (get_type () == SubstLookupSubTable::Extension)) |
| 1429 { |
| 1430 /* The spec says all subtables of an Extension lookup should |
| 1431 * have the same type. This is specially important if one has |
| 1432 * a reverse type! |
| 1433 * |
| 1434 * We just check that they are all either forward, or reverse. */ |
| 1435 unsigned int type = get_subtable (0).u.extension.get_type (); |
| 1436 unsigned int count = get_subtable_count (); |
| 1437 for (unsigned int i = 1; i < count; i++) |
| 1438 if (get_subtable (i).u.extension.get_type () != type) |
| 1439 » return TRACE_RETURN (false); |
| 1440 } |
| 1441 return TRACE_RETURN (true); |
1129 } | 1442 } |
1130 }; | 1443 }; |
1131 | 1444 |
1132 typedef OffsetListOf<SubstLookup> SubstLookupList; | 1445 typedef OffsetListOf<SubstLookup> SubstLookupList; |
1133 | 1446 |
1134 /* | 1447 /* |
1135 * GSUB -- The Glyph Substitution Table | 1448 * GSUB -- The Glyph Substitution Table |
1136 */ | 1449 */ |
1137 | 1450 |
1138 struct GSUB : GSUBGPOS | 1451 struct GSUB : GSUBGPOS |
1139 { | 1452 { |
1140 static const hb_tag_t Tag = HB_OT_TAG_GSUB; | 1453 static const hb_tag_t Tag = HB_OT_TAG_GSUB; |
1141 | 1454 |
1142 inline const SubstLookup& get_lookup (unsigned int i) const | 1455 inline const SubstLookup& get_lookup (unsigned int i) const |
1143 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); } | 1456 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); } |
1144 | 1457 |
1145 inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_inde
x) const | 1458 template <typename set_t> |
1146 { return get_lookup (lookup_index).apply_string (c); } | 1459 inline void add_coverage (set_t *glyphs, unsigned int lookup_index) const |
| 1460 { get_lookup (lookup_index).add_coverage (glyphs); } |
1147 | 1461 |
1148 static inline void substitute_start (hb_buffer_t *buffer); | 1462 static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); |
1149 static inline void substitute_finish (hb_buffer_t *buffer); | 1463 static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer); |
1150 | 1464 |
1151 inline void closure_lookup (hb_closure_context_t *c, | 1465 inline void closure_lookup (hb_closure_context_t *c, |
1152 unsigned int lookup_index) const | 1466 unsigned int lookup_index) const |
1153 { return get_lookup (lookup_index).closure (c); } | 1467 { return get_lookup (lookup_index).closure (c); } |
1154 | 1468 |
1155 inline bool sanitize (hb_sanitize_context_t *c) { | 1469 inline bool sanitize (hb_sanitize_context_t *c) { |
1156 TRACE_SANITIZE (); | 1470 TRACE_SANITIZE (); |
1157 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); | 1471 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); |
1158 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL
ist); | 1472 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL
ist); |
1159 return TRACE_RETURN (list.sanitize (c, this)); | 1473 return TRACE_RETURN (list.sanitize (c, this)); |
1160 } | 1474 } |
1161 public: | 1475 public: |
1162 DEFINE_SIZE_STATIC (10); | 1476 DEFINE_SIZE_STATIC (10); |
1163 }; | 1477 }; |
1164 | 1478 |
1165 | 1479 |
1166 void | 1480 void |
1167 GSUB::substitute_start (hb_buffer_t *buffer) | 1481 GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) |
1168 { | 1482 { |
1169 HB_BUFFER_ALLOCATE_VAR (buffer, props_cache); | 1483 HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props); |
1170 HB_BUFFER_ALLOCATE_VAR (buffer, lig_props); | 1484 HB_BUFFER_ALLOCATE_VAR (buffer, lig_props); |
1171 HB_BUFFER_ALLOCATE_VAR (buffer, syllable); | 1485 HB_BUFFER_ALLOCATE_VAR (buffer, syllable); |
1172 | 1486 |
| 1487 const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; |
1173 unsigned int count = buffer->len; | 1488 unsigned int count = buffer->len; |
1174 for (unsigned int i = 0; i < count; i++) | 1489 for (unsigned int i = 0; i < count; i++) { |
1175 buffer->info[i].props_cache() = buffer->info[i].lig_props() = buffer->info[i
].syllable() = 0; | 1490 buffer->info[i].lig_props() = buffer->info[i].syllable() = 0; |
| 1491 buffer->info[i].glyph_props() = gdef.get_glyph_props (buffer->info[i].codepo
int); |
| 1492 } |
1176 } | 1493 } |
1177 | 1494 |
1178 void | 1495 void |
1179 GSUB::substitute_finish (hb_buffer_t *buffer HB_UNUSED) | 1496 GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE
D) |
1180 { | 1497 { |
1181 } | 1498 } |
1182 | 1499 |
1183 | 1500 |
1184 /* Out-of-class implementation for methods recursing */ | 1501 /* Out-of-class implementation for methods recursing */ |
1185 | 1502 |
1186 inline void ExtensionSubst::closure (hb_closure_context_t *c) const | 1503 inline void ExtensionSubst::closure (hb_closure_context_t *c) const |
1187 { | 1504 { |
1188 get_subtable ().closure (c, get_type ()); | 1505 get_subtable ().closure (c, get_type ()); |
1189 } | 1506 } |
1190 | 1507 |
1191 inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const | 1508 inline const Coverage & ExtensionSubst::get_coverage (void) const |
1192 { | 1509 { |
1193 return get_subtable ().would_apply (glyph_id, get_type ()); | 1510 return get_subtable ().get_coverage (get_type ()); |
1194 } | 1511 } |
1195 | 1512 |
1196 inline bool ExtensionSubst::would_apply (hb_codepoint_t first, hb_codepoint_t se
cond) const | 1513 inline bool ExtensionSubst::would_apply (hb_would_apply_context_t *c) const |
1197 { | 1514 { |
1198 return get_subtable ().would_apply (first, second, get_type ()); | 1515 return get_subtable ().would_apply (c, get_type ()); |
1199 } | 1516 } |
1200 | 1517 |
1201 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const | 1518 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const |
1202 { | 1519 { |
1203 TRACE_APPLY (); | 1520 TRACE_APPLY (); |
1204 return TRACE_RETURN (get_subtable ().apply (c, get_type ())); | 1521 return TRACE_RETURN (get_subtable ().apply (c, get_type ())); |
1205 } | 1522 } |
1206 | 1523 |
1207 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c) | 1524 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c) |
1208 { | 1525 { |
1209 TRACE_SANITIZE (); | 1526 TRACE_SANITIZE (); |
1210 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false); | 1527 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false); |
1211 unsigned int offset = get_offset (); | 1528 unsigned int offset = get_offset (); |
1212 if (unlikely (!offset)) return TRACE_RETURN (true); | 1529 if (unlikely (!offset)) return TRACE_RETURN (true); |
1213 return TRACE_RETURN (StructAtOffset<SubstLookupSubTable> (this, offset).saniti
ze (c, get_type ())); | 1530 return TRACE_RETURN (StructAtOffset<SubstLookupSubTable> (this, offset).saniti
ze (c, get_type ())); |
1214 } | 1531 } |
1215 | 1532 |
1216 inline bool ExtensionSubst::is_reverse (void) const | 1533 inline bool ExtensionSubst::is_reverse (void) const |
1217 { | 1534 { |
1218 unsigned int type = get_type (); | 1535 unsigned int type = get_type (); |
1219 if (unlikely (type == SubstLookupSubTable::Extension)) | 1536 if (unlikely (type == SubstLookupSubTable::Extension)) |
1220 return CastR<ExtensionSubst> (get_subtable()).is_reverse (); | 1537 return CastR<ExtensionSubst> (get_subtable()).is_reverse (); |
1221 return SubstLookup::lookup_type_is_reverse (type); | 1538 return SubstLookup::lookup_type_is_reverse (type); |
1222 } | 1539 } |
1223 | 1540 |
1224 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_
index) | 1541 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_
index) |
1225 { | 1542 { |
1226 const GSUB &gsub = *(c->face->ot_layout->gsub); | 1543 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); |
1227 const SubstLookup &l = gsub.get_lookup (lookup_index); | 1544 const SubstLookup &l = gsub.get_lookup (lookup_index); |
1228 | 1545 |
1229 if (unlikely (c->nesting_level_left == 0)) | 1546 if (unlikely (c->nesting_level_left == 0)) |
1230 return; | 1547 return; |
1231 | 1548 |
1232 c->nesting_level_left--; | 1549 c->nesting_level_left--; |
1233 l.closure (c); | 1550 l.closure (c); |
1234 c->nesting_level_left++; | 1551 c->nesting_level_left++; |
1235 } | 1552 } |
1236 | 1553 |
1237 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index) | 1554 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index) |
1238 { | 1555 { |
1239 const GSUB &gsub = *(c->face->ot_layout->gsub); | 1556 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); |
1240 const SubstLookup &l = gsub.get_lookup (lookup_index); | 1557 const SubstLookup &l = gsub.get_lookup (lookup_index); |
1241 | 1558 |
1242 if (unlikely (c->nesting_level_left == 0)) | 1559 if (unlikely (c->nesting_level_left == 0)) |
1243 return false; | 1560 return false; |
1244 | 1561 |
1245 hb_apply_context_t new_c (*c); | 1562 hb_apply_context_t new_c (*c); |
1246 new_c.nesting_level_left--; | 1563 new_c.nesting_level_left--; |
1247 new_c.set_lookup (l); | 1564 new_c.set_lookup (l); |
1248 return l.apply_once (&new_c); | 1565 return l.apply_once (&new_c); |
1249 } | 1566 } |
1250 | 1567 |
1251 | 1568 |
| 1569 } // namespace OT |
| 1570 |
1252 | 1571 |
1253 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ | 1572 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ |
OLD | NEW |