xref: /aosp_15_r20/external/harfbuzz_ng/src/OT/glyf/SimpleGlyph.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_SIMPLEGLYPH_HH
2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_SIMPLEGLYPH_HH
3*2d1272b8SAndroid Build Coastguard Worker 
4*2d1272b8SAndroid Build Coastguard Worker 
5*2d1272b8SAndroid Build Coastguard Worker #include "../../hb-open-type.hh"
6*2d1272b8SAndroid Build Coastguard Worker 
7*2d1272b8SAndroid Build Coastguard Worker 
8*2d1272b8SAndroid Build Coastguard Worker namespace OT {
9*2d1272b8SAndroid Build Coastguard Worker namespace glyf_impl {
10*2d1272b8SAndroid Build Coastguard Worker 
11*2d1272b8SAndroid Build Coastguard Worker 
12*2d1272b8SAndroid Build Coastguard Worker struct SimpleGlyph
13*2d1272b8SAndroid Build Coastguard Worker {
14*2d1272b8SAndroid Build Coastguard Worker   enum simple_glyph_flag_t
15*2d1272b8SAndroid Build Coastguard Worker   {
16*2d1272b8SAndroid Build Coastguard Worker     FLAG_ON_CURVE       = 0x01,
17*2d1272b8SAndroid Build Coastguard Worker     FLAG_X_SHORT        = 0x02,
18*2d1272b8SAndroid Build Coastguard Worker     FLAG_Y_SHORT        = 0x04,
19*2d1272b8SAndroid Build Coastguard Worker     FLAG_REPEAT         = 0x08,
20*2d1272b8SAndroid Build Coastguard Worker     FLAG_X_SAME         = 0x10,
21*2d1272b8SAndroid Build Coastguard Worker     FLAG_Y_SAME         = 0x20,
22*2d1272b8SAndroid Build Coastguard Worker     FLAG_OVERLAP_SIMPLE = 0x40,
23*2d1272b8SAndroid Build Coastguard Worker     FLAG_CUBIC          = 0x80
24*2d1272b8SAndroid Build Coastguard Worker   };
25*2d1272b8SAndroid Build Coastguard Worker 
26*2d1272b8SAndroid Build Coastguard Worker   const GlyphHeader &header;
27*2d1272b8SAndroid Build Coastguard Worker   hb_bytes_t bytes;
SimpleGlyphOT::glyf_impl::SimpleGlyph28*2d1272b8SAndroid Build Coastguard Worker   SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
29*2d1272b8SAndroid Build Coastguard Worker     header (header_), bytes (bytes_) {}
30*2d1272b8SAndroid Build Coastguard Worker 
instruction_len_offsetOT::glyf_impl::SimpleGlyph31*2d1272b8SAndroid Build Coastguard Worker   unsigned int instruction_len_offset () const
32*2d1272b8SAndroid Build Coastguard Worker   { return GlyphHeader::static_size + 2 * header.numberOfContours; }
33*2d1272b8SAndroid Build Coastguard Worker 
lengthOT::glyf_impl::SimpleGlyph34*2d1272b8SAndroid Build Coastguard Worker   unsigned int length (unsigned int instruction_len) const
35*2d1272b8SAndroid Build Coastguard Worker   { return instruction_len_offset () + 2 + instruction_len; }
36*2d1272b8SAndroid Build Coastguard Worker 
has_instructions_lengthOT::glyf_impl::SimpleGlyph37*2d1272b8SAndroid Build Coastguard Worker   bool has_instructions_length () const
38*2d1272b8SAndroid Build Coastguard Worker   {
39*2d1272b8SAndroid Build Coastguard Worker     return instruction_len_offset () + 2 <= bytes.length;
40*2d1272b8SAndroid Build Coastguard Worker   }
41*2d1272b8SAndroid Build Coastguard Worker 
instructions_lengthOT::glyf_impl::SimpleGlyph42*2d1272b8SAndroid Build Coastguard Worker   unsigned int instructions_length () const
43*2d1272b8SAndroid Build Coastguard Worker   {
44*2d1272b8SAndroid Build Coastguard Worker     unsigned int instruction_length_offset = instruction_len_offset ();
45*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
46*2d1272b8SAndroid Build Coastguard Worker 
47*2d1272b8SAndroid Build Coastguard Worker     const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
48*2d1272b8SAndroid Build Coastguard Worker     /* Out of bounds of the current glyph */
49*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (length (instructionLength) > bytes.length)) return 0;
50*2d1272b8SAndroid Build Coastguard Worker     return instructionLength;
51*2d1272b8SAndroid Build Coastguard Worker   }
52*2d1272b8SAndroid Build Coastguard Worker 
trim_paddingOT::glyf_impl::SimpleGlyph53*2d1272b8SAndroid Build Coastguard Worker   const hb_bytes_t trim_padding () const
54*2d1272b8SAndroid Build Coastguard Worker   {
55*2d1272b8SAndroid Build Coastguard Worker     /* based on FontTools _g_l_y_f.py::trim */
56*2d1272b8SAndroid Build Coastguard Worker     const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
57*2d1272b8SAndroid Build Coastguard Worker     const uint8_t *glyph_end = glyph + bytes.length;
58*2d1272b8SAndroid Build Coastguard Worker     /* simple glyph w/contours, possibly trimmable */
59*2d1272b8SAndroid Build Coastguard Worker     glyph += instruction_len_offset ();
60*2d1272b8SAndroid Build Coastguard Worker 
61*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (glyph + 2 >= glyph_end)) return hb_bytes_t ();
62*2d1272b8SAndroid Build Coastguard Worker     unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
63*2d1272b8SAndroid Build Coastguard Worker     unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
64*2d1272b8SAndroid Build Coastguard Worker 
65*2d1272b8SAndroid Build Coastguard Worker     glyph += 2 + num_instructions;
66*2d1272b8SAndroid Build Coastguard Worker 
67*2d1272b8SAndroid Build Coastguard Worker     unsigned int coord_bytes = 0;
68*2d1272b8SAndroid Build Coastguard Worker     unsigned int coords_with_flags = 0;
69*2d1272b8SAndroid Build Coastguard Worker     while (glyph < glyph_end)
70*2d1272b8SAndroid Build Coastguard Worker     {
71*2d1272b8SAndroid Build Coastguard Worker       uint8_t flag = *glyph;
72*2d1272b8SAndroid Build Coastguard Worker       glyph++;
73*2d1272b8SAndroid Build Coastguard Worker 
74*2d1272b8SAndroid Build Coastguard Worker       unsigned int repeat = 1;
75*2d1272b8SAndroid Build Coastguard Worker       if (flag & FLAG_REPEAT)
76*2d1272b8SAndroid Build Coastguard Worker       {
77*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (glyph >= glyph_end)) return hb_bytes_t ();
78*2d1272b8SAndroid Build Coastguard Worker 	repeat = *glyph + 1;
79*2d1272b8SAndroid Build Coastguard Worker 	glyph++;
80*2d1272b8SAndroid Build Coastguard Worker       }
81*2d1272b8SAndroid Build Coastguard Worker 
82*2d1272b8SAndroid Build Coastguard Worker       unsigned int xBytes, yBytes;
83*2d1272b8SAndroid Build Coastguard Worker       xBytes = yBytes = 0;
84*2d1272b8SAndroid Build Coastguard Worker       if (flag & FLAG_X_SHORT) xBytes = 1;
85*2d1272b8SAndroid Build Coastguard Worker       else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
86*2d1272b8SAndroid Build Coastguard Worker 
87*2d1272b8SAndroid Build Coastguard Worker       if (flag & FLAG_Y_SHORT) yBytes = 1;
88*2d1272b8SAndroid Build Coastguard Worker       else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
89*2d1272b8SAndroid Build Coastguard Worker 
90*2d1272b8SAndroid Build Coastguard Worker       coord_bytes += (xBytes + yBytes) * repeat;
91*2d1272b8SAndroid Build Coastguard Worker       coords_with_flags += repeat;
92*2d1272b8SAndroid Build Coastguard Worker       if (coords_with_flags >= num_coordinates) break;
93*2d1272b8SAndroid Build Coastguard Worker     }
94*2d1272b8SAndroid Build Coastguard Worker 
95*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (coords_with_flags != num_coordinates)) return hb_bytes_t ();
96*2d1272b8SAndroid Build Coastguard Worker     return bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph));
97*2d1272b8SAndroid Build Coastguard Worker   }
98*2d1272b8SAndroid Build Coastguard Worker 
99*2d1272b8SAndroid Build Coastguard Worker   /* zero instruction length */
drop_hintsOT::glyf_impl::SimpleGlyph100*2d1272b8SAndroid Build Coastguard Worker   void drop_hints ()
101*2d1272b8SAndroid Build Coastguard Worker   {
102*2d1272b8SAndroid Build Coastguard Worker     if (!has_instructions_length ()) return;
103*2d1272b8SAndroid Build Coastguard Worker     GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
104*2d1272b8SAndroid Build Coastguard Worker     (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
105*2d1272b8SAndroid Build Coastguard Worker   }
106*2d1272b8SAndroid Build Coastguard Worker 
drop_hints_bytesOT::glyf_impl::SimpleGlyph107*2d1272b8SAndroid Build Coastguard Worker   void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
108*2d1272b8SAndroid Build Coastguard Worker   {
109*2d1272b8SAndroid Build Coastguard Worker     unsigned int instructions_len = instructions_length ();
110*2d1272b8SAndroid Build Coastguard Worker     unsigned int glyph_length = length (instructions_len);
111*2d1272b8SAndroid Build Coastguard Worker     dest_start = bytes.sub_array (0, glyph_length - instructions_len);
112*2d1272b8SAndroid Build Coastguard Worker     dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
113*2d1272b8SAndroid Build Coastguard Worker   }
114*2d1272b8SAndroid Build Coastguard Worker 
set_overlaps_flagOT::glyf_impl::SimpleGlyph115*2d1272b8SAndroid Build Coastguard Worker   void set_overlaps_flag ()
116*2d1272b8SAndroid Build Coastguard Worker   {
117*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!header.numberOfContours)) return;
118*2d1272b8SAndroid Build Coastguard Worker 
119*2d1272b8SAndroid Build Coastguard Worker     unsigned flags_offset = length (instructions_length ());
120*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (flags_offset + 1 > bytes.length)) return;
121*2d1272b8SAndroid Build Coastguard Worker 
122*2d1272b8SAndroid Build Coastguard Worker     HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
123*2d1272b8SAndroid Build Coastguard Worker     first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
124*2d1272b8SAndroid Build Coastguard Worker   }
125*2d1272b8SAndroid Build Coastguard Worker 
read_flagsOT::glyf_impl::SimpleGlyph126*2d1272b8SAndroid Build Coastguard Worker   static bool read_flags (const HBUINT8 *&p /* IN/OUT */,
127*2d1272b8SAndroid Build Coastguard Worker 			  hb_array_t<contour_point_t> points_ /* IN/OUT */,
128*2d1272b8SAndroid Build Coastguard Worker 			  const HBUINT8 *end)
129*2d1272b8SAndroid Build Coastguard Worker   {
130*2d1272b8SAndroid Build Coastguard Worker     unsigned count = points_.length;
131*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < count;)
132*2d1272b8SAndroid Build Coastguard Worker     {
133*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (p + 1 > end)) return false;
134*2d1272b8SAndroid Build Coastguard Worker       uint8_t flag = *p++;
135*2d1272b8SAndroid Build Coastguard Worker       points_.arrayZ[i++].flag = flag;
136*2d1272b8SAndroid Build Coastguard Worker       if (flag & FLAG_REPEAT)
137*2d1272b8SAndroid Build Coastguard Worker       {
138*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (p + 1 > end)) return false;
139*2d1272b8SAndroid Build Coastguard Worker 	unsigned int repeat_count = *p++;
140*2d1272b8SAndroid Build Coastguard Worker 	unsigned stop = hb_min (i + repeat_count, count);
141*2d1272b8SAndroid Build Coastguard Worker 	for (; i < stop; i++)
142*2d1272b8SAndroid Build Coastguard Worker 	  points_.arrayZ[i].flag = flag;
143*2d1272b8SAndroid Build Coastguard Worker       }
144*2d1272b8SAndroid Build Coastguard Worker     }
145*2d1272b8SAndroid Build Coastguard Worker     return true;
146*2d1272b8SAndroid Build Coastguard Worker   }
147*2d1272b8SAndroid Build Coastguard Worker 
read_pointsOT::glyf_impl::SimpleGlyph148*2d1272b8SAndroid Build Coastguard Worker   static bool read_points (const HBUINT8 *&p /* IN/OUT */,
149*2d1272b8SAndroid Build Coastguard Worker 			   hb_array_t<contour_point_t> points_ /* IN/OUT */,
150*2d1272b8SAndroid Build Coastguard Worker 			   const HBUINT8 *end,
151*2d1272b8SAndroid Build Coastguard Worker 			   float contour_point_t::*m,
152*2d1272b8SAndroid Build Coastguard Worker 			   const simple_glyph_flag_t short_flag,
153*2d1272b8SAndroid Build Coastguard Worker 			   const simple_glyph_flag_t same_flag)
154*2d1272b8SAndroid Build Coastguard Worker   {
155*2d1272b8SAndroid Build Coastguard Worker     int v = 0;
156*2d1272b8SAndroid Build Coastguard Worker 
157*2d1272b8SAndroid Build Coastguard Worker     for (auto &point : points_)
158*2d1272b8SAndroid Build Coastguard Worker     {
159*2d1272b8SAndroid Build Coastguard Worker       unsigned flag = point.flag;
160*2d1272b8SAndroid Build Coastguard Worker       if (flag & short_flag)
161*2d1272b8SAndroid Build Coastguard Worker       {
162*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (p + 1 > end)) return false;
163*2d1272b8SAndroid Build Coastguard Worker 	if (flag & same_flag)
164*2d1272b8SAndroid Build Coastguard Worker 	  v += *p++;
165*2d1272b8SAndroid Build Coastguard Worker 	else
166*2d1272b8SAndroid Build Coastguard Worker 	  v -= *p++;
167*2d1272b8SAndroid Build Coastguard Worker       }
168*2d1272b8SAndroid Build Coastguard Worker       else
169*2d1272b8SAndroid Build Coastguard Worker       {
170*2d1272b8SAndroid Build Coastguard Worker 	if (!(flag & same_flag))
171*2d1272b8SAndroid Build Coastguard Worker 	{
172*2d1272b8SAndroid Build Coastguard Worker 	  if (unlikely (p + HBINT16::static_size > end)) return false;
173*2d1272b8SAndroid Build Coastguard Worker 	  v += *(const HBINT16 *) p;
174*2d1272b8SAndroid Build Coastguard Worker 	  p += HBINT16::static_size;
175*2d1272b8SAndroid Build Coastguard Worker 	}
176*2d1272b8SAndroid Build Coastguard Worker       }
177*2d1272b8SAndroid Build Coastguard Worker       point.*m = v;
178*2d1272b8SAndroid Build Coastguard Worker     }
179*2d1272b8SAndroid Build Coastguard Worker     return true;
180*2d1272b8SAndroid Build Coastguard Worker   }
181*2d1272b8SAndroid Build Coastguard Worker 
get_contour_pointsOT::glyf_impl::SimpleGlyph182*2d1272b8SAndroid Build Coastguard Worker   bool get_contour_points (contour_point_vector_t &points /* OUT */,
183*2d1272b8SAndroid Build Coastguard Worker 			   bool phantom_only = false) const
184*2d1272b8SAndroid Build Coastguard Worker   {
185*2d1272b8SAndroid Build Coastguard Worker     const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
186*2d1272b8SAndroid Build Coastguard Worker     int num_contours = header.numberOfContours;
187*2d1272b8SAndroid Build Coastguard Worker     assert (num_contours > 0);
188*2d1272b8SAndroid Build Coastguard Worker     /* One extra item at the end, for the instruction-count below. */
189*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
190*2d1272b8SAndroid Build Coastguard Worker     unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
191*2d1272b8SAndroid Build Coastguard Worker 
192*2d1272b8SAndroid Build Coastguard Worker     unsigned old_length = points.length;
193*2d1272b8SAndroid Build Coastguard Worker     points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
194*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!points.resize (points.length + num_points, false))) return false;
195*2d1272b8SAndroid Build Coastguard Worker     auto points_ = points.as_array ().sub_array (old_length);
196*2d1272b8SAndroid Build Coastguard Worker     if (!phantom_only)
197*2d1272b8SAndroid Build Coastguard Worker       hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points);
198*2d1272b8SAndroid Build Coastguard Worker     if (phantom_only) return true;
199*2d1272b8SAndroid Build Coastguard Worker 
200*2d1272b8SAndroid Build Coastguard Worker     for (int i = 0; i < num_contours; i++)
201*2d1272b8SAndroid Build Coastguard Worker       points_[endPtsOfContours[i]].is_end_point = true;
202*2d1272b8SAndroid Build Coastguard Worker 
203*2d1272b8SAndroid Build Coastguard Worker     /* Skip instructions */
204*2d1272b8SAndroid Build Coastguard Worker     const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
205*2d1272b8SAndroid Build Coastguard Worker 						 endPtsOfContours[num_contours]);
206*2d1272b8SAndroid Build Coastguard Worker 
207*2d1272b8SAndroid Build Coastguard Worker     if (unlikely ((const char *) p < bytes.arrayZ)) return false; /* Unlikely overflow */
208*2d1272b8SAndroid Build Coastguard Worker     const HBUINT8 *end = (const HBUINT8 *) (bytes.arrayZ + bytes.length);
209*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (p >= end)) return false;
210*2d1272b8SAndroid Build Coastguard Worker 
211*2d1272b8SAndroid Build Coastguard Worker     /* Read x & y coordinates */
212*2d1272b8SAndroid Build Coastguard Worker     return read_flags (p, points_, end)
213*2d1272b8SAndroid Build Coastguard Worker         && read_points (p, points_, end, &contour_point_t::x,
214*2d1272b8SAndroid Build Coastguard Worker 			FLAG_X_SHORT, FLAG_X_SAME)
215*2d1272b8SAndroid Build Coastguard Worker 	&& read_points (p, points_, end, &contour_point_t::y,
216*2d1272b8SAndroid Build Coastguard Worker 			FLAG_Y_SHORT, FLAG_Y_SAME);
217*2d1272b8SAndroid Build Coastguard Worker   }
218*2d1272b8SAndroid Build Coastguard Worker 
encode_coordOT::glyf_impl::SimpleGlyph219*2d1272b8SAndroid Build Coastguard Worker   static void encode_coord (int value,
220*2d1272b8SAndroid Build Coastguard Worker                             unsigned &flag,
221*2d1272b8SAndroid Build Coastguard Worker                             const simple_glyph_flag_t short_flag,
222*2d1272b8SAndroid Build Coastguard Worker                             const simple_glyph_flag_t same_flag,
223*2d1272b8SAndroid Build Coastguard Worker                             hb_vector_t<uint8_t> &coords /* OUT */)
224*2d1272b8SAndroid Build Coastguard Worker   {
225*2d1272b8SAndroid Build Coastguard Worker     if (value == 0)
226*2d1272b8SAndroid Build Coastguard Worker     {
227*2d1272b8SAndroid Build Coastguard Worker       flag |= same_flag;
228*2d1272b8SAndroid Build Coastguard Worker     }
229*2d1272b8SAndroid Build Coastguard Worker     else if (value >= -255 && value <= 255)
230*2d1272b8SAndroid Build Coastguard Worker     {
231*2d1272b8SAndroid Build Coastguard Worker       flag |= short_flag;
232*2d1272b8SAndroid Build Coastguard Worker       if (value > 0) flag |= same_flag;
233*2d1272b8SAndroid Build Coastguard Worker       else value = -value;
234*2d1272b8SAndroid Build Coastguard Worker 
235*2d1272b8SAndroid Build Coastguard Worker       coords.arrayZ[coords.length++] = (uint8_t) value;
236*2d1272b8SAndroid Build Coastguard Worker     }
237*2d1272b8SAndroid Build Coastguard Worker     else
238*2d1272b8SAndroid Build Coastguard Worker     {
239*2d1272b8SAndroid Build Coastguard Worker       int16_t val = value;
240*2d1272b8SAndroid Build Coastguard Worker       coords.arrayZ[coords.length++] = val >> 8;
241*2d1272b8SAndroid Build Coastguard Worker       coords.arrayZ[coords.length++] = val & 0xff;
242*2d1272b8SAndroid Build Coastguard Worker     }
243*2d1272b8SAndroid Build Coastguard Worker   }
244*2d1272b8SAndroid Build Coastguard Worker 
encode_flagOT::glyf_impl::SimpleGlyph245*2d1272b8SAndroid Build Coastguard Worker   static void encode_flag (unsigned flag,
246*2d1272b8SAndroid Build Coastguard Worker                            unsigned &repeat,
247*2d1272b8SAndroid Build Coastguard Worker                            unsigned lastflag,
248*2d1272b8SAndroid Build Coastguard Worker                            hb_vector_t<uint8_t> &flags /* OUT */)
249*2d1272b8SAndroid Build Coastguard Worker   {
250*2d1272b8SAndroid Build Coastguard Worker     if (flag == lastflag && repeat != 255)
251*2d1272b8SAndroid Build Coastguard Worker     {
252*2d1272b8SAndroid Build Coastguard Worker       repeat++;
253*2d1272b8SAndroid Build Coastguard Worker       if (repeat == 1)
254*2d1272b8SAndroid Build Coastguard Worker       {
255*2d1272b8SAndroid Build Coastguard Worker         /* We know there's room. */
256*2d1272b8SAndroid Build Coastguard Worker         flags.arrayZ[flags.length++] = flag;
257*2d1272b8SAndroid Build Coastguard Worker       }
258*2d1272b8SAndroid Build Coastguard Worker       else
259*2d1272b8SAndroid Build Coastguard Worker       {
260*2d1272b8SAndroid Build Coastguard Worker         unsigned len = flags.length;
261*2d1272b8SAndroid Build Coastguard Worker         flags.arrayZ[len-2] = flag | FLAG_REPEAT;
262*2d1272b8SAndroid Build Coastguard Worker         flags.arrayZ[len-1] = repeat;
263*2d1272b8SAndroid Build Coastguard Worker       }
264*2d1272b8SAndroid Build Coastguard Worker     }
265*2d1272b8SAndroid Build Coastguard Worker     else
266*2d1272b8SAndroid Build Coastguard Worker     {
267*2d1272b8SAndroid Build Coastguard Worker       repeat = 0;
268*2d1272b8SAndroid Build Coastguard Worker       flags.arrayZ[flags.length++] = flag;
269*2d1272b8SAndroid Build Coastguard Worker     }
270*2d1272b8SAndroid Build Coastguard Worker   }
271*2d1272b8SAndroid Build Coastguard Worker 
compile_bytes_with_deltasOT::glyf_impl::SimpleGlyph272*2d1272b8SAndroid Build Coastguard Worker   bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
273*2d1272b8SAndroid Build Coastguard Worker                                   bool no_hinting,
274*2d1272b8SAndroid Build Coastguard Worker                                   hb_bytes_t &dest_bytes /* OUT */)
275*2d1272b8SAndroid Build Coastguard Worker   {
276*2d1272b8SAndroid Build Coastguard Worker     if (header.numberOfContours == 0 || all_points.length <= 4)
277*2d1272b8SAndroid Build Coastguard Worker     {
278*2d1272b8SAndroid Build Coastguard Worker       dest_bytes = hb_bytes_t ();
279*2d1272b8SAndroid Build Coastguard Worker       return true;
280*2d1272b8SAndroid Build Coastguard Worker     }
281*2d1272b8SAndroid Build Coastguard Worker     unsigned num_points = all_points.length - 4;
282*2d1272b8SAndroid Build Coastguard Worker 
283*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<uint8_t> flags, x_coords, y_coords;
284*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!flags.alloc (num_points, true))) return false;
285*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!x_coords.alloc (2*num_points, true))) return false;
286*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!y_coords.alloc (2*num_points, true))) return false;
287*2d1272b8SAndroid Build Coastguard Worker 
288*2d1272b8SAndroid Build Coastguard Worker     unsigned lastflag = 255, repeat = 0;
289*2d1272b8SAndroid Build Coastguard Worker     int prev_x = 0, prev_y = 0;
290*2d1272b8SAndroid Build Coastguard Worker 
291*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < num_points; i++)
292*2d1272b8SAndroid Build Coastguard Worker     {
293*2d1272b8SAndroid Build Coastguard Worker       unsigned flag = all_points.arrayZ[i].flag;
294*2d1272b8SAndroid Build Coastguard Worker       flag &= FLAG_ON_CURVE | FLAG_OVERLAP_SIMPLE | FLAG_CUBIC;
295*2d1272b8SAndroid Build Coastguard Worker 
296*2d1272b8SAndroid Build Coastguard Worker       int cur_x = roundf (all_points.arrayZ[i].x);
297*2d1272b8SAndroid Build Coastguard Worker       int cur_y = roundf (all_points.arrayZ[i].y);
298*2d1272b8SAndroid Build Coastguard Worker       encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
299*2d1272b8SAndroid Build Coastguard Worker       encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
300*2d1272b8SAndroid Build Coastguard Worker       encode_flag (flag, repeat, lastflag, flags);
301*2d1272b8SAndroid Build Coastguard Worker 
302*2d1272b8SAndroid Build Coastguard Worker       prev_x = cur_x;
303*2d1272b8SAndroid Build Coastguard Worker       prev_y = cur_y;
304*2d1272b8SAndroid Build Coastguard Worker       lastflag = flag;
305*2d1272b8SAndroid Build Coastguard Worker     }
306*2d1272b8SAndroid Build Coastguard Worker 
307*2d1272b8SAndroid Build Coastguard Worker     unsigned len_before_instrs = 2 * header.numberOfContours + 2;
308*2d1272b8SAndroid Build Coastguard Worker     unsigned len_instrs = instructions_length ();
309*2d1272b8SAndroid Build Coastguard Worker     unsigned total_len = len_before_instrs + flags.length + x_coords.length + y_coords.length;
310*2d1272b8SAndroid Build Coastguard Worker 
311*2d1272b8SAndroid Build Coastguard Worker     if (!no_hinting)
312*2d1272b8SAndroid Build Coastguard Worker       total_len += len_instrs;
313*2d1272b8SAndroid Build Coastguard Worker 
314*2d1272b8SAndroid Build Coastguard Worker     char *p = (char *) hb_malloc (total_len);
315*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!p)) return false;
316*2d1272b8SAndroid Build Coastguard Worker 
317*2d1272b8SAndroid Build Coastguard Worker     const char *src = bytes.arrayZ + GlyphHeader::static_size;
318*2d1272b8SAndroid Build Coastguard Worker     char *cur = p;
319*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (p, src, len_before_instrs);
320*2d1272b8SAndroid Build Coastguard Worker 
321*2d1272b8SAndroid Build Coastguard Worker     cur += len_before_instrs;
322*2d1272b8SAndroid Build Coastguard Worker     src += len_before_instrs;
323*2d1272b8SAndroid Build Coastguard Worker 
324*2d1272b8SAndroid Build Coastguard Worker     if (!no_hinting)
325*2d1272b8SAndroid Build Coastguard Worker     {
326*2d1272b8SAndroid Build Coastguard Worker       hb_memcpy (cur, src, len_instrs);
327*2d1272b8SAndroid Build Coastguard Worker       cur += len_instrs;
328*2d1272b8SAndroid Build Coastguard Worker     }
329*2d1272b8SAndroid Build Coastguard Worker 
330*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (cur, flags.arrayZ, flags.length);
331*2d1272b8SAndroid Build Coastguard Worker     cur += flags.length;
332*2d1272b8SAndroid Build Coastguard Worker 
333*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (cur, x_coords.arrayZ, x_coords.length);
334*2d1272b8SAndroid Build Coastguard Worker     cur += x_coords.length;
335*2d1272b8SAndroid Build Coastguard Worker 
336*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (cur, y_coords.arrayZ, y_coords.length);
337*2d1272b8SAndroid Build Coastguard Worker 
338*2d1272b8SAndroid Build Coastguard Worker     dest_bytes = hb_bytes_t (p, total_len);
339*2d1272b8SAndroid Build Coastguard Worker     return true;
340*2d1272b8SAndroid Build Coastguard Worker   }
341*2d1272b8SAndroid Build Coastguard Worker };
342*2d1272b8SAndroid Build Coastguard Worker 
343*2d1272b8SAndroid Build Coastguard Worker 
344*2d1272b8SAndroid Build Coastguard Worker } /* namespace glyf_impl */
345*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */
346*2d1272b8SAndroid Build Coastguard Worker 
347*2d1272b8SAndroid Build Coastguard Worker 
348*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_SIMPLEGLYPH_HH */
349