1#ifndef OT_GLYF_SUBSETGLYPH_HH
2#define OT_GLYF_SUBSETGLYPH_HH
3
4
5#include "../../hb-open-type.hh"
6
7
8namespace OT {
9
10struct glyf_accelerator_t;
11
12namespace glyf_impl {
13
14
15struct SubsetGlyph
16{
17 hb_codepoint_t old_gid;
18 Glyph source_glyph;
19 hb_bytes_t dest_start; /* region of source_glyph to copy first */
20 hb_bytes_t dest_end; /* region of source_glyph to copy second */
21 bool allocated;
22
23 bool serialize (hb_serialize_context_t *c,
24 bool use_short_loca,
25 const hb_subset_plan_t *plan) const
26 {
27 TRACE_SERIALIZE (this);
28
29 hb_bytes_t dest_glyph = dest_start.copy (c);
30 hb_bytes_t end_copy = dest_end.copy (c);
31 if (!end_copy.arrayZ || !dest_glyph.arrayZ) {
32 return false;
33 }
34
35 dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length);
36 unsigned int pad_length = use_short_loca ? padding () : 0;
37 DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
38
39 HBUINT8 pad;
40 pad = 0;
41 while (pad_length > 0)
42 {
43 (void) c->embed (pad);
44 pad_length--;
45 }
46
47 if (unlikely (!dest_glyph.length)) return_trace (true);
48
49 /* update components gids. */
50 for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
51 {
52 hb_codepoint_t new_gid;
53 if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
54 const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
55 }
56#ifndef HB_NO_VAR_COMPOSITES
57 for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ())
58 {
59 hb_codepoint_t new_gid;
60 if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
61 const_cast<VarCompositeGlyphRecord &> (_).set_gid (new_gid);
62 }
63#endif
64
65#ifndef HB_NO_BEYOND_64K
66 auto it = Glyph (dest_glyph).get_composite_iterator ();
67 if (it)
68 {
69 /* lower GID24 to GID16 in components if possible.
70 *
71 * TODO: VarComposite. Not as critical, since VarComposite supports
72 * gid24 from the first version. */
73 char *p = it ? (char *) &*it : nullptr;
74 char *q = p;
75 const char *end = dest_glyph.arrayZ + dest_glyph.length;
76 while (it)
77 {
78 auto &rec = const_cast<CompositeGlyphRecord &> (*it);
79 ++it;
80
81 q += rec.get_size ();
82
83 rec.lower_gid_24_to_16 ();
84
85 unsigned size = rec.get_size ();
86
87 memmove (p, &rec, size);
88
89 p += size;
90 }
91 memmove (p, q, end - q);
92 p += end - q;
93
94 /* We want to shorten the glyph, but we can't do that without
95 * updating the length in the loca table, which is already
96 * written out :-(. So we just fill the rest of the glyph with
97 * harmless instructions, since that's what they will be
98 * interpreted as.
99 *
100 * Should move the lowering to _populate_subset_glyphs() to
101 * fix this issue. */
102
103 hb_memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p);
104 p += end - p;
105 dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ);
106
107 // TODO: Padding; & trim serialized bytes.
108 // TODO: Update length in loca. Ugh.
109 }
110#endif
111
112 if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
113 Glyph (dest_glyph).drop_hints ();
114
115 if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
116 Glyph (dest_glyph).set_overlaps_flag ();
117
118 return_trace (true);
119 }
120
121 bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
122 hb_font_t *font,
123 const glyf_accelerator_t &glyf)
124 {
125 allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
126 return allocated;
127 }
128
129 void free_compiled_bytes ()
130 {
131 if (likely (allocated)) {
132 allocated = false;
133 dest_start.fini ();
134 dest_end.fini ();
135 }
136 }
137
138 void drop_hints_bytes ()
139 { source_glyph.drop_hints_bytes (dest_start, dest_end); }
140
141 unsigned int length () const { return dest_start.length + dest_end.length; }
142 /* pad to 2 to ensure 2-byte loca will be ok */
143 unsigned int padding () const { return length () % 2; }
144 unsigned int padded_size () const { return length () + padding (); }
145};
146
147
148} /* namespace glyf_impl */
149} /* namespace OT */
150
151
152#endif /* OT_GLYF_SUBSETGLYPH_HH */
153