xref: /aosp_15_r20/external/harfbuzz_ng/src/OT/glyf/Glyph.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_GLYPH_HH
2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_GLYPH_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 #include "GlyphHeader.hh"
8*2d1272b8SAndroid Build Coastguard Worker #include "SimpleGlyph.hh"
9*2d1272b8SAndroid Build Coastguard Worker #include "CompositeGlyph.hh"
10*2d1272b8SAndroid Build Coastguard Worker 
11*2d1272b8SAndroid Build Coastguard Worker 
12*2d1272b8SAndroid Build Coastguard Worker namespace OT {
13*2d1272b8SAndroid Build Coastguard Worker 
14*2d1272b8SAndroid Build Coastguard Worker struct glyf_accelerator_t;
15*2d1272b8SAndroid Build Coastguard Worker 
16*2d1272b8SAndroid Build Coastguard Worker namespace glyf_impl {
17*2d1272b8SAndroid Build Coastguard Worker 
18*2d1272b8SAndroid Build Coastguard Worker 
19*2d1272b8SAndroid Build Coastguard Worker enum phantom_point_index_t
20*2d1272b8SAndroid Build Coastguard Worker {
21*2d1272b8SAndroid Build Coastguard Worker   PHANTOM_LEFT   = 0,
22*2d1272b8SAndroid Build Coastguard Worker   PHANTOM_RIGHT  = 1,
23*2d1272b8SAndroid Build Coastguard Worker   PHANTOM_TOP    = 2,
24*2d1272b8SAndroid Build Coastguard Worker   PHANTOM_BOTTOM = 3,
25*2d1272b8SAndroid Build Coastguard Worker   PHANTOM_COUNT  = 4
26*2d1272b8SAndroid Build Coastguard Worker };
27*2d1272b8SAndroid Build Coastguard Worker 
28*2d1272b8SAndroid Build Coastguard Worker struct Glyph
29*2d1272b8SAndroid Build Coastguard Worker {
30*2d1272b8SAndroid Build Coastguard Worker   enum glyph_type_t {
31*2d1272b8SAndroid Build Coastguard Worker     EMPTY,
32*2d1272b8SAndroid Build Coastguard Worker     SIMPLE,
33*2d1272b8SAndroid Build Coastguard Worker     COMPOSITE,
34*2d1272b8SAndroid Build Coastguard Worker   };
35*2d1272b8SAndroid Build Coastguard Worker 
36*2d1272b8SAndroid Build Coastguard Worker   public:
get_composite_iteratorOT::glyf_impl::Glyph37*2d1272b8SAndroid Build Coastguard Worker   composite_iter_t get_composite_iterator () const
38*2d1272b8SAndroid Build Coastguard Worker   {
39*2d1272b8SAndroid Build Coastguard Worker     if (type != COMPOSITE) return composite_iter_t ();
40*2d1272b8SAndroid Build Coastguard Worker     return CompositeGlyph (*header, bytes).iter ();
41*2d1272b8SAndroid Build Coastguard Worker   }
42*2d1272b8SAndroid Build Coastguard Worker 
trim_paddingOT::glyf_impl::Glyph43*2d1272b8SAndroid Build Coastguard Worker   const hb_bytes_t trim_padding () const
44*2d1272b8SAndroid Build Coastguard Worker   {
45*2d1272b8SAndroid Build Coastguard Worker     switch (type) {
46*2d1272b8SAndroid Build Coastguard Worker     case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
47*2d1272b8SAndroid Build Coastguard Worker     case SIMPLE:    return SimpleGlyph (*header, bytes).trim_padding ();
48*2d1272b8SAndroid Build Coastguard Worker     case EMPTY:     return bytes;
49*2d1272b8SAndroid Build Coastguard Worker     default:        return bytes;
50*2d1272b8SAndroid Build Coastguard Worker     }
51*2d1272b8SAndroid Build Coastguard Worker   }
52*2d1272b8SAndroid Build Coastguard Worker 
drop_hintsOT::glyf_impl::Glyph53*2d1272b8SAndroid Build Coastguard Worker   void drop_hints ()
54*2d1272b8SAndroid Build Coastguard Worker   {
55*2d1272b8SAndroid Build Coastguard Worker     switch (type) {
56*2d1272b8SAndroid Build Coastguard Worker     case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
57*2d1272b8SAndroid Build Coastguard Worker     case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints (); return;
58*2d1272b8SAndroid Build Coastguard Worker     case EMPTY:     return;
59*2d1272b8SAndroid Build Coastguard Worker     }
60*2d1272b8SAndroid Build Coastguard Worker   }
61*2d1272b8SAndroid Build Coastguard Worker 
set_overlaps_flagOT::glyf_impl::Glyph62*2d1272b8SAndroid Build Coastguard Worker   void set_overlaps_flag ()
63*2d1272b8SAndroid Build Coastguard Worker   {
64*2d1272b8SAndroid Build Coastguard Worker     switch (type) {
65*2d1272b8SAndroid Build Coastguard Worker     case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
66*2d1272b8SAndroid Build Coastguard Worker     case SIMPLE:    SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
67*2d1272b8SAndroid Build Coastguard Worker     case EMPTY:     return;
68*2d1272b8SAndroid Build Coastguard Worker     }
69*2d1272b8SAndroid Build Coastguard Worker   }
70*2d1272b8SAndroid Build Coastguard Worker 
drop_hints_bytesOT::glyf_impl::Glyph71*2d1272b8SAndroid Build Coastguard Worker   void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
72*2d1272b8SAndroid Build Coastguard Worker   {
73*2d1272b8SAndroid Build Coastguard Worker     switch (type) {
74*2d1272b8SAndroid Build Coastguard Worker     case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
75*2d1272b8SAndroid Build Coastguard Worker     case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
76*2d1272b8SAndroid Build Coastguard Worker     case EMPTY:     return;
77*2d1272b8SAndroid Build Coastguard Worker     }
78*2d1272b8SAndroid Build Coastguard Worker   }
79*2d1272b8SAndroid Build Coastguard Worker 
is_compositeOT::glyf_impl::Glyph80*2d1272b8SAndroid Build Coastguard Worker   bool is_composite () const
81*2d1272b8SAndroid Build Coastguard Worker   { return type == COMPOSITE; }
82*2d1272b8SAndroid Build Coastguard Worker 
get_all_points_without_varOT::glyf_impl::Glyph83*2d1272b8SAndroid Build Coastguard Worker   bool get_all_points_without_var (const hb_face_t *face,
84*2d1272b8SAndroid Build Coastguard Worker                                    contour_point_vector_t &points /* OUT */) const
85*2d1272b8SAndroid Build Coastguard Worker   {
86*2d1272b8SAndroid Build Coastguard Worker     switch (type) {
87*2d1272b8SAndroid Build Coastguard Worker     case SIMPLE:
88*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points)))
89*2d1272b8SAndroid Build Coastguard Worker         return false;
90*2d1272b8SAndroid Build Coastguard Worker       break;
91*2d1272b8SAndroid Build Coastguard Worker     case COMPOSITE:
92*2d1272b8SAndroid Build Coastguard Worker     {
93*2d1272b8SAndroid Build Coastguard Worker       for (auto &item : get_composite_iterator ())
94*2d1272b8SAndroid Build Coastguard Worker         if (unlikely (!item.get_points (points))) return false;
95*2d1272b8SAndroid Build Coastguard Worker       break;
96*2d1272b8SAndroid Build Coastguard Worker     }
97*2d1272b8SAndroid Build Coastguard Worker     case EMPTY:
98*2d1272b8SAndroid Build Coastguard Worker       break;
99*2d1272b8SAndroid Build Coastguard Worker     }
100*2d1272b8SAndroid Build Coastguard Worker 
101*2d1272b8SAndroid Build Coastguard Worker     /* Init phantom points */
102*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
103*2d1272b8SAndroid Build Coastguard Worker     hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
104*2d1272b8SAndroid Build Coastguard Worker     {
105*2d1272b8SAndroid Build Coastguard Worker       int lsb = 0;
106*2d1272b8SAndroid Build Coastguard Worker       int h_delta = face->table.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
107*2d1272b8SAndroid Build Coastguard Worker                     (int) header->xMin - lsb : 0;
108*2d1272b8SAndroid Build Coastguard Worker       HB_UNUSED int tsb = 0;
109*2d1272b8SAndroid Build Coastguard Worker       int v_orig  = (int) header->yMax +
110*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
111*2d1272b8SAndroid Build Coastguard Worker                     ((void) face->table.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
112*2d1272b8SAndroid Build Coastguard Worker #else
113*2d1272b8SAndroid Build Coastguard Worker                     0
114*2d1272b8SAndroid Build Coastguard Worker #endif
115*2d1272b8SAndroid Build Coastguard Worker                     ;
116*2d1272b8SAndroid Build Coastguard Worker       unsigned h_adv = face->table.hmtx->get_advance_without_var_unscaled (gid);
117*2d1272b8SAndroid Build Coastguard Worker       unsigned v_adv =
118*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
119*2d1272b8SAndroid Build Coastguard Worker                        face->table.vmtx->get_advance_without_var_unscaled (gid)
120*2d1272b8SAndroid Build Coastguard Worker #else
121*2d1272b8SAndroid Build Coastguard Worker                        - face->get_upem ()
122*2d1272b8SAndroid Build Coastguard Worker #endif
123*2d1272b8SAndroid Build Coastguard Worker                        ;
124*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_LEFT].x = h_delta;
125*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta;
126*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_TOP].y = v_orig;
127*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
128*2d1272b8SAndroid Build Coastguard Worker     }
129*2d1272b8SAndroid Build Coastguard Worker     return true;
130*2d1272b8SAndroid Build Coastguard Worker   }
131*2d1272b8SAndroid Build Coastguard Worker 
update_mtxOT::glyf_impl::Glyph132*2d1272b8SAndroid Build Coastguard Worker   void update_mtx (const hb_subset_plan_t *plan,
133*2d1272b8SAndroid Build Coastguard Worker                    int xMin, int xMax,
134*2d1272b8SAndroid Build Coastguard Worker                    int yMin, int yMax,
135*2d1272b8SAndroid Build Coastguard Worker                    const contour_point_vector_t &all_points) const
136*2d1272b8SAndroid Build Coastguard Worker   {
137*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t new_gid = 0;
138*2d1272b8SAndroid Build Coastguard Worker     if (!plan->new_gid_for_old_gid (gid, &new_gid))
139*2d1272b8SAndroid Build Coastguard Worker       return;
140*2d1272b8SAndroid Build Coastguard Worker 
141*2d1272b8SAndroid Build Coastguard Worker     if (type != EMPTY)
142*2d1272b8SAndroid Build Coastguard Worker     {
143*2d1272b8SAndroid Build Coastguard Worker       plan->bounds_width_vec[new_gid] = xMax - xMin;
144*2d1272b8SAndroid Build Coastguard Worker       plan->bounds_height_vec[new_gid] = yMax - yMin;
145*2d1272b8SAndroid Build Coastguard Worker     }
146*2d1272b8SAndroid Build Coastguard Worker 
147*2d1272b8SAndroid Build Coastguard Worker     unsigned len = all_points.length;
148*2d1272b8SAndroid Build Coastguard Worker     float leftSideX = all_points[len - 4].x;
149*2d1272b8SAndroid Build Coastguard Worker     float rightSideX = all_points[len - 3].x;
150*2d1272b8SAndroid Build Coastguard Worker     float topSideY = all_points[len - 2].y;
151*2d1272b8SAndroid Build Coastguard Worker     float bottomSideY = all_points[len - 1].y;
152*2d1272b8SAndroid Build Coastguard Worker 
153*2d1272b8SAndroid Build Coastguard Worker     uint32_t hash = hb_hash (new_gid);
154*2d1272b8SAndroid Build Coastguard Worker 
155*2d1272b8SAndroid Build Coastguard Worker     signed hori_aw = roundf (rightSideX - leftSideX);
156*2d1272b8SAndroid Build Coastguard Worker     if (hori_aw < 0) hori_aw = 0;
157*2d1272b8SAndroid Build Coastguard Worker     int lsb = roundf (xMin - leftSideX);
158*2d1272b8SAndroid Build Coastguard Worker     plan->hmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) hori_aw, lsb));
159*2d1272b8SAndroid Build Coastguard Worker     //flag value should be computed using non-empty glyphs
160*2d1272b8SAndroid Build Coastguard Worker     if (type != EMPTY && lsb != xMin)
161*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.allXMinIsLsb = false;
162*2d1272b8SAndroid Build Coastguard Worker 
163*2d1272b8SAndroid Build Coastguard Worker     signed vert_aw = roundf (topSideY - bottomSideY);
164*2d1272b8SAndroid Build Coastguard Worker     if (vert_aw < 0) vert_aw = 0;
165*2d1272b8SAndroid Build Coastguard Worker     int tsb = roundf (topSideY - yMax);
166*2d1272b8SAndroid Build Coastguard Worker     plan->vmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) vert_aw, tsb));
167*2d1272b8SAndroid Build Coastguard Worker   }
168*2d1272b8SAndroid Build Coastguard Worker 
compile_header_bytesOT::glyf_impl::Glyph169*2d1272b8SAndroid Build Coastguard Worker   bool compile_header_bytes (const hb_subset_plan_t *plan,
170*2d1272b8SAndroid Build Coastguard Worker                              const contour_point_vector_t &all_points,
171*2d1272b8SAndroid Build Coastguard Worker                              hb_bytes_t &dest_bytes /* OUT */) const
172*2d1272b8SAndroid Build Coastguard Worker   {
173*2d1272b8SAndroid Build Coastguard Worker     GlyphHeader *glyph_header = nullptr;
174*2d1272b8SAndroid Build Coastguard Worker     if (!plan->pinned_at_default && type != EMPTY && all_points.length >= 4)
175*2d1272b8SAndroid Build Coastguard Worker     {
176*2d1272b8SAndroid Build Coastguard Worker       glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
177*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!glyph_header)) return false;
178*2d1272b8SAndroid Build Coastguard Worker     }
179*2d1272b8SAndroid Build Coastguard Worker 
180*2d1272b8SAndroid Build Coastguard Worker     float xMin = 0, xMax = 0;
181*2d1272b8SAndroid Build Coastguard Worker     float yMin = 0, yMax = 0;
182*2d1272b8SAndroid Build Coastguard Worker     if (all_points.length > 4)
183*2d1272b8SAndroid Build Coastguard Worker     {
184*2d1272b8SAndroid Build Coastguard Worker       xMin = xMax = all_points[0].x;
185*2d1272b8SAndroid Build Coastguard Worker       yMin = yMax = all_points[0].y;
186*2d1272b8SAndroid Build Coastguard Worker 
187*2d1272b8SAndroid Build Coastguard Worker       unsigned count = all_points.length - 4;
188*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 1; i < count; i++)
189*2d1272b8SAndroid Build Coastguard Worker       {
190*2d1272b8SAndroid Build Coastguard Worker 	float x = all_points[i].x;
191*2d1272b8SAndroid Build Coastguard Worker 	float y = all_points[i].y;
192*2d1272b8SAndroid Build Coastguard Worker 	xMin = hb_min (xMin, x);
193*2d1272b8SAndroid Build Coastguard Worker 	xMax = hb_max (xMax, x);
194*2d1272b8SAndroid Build Coastguard Worker 	yMin = hb_min (yMin, y);
195*2d1272b8SAndroid Build Coastguard Worker 	yMax = hb_max (yMax, y);
196*2d1272b8SAndroid Build Coastguard Worker       }
197*2d1272b8SAndroid Build Coastguard Worker     }
198*2d1272b8SAndroid Build Coastguard Worker 
199*2d1272b8SAndroid Build Coastguard Worker 
200*2d1272b8SAndroid Build Coastguard Worker     // These are destined for storage in a 16 bit field to clamp the values to
201*2d1272b8SAndroid Build Coastguard Worker     // fit into a 16 bit signed integer.
202*2d1272b8SAndroid Build Coastguard Worker     int rounded_xMin = hb_clamp (roundf (xMin), -32768.0f, 32767.0f);
203*2d1272b8SAndroid Build Coastguard Worker     int rounded_xMax = hb_clamp (roundf (xMax), -32768.0f, 32767.0f);
204*2d1272b8SAndroid Build Coastguard Worker     int rounded_yMin = hb_clamp (roundf (yMin), -32768.0f, 32767.0f);
205*2d1272b8SAndroid Build Coastguard Worker     int rounded_yMax = hb_clamp (roundf (yMax), -32768.0f, 32767.0f);
206*2d1272b8SAndroid Build Coastguard Worker 
207*2d1272b8SAndroid Build Coastguard Worker     update_mtx (plan, rounded_xMin, rounded_xMax, rounded_yMin, rounded_yMax, all_points);
208*2d1272b8SAndroid Build Coastguard Worker 
209*2d1272b8SAndroid Build Coastguard Worker     if (type != EMPTY)
210*2d1272b8SAndroid Build Coastguard Worker     {
211*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, rounded_xMin);
212*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, rounded_yMin);
213*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, rounded_xMax);
214*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, rounded_yMax);
215*2d1272b8SAndroid Build Coastguard Worker     }
216*2d1272b8SAndroid Build Coastguard Worker 
217*2d1272b8SAndroid Build Coastguard Worker     /* when pinned at default, no need to compile glyph header
218*2d1272b8SAndroid Build Coastguard Worker      * and for empty glyphs: all_points only include phantom points.
219*2d1272b8SAndroid Build Coastguard Worker      * just update metrics and then return */
220*2d1272b8SAndroid Build Coastguard Worker     if (!glyph_header)
221*2d1272b8SAndroid Build Coastguard Worker       return true;
222*2d1272b8SAndroid Build Coastguard Worker 
223*2d1272b8SAndroid Build Coastguard Worker     glyph_header->numberOfContours = header->numberOfContours;
224*2d1272b8SAndroid Build Coastguard Worker 
225*2d1272b8SAndroid Build Coastguard Worker     glyph_header->xMin = rounded_xMin;
226*2d1272b8SAndroid Build Coastguard Worker     glyph_header->yMin = rounded_yMin;
227*2d1272b8SAndroid Build Coastguard Worker     glyph_header->xMax = rounded_xMax;
228*2d1272b8SAndroid Build Coastguard Worker     glyph_header->yMax = rounded_yMax;
229*2d1272b8SAndroid Build Coastguard Worker 
230*2d1272b8SAndroid Build Coastguard Worker     dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
231*2d1272b8SAndroid Build Coastguard Worker     return true;
232*2d1272b8SAndroid Build Coastguard Worker   }
233*2d1272b8SAndroid Build Coastguard Worker 
compile_bytes_with_deltasOT::glyf_impl::Glyph234*2d1272b8SAndroid Build Coastguard Worker   bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
235*2d1272b8SAndroid Build Coastguard Worker                                   hb_font_t *font,
236*2d1272b8SAndroid Build Coastguard Worker                                   const glyf_accelerator_t &glyf,
237*2d1272b8SAndroid Build Coastguard Worker                                   hb_bytes_t &dest_start,  /* IN/OUT */
238*2d1272b8SAndroid Build Coastguard Worker                                   hb_bytes_t &dest_end /* OUT */)
239*2d1272b8SAndroid Build Coastguard Worker   {
240*2d1272b8SAndroid Build Coastguard Worker     contour_point_vector_t all_points, points_with_deltas;
241*2d1272b8SAndroid Build Coastguard Worker     unsigned composite_contours = 0;
242*2d1272b8SAndroid Build Coastguard Worker     head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info;
243*2d1272b8SAndroid Build Coastguard Worker     unsigned *composite_contours_p = &composite_contours;
244*2d1272b8SAndroid Build Coastguard Worker 
245*2d1272b8SAndroid Build Coastguard Worker     // don't compute head/maxp values when glyph has no contours(type is EMPTY)
246*2d1272b8SAndroid Build Coastguard Worker     // also ignore .notdef glyph when --notdef-outline is not enabled
247*2d1272b8SAndroid Build Coastguard Worker     if (type == EMPTY ||
248*2d1272b8SAndroid Build Coastguard Worker         (gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)))
249*2d1272b8SAndroid Build Coastguard Worker     {
250*2d1272b8SAndroid Build Coastguard Worker       head_maxp_info_p = nullptr;
251*2d1272b8SAndroid Build Coastguard Worker       composite_contours_p = nullptr;
252*2d1272b8SAndroid Build Coastguard Worker     }
253*2d1272b8SAndroid Build Coastguard Worker 
254*2d1272b8SAndroid Build Coastguard Worker     if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
255*2d1272b8SAndroid Build Coastguard Worker       return false;
256*2d1272b8SAndroid Build Coastguard Worker 
257*2d1272b8SAndroid Build Coastguard Worker     // .notdef, set type to empty so we only update metrics and don't compile bytes for
258*2d1272b8SAndroid Build Coastguard Worker     // it
259*2d1272b8SAndroid Build Coastguard Worker     if (gid == 0 &&
260*2d1272b8SAndroid Build Coastguard Worker         !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
261*2d1272b8SAndroid Build Coastguard Worker     {
262*2d1272b8SAndroid Build Coastguard Worker       type = EMPTY;
263*2d1272b8SAndroid Build Coastguard Worker       dest_start = hb_bytes_t ();
264*2d1272b8SAndroid Build Coastguard Worker       dest_end = hb_bytes_t ();
265*2d1272b8SAndroid Build Coastguard Worker     }
266*2d1272b8SAndroid Build Coastguard Worker 
267*2d1272b8SAndroid Build Coastguard Worker     //dont compile bytes when pinned at default, just recalculate bounds
268*2d1272b8SAndroid Build Coastguard Worker     if (!plan->pinned_at_default)
269*2d1272b8SAndroid Build Coastguard Worker     {
270*2d1272b8SAndroid Build Coastguard Worker       switch (type)
271*2d1272b8SAndroid Build Coastguard Worker       {
272*2d1272b8SAndroid Build Coastguard Worker       case COMPOSITE:
273*2d1272b8SAndroid Build Coastguard Worker         if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
274*2d1272b8SAndroid Build Coastguard Worker                                                                         points_with_deltas,
275*2d1272b8SAndroid Build Coastguard Worker                                                                         dest_end))
276*2d1272b8SAndroid Build Coastguard Worker           return false;
277*2d1272b8SAndroid Build Coastguard Worker         break;
278*2d1272b8SAndroid Build Coastguard Worker       case SIMPLE:
279*2d1272b8SAndroid Build Coastguard Worker         if (!SimpleGlyph (*header, bytes).compile_bytes_with_deltas (all_points,
280*2d1272b8SAndroid Build Coastguard Worker                                                                      plan->flags & HB_SUBSET_FLAGS_NO_HINTING,
281*2d1272b8SAndroid Build Coastguard Worker                                                                      dest_end))
282*2d1272b8SAndroid Build Coastguard Worker           return false;
283*2d1272b8SAndroid Build Coastguard Worker         break;
284*2d1272b8SAndroid Build Coastguard Worker       case EMPTY:
285*2d1272b8SAndroid Build Coastguard Worker         /* set empty bytes for empty glyph
286*2d1272b8SAndroid Build Coastguard Worker          * do not use source glyph's pointers */
287*2d1272b8SAndroid Build Coastguard Worker         dest_start = hb_bytes_t ();
288*2d1272b8SAndroid Build Coastguard Worker         dest_end = hb_bytes_t ();
289*2d1272b8SAndroid Build Coastguard Worker         break;
290*2d1272b8SAndroid Build Coastguard Worker       }
291*2d1272b8SAndroid Build Coastguard Worker     }
292*2d1272b8SAndroid Build Coastguard Worker 
293*2d1272b8SAndroid Build Coastguard Worker     if (!compile_header_bytes (plan, all_points, dest_start))
294*2d1272b8SAndroid Build Coastguard Worker     {
295*2d1272b8SAndroid Build Coastguard Worker       dest_end.fini ();
296*2d1272b8SAndroid Build Coastguard Worker       return false;
297*2d1272b8SAndroid Build Coastguard Worker     }
298*2d1272b8SAndroid Build Coastguard Worker     return true;
299*2d1272b8SAndroid Build Coastguard Worker   }
300*2d1272b8SAndroid Build Coastguard Worker 
301*2d1272b8SAndroid Build Coastguard Worker 
302*2d1272b8SAndroid Build Coastguard Worker   /* Note: Recursively calls itself.
303*2d1272b8SAndroid Build Coastguard Worker    * all_points includes phantom points
304*2d1272b8SAndroid Build Coastguard Worker    */
305*2d1272b8SAndroid Build Coastguard Worker   template <typename accelerator_t>
get_pointsOT::glyf_impl::Glyph306*2d1272b8SAndroid Build Coastguard Worker   bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
307*2d1272b8SAndroid Build Coastguard Worker 		   contour_point_vector_t &all_points /* OUT */,
308*2d1272b8SAndroid Build Coastguard Worker 		   contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
309*2d1272b8SAndroid Build Coastguard Worker 		   head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
310*2d1272b8SAndroid Build Coastguard Worker 		   unsigned *composite_contours = nullptr, /* OUT */
311*2d1272b8SAndroid Build Coastguard Worker 		   bool shift_points_hori = true,
312*2d1272b8SAndroid Build Coastguard Worker 		   bool use_my_metrics = true,
313*2d1272b8SAndroid Build Coastguard Worker 		   bool phantom_only = false,
314*2d1272b8SAndroid Build Coastguard Worker 		   hb_array_t<const int> coords = hb_array_t<const int> (),
315*2d1272b8SAndroid Build Coastguard Worker 		   hb_map_t *current_glyphs = nullptr,
316*2d1272b8SAndroid Build Coastguard Worker 		   unsigned int depth = 0,
317*2d1272b8SAndroid Build Coastguard Worker 		   unsigned *edge_count = nullptr) const
318*2d1272b8SAndroid Build Coastguard Worker   {
319*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
320*2d1272b8SAndroid Build Coastguard Worker     unsigned stack_edge_count = 0;
321*2d1272b8SAndroid Build Coastguard Worker     if (!edge_count) edge_count = &stack_edge_count;
322*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (*edge_count > HB_MAX_GRAPH_EDGE_COUNT)) return false;
323*2d1272b8SAndroid Build Coastguard Worker     (*edge_count)++;
324*2d1272b8SAndroid Build Coastguard Worker 
325*2d1272b8SAndroid Build Coastguard Worker     hb_map_t current_glyphs_stack;
326*2d1272b8SAndroid Build Coastguard Worker     if (current_glyphs == nullptr)
327*2d1272b8SAndroid Build Coastguard Worker       current_glyphs = &current_glyphs_stack;
328*2d1272b8SAndroid Build Coastguard Worker 
329*2d1272b8SAndroid Build Coastguard Worker     if (head_maxp_info)
330*2d1272b8SAndroid Build Coastguard Worker     {
331*2d1272b8SAndroid Build Coastguard Worker       head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
332*2d1272b8SAndroid Build Coastguard Worker     }
333*2d1272b8SAndroid Build Coastguard Worker 
334*2d1272b8SAndroid Build Coastguard Worker     if (!coords)
335*2d1272b8SAndroid Build Coastguard Worker       coords = hb_array (font->coords, font->num_coords);
336*2d1272b8SAndroid Build Coastguard Worker 
337*2d1272b8SAndroid Build Coastguard Worker     contour_point_vector_t stack_points;
338*2d1272b8SAndroid Build Coastguard Worker     contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points;
339*2d1272b8SAndroid Build Coastguard Worker     unsigned old_length = points.length;
340*2d1272b8SAndroid Build Coastguard Worker 
341*2d1272b8SAndroid Build Coastguard Worker     switch (type) {
342*2d1272b8SAndroid Build Coastguard Worker     case SIMPLE:
343*2d1272b8SAndroid Build Coastguard Worker       if (depth == 0 && head_maxp_info)
344*2d1272b8SAndroid Build Coastguard Worker         head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours);
345*2d1272b8SAndroid Build Coastguard Worker       if (depth > 0 && composite_contours)
346*2d1272b8SAndroid Build Coastguard Worker         *composite_contours += (unsigned) header->numberOfContours;
347*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (all_points, phantom_only)))
348*2d1272b8SAndroid Build Coastguard Worker 	return false;
349*2d1272b8SAndroid Build Coastguard Worker       break;
350*2d1272b8SAndroid Build Coastguard Worker     case COMPOSITE:
351*2d1272b8SAndroid Build Coastguard Worker     {
352*2d1272b8SAndroid Build Coastguard Worker       for (auto &item : get_composite_iterator ())
353*2d1272b8SAndroid Build Coastguard Worker         if (unlikely (!item.get_points (points))) return false;
354*2d1272b8SAndroid Build Coastguard Worker       break;
355*2d1272b8SAndroid Build Coastguard Worker     }
356*2d1272b8SAndroid Build Coastguard Worker     case EMPTY:
357*2d1272b8SAndroid Build Coastguard Worker       break;
358*2d1272b8SAndroid Build Coastguard Worker     }
359*2d1272b8SAndroid Build Coastguard Worker 
360*2d1272b8SAndroid Build Coastguard Worker     /* Init phantom points */
361*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
362*2d1272b8SAndroid Build Coastguard Worker     hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
363*2d1272b8SAndroid Build Coastguard Worker     {
364*2d1272b8SAndroid Build Coastguard Worker       int lsb = 0;
365*2d1272b8SAndroid Build Coastguard Worker       int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
366*2d1272b8SAndroid Build Coastguard Worker 		    (int) header->xMin - lsb : 0;
367*2d1272b8SAndroid Build Coastguard Worker       HB_UNUSED int tsb = 0;
368*2d1272b8SAndroid Build Coastguard Worker       int v_orig  = (int) header->yMax +
369*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
370*2d1272b8SAndroid Build Coastguard Worker 		    ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
371*2d1272b8SAndroid Build Coastguard Worker #else
372*2d1272b8SAndroid Build Coastguard Worker 		    0
373*2d1272b8SAndroid Build Coastguard Worker #endif
374*2d1272b8SAndroid Build Coastguard Worker 		    ;
375*2d1272b8SAndroid Build Coastguard Worker       unsigned h_adv = glyf_accelerator.hmtx->get_advance_without_var_unscaled (gid);
376*2d1272b8SAndroid Build Coastguard Worker       unsigned v_adv =
377*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL
378*2d1272b8SAndroid Build Coastguard Worker 		       glyf_accelerator.vmtx->get_advance_without_var_unscaled (gid)
379*2d1272b8SAndroid Build Coastguard Worker #else
380*2d1272b8SAndroid Build Coastguard Worker 		       - font->face->get_upem ()
381*2d1272b8SAndroid Build Coastguard Worker #endif
382*2d1272b8SAndroid Build Coastguard Worker 		       ;
383*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_LEFT].x = h_delta;
384*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta;
385*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_TOP].y = v_orig;
386*2d1272b8SAndroid Build Coastguard Worker       phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
387*2d1272b8SAndroid Build Coastguard Worker     }
388*2d1272b8SAndroid Build Coastguard Worker 
389*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
390*2d1272b8SAndroid Build Coastguard Worker     if (coords)
391*2d1272b8SAndroid Build Coastguard Worker       glyf_accelerator.gvar->apply_deltas_to_points (gid,
392*2d1272b8SAndroid Build Coastguard Worker 						     coords,
393*2d1272b8SAndroid Build Coastguard Worker 						     points.as_array ().sub_array (old_length),
394*2d1272b8SAndroid Build Coastguard Worker 						     phantom_only && type == SIMPLE);
395*2d1272b8SAndroid Build Coastguard Worker #endif
396*2d1272b8SAndroid Build Coastguard Worker 
397*2d1272b8SAndroid Build Coastguard Worker     // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
398*2d1272b8SAndroid Build Coastguard Worker     // with child glyphs' points
399*2d1272b8SAndroid Build Coastguard Worker     if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
400*2d1272b8SAndroid Build Coastguard Worker     {
401*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!points_with_deltas->resize (points.length))) return false;
402*2d1272b8SAndroid Build Coastguard Worker       *points_with_deltas = points;
403*2d1272b8SAndroid Build Coastguard Worker     }
404*2d1272b8SAndroid Build Coastguard Worker 
405*2d1272b8SAndroid Build Coastguard Worker     switch (type) {
406*2d1272b8SAndroid Build Coastguard Worker     case SIMPLE:
407*2d1272b8SAndroid Build Coastguard Worker       if (depth == 0 && head_maxp_info)
408*2d1272b8SAndroid Build Coastguard Worker         head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4);
409*2d1272b8SAndroid Build Coastguard Worker       break;
410*2d1272b8SAndroid Build Coastguard Worker     case COMPOSITE:
411*2d1272b8SAndroid Build Coastguard Worker     {
412*2d1272b8SAndroid Build Coastguard Worker       unsigned int comp_index = 0;
413*2d1272b8SAndroid Build Coastguard Worker       for (auto &item : get_composite_iterator ())
414*2d1272b8SAndroid Build Coastguard Worker       {
415*2d1272b8SAndroid Build Coastguard Worker 	hb_codepoint_t item_gid = item.get_gid ();
416*2d1272b8SAndroid Build Coastguard Worker 
417*2d1272b8SAndroid Build Coastguard Worker         if (unlikely (current_glyphs->has (item_gid)))
418*2d1272b8SAndroid Build Coastguard Worker 	  continue;
419*2d1272b8SAndroid Build Coastguard Worker 
420*2d1272b8SAndroid Build Coastguard Worker 	current_glyphs->add (item_gid);
421*2d1272b8SAndroid Build Coastguard Worker 
422*2d1272b8SAndroid Build Coastguard Worker 	unsigned old_count = all_points.length;
423*2d1272b8SAndroid Build Coastguard Worker 
424*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
425*2d1272b8SAndroid Build Coastguard Worker 		      !glyf_accelerator.glyph_for_gid (item_gid)
426*2d1272b8SAndroid Build Coastguard Worker 				       .get_points (font,
427*2d1272b8SAndroid Build Coastguard Worker 						    glyf_accelerator,
428*2d1272b8SAndroid Build Coastguard Worker 						    all_points,
429*2d1272b8SAndroid Build Coastguard Worker 						    points_with_deltas,
430*2d1272b8SAndroid Build Coastguard Worker 						    head_maxp_info,
431*2d1272b8SAndroid Build Coastguard Worker 						    composite_contours,
432*2d1272b8SAndroid Build Coastguard Worker 						    shift_points_hori,
433*2d1272b8SAndroid Build Coastguard Worker 						    use_my_metrics,
434*2d1272b8SAndroid Build Coastguard Worker 						    phantom_only,
435*2d1272b8SAndroid Build Coastguard Worker 						    coords,
436*2d1272b8SAndroid Build Coastguard Worker 						    current_glyphs,
437*2d1272b8SAndroid Build Coastguard Worker 						    depth + 1,
438*2d1272b8SAndroid Build Coastguard Worker 						    edge_count)))
439*2d1272b8SAndroid Build Coastguard Worker 	{
440*2d1272b8SAndroid Build Coastguard Worker 	  current_glyphs->del (item_gid);
441*2d1272b8SAndroid Build Coastguard Worker 	  return false;
442*2d1272b8SAndroid Build Coastguard Worker 	}
443*2d1272b8SAndroid Build Coastguard Worker 
444*2d1272b8SAndroid Build Coastguard Worker 	auto comp_points = all_points.as_array ().sub_array (old_count);
445*2d1272b8SAndroid Build Coastguard Worker 
446*2d1272b8SAndroid Build Coastguard Worker 	/* Copy phantom points from component if USE_MY_METRICS flag set */
447*2d1272b8SAndroid Build Coastguard Worker 	if (use_my_metrics && item.is_use_my_metrics ())
448*2d1272b8SAndroid Build Coastguard Worker 	  for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
449*2d1272b8SAndroid Build Coastguard Worker 	    phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
450*2d1272b8SAndroid Build Coastguard Worker 
451*2d1272b8SAndroid Build Coastguard Worker 	if (comp_points) // Empty in case of phantom_only
452*2d1272b8SAndroid Build Coastguard Worker 	{
453*2d1272b8SAndroid Build Coastguard Worker 	  float matrix[4];
454*2d1272b8SAndroid Build Coastguard Worker 	  contour_point_t default_trans;
455*2d1272b8SAndroid Build Coastguard Worker 	  item.get_transformation (matrix, default_trans);
456*2d1272b8SAndroid Build Coastguard Worker 
457*2d1272b8SAndroid Build Coastguard Worker 	  /* Apply component transformation & translation (with deltas applied) */
458*2d1272b8SAndroid Build Coastguard Worker 	  item.transform_points (comp_points, matrix, points[comp_index]);
459*2d1272b8SAndroid Build Coastguard Worker 	}
460*2d1272b8SAndroid Build Coastguard Worker 
461*2d1272b8SAndroid Build Coastguard Worker 	if (item.is_anchored () && !phantom_only)
462*2d1272b8SAndroid Build Coastguard Worker 	{
463*2d1272b8SAndroid Build Coastguard Worker 	  unsigned int p1, p2;
464*2d1272b8SAndroid Build Coastguard Worker 	  item.get_anchor_points (p1, p2);
465*2d1272b8SAndroid Build Coastguard Worker 	  if (likely (p1 < all_points.length && p2 < comp_points.length))
466*2d1272b8SAndroid Build Coastguard Worker 	  {
467*2d1272b8SAndroid Build Coastguard Worker 	    contour_point_t delta;
468*2d1272b8SAndroid Build Coastguard Worker 	    delta.init (all_points[p1].x - comp_points[p2].x,
469*2d1272b8SAndroid Build Coastguard Worker 			all_points[p1].y - comp_points[p2].y);
470*2d1272b8SAndroid Build Coastguard Worker 
471*2d1272b8SAndroid Build Coastguard Worker 	    item.translate (delta, comp_points);
472*2d1272b8SAndroid Build Coastguard Worker 	  }
473*2d1272b8SAndroid Build Coastguard Worker 	}
474*2d1272b8SAndroid Build Coastguard Worker 
475*2d1272b8SAndroid Build Coastguard Worker 	all_points.resize (all_points.length - PHANTOM_COUNT);
476*2d1272b8SAndroid Build Coastguard Worker 
477*2d1272b8SAndroid Build Coastguard Worker 	if (all_points.length > HB_GLYF_MAX_POINTS)
478*2d1272b8SAndroid Build Coastguard Worker 	{
479*2d1272b8SAndroid Build Coastguard Worker 	  current_glyphs->del (item_gid);
480*2d1272b8SAndroid Build Coastguard Worker 	  return false;
481*2d1272b8SAndroid Build Coastguard Worker 	}
482*2d1272b8SAndroid Build Coastguard Worker 
483*2d1272b8SAndroid Build Coastguard Worker 	comp_index++;
484*2d1272b8SAndroid Build Coastguard Worker         current_glyphs->del (item_gid);
485*2d1272b8SAndroid Build Coastguard Worker       }
486*2d1272b8SAndroid Build Coastguard Worker 
487*2d1272b8SAndroid Build Coastguard Worker       if (head_maxp_info && depth == 0)
488*2d1272b8SAndroid Build Coastguard Worker       {
489*2d1272b8SAndroid Build Coastguard Worker         if (composite_contours)
490*2d1272b8SAndroid Build Coastguard Worker           head_maxp_info->maxCompositeContours = hb_max (head_maxp_info->maxCompositeContours, *composite_contours);
491*2d1272b8SAndroid Build Coastguard Worker         head_maxp_info->maxCompositePoints = hb_max (head_maxp_info->maxCompositePoints, all_points.length);
492*2d1272b8SAndroid Build Coastguard Worker         head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
493*2d1272b8SAndroid Build Coastguard Worker       }
494*2d1272b8SAndroid Build Coastguard Worker       all_points.extend (phantoms);
495*2d1272b8SAndroid Build Coastguard Worker     } break;
496*2d1272b8SAndroid Build Coastguard Worker     case EMPTY:
497*2d1272b8SAndroid Build Coastguard Worker       all_points.extend (phantoms);
498*2d1272b8SAndroid Build Coastguard Worker       break;
499*2d1272b8SAndroid Build Coastguard Worker     }
500*2d1272b8SAndroid Build Coastguard Worker 
501*2d1272b8SAndroid Build Coastguard Worker     if (depth == 0 && shift_points_hori) /* Apply at top level */
502*2d1272b8SAndroid Build Coastguard Worker     {
503*2d1272b8SAndroid Build Coastguard Worker       /* Undocumented rasterizer behavior:
504*2d1272b8SAndroid Build Coastguard Worker        * Shift points horizontally by the updated left side bearing
505*2d1272b8SAndroid Build Coastguard Worker        */
506*2d1272b8SAndroid Build Coastguard Worker       float v = -phantoms[PHANTOM_LEFT].x;
507*2d1272b8SAndroid Build Coastguard Worker       if (v)
508*2d1272b8SAndroid Build Coastguard Worker         for (auto &point : all_points)
509*2d1272b8SAndroid Build Coastguard Worker 	  point.x += v;
510*2d1272b8SAndroid Build Coastguard Worker     }
511*2d1272b8SAndroid Build Coastguard Worker 
512*2d1272b8SAndroid Build Coastguard Worker     return !all_points.in_error ();
513*2d1272b8SAndroid Build Coastguard Worker   }
514*2d1272b8SAndroid Build Coastguard Worker 
get_extents_without_var_scaledOT::glyf_impl::Glyph515*2d1272b8SAndroid Build Coastguard Worker   bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator,
516*2d1272b8SAndroid Build Coastguard Worker 				       hb_glyph_extents_t *extents) const
517*2d1272b8SAndroid Build Coastguard Worker   {
518*2d1272b8SAndroid Build Coastguard Worker     if (type == EMPTY) return true; /* Empty glyph; zero extents. */
519*2d1272b8SAndroid Build Coastguard Worker     return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents);
520*2d1272b8SAndroid Build Coastguard Worker   }
521*2d1272b8SAndroid Build Coastguard Worker 
get_bytesOT::glyf_impl::Glyph522*2d1272b8SAndroid Build Coastguard Worker   hb_bytes_t get_bytes () const { return bytes; }
get_typeOT::glyf_impl::Glyph523*2d1272b8SAndroid Build Coastguard Worker   glyph_type_t get_type () const { return type; }
get_headerOT::glyf_impl::Glyph524*2d1272b8SAndroid Build Coastguard Worker   const GlyphHeader *get_header () const { return header; }
525*2d1272b8SAndroid Build Coastguard Worker 
GlyphOT::glyf_impl::Glyph526*2d1272b8SAndroid Build Coastguard Worker   Glyph () : bytes (),
527*2d1272b8SAndroid Build Coastguard Worker              header (bytes.as<GlyphHeader> ()),
528*2d1272b8SAndroid Build Coastguard Worker              gid (-1),
529*2d1272b8SAndroid Build Coastguard Worker              type(EMPTY)
530*2d1272b8SAndroid Build Coastguard Worker   {}
531*2d1272b8SAndroid Build Coastguard Worker 
GlyphOT::glyf_impl::Glyph532*2d1272b8SAndroid Build Coastguard Worker   Glyph (hb_bytes_t bytes_,
533*2d1272b8SAndroid Build Coastguard Worker 	 hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_),
534*2d1272b8SAndroid Build Coastguard Worker                                                 header (bytes.as<GlyphHeader> ()),
535*2d1272b8SAndroid Build Coastguard Worker                                                 gid (gid_)
536*2d1272b8SAndroid Build Coastguard Worker   {
537*2d1272b8SAndroid Build Coastguard Worker     int num_contours = header->numberOfContours;
538*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (num_contours == 0)) type = EMPTY;
539*2d1272b8SAndroid Build Coastguard Worker     else if (num_contours > 0) type = SIMPLE;
540*2d1272b8SAndroid Build Coastguard Worker     else if (num_contours <= -1) type = COMPOSITE;
541*2d1272b8SAndroid Build Coastguard Worker     else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild.
542*2d1272b8SAndroid Build Coastguard Worker   }
543*2d1272b8SAndroid Build Coastguard Worker 
544*2d1272b8SAndroid Build Coastguard Worker   protected:
545*2d1272b8SAndroid Build Coastguard Worker   hb_bytes_t bytes;
546*2d1272b8SAndroid Build Coastguard Worker   const GlyphHeader *header;
547*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t gid;
548*2d1272b8SAndroid Build Coastguard Worker   glyph_type_t type;
549*2d1272b8SAndroid Build Coastguard Worker };
550*2d1272b8SAndroid Build Coastguard Worker 
551*2d1272b8SAndroid Build Coastguard Worker 
552*2d1272b8SAndroid Build Coastguard Worker } /* namespace glyf_impl */
553*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */
554*2d1272b8SAndroid Build Coastguard Worker 
555*2d1272b8SAndroid Build Coastguard Worker 
556*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_GLYPH_HH */
557