Skip to content

Commit a28fb47

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

File tree

1 file changed

+38
-63
lines changed

1 file changed

+38
-63
lines changed

src/ft2font.cpp

+38-63
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,21 @@ 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+
};
280265
if (FT_Error error = FT_Outline_Decompose(
281266
&face->glyph->outline, &ft_outline_funcs, &decomposer)) {
282267
throw std::runtime_error("FT_Outline_Decompose failed with error " +
283268
std::to_string(error));
284269
}
285-
if (!decomposer.index) { // Don't append CLOSEPOLY to null glyphs.
270+
if (vertices.empty()) { // Don't append CLOSEPOLY to null glyphs.
286271
return;
287272
}
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;
273+
vertices.push_back(0);
274+
vertices.push_back(0);
275+
codes.push_back(CLOSEPOLY);
301276
}
302277

303278
FT2Font::FT2Font(FT_Open_Args &open_args,

0 commit comments

Comments
 (0)