xref: /aosp_15_r20/external/harfbuzz_ng/src/OT/glyf/CompositeGlyph.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_COMPOSITEGLYPH_HH
2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_COMPOSITEGLYPH_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 "composite-iter.hh"
7*2d1272b8SAndroid Build Coastguard Worker 
8*2d1272b8SAndroid Build Coastguard Worker 
9*2d1272b8SAndroid Build Coastguard Worker namespace OT {
10*2d1272b8SAndroid Build Coastguard Worker namespace glyf_impl {
11*2d1272b8SAndroid Build Coastguard Worker 
12*2d1272b8SAndroid Build Coastguard Worker 
13*2d1272b8SAndroid Build Coastguard Worker struct CompositeGlyphRecord
14*2d1272b8SAndroid Build Coastguard Worker {
15*2d1272b8SAndroid Build Coastguard Worker   protected:
16*2d1272b8SAndroid Build Coastguard Worker   enum composite_glyph_flag_t
17*2d1272b8SAndroid Build Coastguard Worker   {
18*2d1272b8SAndroid Build Coastguard Worker     ARG_1_AND_2_ARE_WORDS	= 0x0001,
19*2d1272b8SAndroid Build Coastguard Worker     ARGS_ARE_XY_VALUES		= 0x0002,
20*2d1272b8SAndroid Build Coastguard Worker     ROUND_XY_TO_GRID		= 0x0004,
21*2d1272b8SAndroid Build Coastguard Worker     WE_HAVE_A_SCALE		= 0x0008,
22*2d1272b8SAndroid Build Coastguard Worker     MORE_COMPONENTS		= 0x0020,
23*2d1272b8SAndroid Build Coastguard Worker     WE_HAVE_AN_X_AND_Y_SCALE	= 0x0040,
24*2d1272b8SAndroid Build Coastguard Worker     WE_HAVE_A_TWO_BY_TWO	= 0x0080,
25*2d1272b8SAndroid Build Coastguard Worker     WE_HAVE_INSTRUCTIONS	= 0x0100,
26*2d1272b8SAndroid Build Coastguard Worker     USE_MY_METRICS		= 0x0200,
27*2d1272b8SAndroid Build Coastguard Worker     OVERLAP_COMPOUND		= 0x0400,
28*2d1272b8SAndroid Build Coastguard Worker     SCALED_COMPONENT_OFFSET	= 0x0800,
29*2d1272b8SAndroid Build Coastguard Worker     UNSCALED_COMPONENT_OFFSET	= 0x1000,
30*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
31*2d1272b8SAndroid Build Coastguard Worker     GID_IS_24BIT		= 0x2000
32*2d1272b8SAndroid Build Coastguard Worker #endif
33*2d1272b8SAndroid Build Coastguard Worker   };
34*2d1272b8SAndroid Build Coastguard Worker 
35*2d1272b8SAndroid Build Coastguard Worker   public:
get_sizeOT::glyf_impl::CompositeGlyphRecord36*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_size () const
37*2d1272b8SAndroid Build Coastguard Worker   {
38*2d1272b8SAndroid Build Coastguard Worker     unsigned int size = min_size;
39*2d1272b8SAndroid Build Coastguard Worker     /* glyphIndex is 24bit instead of 16bit */
40*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
41*2d1272b8SAndroid Build Coastguard Worker     if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size;
42*2d1272b8SAndroid Build Coastguard Worker #endif
43*2d1272b8SAndroid Build Coastguard Worker     /* arg1 and 2 are int16 */
44*2d1272b8SAndroid Build Coastguard Worker     if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
45*2d1272b8SAndroid Build Coastguard Worker     /* arg1 and 2 are int8 */
46*2d1272b8SAndroid Build Coastguard Worker     else size += 2;
47*2d1272b8SAndroid Build Coastguard Worker 
48*2d1272b8SAndroid Build Coastguard Worker     /* One x 16 bit (scale) */
49*2d1272b8SAndroid Build Coastguard Worker     if (flags & WE_HAVE_A_SCALE) size += 2;
50*2d1272b8SAndroid Build Coastguard Worker     /* Two x 16 bit (xscale, yscale) */
51*2d1272b8SAndroid Build Coastguard Worker     else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
52*2d1272b8SAndroid Build Coastguard Worker     /* Four x 16 bit (xscale, scale01, scale10, yscale) */
53*2d1272b8SAndroid Build Coastguard Worker     else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
54*2d1272b8SAndroid Build Coastguard Worker 
55*2d1272b8SAndroid Build Coastguard Worker     return size;
56*2d1272b8SAndroid Build Coastguard Worker   }
57*2d1272b8SAndroid Build Coastguard Worker 
drop_instructions_flagOT::glyf_impl::CompositeGlyphRecord58*2d1272b8SAndroid Build Coastguard Worker   void drop_instructions_flag ()  { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
set_overlaps_flagOT::glyf_impl::CompositeGlyphRecord59*2d1272b8SAndroid Build Coastguard Worker   void set_overlaps_flag ()
60*2d1272b8SAndroid Build Coastguard Worker   {
61*2d1272b8SAndroid Build Coastguard Worker     flags = (uint16_t) flags | OVERLAP_COMPOUND;
62*2d1272b8SAndroid Build Coastguard Worker   }
63*2d1272b8SAndroid Build Coastguard Worker 
has_instructionsOT::glyf_impl::CompositeGlyphRecord64*2d1272b8SAndroid Build Coastguard Worker   bool has_instructions ()  const { return   flags & WE_HAVE_INSTRUCTIONS; }
65*2d1272b8SAndroid Build Coastguard Worker 
has_moreOT::glyf_impl::CompositeGlyphRecord66*2d1272b8SAndroid Build Coastguard Worker   bool has_more ()          const { return   flags & MORE_COMPONENTS; }
is_use_my_metricsOT::glyf_impl::CompositeGlyphRecord67*2d1272b8SAndroid Build Coastguard Worker   bool is_use_my_metrics () const { return   flags & USE_MY_METRICS; }
is_anchoredOT::glyf_impl::CompositeGlyphRecord68*2d1272b8SAndroid Build Coastguard Worker   bool is_anchored ()       const { return !(flags & ARGS_ARE_XY_VALUES); }
get_anchor_pointsOT::glyf_impl::CompositeGlyphRecord69*2d1272b8SAndroid Build Coastguard Worker   void get_anchor_points (unsigned int &point1, unsigned int &point2) const
70*2d1272b8SAndroid Build Coastguard Worker   {
71*2d1272b8SAndroid Build Coastguard Worker     const auto *p = &StructAfter<const HBUINT8> (flags);
72*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
73*2d1272b8SAndroid Build Coastguard Worker     if (flags & GID_IS_24BIT)
74*2d1272b8SAndroid Build Coastguard Worker       p += HBGlyphID24::static_size;
75*2d1272b8SAndroid Build Coastguard Worker     else
76*2d1272b8SAndroid Build Coastguard Worker #endif
77*2d1272b8SAndroid Build Coastguard Worker       p += HBGlyphID16::static_size;
78*2d1272b8SAndroid Build Coastguard Worker     if (flags & ARG_1_AND_2_ARE_WORDS)
79*2d1272b8SAndroid Build Coastguard Worker     {
80*2d1272b8SAndroid Build Coastguard Worker       point1 = ((const HBUINT16 *) p)[0];
81*2d1272b8SAndroid Build Coastguard Worker       point2 = ((const HBUINT16 *) p)[1];
82*2d1272b8SAndroid Build Coastguard Worker     }
83*2d1272b8SAndroid Build Coastguard Worker     else
84*2d1272b8SAndroid Build Coastguard Worker     {
85*2d1272b8SAndroid Build Coastguard Worker       point1 = p[0];
86*2d1272b8SAndroid Build Coastguard Worker       point2 = p[1];
87*2d1272b8SAndroid Build Coastguard Worker     }
88*2d1272b8SAndroid Build Coastguard Worker   }
89*2d1272b8SAndroid Build Coastguard Worker 
transformOT::glyf_impl::CompositeGlyphRecord90*2d1272b8SAndroid Build Coastguard Worker   static void transform (const float (&matrix)[4],
91*2d1272b8SAndroid Build Coastguard Worker 			 hb_array_t<contour_point_t> points)
92*2d1272b8SAndroid Build Coastguard Worker   {
93*2d1272b8SAndroid Build Coastguard Worker     if (matrix[0] != 1.f || matrix[1] != 0.f ||
94*2d1272b8SAndroid Build Coastguard Worker 	matrix[2] != 0.f || matrix[3] != 1.f)
95*2d1272b8SAndroid Build Coastguard Worker       for (auto &point : points)
96*2d1272b8SAndroid Build Coastguard Worker         point.transform (matrix);
97*2d1272b8SAndroid Build Coastguard Worker   }
98*2d1272b8SAndroid Build Coastguard Worker 
translateOT::glyf_impl::CompositeGlyphRecord99*2d1272b8SAndroid Build Coastguard Worker   static void translate (const contour_point_t &trans,
100*2d1272b8SAndroid Build Coastguard Worker 			 hb_array_t<contour_point_t> points)
101*2d1272b8SAndroid Build Coastguard Worker   {
102*2d1272b8SAndroid Build Coastguard Worker     if (HB_OPTIMIZE_SIZE_VAL)
103*2d1272b8SAndroid Build Coastguard Worker     {
104*2d1272b8SAndroid Build Coastguard Worker       if (trans.x != 0.f || trans.y != 0.f)
105*2d1272b8SAndroid Build Coastguard Worker         for (auto &point : points)
106*2d1272b8SAndroid Build Coastguard Worker 	  point.translate (trans);
107*2d1272b8SAndroid Build Coastguard Worker     }
108*2d1272b8SAndroid Build Coastguard Worker     else
109*2d1272b8SAndroid Build Coastguard Worker     {
110*2d1272b8SAndroid Build Coastguard Worker       if (trans.x != 0.f && trans.y != 0.f)
111*2d1272b8SAndroid Build Coastguard Worker         for (auto &point : points)
112*2d1272b8SAndroid Build Coastguard Worker 	  point.translate (trans);
113*2d1272b8SAndroid Build Coastguard Worker       else
114*2d1272b8SAndroid Build Coastguard Worker       {
115*2d1272b8SAndroid Build Coastguard Worker 	if (trans.x != 0.f)
116*2d1272b8SAndroid Build Coastguard Worker 	  for (auto &point : points)
117*2d1272b8SAndroid Build Coastguard Worker 	    point.x += trans.x;
118*2d1272b8SAndroid Build Coastguard Worker 	else if (trans.y != 0.f)
119*2d1272b8SAndroid Build Coastguard Worker 	  for (auto &point : points)
120*2d1272b8SAndroid Build Coastguard Worker 	    point.y += trans.y;
121*2d1272b8SAndroid Build Coastguard Worker       }
122*2d1272b8SAndroid Build Coastguard Worker     }
123*2d1272b8SAndroid Build Coastguard Worker   }
124*2d1272b8SAndroid Build Coastguard Worker 
transform_pointsOT::glyf_impl::CompositeGlyphRecord125*2d1272b8SAndroid Build Coastguard Worker   void transform_points (hb_array_t<contour_point_t> points,
126*2d1272b8SAndroid Build Coastguard Worker 			 const float (&matrix)[4],
127*2d1272b8SAndroid Build Coastguard Worker 			 const contour_point_t &trans) const
128*2d1272b8SAndroid Build Coastguard Worker   {
129*2d1272b8SAndroid Build Coastguard Worker     if (scaled_offsets ())
130*2d1272b8SAndroid Build Coastguard Worker     {
131*2d1272b8SAndroid Build Coastguard Worker       translate (trans, points);
132*2d1272b8SAndroid Build Coastguard Worker       transform (matrix, points);
133*2d1272b8SAndroid Build Coastguard Worker     }
134*2d1272b8SAndroid Build Coastguard Worker     else
135*2d1272b8SAndroid Build Coastguard Worker     {
136*2d1272b8SAndroid Build Coastguard Worker       transform (matrix, points);
137*2d1272b8SAndroid Build Coastguard Worker       translate (trans, points);
138*2d1272b8SAndroid Build Coastguard Worker     }
139*2d1272b8SAndroid Build Coastguard Worker   }
140*2d1272b8SAndroid Build Coastguard Worker 
get_pointsOT::glyf_impl::CompositeGlyphRecord141*2d1272b8SAndroid Build Coastguard Worker   bool get_points (contour_point_vector_t &points) const
142*2d1272b8SAndroid Build Coastguard Worker   {
143*2d1272b8SAndroid Build Coastguard Worker     float matrix[4];
144*2d1272b8SAndroid Build Coastguard Worker     contour_point_t trans;
145*2d1272b8SAndroid Build Coastguard Worker     get_transformation (matrix, trans);
146*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points
147*2d1272b8SAndroid Build Coastguard Worker     points.push (trans);
148*2d1272b8SAndroid Build Coastguard Worker     return true;
149*2d1272b8SAndroid Build Coastguard Worker   }
150*2d1272b8SAndroid Build Coastguard Worker 
compile_with_pointOT::glyf_impl::CompositeGlyphRecord151*2d1272b8SAndroid Build Coastguard Worker   unsigned compile_with_point (const contour_point_t &point,
152*2d1272b8SAndroid Build Coastguard Worker                                char *out) const
153*2d1272b8SAndroid Build Coastguard Worker   {
154*2d1272b8SAndroid Build Coastguard Worker     const HBINT8 *p = &StructAfter<const HBINT8> (flags);
155*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
156*2d1272b8SAndroid Build Coastguard Worker     if (flags & GID_IS_24BIT)
157*2d1272b8SAndroid Build Coastguard Worker       p += HBGlyphID24::static_size;
158*2d1272b8SAndroid Build Coastguard Worker     else
159*2d1272b8SAndroid Build Coastguard Worker #endif
160*2d1272b8SAndroid Build Coastguard Worker       p += HBGlyphID16::static_size;
161*2d1272b8SAndroid Build Coastguard Worker 
162*2d1272b8SAndroid Build Coastguard Worker     unsigned len = get_size ();
163*2d1272b8SAndroid Build Coastguard Worker     unsigned len_before_val = (const char *)p - (const char *)this;
164*2d1272b8SAndroid Build Coastguard Worker     if (flags & ARG_1_AND_2_ARE_WORDS)
165*2d1272b8SAndroid Build Coastguard Worker     {
166*2d1272b8SAndroid Build Coastguard Worker       // no overflow, copy value
167*2d1272b8SAndroid Build Coastguard Worker       hb_memcpy (out, this, len);
168*2d1272b8SAndroid Build Coastguard Worker 
169*2d1272b8SAndroid Build Coastguard Worker       HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
170*2d1272b8SAndroid Build Coastguard Worker       o[0] = roundf (point.x);
171*2d1272b8SAndroid Build Coastguard Worker       o[1] = roundf (point.y);
172*2d1272b8SAndroid Build Coastguard Worker     }
173*2d1272b8SAndroid Build Coastguard Worker     else
174*2d1272b8SAndroid Build Coastguard Worker     {
175*2d1272b8SAndroid Build Coastguard Worker       int new_x = roundf (point.x);
176*2d1272b8SAndroid Build Coastguard Worker       int new_y = roundf (point.y);
177*2d1272b8SAndroid Build Coastguard Worker       if (new_x <= 127 && new_x >= -128 &&
178*2d1272b8SAndroid Build Coastguard Worker           new_y <= 127 && new_y >= -128)
179*2d1272b8SAndroid Build Coastguard Worker       {
180*2d1272b8SAndroid Build Coastguard Worker         hb_memcpy (out, this, len);
181*2d1272b8SAndroid Build Coastguard Worker         HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
182*2d1272b8SAndroid Build Coastguard Worker         o[0] = new_x;
183*2d1272b8SAndroid Build Coastguard Worker         o[1] = new_y;
184*2d1272b8SAndroid Build Coastguard Worker       }
185*2d1272b8SAndroid Build Coastguard Worker       else
186*2d1272b8SAndroid Build Coastguard Worker       {
187*2d1272b8SAndroid Build Coastguard Worker         // new point value has an int8 overflow
188*2d1272b8SAndroid Build Coastguard Worker         hb_memcpy (out, this, len_before_val);
189*2d1272b8SAndroid Build Coastguard Worker 
190*2d1272b8SAndroid Build Coastguard Worker         //update flags
191*2d1272b8SAndroid Build Coastguard Worker         CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
192*2d1272b8SAndroid Build Coastguard Worker         o->flags = flags | ARG_1_AND_2_ARE_WORDS;
193*2d1272b8SAndroid Build Coastguard Worker         out += len_before_val;
194*2d1272b8SAndroid Build Coastguard Worker 
195*2d1272b8SAndroid Build Coastguard Worker         HBINT16 new_value;
196*2d1272b8SAndroid Build Coastguard Worker         new_value = new_x;
197*2d1272b8SAndroid Build Coastguard Worker         hb_memcpy (out, &new_value, HBINT16::static_size);
198*2d1272b8SAndroid Build Coastguard Worker         out += HBINT16::static_size;
199*2d1272b8SAndroid Build Coastguard Worker 
200*2d1272b8SAndroid Build Coastguard Worker         new_value = new_y;
201*2d1272b8SAndroid Build Coastguard Worker         hb_memcpy (out, &new_value, HBINT16::static_size);
202*2d1272b8SAndroid Build Coastguard Worker         out += HBINT16::static_size;
203*2d1272b8SAndroid Build Coastguard Worker 
204*2d1272b8SAndroid Build Coastguard Worker         hb_memcpy (out, p+2, len - len_before_val - 2);
205*2d1272b8SAndroid Build Coastguard Worker         len += 2;
206*2d1272b8SAndroid Build Coastguard Worker       }
207*2d1272b8SAndroid Build Coastguard Worker     }
208*2d1272b8SAndroid Build Coastguard Worker     return len;
209*2d1272b8SAndroid Build Coastguard Worker   }
210*2d1272b8SAndroid Build Coastguard Worker 
211*2d1272b8SAndroid Build Coastguard Worker   protected:
scaled_offsetsOT::glyf_impl::CompositeGlyphRecord212*2d1272b8SAndroid Build Coastguard Worker   bool scaled_offsets () const
213*2d1272b8SAndroid Build Coastguard Worker   { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
214*2d1272b8SAndroid Build Coastguard Worker 
215*2d1272b8SAndroid Build Coastguard Worker   public:
get_transformationOT::glyf_impl::CompositeGlyphRecord216*2d1272b8SAndroid Build Coastguard Worker   bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
217*2d1272b8SAndroid Build Coastguard Worker   {
218*2d1272b8SAndroid Build Coastguard Worker     matrix[0] = matrix[3] = 1.f;
219*2d1272b8SAndroid Build Coastguard Worker     matrix[1] = matrix[2] = 0.f;
220*2d1272b8SAndroid Build Coastguard Worker 
221*2d1272b8SAndroid Build Coastguard Worker     const auto *p = &StructAfter<const HBINT8> (flags);
222*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
223*2d1272b8SAndroid Build Coastguard Worker     if (flags & GID_IS_24BIT)
224*2d1272b8SAndroid Build Coastguard Worker       p += HBGlyphID24::static_size;
225*2d1272b8SAndroid Build Coastguard Worker     else
226*2d1272b8SAndroid Build Coastguard Worker #endif
227*2d1272b8SAndroid Build Coastguard Worker       p += HBGlyphID16::static_size;
228*2d1272b8SAndroid Build Coastguard Worker     int tx, ty;
229*2d1272b8SAndroid Build Coastguard Worker     if (flags & ARG_1_AND_2_ARE_WORDS)
230*2d1272b8SAndroid Build Coastguard Worker     {
231*2d1272b8SAndroid Build Coastguard Worker       tx = *(const HBINT16 *) p;
232*2d1272b8SAndroid Build Coastguard Worker       p += HBINT16::static_size;
233*2d1272b8SAndroid Build Coastguard Worker       ty = *(const HBINT16 *) p;
234*2d1272b8SAndroid Build Coastguard Worker       p += HBINT16::static_size;
235*2d1272b8SAndroid Build Coastguard Worker     }
236*2d1272b8SAndroid Build Coastguard Worker     else
237*2d1272b8SAndroid Build Coastguard Worker     {
238*2d1272b8SAndroid Build Coastguard Worker       tx = *p++;
239*2d1272b8SAndroid Build Coastguard Worker       ty = *p++;
240*2d1272b8SAndroid Build Coastguard Worker     }
241*2d1272b8SAndroid Build Coastguard Worker     if (is_anchored ()) tx = ty = 0;
242*2d1272b8SAndroid Build Coastguard Worker 
243*2d1272b8SAndroid Build Coastguard Worker     /* set is_end_point flag to true, used by IUP delta optimization */
244*2d1272b8SAndroid Build Coastguard Worker     trans.init ((float) tx, (float) ty, true);
245*2d1272b8SAndroid Build Coastguard Worker 
246*2d1272b8SAndroid Build Coastguard Worker     {
247*2d1272b8SAndroid Build Coastguard Worker       const F2DOT14 *points = (const F2DOT14 *) p;
248*2d1272b8SAndroid Build Coastguard Worker       if (flags & WE_HAVE_A_SCALE)
249*2d1272b8SAndroid Build Coastguard Worker       {
250*2d1272b8SAndroid Build Coastguard Worker 	matrix[0] = matrix[3] = points[0].to_float ();
251*2d1272b8SAndroid Build Coastguard Worker 	return true;
252*2d1272b8SAndroid Build Coastguard Worker       }
253*2d1272b8SAndroid Build Coastguard Worker       else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
254*2d1272b8SAndroid Build Coastguard Worker       {
255*2d1272b8SAndroid Build Coastguard Worker 	matrix[0] = points[0].to_float ();
256*2d1272b8SAndroid Build Coastguard Worker 	matrix[3] = points[1].to_float ();
257*2d1272b8SAndroid Build Coastguard Worker 	return true;
258*2d1272b8SAndroid Build Coastguard Worker       }
259*2d1272b8SAndroid Build Coastguard Worker       else if (flags & WE_HAVE_A_TWO_BY_TWO)
260*2d1272b8SAndroid Build Coastguard Worker       {
261*2d1272b8SAndroid Build Coastguard Worker 	matrix[0] = points[0].to_float ();
262*2d1272b8SAndroid Build Coastguard Worker 	matrix[1] = points[1].to_float ();
263*2d1272b8SAndroid Build Coastguard Worker 	matrix[2] = points[2].to_float ();
264*2d1272b8SAndroid Build Coastguard Worker 	matrix[3] = points[3].to_float ();
265*2d1272b8SAndroid Build Coastguard Worker 	return true;
266*2d1272b8SAndroid Build Coastguard Worker       }
267*2d1272b8SAndroid Build Coastguard Worker     }
268*2d1272b8SAndroid Build Coastguard Worker     return tx || ty;
269*2d1272b8SAndroid Build Coastguard Worker   }
270*2d1272b8SAndroid Build Coastguard Worker 
get_gidOT::glyf_impl::CompositeGlyphRecord271*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t get_gid () const
272*2d1272b8SAndroid Build Coastguard Worker   {
273*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
274*2d1272b8SAndroid Build Coastguard Worker     if (flags & GID_IS_24BIT)
275*2d1272b8SAndroid Build Coastguard Worker       return StructAfter<const HBGlyphID24> (flags);
276*2d1272b8SAndroid Build Coastguard Worker     else
277*2d1272b8SAndroid Build Coastguard Worker #endif
278*2d1272b8SAndroid Build Coastguard Worker       return StructAfter<const HBGlyphID16> (flags);
279*2d1272b8SAndroid Build Coastguard Worker   }
set_gidOT::glyf_impl::CompositeGlyphRecord280*2d1272b8SAndroid Build Coastguard Worker   void set_gid (hb_codepoint_t gid)
281*2d1272b8SAndroid Build Coastguard Worker   {
282*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
283*2d1272b8SAndroid Build Coastguard Worker     if (flags & GID_IS_24BIT)
284*2d1272b8SAndroid Build Coastguard Worker       StructAfter<HBGlyphID24> (flags) = gid;
285*2d1272b8SAndroid Build Coastguard Worker     else
286*2d1272b8SAndroid Build Coastguard Worker #endif
287*2d1272b8SAndroid Build Coastguard Worker       /* TODO assert? */
288*2d1272b8SAndroid Build Coastguard Worker       StructAfter<HBGlyphID16> (flags) = gid;
289*2d1272b8SAndroid Build Coastguard Worker   }
290*2d1272b8SAndroid Build Coastguard Worker 
291*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K
lower_gid_24_to_16OT::glyf_impl::CompositeGlyphRecord292*2d1272b8SAndroid Build Coastguard Worker   void lower_gid_24_to_16 ()
293*2d1272b8SAndroid Build Coastguard Worker   {
294*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t gid = get_gid ();
295*2d1272b8SAndroid Build Coastguard Worker     if (!(flags & GID_IS_24BIT) || gid > 0xFFFFu)
296*2d1272b8SAndroid Build Coastguard Worker       return;
297*2d1272b8SAndroid Build Coastguard Worker 
298*2d1272b8SAndroid Build Coastguard Worker     /* Lower the flag and move the rest of the struct down. */
299*2d1272b8SAndroid Build Coastguard Worker 
300*2d1272b8SAndroid Build Coastguard Worker     unsigned size = get_size ();
301*2d1272b8SAndroid Build Coastguard Worker     char *end = (char *) this + size;
302*2d1272b8SAndroid Build Coastguard Worker     char *p = &StructAfter<char> (flags);
303*2d1272b8SAndroid Build Coastguard Worker     p += HBGlyphID24::static_size;
304*2d1272b8SAndroid Build Coastguard Worker 
305*2d1272b8SAndroid Build Coastguard Worker     flags = flags & ~GID_IS_24BIT;
306*2d1272b8SAndroid Build Coastguard Worker     set_gid (gid);
307*2d1272b8SAndroid Build Coastguard Worker 
308*2d1272b8SAndroid Build Coastguard Worker     memmove (p - HBGlyphID24::static_size + HBGlyphID16::static_size, p, end - p);
309*2d1272b8SAndroid Build Coastguard Worker   }
310*2d1272b8SAndroid Build Coastguard Worker #endif
311*2d1272b8SAndroid Build Coastguard Worker 
312*2d1272b8SAndroid Build Coastguard Worker   protected:
313*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	flags;
314*2d1272b8SAndroid Build Coastguard Worker   HBUINT24	pad;
315*2d1272b8SAndroid Build Coastguard Worker   public:
316*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (4);
317*2d1272b8SAndroid Build Coastguard Worker };
318*2d1272b8SAndroid Build Coastguard Worker 
319*2d1272b8SAndroid Build Coastguard Worker using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>;
320*2d1272b8SAndroid Build Coastguard Worker 
321*2d1272b8SAndroid Build Coastguard Worker struct CompositeGlyph
322*2d1272b8SAndroid Build Coastguard Worker {
323*2d1272b8SAndroid Build Coastguard Worker   const GlyphHeader &header;
324*2d1272b8SAndroid Build Coastguard Worker   hb_bytes_t bytes;
CompositeGlyphOT::glyf_impl::CompositeGlyph325*2d1272b8SAndroid Build Coastguard Worker   CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
326*2d1272b8SAndroid Build Coastguard Worker     header (header_), bytes (bytes_) {}
327*2d1272b8SAndroid Build Coastguard Worker 
iterOT::glyf_impl::CompositeGlyph328*2d1272b8SAndroid Build Coastguard Worker   composite_iter_t iter () const
329*2d1272b8SAndroid Build Coastguard Worker   { return composite_iter_t (bytes, &StructAfter<CompositeGlyphRecord, GlyphHeader> (header)); }
330*2d1272b8SAndroid Build Coastguard Worker 
instructions_lengthOT::glyf_impl::CompositeGlyph331*2d1272b8SAndroid Build Coastguard Worker   unsigned int instructions_length (hb_bytes_t bytes) const
332*2d1272b8SAndroid Build Coastguard Worker   {
333*2d1272b8SAndroid Build Coastguard Worker     unsigned int start = bytes.length;
334*2d1272b8SAndroid Build Coastguard Worker     unsigned int end = bytes.length;
335*2d1272b8SAndroid Build Coastguard Worker     const CompositeGlyphRecord *last = nullptr;
336*2d1272b8SAndroid Build Coastguard Worker     for (auto &item : iter ())
337*2d1272b8SAndroid Build Coastguard Worker       last = &item;
338*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!last)) return 0;
339*2d1272b8SAndroid Build Coastguard Worker 
340*2d1272b8SAndroid Build Coastguard Worker     if (last->has_instructions ())
341*2d1272b8SAndroid Build Coastguard Worker       start = (char *) last - &bytes + last->get_size ();
342*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (start > end)) return 0;
343*2d1272b8SAndroid Build Coastguard Worker     return end - start;
344*2d1272b8SAndroid Build Coastguard Worker   }
345*2d1272b8SAndroid Build Coastguard Worker 
346*2d1272b8SAndroid Build Coastguard Worker   /* Trimming for composites not implemented.
347*2d1272b8SAndroid Build Coastguard Worker    * If removing hints it falls out of that. */
trim_paddingOT::glyf_impl::CompositeGlyph348*2d1272b8SAndroid Build Coastguard Worker   const hb_bytes_t trim_padding () const { return bytes; }
349*2d1272b8SAndroid Build Coastguard Worker 
drop_hintsOT::glyf_impl::CompositeGlyph350*2d1272b8SAndroid Build Coastguard Worker   void drop_hints ()
351*2d1272b8SAndroid Build Coastguard Worker   {
352*2d1272b8SAndroid Build Coastguard Worker     for (const auto &_ : iter ())
353*2d1272b8SAndroid Build Coastguard Worker       const_cast<CompositeGlyphRecord &> (_).drop_instructions_flag ();
354*2d1272b8SAndroid Build Coastguard Worker   }
355*2d1272b8SAndroid Build Coastguard Worker 
356*2d1272b8SAndroid Build Coastguard Worker   /* Chop instructions off the end */
drop_hints_bytesOT::glyf_impl::CompositeGlyph357*2d1272b8SAndroid Build Coastguard Worker   void drop_hints_bytes (hb_bytes_t &dest_start) const
358*2d1272b8SAndroid Build Coastguard Worker   { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
359*2d1272b8SAndroid Build Coastguard Worker 
set_overlaps_flagOT::glyf_impl::CompositeGlyph360*2d1272b8SAndroid Build Coastguard Worker   void set_overlaps_flag ()
361*2d1272b8SAndroid Build Coastguard Worker   {
362*2d1272b8SAndroid Build Coastguard Worker     CompositeGlyphRecord& glyph_chain = const_cast<CompositeGlyphRecord &> (
363*2d1272b8SAndroid Build Coastguard Worker 	StructAfter<CompositeGlyphRecord, GlyphHeader> (header));
364*2d1272b8SAndroid Build Coastguard Worker     if (!bytes.check_range(&glyph_chain, CompositeGlyphRecord::min_size))
365*2d1272b8SAndroid Build Coastguard Worker       return;
366*2d1272b8SAndroid Build Coastguard Worker     glyph_chain.set_overlaps_flag ();
367*2d1272b8SAndroid Build Coastguard Worker   }
368*2d1272b8SAndroid Build Coastguard Worker 
compile_bytes_with_deltasOT::glyf_impl::CompositeGlyph369*2d1272b8SAndroid Build Coastguard Worker   bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
370*2d1272b8SAndroid Build Coastguard Worker                                   const contour_point_vector_t &points_with_deltas,
371*2d1272b8SAndroid Build Coastguard Worker                                   hb_bytes_t &dest_bytes /* OUT */)
372*2d1272b8SAndroid Build Coastguard Worker   {
373*2d1272b8SAndroid Build Coastguard Worker     if (source_bytes.length <= GlyphHeader::static_size ||
374*2d1272b8SAndroid Build Coastguard Worker         header.numberOfContours != -1)
375*2d1272b8SAndroid Build Coastguard Worker     {
376*2d1272b8SAndroid Build Coastguard Worker       dest_bytes = hb_bytes_t ();
377*2d1272b8SAndroid Build Coastguard Worker       return true;
378*2d1272b8SAndroid Build Coastguard Worker     }
379*2d1272b8SAndroid Build Coastguard Worker 
380*2d1272b8SAndroid Build Coastguard Worker     unsigned source_len = source_bytes.length - GlyphHeader::static_size;
381*2d1272b8SAndroid Build Coastguard Worker 
382*2d1272b8SAndroid Build Coastguard Worker     /* try to allocate more memories than source glyph bytes
383*2d1272b8SAndroid Build Coastguard Worker      * in case that there might be an overflow for int8 value
384*2d1272b8SAndroid Build Coastguard Worker      * and we would need to use int16 instead */
385*2d1272b8SAndroid Build Coastguard Worker     char *o = (char *) hb_calloc (source_len * 2, sizeof (char));
386*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!o)) return false;
387*2d1272b8SAndroid Build Coastguard Worker 
388*2d1272b8SAndroid Build Coastguard Worker     const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
389*2d1272b8SAndroid Build Coastguard Worker     auto it = composite_iter_t (hb_bytes_t ((const char *)c, source_len), c);
390*2d1272b8SAndroid Build Coastguard Worker 
391*2d1272b8SAndroid Build Coastguard Worker     char *p = o;
392*2d1272b8SAndroid Build Coastguard Worker     unsigned i = 0, source_comp_len = 0;
393*2d1272b8SAndroid Build Coastguard Worker     for (const auto &component : it)
394*2d1272b8SAndroid Build Coastguard Worker     {
395*2d1272b8SAndroid Build Coastguard Worker       /* last 4 points in points_with_deltas are phantom points and should not be included */
396*2d1272b8SAndroid Build Coastguard Worker       if (i >= points_with_deltas.length - 4) {
397*2d1272b8SAndroid Build Coastguard Worker         hb_free (o);
398*2d1272b8SAndroid Build Coastguard Worker         return false;
399*2d1272b8SAndroid Build Coastguard Worker       }
400*2d1272b8SAndroid Build Coastguard Worker 
401*2d1272b8SAndroid Build Coastguard Worker       unsigned comp_len = component.get_size ();
402*2d1272b8SAndroid Build Coastguard Worker       if (component.is_anchored ())
403*2d1272b8SAndroid Build Coastguard Worker       {
404*2d1272b8SAndroid Build Coastguard Worker         hb_memcpy (p, &component, comp_len);
405*2d1272b8SAndroid Build Coastguard Worker         p += comp_len;
406*2d1272b8SAndroid Build Coastguard Worker       }
407*2d1272b8SAndroid Build Coastguard Worker       else
408*2d1272b8SAndroid Build Coastguard Worker       {
409*2d1272b8SAndroid Build Coastguard Worker         unsigned new_len = component.compile_with_point (points_with_deltas[i], p);
410*2d1272b8SAndroid Build Coastguard Worker         p += new_len;
411*2d1272b8SAndroid Build Coastguard Worker       }
412*2d1272b8SAndroid Build Coastguard Worker       i++;
413*2d1272b8SAndroid Build Coastguard Worker       source_comp_len += comp_len;
414*2d1272b8SAndroid Build Coastguard Worker     }
415*2d1272b8SAndroid Build Coastguard Worker 
416*2d1272b8SAndroid Build Coastguard Worker     //copy instructions if any
417*2d1272b8SAndroid Build Coastguard Worker     if (source_len > source_comp_len)
418*2d1272b8SAndroid Build Coastguard Worker     {
419*2d1272b8SAndroid Build Coastguard Worker       unsigned instr_len = source_len - source_comp_len;
420*2d1272b8SAndroid Build Coastguard Worker       hb_memcpy (p, (const char *)c + source_comp_len, instr_len);
421*2d1272b8SAndroid Build Coastguard Worker       p += instr_len;
422*2d1272b8SAndroid Build Coastguard Worker     }
423*2d1272b8SAndroid Build Coastguard Worker 
424*2d1272b8SAndroid Build Coastguard Worker     unsigned len = p - o;
425*2d1272b8SAndroid Build Coastguard Worker     dest_bytes = hb_bytes_t (o, len);
426*2d1272b8SAndroid Build Coastguard Worker     return true;
427*2d1272b8SAndroid Build Coastguard Worker   }
428*2d1272b8SAndroid Build Coastguard Worker };
429*2d1272b8SAndroid Build Coastguard Worker 
430*2d1272b8SAndroid Build Coastguard Worker 
431*2d1272b8SAndroid Build Coastguard Worker } /* namespace glyf_impl */
432*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */
433*2d1272b8SAndroid Build Coastguard Worker 
434*2d1272b8SAndroid Build Coastguard Worker 
435*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_COMPOSITEGLYPH_HH */
436