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