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