1 #ifndef OT_LAYOUT_GSUB_SEQUENCE_HH
2 #define OT_LAYOUT_GSUB_SEQUENCE_HH
10 template <typename Types>
14 Array16Of<typename Types::HBGlyphID>
15 substitute; /* String of GlyphIDs to substitute */
17 DEFINE_SIZE_ARRAY (2, substitute);
19 bool sanitize (hb_sanitize_context_t *c) const
21 TRACE_SANITIZE (this);
22 return_trace (substitute.sanitize (c));
25 bool intersects (const hb_set_t *glyphs) const
26 { return hb_all (substitute, glyphs); }
28 void closure (hb_closure_context_t *c) const
29 { c->output->add_array (substitute.arrayZ, substitute.len); }
31 void collect_glyphs (hb_collect_glyphs_context_t *c) const
32 { c->output->add_array (substitute.arrayZ, substitute.len); }
34 bool apply (hb_ot_apply_context_t *c) const
37 unsigned int count = substitute.len;
39 /* Special-case to make it in-place and not consider this
40 * as a "multiplied" substitution. */
41 if (unlikely (count == 1))
43 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
45 c->buffer->sync_so_far ();
46 c->buffer->message (c->font,
47 "replacing glyph at %u (multiple substitution)",
51 c->replace_glyph (substitute.arrayZ[0]);
53 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
55 c->buffer->message (c->font,
56 "replaced glyph at %u (multiple substitution)",
62 /* Spec disallows this, but Uniscribe allows it.
63 * https://github.com/harfbuzz/harfbuzz/issues/253 */
64 else if (unlikely (count == 0))
66 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
68 c->buffer->sync_so_far ();
69 c->buffer->message (c->font,
70 "deleting glyph at %u (multiple substitution)",
74 c->buffer->delete_glyph ();
76 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
78 c->buffer->sync_so_far ();
79 c->buffer->message (c->font,
80 "deleted glyph at %u (multiple substitution)",
87 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
89 c->buffer->sync_so_far ();
90 c->buffer->message (c->font,
91 "multiplying glyph at %u",
95 unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
96 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
97 unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
99 for (unsigned int i = 0; i < count; i++)
101 /* If is attached to a ligature, don't disturb that.
102 * https://github.com/harfbuzz/harfbuzz/issues/3069 */
104 _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
105 c->output_glyph_for_component (substitute.arrayZ[i], klass);
107 c->buffer->skip_glyph ();
109 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
111 c->buffer->sync_so_far ();
113 char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
116 for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++)
120 snprintf (p, sizeof(buf) - (p - buf), "%u", i);
124 c->buffer->message (c->font,
125 "multiplied glyphs at %s",
132 template <typename Iterator,
133 hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
134 bool serialize (hb_serialize_context_t *c,
137 TRACE_SERIALIZE (this);
138 return_trace (substitute.serialize (c, subst));
141 bool subset (hb_subset_context_t *c) const
144 const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
145 const hb_map_t &glyph_map = *c->plan->glyph_map;
147 if (!intersects (&glyphset)) return_trace (false);
150 + hb_iter (substitute)
154 auto *out = c->serializer->start_embed (*this);
155 return_trace (out->serialize (c->serializer, it));
165 #endif /* OT_LAYOUT_GSUB_SEQUENCE_HH */