xref: /aosp_15_r20/external/harfbuzz_ng/src/OT/glyf/glyf.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_GLYF_HH
2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_GLYF_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 #include "../../hb-ot-head-table.hh"
7*2d1272b8SAndroid Build Coastguard Worker #include "../../hb-ot-hmtx-table.hh"
8*2d1272b8SAndroid Build Coastguard Worker #include "../../hb-ot-var-gvar-table.hh"
9*2d1272b8SAndroid Build Coastguard Worker #include "../../hb-draw.hh"
10*2d1272b8SAndroid Build Coastguard Worker #include "../../hb-paint.hh"
11*2d1272b8SAndroid Build Coastguard Worker 
12*2d1272b8SAndroid Build Coastguard Worker #include "glyf-helpers.hh"
13*2d1272b8SAndroid Build Coastguard Worker #include "Glyph.hh"
14*2d1272b8SAndroid Build Coastguard Worker #include "SubsetGlyph.hh"
15*2d1272b8SAndroid Build Coastguard Worker #include "loca.hh"
16*2d1272b8SAndroid Build Coastguard Worker #include "path-builder.hh"
17*2d1272b8SAndroid Build Coastguard Worker 
18*2d1272b8SAndroid Build Coastguard Worker 
19*2d1272b8SAndroid Build Coastguard Worker namespace OT {
20*2d1272b8SAndroid Build Coastguard Worker 
21*2d1272b8SAndroid Build Coastguard Worker 
22*2d1272b8SAndroid Build Coastguard Worker /*
23*2d1272b8SAndroid Build Coastguard Worker  * glyf -- TrueType Glyph Data
24*2d1272b8SAndroid Build Coastguard Worker  * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
25*2d1272b8SAndroid Build Coastguard Worker  */
26*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
27*2d1272b8SAndroid Build Coastguard Worker 
28*2d1272b8SAndroid Build Coastguard Worker struct glyf
29*2d1272b8SAndroid Build Coastguard Worker {
30*2d1272b8SAndroid Build Coastguard Worker   friend struct glyf_accelerator_t;
31*2d1272b8SAndroid Build Coastguard Worker 
32*2d1272b8SAndroid Build Coastguard Worker   static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
33*2d1272b8SAndroid Build Coastguard Worker 
has_valid_glyf_formatOT::glyf34*2d1272b8SAndroid Build Coastguard Worker   static bool has_valid_glyf_format(const hb_face_t* face)
35*2d1272b8SAndroid Build Coastguard Worker   {
36*2d1272b8SAndroid Build Coastguard Worker     const OT::head &head = *face->table.head;
37*2d1272b8SAndroid Build Coastguard Worker     return head.indexToLocFormat <= 1 && head.glyphDataFormat <= 1;
38*2d1272b8SAndroid Build Coastguard Worker   }
39*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::glyf40*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
41*2d1272b8SAndroid Build Coastguard Worker   {
42*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
43*2d1272b8SAndroid Build Coastguard Worker     /* Runtime checks as eager sanitizing each glyph is costy */
44*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
45*2d1272b8SAndroid Build Coastguard Worker   }
46*2d1272b8SAndroid Build Coastguard Worker 
47*2d1272b8SAndroid Build Coastguard Worker   /* requires source of SubsetGlyph complains the identifier isn't declared */
48*2d1272b8SAndroid Build Coastguard Worker   template <typename Iterator>
serializeOT::glyf49*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c,
50*2d1272b8SAndroid Build Coastguard Worker 		  Iterator it,
51*2d1272b8SAndroid Build Coastguard Worker                   bool use_short_loca,
52*2d1272b8SAndroid Build Coastguard Worker 		  const hb_subset_plan_t *plan)
53*2d1272b8SAndroid Build Coastguard Worker   {
54*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
55*2d1272b8SAndroid Build Coastguard Worker 
56*2d1272b8SAndroid Build Coastguard Worker     unsigned init_len = c->length ();
57*2d1272b8SAndroid Build Coastguard Worker     for (auto &_ : it)
58*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!_.serialize (c, use_short_loca, plan)))
59*2d1272b8SAndroid Build Coastguard Worker         return false;
60*2d1272b8SAndroid Build Coastguard Worker 
61*2d1272b8SAndroid Build Coastguard Worker     /* As a special case when all glyph in the font are empty, add a zero byte
62*2d1272b8SAndroid Build Coastguard Worker      * to the table, so that OTS doesn’t reject it, and to make the table work
63*2d1272b8SAndroid Build Coastguard Worker      * on Windows as well.
64*2d1272b8SAndroid Build Coastguard Worker      * See https://github.com/khaledhosny/ots/issues/52 */
65*2d1272b8SAndroid Build Coastguard Worker     if (init_len == c->length ())
66*2d1272b8SAndroid Build Coastguard Worker     {
67*2d1272b8SAndroid Build Coastguard Worker       HBUINT8 empty_byte;
68*2d1272b8SAndroid Build Coastguard Worker       empty_byte = 0;
69*2d1272b8SAndroid Build Coastguard Worker       c->copy (empty_byte);
70*2d1272b8SAndroid Build Coastguard Worker     }
71*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
72*2d1272b8SAndroid Build Coastguard Worker   }
73*2d1272b8SAndroid Build Coastguard Worker 
74*2d1272b8SAndroid Build Coastguard Worker   /* Byte region(s) per glyph to output
75*2d1272b8SAndroid Build Coastguard Worker      unpadded, hints removed if so requested
76*2d1272b8SAndroid Build Coastguard Worker      If we fail to process a glyph we produce an empty (0-length) glyph */
subsetOT::glyf77*2d1272b8SAndroid Build Coastguard Worker   bool subset (hb_subset_context_t *c) const
78*2d1272b8SAndroid Build Coastguard Worker   {
79*2d1272b8SAndroid Build Coastguard Worker     TRACE_SUBSET (this);
80*2d1272b8SAndroid Build Coastguard Worker 
81*2d1272b8SAndroid Build Coastguard Worker     if (!has_valid_glyf_format (c->plan->source)) {
82*2d1272b8SAndroid Build Coastguard Worker       // glyf format is unknown don't attempt to subset it.
83*2d1272b8SAndroid Build Coastguard Worker       DEBUG_MSG (SUBSET, nullptr,
84*2d1272b8SAndroid Build Coastguard Worker                  "unkown glyf format, dropping from subset.");
85*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
86*2d1272b8SAndroid Build Coastguard Worker     }
87*2d1272b8SAndroid Build Coastguard Worker 
88*2d1272b8SAndroid Build Coastguard Worker     hb_font_t *font = nullptr;
89*2d1272b8SAndroid Build Coastguard Worker     if (c->plan->normalized_coords)
90*2d1272b8SAndroid Build Coastguard Worker     {
91*2d1272b8SAndroid Build Coastguard Worker       font = _create_font_for_instancing (c->plan);
92*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!font))
93*2d1272b8SAndroid Build Coastguard Worker 	return_trace (false);
94*2d1272b8SAndroid Build Coastguard Worker     }
95*2d1272b8SAndroid Build Coastguard Worker 
96*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<unsigned> padded_offsets;
97*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true)))
98*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
99*2d1272b8SAndroid Build Coastguard Worker 
100*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
101*2d1272b8SAndroid Build Coastguard Worker     if (!_populate_subset_glyphs (c->plan, font, glyphs))
102*2d1272b8SAndroid Build Coastguard Worker     {
103*2d1272b8SAndroid Build Coastguard Worker       hb_font_destroy (font);
104*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
105*2d1272b8SAndroid Build Coastguard Worker     }
106*2d1272b8SAndroid Build Coastguard Worker 
107*2d1272b8SAndroid Build Coastguard Worker     if (font)
108*2d1272b8SAndroid Build Coastguard Worker       hb_font_destroy (font);
109*2d1272b8SAndroid Build Coastguard Worker 
110*2d1272b8SAndroid Build Coastguard Worker     unsigned max_offset = 0;
111*2d1272b8SAndroid Build Coastguard Worker     for (auto &g : glyphs)
112*2d1272b8SAndroid Build Coastguard Worker     {
113*2d1272b8SAndroid Build Coastguard Worker       unsigned size = g.padded_size ();
114*2d1272b8SAndroid Build Coastguard Worker       padded_offsets.push (size);
115*2d1272b8SAndroid Build Coastguard Worker       max_offset += size;
116*2d1272b8SAndroid Build Coastguard Worker     }
117*2d1272b8SAndroid Build Coastguard Worker 
118*2d1272b8SAndroid Build Coastguard Worker     bool use_short_loca = false;
119*2d1272b8SAndroid Build Coastguard Worker     if (likely (!c->plan->force_long_loca))
120*2d1272b8SAndroid Build Coastguard Worker       use_short_loca = max_offset < 0x1FFFF;
121*2d1272b8SAndroid Build Coastguard Worker 
122*2d1272b8SAndroid Build Coastguard Worker     if (!use_short_loca)
123*2d1272b8SAndroid Build Coastguard Worker     {
124*2d1272b8SAndroid Build Coastguard Worker       padded_offsets.resize (0);
125*2d1272b8SAndroid Build Coastguard Worker       for (auto &g : glyphs)
126*2d1272b8SAndroid Build Coastguard Worker 	padded_offsets.push (g.length ());
127*2d1272b8SAndroid Build Coastguard Worker     }
128*2d1272b8SAndroid Build Coastguard Worker 
129*2d1272b8SAndroid Build Coastguard Worker     auto *glyf_prime = c->serializer->start_embed <glyf> ();
130*2d1272b8SAndroid Build Coastguard Worker     bool result = glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
131*2d1272b8SAndroid Build Coastguard Worker     if (c->plan->normalized_coords && !c->plan->pinned_at_default)
132*2d1272b8SAndroid Build Coastguard Worker       _free_compiled_subset_glyphs (glyphs);
133*2d1272b8SAndroid Build Coastguard Worker 
134*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!c->serializer->check_success (glyf_impl::_add_loca_and_head (c,
135*2d1272b8SAndroid Build Coastguard Worker 						 padded_offsets.iter (),
136*2d1272b8SAndroid Build Coastguard Worker 						 use_short_loca))))
137*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
138*2d1272b8SAndroid Build Coastguard Worker 
139*2d1272b8SAndroid Build Coastguard Worker     return result;
140*2d1272b8SAndroid Build Coastguard Worker   }
141*2d1272b8SAndroid Build Coastguard Worker 
142*2d1272b8SAndroid Build Coastguard Worker   bool
143*2d1272b8SAndroid Build Coastguard Worker   _populate_subset_glyphs (const hb_subset_plan_t   *plan,
144*2d1272b8SAndroid Build Coastguard Worker 			   hb_font_t                *font,
145*2d1272b8SAndroid Build Coastguard Worker 			   hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const;
146*2d1272b8SAndroid Build Coastguard Worker 
147*2d1272b8SAndroid Build Coastguard Worker   hb_font_t *
148*2d1272b8SAndroid Build Coastguard Worker   _create_font_for_instancing (const hb_subset_plan_t *plan) const;
149*2d1272b8SAndroid Build Coastguard Worker 
_free_compiled_subset_glyphsOT::glyf150*2d1272b8SAndroid Build Coastguard Worker   void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
151*2d1272b8SAndroid Build Coastguard Worker   {
152*2d1272b8SAndroid Build Coastguard Worker     for (auto &g : glyphs)
153*2d1272b8SAndroid Build Coastguard Worker       g.free_compiled_bytes ();
154*2d1272b8SAndroid Build Coastguard Worker   }
155*2d1272b8SAndroid Build Coastguard Worker 
156*2d1272b8SAndroid Build Coastguard Worker   protected:
157*2d1272b8SAndroid Build Coastguard Worker   UnsizedArrayOf<HBUINT8>
158*2d1272b8SAndroid Build Coastguard Worker 		dataZ;	/* Glyphs data. */
159*2d1272b8SAndroid Build Coastguard Worker   public:
160*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (0);	/* In reality, this is UNBOUNDED() type; but since we always
161*2d1272b8SAndroid Build Coastguard Worker 			 * check the size externally, allow Null() object of it by
162*2d1272b8SAndroid Build Coastguard Worker 			 * defining it _MIN instead. */
163*2d1272b8SAndroid Build Coastguard Worker };
164*2d1272b8SAndroid Build Coastguard Worker 
165*2d1272b8SAndroid Build Coastguard Worker struct glyf_accelerator_t
166*2d1272b8SAndroid Build Coastguard Worker {
glyf_accelerator_tOT::glyf_accelerator_t167*2d1272b8SAndroid Build Coastguard Worker   glyf_accelerator_t (hb_face_t *face)
168*2d1272b8SAndroid Build Coastguard Worker   {
169*2d1272b8SAndroid Build Coastguard Worker     short_offset = false;
170*2d1272b8SAndroid Build Coastguard Worker     num_glyphs = 0;
171*2d1272b8SAndroid Build Coastguard Worker     loca_table = nullptr;
172*2d1272b8SAndroid Build Coastguard Worker     glyf_table = nullptr;
173*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
174*2d1272b8SAndroid Build Coastguard Worker     gvar = nullptr;
175*2d1272b8SAndroid Build Coastguard Worker #endif
176*2d1272b8SAndroid Build Coastguard Worker     hmtx = nullptr;
177*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
178*2d1272b8SAndroid Build Coastguard Worker     vmtx = nullptr;
179*2d1272b8SAndroid Build Coastguard Worker #endif
180*2d1272b8SAndroid Build Coastguard Worker     const OT::head &head = *face->table.head;
181*2d1272b8SAndroid Build Coastguard Worker     if (!glyf::has_valid_glyf_format (face))
182*2d1272b8SAndroid Build Coastguard Worker       /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
183*2d1272b8SAndroid Build Coastguard Worker       return;
184*2d1272b8SAndroid Build Coastguard Worker     short_offset = 0 == head.indexToLocFormat;
185*2d1272b8SAndroid Build Coastguard Worker 
186*2d1272b8SAndroid Build Coastguard Worker     loca_table = face->table.loca.get_blob (); // Needs no destruct!
187*2d1272b8SAndroid Build Coastguard Worker     glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
188*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
189*2d1272b8SAndroid Build Coastguard Worker     gvar = face->table.gvar;
190*2d1272b8SAndroid Build Coastguard Worker #endif
191*2d1272b8SAndroid Build Coastguard Worker     hmtx = face->table.hmtx;
192*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
193*2d1272b8SAndroid Build Coastguard Worker     vmtx = face->table.vmtx;
194*2d1272b8SAndroid Build Coastguard Worker #endif
195*2d1272b8SAndroid Build Coastguard Worker 
196*2d1272b8SAndroid Build Coastguard Worker     num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
197*2d1272b8SAndroid Build Coastguard Worker     num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
198*2d1272b8SAndroid Build Coastguard Worker   }
~glyf_accelerator_tOT::glyf_accelerator_t199*2d1272b8SAndroid Build Coastguard Worker   ~glyf_accelerator_t ()
200*2d1272b8SAndroid Build Coastguard Worker   {
201*2d1272b8SAndroid Build Coastguard Worker     glyf_table.destroy ();
202*2d1272b8SAndroid Build Coastguard Worker   }
203*2d1272b8SAndroid Build Coastguard Worker 
has_dataOT::glyf_accelerator_t204*2d1272b8SAndroid Build Coastguard Worker   bool has_data () const { return num_glyphs; }
205*2d1272b8SAndroid Build Coastguard Worker 
206*2d1272b8SAndroid Build Coastguard Worker   protected:
207*2d1272b8SAndroid Build Coastguard Worker   template<typename T>
get_pointsOT::glyf_accelerator_t208*2d1272b8SAndroid Build Coastguard Worker   bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer,
209*2d1272b8SAndroid Build Coastguard Worker 		   hb_array_t<const int> coords = hb_array_t<const int> ()) const
210*2d1272b8SAndroid Build Coastguard Worker   {
211*2d1272b8SAndroid Build Coastguard Worker     if (!coords)
212*2d1272b8SAndroid Build Coastguard Worker       coords = hb_array (font->coords, font->num_coords);
213*2d1272b8SAndroid Build Coastguard Worker 
214*2d1272b8SAndroid Build Coastguard Worker     if (gid >= num_glyphs) return false;
215*2d1272b8SAndroid Build Coastguard Worker 
216*2d1272b8SAndroid Build Coastguard Worker     /* Making this allocfree is not that easy
217*2d1272b8SAndroid Build Coastguard Worker        https://github.com/harfbuzz/harfbuzz/issues/2095
218*2d1272b8SAndroid Build Coastguard Worker        mostly because of gvar handling in VF fonts,
219*2d1272b8SAndroid Build Coastguard Worker        perhaps a separate path for non-VF fonts can be considered */
220*2d1272b8SAndroid Build Coastguard Worker     contour_point_vector_t all_points;
221*2d1272b8SAndroid Build Coastguard Worker 
222*2d1272b8SAndroid Build Coastguard Worker     bool phantom_only = !consumer.is_consuming_contour_points ();
223*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
224*2d1272b8SAndroid Build Coastguard Worker       return false;
225*2d1272b8SAndroid Build Coastguard Worker 
226*2d1272b8SAndroid Build Coastguard Worker     unsigned count = all_points.length;
227*2d1272b8SAndroid Build Coastguard Worker     assert (count >= glyf_impl::PHANTOM_COUNT);
228*2d1272b8SAndroid Build Coastguard Worker     count -= glyf_impl::PHANTOM_COUNT;
229*2d1272b8SAndroid Build Coastguard Worker 
230*2d1272b8SAndroid Build Coastguard Worker     if (consumer.is_consuming_contour_points ())
231*2d1272b8SAndroid Build Coastguard Worker     {
232*2d1272b8SAndroid Build Coastguard Worker       for (auto &point : all_points.as_array ().sub_array (0, count))
233*2d1272b8SAndroid Build Coastguard Worker 	consumer.consume_point (point);
234*2d1272b8SAndroid Build Coastguard Worker       consumer.points_end ();
235*2d1272b8SAndroid Build Coastguard Worker     }
236*2d1272b8SAndroid Build Coastguard Worker 
237*2d1272b8SAndroid Build Coastguard Worker     /* Where to write phantoms, nullptr if not requested */
238*2d1272b8SAndroid Build Coastguard Worker     contour_point_t *phantoms = consumer.get_phantoms_sink ();
239*2d1272b8SAndroid Build Coastguard Worker     if (phantoms)
240*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i)
241*2d1272b8SAndroid Build Coastguard Worker 	phantoms[i] = all_points.arrayZ[count + i];
242*2d1272b8SAndroid Build Coastguard Worker 
243*2d1272b8SAndroid Build Coastguard Worker     return true;
244*2d1272b8SAndroid Build Coastguard Worker   }
245*2d1272b8SAndroid Build Coastguard Worker 
246*2d1272b8SAndroid Build Coastguard Worker   public:
247*2d1272b8SAndroid Build Coastguard Worker 
248*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
249*2d1272b8SAndroid Build Coastguard Worker   struct points_aggregator_t
250*2d1272b8SAndroid Build Coastguard Worker   {
251*2d1272b8SAndroid Build Coastguard Worker     hb_font_t *font;
252*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_extents_t *extents;
253*2d1272b8SAndroid Build Coastguard Worker     contour_point_t *phantoms;
254*2d1272b8SAndroid Build Coastguard Worker     bool scaled;
255*2d1272b8SAndroid Build Coastguard Worker 
256*2d1272b8SAndroid Build Coastguard Worker     struct contour_bounds_t
257*2d1272b8SAndroid Build Coastguard Worker     {
contour_bounds_tOT::glyf_accelerator_t::points_aggregator_t::contour_bounds_t258*2d1272b8SAndroid Build Coastguard Worker       contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
259*2d1272b8SAndroid Build Coastguard Worker 
addOT::glyf_accelerator_t::points_aggregator_t::contour_bounds_t260*2d1272b8SAndroid Build Coastguard Worker       void add (const contour_point_t &p)
261*2d1272b8SAndroid Build Coastguard Worker       {
262*2d1272b8SAndroid Build Coastguard Worker 	min_x = hb_min (min_x, p.x);
263*2d1272b8SAndroid Build Coastguard Worker 	min_y = hb_min (min_y, p.y);
264*2d1272b8SAndroid Build Coastguard Worker 	max_x = hb_max (max_x, p.x);
265*2d1272b8SAndroid Build Coastguard Worker 	max_y = hb_max (max_y, p.y);
266*2d1272b8SAndroid Build Coastguard Worker       }
267*2d1272b8SAndroid Build Coastguard Worker 
emptyOT::glyf_accelerator_t::points_aggregator_t::contour_bounds_t268*2d1272b8SAndroid Build Coastguard Worker       bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
269*2d1272b8SAndroid Build Coastguard Worker 
get_extentsOT::glyf_accelerator_t::points_aggregator_t::contour_bounds_t270*2d1272b8SAndroid Build Coastguard Worker       void get_extents (hb_font_t *font, hb_glyph_extents_t *extents, bool scaled)
271*2d1272b8SAndroid Build Coastguard Worker       {
272*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (empty ()))
273*2d1272b8SAndroid Build Coastguard Worker 	{
274*2d1272b8SAndroid Build Coastguard Worker 	  extents->width = 0;
275*2d1272b8SAndroid Build Coastguard Worker 	  extents->x_bearing = 0;
276*2d1272b8SAndroid Build Coastguard Worker 	  extents->height = 0;
277*2d1272b8SAndroid Build Coastguard Worker 	  extents->y_bearing = 0;
278*2d1272b8SAndroid Build Coastguard Worker 	  return;
279*2d1272b8SAndroid Build Coastguard Worker 	}
280*2d1272b8SAndroid Build Coastguard Worker 	{
281*2d1272b8SAndroid Build Coastguard Worker 	  extents->x_bearing = roundf (min_x);
282*2d1272b8SAndroid Build Coastguard Worker 	  extents->width = roundf (max_x - extents->x_bearing);
283*2d1272b8SAndroid Build Coastguard Worker 	  extents->y_bearing = roundf (max_y);
284*2d1272b8SAndroid Build Coastguard Worker 	  extents->height = roundf (min_y - extents->y_bearing);
285*2d1272b8SAndroid Build Coastguard Worker 
286*2d1272b8SAndroid Build Coastguard Worker 	  if (scaled)
287*2d1272b8SAndroid Build Coastguard Worker 	    font->scale_glyph_extents (extents);
288*2d1272b8SAndroid Build Coastguard Worker 	}
289*2d1272b8SAndroid Build Coastguard Worker       }
290*2d1272b8SAndroid Build Coastguard Worker 
291*2d1272b8SAndroid Build Coastguard Worker       protected:
292*2d1272b8SAndroid Build Coastguard Worker       float min_x, min_y, max_x, max_y;
293*2d1272b8SAndroid Build Coastguard Worker     } bounds;
294*2d1272b8SAndroid Build Coastguard Worker 
points_aggregator_tOT::glyf_accelerator_t::points_aggregator_t295*2d1272b8SAndroid Build Coastguard Worker     points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_, bool scaled_)
296*2d1272b8SAndroid Build Coastguard Worker     {
297*2d1272b8SAndroid Build Coastguard Worker       font = font_;
298*2d1272b8SAndroid Build Coastguard Worker       extents = extents_;
299*2d1272b8SAndroid Build Coastguard Worker       phantoms = phantoms_;
300*2d1272b8SAndroid Build Coastguard Worker       scaled = scaled_;
301*2d1272b8SAndroid Build Coastguard Worker       if (extents) bounds = contour_bounds_t ();
302*2d1272b8SAndroid Build Coastguard Worker     }
303*2d1272b8SAndroid Build Coastguard Worker 
304*2d1272b8SAndroid Build Coastguard Worker     HB_ALWAYS_INLINE
consume_pointOT::glyf_accelerator_t::points_aggregator_t305*2d1272b8SAndroid Build Coastguard Worker     void consume_point (const contour_point_t &point) { bounds.add (point); }
points_endOT::glyf_accelerator_t::points_aggregator_t306*2d1272b8SAndroid Build Coastguard Worker     void points_end () { bounds.get_extents (font, extents, scaled); }
307*2d1272b8SAndroid Build Coastguard Worker 
is_consuming_contour_pointsOT::glyf_accelerator_t::points_aggregator_t308*2d1272b8SAndroid Build Coastguard Worker     bool is_consuming_contour_points () { return extents; }
get_phantoms_sinkOT::glyf_accelerator_t::points_aggregator_t309*2d1272b8SAndroid Build Coastguard Worker     contour_point_t *get_phantoms_sink () { return phantoms; }
310*2d1272b8SAndroid Build Coastguard Worker   };
311*2d1272b8SAndroid Build Coastguard Worker 
312*2d1272b8SAndroid Build Coastguard Worker   unsigned
get_advance_with_var_unscaledOT::glyf_accelerator_t313*2d1272b8SAndroid Build Coastguard Worker   get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
314*2d1272b8SAndroid Build Coastguard Worker   {
315*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (gid >= num_glyphs)) return 0;
316*2d1272b8SAndroid Build Coastguard Worker 
317*2d1272b8SAndroid Build Coastguard Worker     bool success = false;
318*2d1272b8SAndroid Build Coastguard Worker 
319*2d1272b8SAndroid Build Coastguard Worker     contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
320*2d1272b8SAndroid Build Coastguard Worker     if (font->num_coords)
321*2d1272b8SAndroid Build Coastguard Worker       success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
322*2d1272b8SAndroid Build Coastguard Worker 
323*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!success))
324*2d1272b8SAndroid Build Coastguard Worker       return
325*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
326*2d1272b8SAndroid Build Coastguard Worker 	is_vertical ? vmtx->get_advance_without_var_unscaled (gid) :
327*2d1272b8SAndroid Build Coastguard Worker #endif
328*2d1272b8SAndroid Build Coastguard Worker 	hmtx->get_advance_without_var_unscaled (gid);
329*2d1272b8SAndroid Build Coastguard Worker 
330*2d1272b8SAndroid Build Coastguard Worker     float result = is_vertical
331*2d1272b8SAndroid Build Coastguard Worker 		 ? phantoms[glyf_impl::PHANTOM_TOP].y - phantoms[glyf_impl::PHANTOM_BOTTOM].y
332*2d1272b8SAndroid Build Coastguard Worker 		 : phantoms[glyf_impl::PHANTOM_RIGHT].x - phantoms[glyf_impl::PHANTOM_LEFT].x;
333*2d1272b8SAndroid Build Coastguard Worker     return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
334*2d1272b8SAndroid Build Coastguard Worker   }
335*2d1272b8SAndroid Build Coastguard Worker 
get_leading_bearing_with_var_unscaledOT::glyf_accelerator_t336*2d1272b8SAndroid Build Coastguard Worker   bool get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical, int *lsb) const
337*2d1272b8SAndroid Build Coastguard Worker   {
338*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (gid >= num_glyphs)) return false;
339*2d1272b8SAndroid Build Coastguard Worker 
340*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_extents_t extents;
341*2d1272b8SAndroid Build Coastguard Worker 
342*2d1272b8SAndroid Build Coastguard Worker     contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
343*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false))))
344*2d1272b8SAndroid Build Coastguard Worker       return false;
345*2d1272b8SAndroid Build Coastguard Worker 
346*2d1272b8SAndroid Build Coastguard Worker     *lsb = is_vertical
347*2d1272b8SAndroid Build Coastguard Worker 	 ? roundf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing
348*2d1272b8SAndroid Build Coastguard Worker 	 : roundf (phantoms[glyf_impl::PHANTOM_LEFT].x);
349*2d1272b8SAndroid Build Coastguard Worker     return true;
350*2d1272b8SAndroid Build Coastguard Worker   }
351*2d1272b8SAndroid Build Coastguard Worker #endif
352*2d1272b8SAndroid Build Coastguard Worker 
get_leading_bearing_without_var_unscaledOT::glyf_accelerator_t353*2d1272b8SAndroid Build Coastguard Worker   bool get_leading_bearing_without_var_unscaled (hb_codepoint_t gid, bool is_vertical, int *lsb) const
354*2d1272b8SAndroid Build Coastguard Worker   {
355*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (gid >= num_glyphs)) return false;
356*2d1272b8SAndroid Build Coastguard Worker     if (is_vertical) return false; // TODO Humm, what to do here?
357*2d1272b8SAndroid Build Coastguard Worker 
358*2d1272b8SAndroid Build Coastguard Worker     *lsb = glyph_for_gid (gid).get_header ()->xMin;
359*2d1272b8SAndroid Build Coastguard Worker     return true;
360*2d1272b8SAndroid Build Coastguard Worker   }
361*2d1272b8SAndroid Build Coastguard Worker 
362*2d1272b8SAndroid Build Coastguard Worker   public:
get_extentsOT::glyf_accelerator_t363*2d1272b8SAndroid Build Coastguard Worker   bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
364*2d1272b8SAndroid Build Coastguard Worker   {
365*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (gid >= num_glyphs)) return false;
366*2d1272b8SAndroid Build Coastguard Worker 
367*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
368*2d1272b8SAndroid Build Coastguard Worker     if (font->num_coords)
369*2d1272b8SAndroid Build Coastguard Worker       return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true));
370*2d1272b8SAndroid Build Coastguard Worker #endif
371*2d1272b8SAndroid Build Coastguard Worker     return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
372*2d1272b8SAndroid Build Coastguard Worker   }
373*2d1272b8SAndroid Build Coastguard Worker 
paint_glyphOT::glyf_accelerator_t374*2d1272b8SAndroid Build Coastguard Worker   bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
375*2d1272b8SAndroid Build Coastguard Worker   {
376*2d1272b8SAndroid Build Coastguard Worker     funcs->push_clip_glyph (data, gid, font);
377*2d1272b8SAndroid Build Coastguard Worker     funcs->color (data, true, foreground);
378*2d1272b8SAndroid Build Coastguard Worker     funcs->pop_clip (data);
379*2d1272b8SAndroid Build Coastguard Worker 
380*2d1272b8SAndroid Build Coastguard Worker     return true;
381*2d1272b8SAndroid Build Coastguard Worker   }
382*2d1272b8SAndroid Build Coastguard Worker 
383*2d1272b8SAndroid Build Coastguard Worker   const glyf_impl::Glyph
glyph_for_gidOT::glyf_accelerator_t384*2d1272b8SAndroid Build Coastguard Worker   glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
385*2d1272b8SAndroid Build Coastguard Worker   {
386*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (gid >= num_glyphs)) return glyf_impl::Glyph ();
387*2d1272b8SAndroid Build Coastguard Worker 
388*2d1272b8SAndroid Build Coastguard Worker     unsigned int start_offset, end_offset;
389*2d1272b8SAndroid Build Coastguard Worker 
390*2d1272b8SAndroid Build Coastguard Worker     if (short_offset)
391*2d1272b8SAndroid Build Coastguard Worker     {
392*2d1272b8SAndroid Build Coastguard Worker       const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
393*2d1272b8SAndroid Build Coastguard Worker       start_offset = 2 * offsets[gid];
394*2d1272b8SAndroid Build Coastguard Worker       end_offset   = 2 * offsets[gid + 1];
395*2d1272b8SAndroid Build Coastguard Worker     }
396*2d1272b8SAndroid Build Coastguard Worker     else
397*2d1272b8SAndroid Build Coastguard Worker     {
398*2d1272b8SAndroid Build Coastguard Worker       const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
399*2d1272b8SAndroid Build Coastguard Worker       start_offset = offsets[gid];
400*2d1272b8SAndroid Build Coastguard Worker       end_offset   = offsets[gid + 1];
401*2d1272b8SAndroid Build Coastguard Worker     }
402*2d1272b8SAndroid Build Coastguard Worker 
403*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
404*2d1272b8SAndroid Build Coastguard Worker       return glyf_impl::Glyph ();
405*2d1272b8SAndroid Build Coastguard Worker 
406*2d1272b8SAndroid Build Coastguard Worker     glyf_impl::Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
407*2d1272b8SAndroid Build Coastguard Worker 			     end_offset - start_offset), gid);
408*2d1272b8SAndroid Build Coastguard Worker     return needs_padding_removal ? glyf_impl::Glyph (glyph.trim_padding (), gid) : glyph;
409*2d1272b8SAndroid Build Coastguard Worker   }
410*2d1272b8SAndroid Build Coastguard Worker 
411*2d1272b8SAndroid Build Coastguard Worker   bool
get_pathOT::glyf_accelerator_t412*2d1272b8SAndroid Build Coastguard Worker   get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
413*2d1272b8SAndroid Build Coastguard Worker   { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
414*2d1272b8SAndroid Build Coastguard Worker 
415*2d1272b8SAndroid Build Coastguard Worker   bool
get_path_atOT::glyf_accelerator_t416*2d1272b8SAndroid Build Coastguard Worker   get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session,
417*2d1272b8SAndroid Build Coastguard Worker 	       hb_array_t<const int> coords) const
418*2d1272b8SAndroid Build Coastguard Worker   { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), coords); }
419*2d1272b8SAndroid Build Coastguard Worker 
420*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
421*2d1272b8SAndroid Build Coastguard Worker   const gvar_accelerator_t *gvar;
422*2d1272b8SAndroid Build Coastguard Worker #endif
423*2d1272b8SAndroid Build Coastguard Worker   const hmtx_accelerator_t *hmtx;
424*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
425*2d1272b8SAndroid Build Coastguard Worker   const vmtx_accelerator_t *vmtx;
426*2d1272b8SAndroid Build Coastguard Worker #endif
427*2d1272b8SAndroid Build Coastguard Worker 
428*2d1272b8SAndroid Build Coastguard Worker   private:
429*2d1272b8SAndroid Build Coastguard Worker   bool short_offset;
430*2d1272b8SAndroid Build Coastguard Worker   unsigned int num_glyphs;
431*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<loca> loca_table;
432*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<glyf> glyf_table;
433*2d1272b8SAndroid Build Coastguard Worker };
434*2d1272b8SAndroid Build Coastguard Worker 
435*2d1272b8SAndroid Build Coastguard Worker 
436*2d1272b8SAndroid Build Coastguard Worker inline bool
_populate_subset_glyphs(const hb_subset_plan_t * plan,hb_font_t * font,hb_vector_t<glyf_impl::SubsetGlyph> & glyphs) const437*2d1272b8SAndroid Build Coastguard Worker glyf::_populate_subset_glyphs (const hb_subset_plan_t   *plan,
438*2d1272b8SAndroid Build Coastguard Worker 			       hb_font_t *font,
439*2d1272b8SAndroid Build Coastguard Worker 			       hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
440*2d1272b8SAndroid Build Coastguard Worker {
441*2d1272b8SAndroid Build Coastguard Worker   OT::glyf_accelerator_t glyf (plan->source);
442*2d1272b8SAndroid Build Coastguard Worker   if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false;
443*2d1272b8SAndroid Build Coastguard Worker 
444*2d1272b8SAndroid Build Coastguard Worker   for (const auto &pair : plan->new_to_old_gid_list)
445*2d1272b8SAndroid Build Coastguard Worker   {
446*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t new_gid = pair.first;
447*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t old_gid = pair.second;
448*2d1272b8SAndroid Build Coastguard Worker     glyf_impl::SubsetGlyph *p = glyphs.push ();
449*2d1272b8SAndroid Build Coastguard Worker     glyf_impl::SubsetGlyph& subset_glyph = *p;
450*2d1272b8SAndroid Build Coastguard Worker     subset_glyph.old_gid = old_gid;
451*2d1272b8SAndroid Build Coastguard Worker 
452*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (old_gid == 0 && new_gid == 0 &&
453*2d1272b8SAndroid Build Coastguard Worker                   !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
454*2d1272b8SAndroid Build Coastguard Worker                   !plan->normalized_coords)
455*2d1272b8SAndroid Build Coastguard Worker       subset_glyph.source_glyph = glyf_impl::Glyph ();
456*2d1272b8SAndroid Build Coastguard Worker     else
457*2d1272b8SAndroid Build Coastguard Worker     {
458*2d1272b8SAndroid Build Coastguard Worker       /* If plan has an accelerator, the preprocessing step already trimmed glyphs.
459*2d1272b8SAndroid Build Coastguard Worker        * Don't trim them again! */
460*2d1272b8SAndroid Build Coastguard Worker       subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, !plan->accelerator);
461*2d1272b8SAndroid Build Coastguard Worker     }
462*2d1272b8SAndroid Build Coastguard Worker 
463*2d1272b8SAndroid Build Coastguard Worker     if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
464*2d1272b8SAndroid Build Coastguard Worker       subset_glyph.drop_hints_bytes ();
465*2d1272b8SAndroid Build Coastguard Worker     else
466*2d1272b8SAndroid Build Coastguard Worker       subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
467*2d1272b8SAndroid Build Coastguard Worker 
468*2d1272b8SAndroid Build Coastguard Worker     if (font)
469*2d1272b8SAndroid Build Coastguard Worker     {
470*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
471*2d1272b8SAndroid Build Coastguard Worker       {
472*2d1272b8SAndroid Build Coastguard Worker         // when pinned at default, only bounds are updated, thus no need to free
473*2d1272b8SAndroid Build Coastguard Worker         if (!plan->pinned_at_default)
474*2d1272b8SAndroid Build Coastguard Worker           _free_compiled_subset_glyphs (glyphs);
475*2d1272b8SAndroid Build Coastguard Worker         return false;
476*2d1272b8SAndroid Build Coastguard Worker       }
477*2d1272b8SAndroid Build Coastguard Worker     }
478*2d1272b8SAndroid Build Coastguard Worker   }
479*2d1272b8SAndroid Build Coastguard Worker   return true;
480*2d1272b8SAndroid Build Coastguard Worker }
481*2d1272b8SAndroid Build Coastguard Worker 
482*2d1272b8SAndroid Build Coastguard Worker inline hb_font_t *
_create_font_for_instancing(const hb_subset_plan_t * plan) const483*2d1272b8SAndroid Build Coastguard Worker glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
484*2d1272b8SAndroid Build Coastguard Worker {
485*2d1272b8SAndroid Build Coastguard Worker   hb_font_t *font = hb_font_create (plan->source);
486*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (font == hb_font_get_empty ())) return nullptr;
487*2d1272b8SAndroid Build Coastguard Worker 
488*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<hb_variation_t> vars;
489*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
490*2d1272b8SAndroid Build Coastguard Worker   {
491*2d1272b8SAndroid Build Coastguard Worker     hb_font_destroy (font);
492*2d1272b8SAndroid Build Coastguard Worker     return nullptr;
493*2d1272b8SAndroid Build Coastguard Worker   }
494*2d1272b8SAndroid Build Coastguard Worker 
495*2d1272b8SAndroid Build Coastguard Worker   for (auto _ : plan->user_axes_location)
496*2d1272b8SAndroid Build Coastguard Worker   {
497*2d1272b8SAndroid Build Coastguard Worker     hb_variation_t var;
498*2d1272b8SAndroid Build Coastguard Worker     var.tag = _.first;
499*2d1272b8SAndroid Build Coastguard Worker     var.value = _.second.middle;
500*2d1272b8SAndroid Build Coastguard Worker     vars.push (var);
501*2d1272b8SAndroid Build Coastguard Worker   }
502*2d1272b8SAndroid Build Coastguard Worker 
503*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
504*2d1272b8SAndroid Build Coastguard Worker   hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
505*2d1272b8SAndroid Build Coastguard Worker #endif
506*2d1272b8SAndroid Build Coastguard Worker   return font;
507*2d1272b8SAndroid Build Coastguard Worker }
508*2d1272b8SAndroid Build Coastguard Worker 
509*2d1272b8SAndroid Build Coastguard Worker 
510*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */
511*2d1272b8SAndroid Build Coastguard Worker 
512*2d1272b8SAndroid Build Coastguard Worker 
513*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_GLYF_HH */
514