• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef OT_GLYF_SUBSETGLYPH_HH
2 #define OT_GLYF_SUBSETGLYPH_HH
3 
4 
5 #include "../../hb-open-type.hh"
6 
7 
8 namespace OT {
9 
10 struct glyf_accelerator_t;
11 
12 namespace glyf_impl {
13 
14 
15 struct 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 
serializeOT::glyf_impl::SubsetGlyph23   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 
compile_bytes_with_deltasOT::glyf_impl::SubsetGlyph121   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 
free_compiled_bytesOT::glyf_impl::SubsetGlyph129   void free_compiled_bytes ()
130   {
131     if (likely (allocated)) {
132       allocated = false;
133       dest_start.fini ();
134       dest_end.fini ();
135     }
136   }
137 
drop_hints_bytesOT::glyf_impl::SubsetGlyph138   void drop_hints_bytes ()
139   { source_glyph.drop_hints_bytes (dest_start, dest_end); }
140 
lengthOT::glyf_impl::SubsetGlyph141   unsigned int      length () const { return dest_start.length + dest_end.length; }
142   /* pad to 2 to ensure 2-byte loca will be ok */
paddingOT::glyf_impl::SubsetGlyph143   unsigned int     padding () const { return length () % 2; }
padded_sizeOT::glyf_impl::SubsetGlyph144   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