@@ -183,64 +183,49 @@ FT2Image::draw_rect_filled(unsigned long x0, unsigned long y0, unsigned long x1,
183183 m_dirty = true ;
184184}
185185
186- // ft_outline_decomposer should be passed to FT_Outline_Decompose. On the
187- // first pass, vertices and codes are set to NULL, and index is simply
188- // incremented for each vertex that should be inserted, so that it is set, at
189- // the end, to the total number of vertices. On a second pass, vertices and
190- // codes should point to correctly sized arrays, and index set again to zero,
191- // to get fill vertices and codes with the outline decomposition.
186+ // ft_outline_decomposer should be passed to FT_Outline_Decompose.
192187struct ft_outline_decomposer
193188{
194- int index;
195- double * vertices;
196- unsigned char * codes;
189+ std::vector<double > &vertices;
190+ std::vector<unsigned char > &codes;
197191};
198192
199193static int
200194ft_outline_move_to (FT_Vector const * to, void * user)
201195{
202196 ft_outline_decomposer* d = reinterpret_cast <ft_outline_decomposer*>(user);
203- if (d->codes ) {
204- if (d->index ) {
205- // Appending CLOSEPOLY is important to make patheffects work.
206- *(d->vertices ++) = 0 ;
207- *(d->vertices ++) = 0 ;
208- *(d->codes ++) = CLOSEPOLY;
209- }
210- *(d->vertices ++) = to->x * (1 . / 64 .);
211- *(d->vertices ++) = to->y * (1 . / 64 .);
212- *(d->codes ++) = MOVETO;
213- }
214- d->index += d->index ? 2 : 1 ;
197+ if (!d->vertices .empty ()) {
198+ // Appending CLOSEPOLY is important to make patheffects work.
199+ d->vertices .push_back (0 );
200+ d->vertices .push_back (0 );
201+ d->codes .push_back (CLOSEPOLY);
202+ }
203+ d->vertices .push_back (to->x * (1 . / 64 .));
204+ d->vertices .push_back (to->y * (1 . / 64 .));
205+ d->codes .push_back (MOVETO);
215206 return 0 ;
216207}
217208
218209static int
219210ft_outline_line_to (FT_Vector const * to, void * user)
220211{
221212 ft_outline_decomposer* d = reinterpret_cast <ft_outline_decomposer*>(user);
222- if (d->codes ) {
223- *(d->vertices ++) = to->x * (1 . / 64 .);
224- *(d->vertices ++) = to->y * (1 . / 64 .);
225- *(d->codes ++) = LINETO;
226- }
227- d->index ++;
213+ d->vertices .push_back (to->x * (1 . / 64 .));
214+ d->vertices .push_back (to->y * (1 . / 64 .));
215+ d->codes .push_back (LINETO);
228216 return 0 ;
229217}
230218
231219static int
232220ft_outline_conic_to (FT_Vector const * control, FT_Vector const * to, void * user)
233221{
234222 ft_outline_decomposer* d = reinterpret_cast <ft_outline_decomposer*>(user);
235- if (d->codes ) {
236- *(d->vertices ++) = control->x * (1 . / 64 .);
237- *(d->vertices ++) = control->y * (1 . / 64 .);
238- *(d->vertices ++) = to->x * (1 . / 64 .);
239- *(d->vertices ++) = to->y * (1 . / 64 .);
240- *(d->codes ++) = CURVE3;
241- *(d->codes ++) = CURVE3;
242- }
243- d->index += 2 ;
223+ d->vertices .push_back (control->x * (1 . / 64 .));
224+ d->vertices .push_back (control->y * (1 . / 64 .));
225+ d->vertices .push_back (to->x * (1 . / 64 .));
226+ d->vertices .push_back (to->y * (1 . / 64 .));
227+ d->codes .push_back (CURVE3);
228+ d->codes .push_back (CURVE3);
244229 return 0 ;
245230}
246231
@@ -249,18 +234,15 @@ ft_outline_cubic_to(
249234 FT_Vector const * c1, FT_Vector const * c2, FT_Vector const * to, void * user)
250235{
251236 ft_outline_decomposer* d = reinterpret_cast <ft_outline_decomposer*>(user);
252- if (d->codes ) {
253- *(d->vertices ++) = c1->x * (1 . / 64 .);
254- *(d->vertices ++) = c1->y * (1 . / 64 .);
255- *(d->vertices ++) = c2->x * (1 . / 64 .);
256- *(d->vertices ++) = c2->y * (1 . / 64 .);
257- *(d->vertices ++) = to->x * (1 . / 64 .);
258- *(d->vertices ++) = to->y * (1 . / 64 .);
259- *(d->codes ++) = CURVE4;
260- *(d->codes ++) = CURVE4;
261- *(d->codes ++) = CURVE4;
262- }
263- d->index += 3 ;
237+ d->vertices .push_back (c1->x * (1 . / 64 .));
238+ d->vertices .push_back (c1->y * (1 . / 64 .));
239+ d->vertices .push_back (c2->x * (1 . / 64 .));
240+ d->vertices .push_back (c2->y * (1 . / 64 .));
241+ d->vertices .push_back (to->x * (1 . / 64 .));
242+ d->vertices .push_back (to->y * (1 . / 64 .));
243+ d->codes .push_back (CURVE4);
244+ d->codes .push_back (CURVE4);
245+ d->codes .push_back (CURVE4);
264246 return 0 ;
265247}
266248
@@ -276,28 +258,28 @@ FT2Font::get_path(std::vector<double> &vertices, std::vector<unsigned char> &cod
276258 if (!face->glyph ) {
277259 throw std::runtime_error (" No glyph loaded" );
278260 }
279- ft_outline_decomposer decomposer = {};
261+ ft_outline_decomposer decomposer = {
262+ vertices,
263+ codes,
264+ };
265+ // We can make a close-enough estimate based on number of points and number of
266+ // contours (which produce a MOVETO each), though it's slightly underestimating due
267+ // to higher-order curves.
268+ size_t estimated_points = static_cast <size_t >(face->glyph ->outline .n_contours ) +
269+ static_cast <size_t >(face->glyph ->outline .n_points );
270+ vertices.reserve (2 * estimated_points);
271+ codes.reserve (estimated_points);
280272 if (FT_Error error = FT_Outline_Decompose (
281273 &face->glyph ->outline , &ft_outline_funcs, &decomposer)) {
282274 throw std::runtime_error (" FT_Outline_Decompose failed with error " +
283275 std::to_string (error));
284276 }
285- if (!decomposer. index ) { // Don't append CLOSEPOLY to null glyphs.
277+ if (vertices. empty () ) { // Don't append CLOSEPOLY to null glyphs.
286278 return ;
287279 }
288- vertices.resize ((decomposer.index + 1 ) * 2 );
289- codes.resize (decomposer.index + 1 );
290- decomposer.index = 0 ;
291- decomposer.vertices = vertices.data ();
292- decomposer.codes = codes.data ();
293- if (FT_Error error = FT_Outline_Decompose (
294- &face->glyph ->outline , &ft_outline_funcs, &decomposer)) {
295- throw std::runtime_error (" FT_Outline_Decompose failed with error " +
296- std::to_string (error));
297- }
298- *(decomposer.vertices ++) = 0 ;
299- *(decomposer.vertices ++) = 0 ;
300- *(decomposer.codes ++) = CLOSEPOLY;
280+ vertices.push_back (0 );
281+ vertices.push_back (0 );
282+ codes.push_back (CLOSEPOLY);
301283}
302284
303285FT2Font::FT2Font (FT_Open_Args &open_args,
0 commit comments