Skip to content

Commit b97fc87

Browse files
committed
Use std::vector directly with FT_Outline_Decompose
This means we only need to do one pass through.
1 parent e3a608b commit b97fc87

File tree

1 file changed

+45
-63
lines changed

1 file changed

+45
-63
lines changed

src/ft2font.cpp

Lines changed: 45 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
192187
struct 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

199193
static int
200194
ft_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

218209
static int
219210
ft_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

231219
static int
232220
ft_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 = vertices,
263+
.codes = 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

303285
FT2Font::FT2Font(FT_Open_Args &open_args,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy