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,2013 Google, Inc. | 3 * Copyright © 2010,2012,2013 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 26 matching lines...) Expand all Loading... |
37 | 37 |
38 struct SingleSubstFormat1 | 38 struct SingleSubstFormat1 |
39 { | 39 { |
40 inline void closure (hb_closure_context_t *c) const | 40 inline void closure (hb_closure_context_t *c) const |
41 { | 41 { |
42 TRACE_CLOSURE (this); | 42 TRACE_CLOSURE (this); |
43 Coverage::Iter iter; | 43 Coverage::Iter iter; |
44 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 44 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
45 hb_codepoint_t glyph_id = iter.get_glyph (); | 45 hb_codepoint_t glyph_id = iter.get_glyph (); |
46 if (c->glyphs->has (glyph_id)) | 46 if (c->glyphs->has (glyph_id)) |
47 » c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF); | 47 » c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); |
48 } | 48 } |
49 } | 49 } |
50 | 50 |
51 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const | 51 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const |
52 { | 52 { |
53 TRACE_COLLECT_GLYPHS (this); | 53 TRACE_COLLECT_GLYPHS (this); |
54 Coverage::Iter iter; | 54 Coverage::Iter iter; |
55 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 55 for (iter.init (this+coverage); iter.more (); iter.next ()) { |
56 hb_codepoint_t glyph_id = iter.get_glyph (); | 56 hb_codepoint_t glyph_id = iter.get_glyph (); |
57 c->input->add (glyph_id); | 57 c->input->add (glyph_id); |
58 c->output->add ((glyph_id + deltaGlyphID) & 0xFFFF); | 58 c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu); |
59 } | 59 } |
60 } | 60 } |
61 | 61 |
62 inline const Coverage &get_coverage (void) const | 62 inline const Coverage &get_coverage (void) const |
63 { | 63 { |
64 return this+coverage; | 64 return this+coverage; |
65 } | 65 } |
66 | 66 |
67 inline bool would_apply (hb_would_apply_context_t *c) const | 67 inline bool would_apply (hb_would_apply_context_t *c) const |
68 { | 68 { |
69 TRACE_WOULD_APPLY (this); | 69 TRACE_WOULD_APPLY (this); |
70 return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[
0]) != NOT_COVERED); | 70 return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[
0]) != NOT_COVERED); |
71 } | 71 } |
72 | 72 |
73 inline bool apply (hb_apply_context_t *c) const | 73 inline bool apply (hb_apply_context_t *c) const |
74 { | 74 { |
75 TRACE_APPLY (this); | 75 TRACE_APPLY (this); |
76 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; | 76 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; |
77 unsigned int index = (this+coverage).get_coverage (glyph_id); | 77 unsigned int index = (this+coverage).get_coverage (glyph_id); |
78 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 78 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
79 | 79 |
80 /* According to the Adobe Annotated OpenType Suite, result is always | 80 /* According to the Adobe Annotated OpenType Suite, result is always |
81 * limited to 16bit. */ | 81 * limited to 16bit. */ |
82 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF; | 82 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu; |
83 c->replace_glyph (glyph_id); | 83 c->replace_glyph (glyph_id); |
84 | 84 |
85 return TRACE_RETURN (true); | 85 return TRACE_RETURN (true); |
86 } | 86 } |
87 | 87 |
88 inline bool serialize (hb_serialize_context_t *c, | 88 inline bool serialize (hb_serialize_context_t *c, |
89 Supplier<GlyphID> &glyphs, | 89 Supplier<GlyphID> &glyphs, |
90 unsigned int num_glyphs, | 90 unsigned int num_glyphs, |
91 int delta) | 91 int delta) |
92 { | 92 { |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 { | 263 { |
264 TRACE_COLLECT_GLYPHS (this); | 264 TRACE_COLLECT_GLYPHS (this); |
265 unsigned int count = substitute.len; | 265 unsigned int count = substitute.len; |
266 for (unsigned int i = 0; i < count; i++) | 266 for (unsigned int i = 0; i < count; i++) |
267 c->output->add (substitute[i]); | 267 c->output->add (substitute[i]); |
268 } | 268 } |
269 | 269 |
270 inline bool apply (hb_apply_context_t *c) const | 270 inline bool apply (hb_apply_context_t *c) const |
271 { | 271 { |
272 TRACE_APPLY (this); | 272 TRACE_APPLY (this); |
273 if (unlikely (!substitute.len)) return TRACE_RETURN (false); | 273 unsigned int count = substitute.len; |
| 274 |
| 275 /* TODO: |
| 276 * Testing shows that Uniscribe actually allows zero-len susbstitute, |
| 277 * which essentially deletes a glyph. We don't allow for now. It |
| 278 * can be confusing to the client since the cluster from the deleted |
| 279 * glyph won't be merged with any output cluster... Also, currently |
| 280 * buffer->move_to() makes assumptions about this too. Perhaps fix |
| 281 * in the future after figuring out what to do with the clusters. |
| 282 */ |
| 283 if (unlikely (!count)) return TRACE_RETURN (false); |
| 284 |
| 285 /* Special-case to make it in-place and not consider this |
| 286 * as a "multiplied" substitution. */ |
| 287 if (unlikely (count == 1)) |
| 288 { |
| 289 c->replace_glyph (substitute.array[0]); |
| 290 return TRACE_RETURN (true); |
| 291 } |
274 | 292 |
275 unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? | 293 unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? |
276 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; | 294 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; |
277 unsigned int count = substitute.len; | 295 |
278 if (count == 1) /* Special-case to make it in-place. */ | 296 for (unsigned int i = 0; i < count; i++) { |
279 { | 297 _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); |
280 c->replace_glyph (substitute.array[0]); | 298 c->output_glyph_for_component (substitute.array[i], klass); |
281 } | 299 } |
282 else | 300 c->buffer->skip_glyph (); |
283 { | |
284 for (unsigned int i = 0; i < count; i++) { | |
285 » _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); | |
286 » c->output_glyph (substitute.array[i], klass); | |
287 } | |
288 c->buffer->skip_glyph (); | |
289 } | |
290 | 301 |
291 return TRACE_RETURN (true); | 302 return TRACE_RETURN (true); |
292 } | 303 } |
293 | 304 |
294 inline bool serialize (hb_serialize_context_t *c, | 305 inline bool serialize (hb_serialize_context_t *c, |
295 Supplier<GlyphID> &glyphs, | 306 Supplier<GlyphID> &glyphs, |
296 unsigned int num_glyphs) | 307 unsigned int num_glyphs) |
297 { | 308 { |
298 TRACE_SERIALIZE (this); | 309 TRACE_SERIALIZE (this); |
299 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); | 310 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 if (likely (c->glyphs[i] != component[i])) | 628 if (likely (c->glyphs[i] != component[i])) |
618 return TRACE_RETURN (false); | 629 return TRACE_RETURN (false); |
619 | 630 |
620 return TRACE_RETURN (true); | 631 return TRACE_RETURN (true); |
621 } | 632 } |
622 | 633 |
623 inline bool apply (hb_apply_context_t *c) const | 634 inline bool apply (hb_apply_context_t *c) const |
624 { | 635 { |
625 TRACE_APPLY (this); | 636 TRACE_APPLY (this); |
626 unsigned int count = component.len; | 637 unsigned int count = component.len; |
627 if (unlikely (count < 1)) return TRACE_RETURN (false); | 638 |
| 639 if (unlikely (!count)) return TRACE_RETURN (false); |
| 640 |
| 641 /* Special-case to make it in-place and not consider this |
| 642 * as a "ligated" substitution. */ |
| 643 if (unlikely (count == 1)) |
| 644 { |
| 645 c->replace_glyph (ligGlyph); |
| 646 return TRACE_RETURN (true); |
| 647 } |
628 | 648 |
629 bool is_mark_ligature = false; | 649 bool is_mark_ligature = false; |
630 unsigned int total_component_count = 0; | 650 unsigned int total_component_count = 0; |
631 | 651 |
632 unsigned int match_length = 0; | 652 unsigned int match_length = 0; |
633 unsigned int match_positions[MAX_CONTEXT_LENGTH]; | 653 unsigned int match_positions[MAX_CONTEXT_LENGTH]; |
634 | 654 |
635 if (likely (!match_input (c, count, | 655 if (likely (!match_input (c, count, |
636 &component[1], | 656 &component[1], |
637 match_glyph, | 657 match_glyph, |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 } | 1351 } |
1332 | 1352 |
1333 void | 1353 void |
1334 GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE
D) | 1354 GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE
D) |
1335 { | 1355 { |
1336 } | 1356 } |
1337 | 1357 |
1338 | 1358 |
1339 /* Out-of-class implementation for methods recursing */ | 1359 /* Out-of-class implementation for methods recursing */ |
1340 | 1360 |
1341 inline bool ExtensionSubst::is_reverse (void) const | 1361 /*static*/ inline bool ExtensionSubst::is_reverse (void) const |
1342 { | 1362 { |
1343 unsigned int type = get_type (); | 1363 unsigned int type = get_type (); |
1344 if (unlikely (type == SubstLookupSubTable::Extension)) | 1364 if (unlikely (type == SubstLookupSubTable::Extension)) |
1345 return CastR<ExtensionSubst> (get_subtable<SubstLookupSubTable>()).is_revers
e (); | 1365 return CastR<ExtensionSubst> (get_subtable<SubstLookupSubTable>()).is_revers
e (); |
1346 return SubstLookup::lookup_type_is_reverse (type); | 1366 return SubstLookup::lookup_type_is_reverse (type); |
1347 } | 1367 } |
1348 | 1368 |
1349 template <typename context_t> | 1369 template <typename context_t> |
1350 inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_
t *c, unsigned int lookup_index) | 1370 /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_fun
c (context_t *c, unsigned int lookup_index) |
1351 { | 1371 { |
1352 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); | 1372 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); |
1353 const SubstLookup &l = gsub.get_lookup (lookup_index); | 1373 const SubstLookup &l = gsub.get_lookup (lookup_index); |
1354 return l.dispatch (c); | 1374 return l.dispatch (c); |
1355 } | 1375 } |
1356 | 1376 |
1357 inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int
lookup_index) | 1377 /*static*/ inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, u
nsigned int lookup_index) |
1358 { | 1378 { |
1359 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); | 1379 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); |
1360 const SubstLookup &l = gsub.get_lookup (lookup_index); | 1380 const SubstLookup &l = gsub.get_lookup (lookup_index); |
1361 unsigned int saved_lookup_props = c->lookup_props; | 1381 unsigned int saved_lookup_props = c->lookup_props; |
1362 c->set_lookup (l); | 1382 c->set_lookup (l); |
1363 bool ret = l.apply_once (c); | 1383 bool ret = l.apply_once (c); |
1364 c->lookup_props = saved_lookup_props; | 1384 c->lookup_props = saved_lookup_props; |
1365 return ret; | 1385 return ret; |
1366 } | 1386 } |
1367 | 1387 |
1368 | 1388 |
1369 } /* namespace OT */ | 1389 } /* namespace OT */ |
1370 | 1390 |
1371 | 1391 |
1372 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ | 1392 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ |
OLD | NEW |