Use `Control_Type' to handle different segment directions.
[ttfautohint.git] / lib / tagloadr.c
blob9d19248da045a29fcb8d2562f0c82e007ec34e14
1 /* tagloadr.c */
3 /*
4 * Copyright (C) 2011-2014 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
16 /* originally file `ftgloadr.c' (2011-Mar-28) from FreeType */
18 /* heavily modified 2011 by Werner Lemberg <wl@gnu.org> */
20 #include <stdlib.h>
21 #include <string.h>
23 #include "tatypes.h"
24 #include "tagloadr.h"
27 /*************************************************************************/
28 /* */
29 /* The glyph loader is a simple object which is used to load a set of */
30 /* glyphs easily. It is critical for the correct loading of composites. */
31 /* */
32 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
33 /* */
34 /* loader.base Is really the bottom of the stack. It describes a */
35 /* single glyph image made of the juxtaposition of */
36 /* several glyphs (those `in the stack'). */
37 /* */
38 /* loader.current Describes the top of the stack, on which a new */
39 /* glyph can be loaded. */
40 /* */
41 /* Rewind Clears the stack. */
42 /* Prepare Set up `loader.current' for addition of a new glyph */
43 /* image. */
44 /* Add Add the `current' glyph image to the `base' one, */
45 /* and prepare for another one. */
46 /* */
47 /*************************************************************************/
50 /* create a new glyph loader */
51 FT_Error
52 TA_GlyphLoader_New(TA_GlyphLoader *aloader)
54 TA_GlyphLoader loader;
57 loader = (TA_GlyphLoader)calloc(1, sizeof (TA_GlyphLoaderRec));
59 if (!loader)
60 return FT_Err_Out_Of_Memory;
62 *aloader = loader;
63 return FT_Err_Ok;
67 /* rewind the glyph loader - reset counters to 0 */
68 void
69 TA_GlyphLoader_Rewind(TA_GlyphLoader loader)
71 TA_GlyphLoad base = &loader->base;
72 TA_GlyphLoad current = &loader->current;
75 base->outline.n_points = 0;
76 base->outline.n_contours = 0;
77 base->num_subglyphs = 0;
79 *current = *base;
83 /* reset the glyph loader, frees all allocated tables */
84 /* and starts from zero */
85 void
86 TA_GlyphLoader_Reset(TA_GlyphLoader loader)
88 free(loader->base.outline.points);
89 free(loader->base.outline.tags);
90 free(loader->base.outline.contours);
91 free(loader->base.extra_points);
92 free(loader->base.subglyphs);
94 loader->base.outline.points = NULL;
95 loader->base.outline.tags = NULL;
96 loader->base.outline.contours = NULL;
97 loader->base.extra_points = NULL;
98 loader->base.subglyphs = NULL;
100 loader->base.extra_points2 = NULL;
102 loader->max_points = 0;
103 loader->max_contours = 0;
104 loader->max_subglyphs = 0;
106 TA_GlyphLoader_Rewind(loader);
110 /* delete a glyph loader */
111 void
112 TA_GlyphLoader_Done(TA_GlyphLoader loader)
114 if (loader)
116 TA_GlyphLoader_Reset(loader);
117 free(loader);
122 /* re-adjust the `current' outline fields */
123 static void
124 TA_GlyphLoader_Adjust_Points(TA_GlyphLoader loader)
126 FT_Outline* base = &loader->base.outline;
127 FT_Outline* current = &loader->current.outline;
130 current->points = base->points + base->n_points;
131 current->tags = base->tags + base->n_points;
132 current->contours = base->contours + base->n_contours;
134 /* handle extra points table - if any */
135 if (loader->use_extra)
137 loader->current.extra_points = loader->base.extra_points
138 + base->n_points;
140 loader->current.extra_points2 = loader->base.extra_points2
141 + base->n_points;
146 FT_Error
147 TA_GlyphLoader_CreateExtra(TA_GlyphLoader loader)
149 loader->base.extra_points =
150 (FT_Vector*)calloc(1, 2 * loader->max_points * sizeof (FT_Vector));
151 if (!loader->base.extra_points)
152 return FT_Err_Out_Of_Memory;
154 loader->use_extra = 1;
155 loader->base.extra_points2 = loader->base.extra_points
156 + loader->max_points;
158 TA_GlyphLoader_Adjust_Points(loader);
160 return FT_Err_Ok;
164 /* re-adjust the `current' subglyphs field */
165 static void
166 TA_GlyphLoader_Adjust_Subglyphs(TA_GlyphLoader loader)
168 TA_GlyphLoad base = &loader->base;
169 TA_GlyphLoad current = &loader->current;
172 current->subglyphs = base->subglyphs + base->num_subglyphs;
176 /* ensure that we can add `n_points' and `n_contours' to our glyph -- */
177 /* this function reallocates its outline tables if necessary, */
178 /* but it DOESN'T change the number of points within the loader */
179 FT_Error
180 TA_GlyphLoader_CheckPoints(TA_GlyphLoader loader,
181 FT_UInt n_points,
182 FT_UInt n_contours)
184 FT_Outline* base = &loader->base.outline;
185 FT_Outline* current = &loader->current.outline;
186 FT_Bool adjust = 0;
188 FT_UInt new_max, old_max;
191 /* check points & tags */
192 new_max = base->n_points + current->n_points + n_points;
193 old_max = loader->max_points;
195 if (new_max > old_max)
197 FT_Vector* points_new;
198 char* tags_new;
201 new_max = TA_PAD_CEIL(new_max, 8);
203 if (new_max > FT_OUTLINE_POINTS_MAX)
204 return FT_Err_Array_Too_Large;
206 points_new = (FT_Vector*)realloc(base->points,
207 new_max * sizeof (FT_Vector));
208 if (!points_new)
209 return FT_Err_Out_Of_Memory;
210 base->points = points_new;
212 tags_new = (char*)realloc(base->tags,
213 new_max * sizeof (char));
214 if (!tags_new)
215 return FT_Err_Out_Of_Memory;
216 base->tags = tags_new;
218 if (loader->use_extra)
220 FT_Vector* extra_points_new;
223 extra_points_new =
224 (FT_Vector*)realloc(loader->base.extra_points,
225 new_max * 2 * sizeof (FT_Vector));
226 if (!extra_points_new)
227 return FT_Err_Out_Of_Memory;
228 loader->base.extra_points = extra_points_new;
230 memmove(loader->base.extra_points + new_max,
231 loader->base.extra_points + old_max,
232 old_max * sizeof (FT_Vector));
234 loader->base.extra_points2 = loader->base.extra_points + new_max;
237 adjust = 1;
238 loader->max_points = new_max;
241 /* check contours */
242 old_max = loader->max_contours;
243 new_max = base->n_contours + current->n_contours + n_contours;
244 if (new_max > old_max)
246 short* contours_new;
249 new_max = TA_PAD_CEIL(new_max, 4);
251 if (new_max > FT_OUTLINE_CONTOURS_MAX)
252 return FT_Err_Array_Too_Large;
254 contours_new = (short*)realloc(base->contours,
255 new_max * sizeof (short));
256 if (!contours_new)
257 return FT_Err_Out_Of_Memory;
258 base->contours = contours_new;
260 adjust = 1;
261 loader->max_contours = new_max;
264 if (adjust)
265 TA_GlyphLoader_Adjust_Points(loader);
267 return FT_Err_Ok;
271 /* ensure that we can add `n_subglyphs' to our glyph -- */
272 /* this function reallocates its subglyphs table if necessary, */
273 /* but it DOES NOT change the number of subglyphs within the loader */
274 FT_Error
275 TA_GlyphLoader_CheckSubGlyphs(TA_GlyphLoader loader,
276 FT_UInt n_subs)
278 FT_UInt new_max, old_max;
280 TA_GlyphLoad base = &loader->base;
281 TA_GlyphLoad current = &loader->current;
284 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
285 old_max = loader->max_subglyphs;
286 if (new_max > old_max)
288 TA_SubGlyph subglyphs_new;
291 new_max = TA_PAD_CEIL(new_max, 2);
292 subglyphs_new = (TA_SubGlyph)realloc(base->subglyphs,
293 new_max * sizeof (TA_SubGlyphRec));
294 if (!subglyphs_new)
295 return FT_Err_Out_Of_Memory;
296 base->subglyphs = subglyphs_new;
298 loader->max_subglyphs = new_max;
300 TA_GlyphLoader_Adjust_Subglyphs(loader);
303 return FT_Err_Ok;
307 /* prepare loader for the addition of a new glyph on top of the base one */
308 void
309 TA_GlyphLoader_Prepare(TA_GlyphLoader loader)
311 TA_GlyphLoad current = &loader->current;
314 current->outline.n_points = 0;
315 current->outline.n_contours = 0;
316 current->num_subglyphs = 0;
318 TA_GlyphLoader_Adjust_Points (loader);
319 TA_GlyphLoader_Adjust_Subglyphs(loader);
323 /* add current glyph to the base image -- and prepare for another */
324 void
325 TA_GlyphLoader_Add(TA_GlyphLoader loader)
327 TA_GlyphLoad base;
328 TA_GlyphLoad current;
330 FT_UInt n_curr_contours;
331 FT_UInt n_base_points;
332 FT_UInt n;
335 if (!loader)
336 return;
338 base = &loader->base;
339 current = &loader->current;
341 n_curr_contours = current->outline.n_contours;
342 n_base_points = base->outline.n_points;
344 base->outline.n_points =
345 (short)(base->outline.n_points + current->outline.n_points);
346 base->outline.n_contours =
347 (short)(base->outline.n_contours + current->outline.n_contours);
349 base->num_subglyphs += current->num_subglyphs;
351 /* adjust contours count in newest outline */
352 for (n = 0; n < n_curr_contours; n++)
353 current->outline.contours[n] =
354 (short)(current->outline.contours[n] + n_base_points);
356 /* prepare for another new glyph image */
357 TA_GlyphLoader_Prepare(loader);
361 FT_Error
362 TA_GlyphLoader_CopyPoints(TA_GlyphLoader target,
363 TA_GlyphLoader source)
365 FT_Error error;
366 FT_UInt num_points = source->base.outline.n_points;
367 FT_UInt num_contours = source->base.outline.n_contours;
370 error = TA_GlyphLoader_CheckPoints(target, num_points, num_contours);
371 if (!error)
373 FT_Outline* out = &target->base.outline;
374 FT_Outline* in = &source->base.outline;
377 memcpy(out->points, in->points, num_points * sizeof (FT_Vector));
378 memcpy(out->contours, in->contours, num_contours * sizeof (short));
379 memcpy(out->tags, in->tags, num_points * sizeof (char));
381 /* do we need to copy the extra points? */
382 if (target->use_extra && source->use_extra)
384 memcpy(target->base.extra_points, source->base.extra_points,
385 num_points * sizeof (FT_Vector));
386 memcpy(target->base.extra_points2, source->base.extra_points2,
387 num_points * sizeof (FT_Vector));
390 out->n_points = (short)num_points;
391 out->n_contours = (short)num_contours;
393 TA_GlyphLoader_Adjust_Points(target);
396 return error;
399 /* end of tagloadr.c */