RIP, Vernon...
[ttfautohint.git] / lib / tagloadr.c
blob8232a77beaa13a6d9d62a00d6b19d542de1a14d5
1 /* tagloadr.c */
3 /*
4 * Copyright (C) 2011-2016 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 = (FT_UInt)base->n_points + (FT_UInt)current->n_points
193 + n_points;
194 old_max = loader->max_points;
196 if (new_max > old_max)
198 FT_Vector* points_new;
199 char* tags_new;
202 new_max = TA_PAD_CEIL(new_max, 8);
204 if (new_max > FT_OUTLINE_POINTS_MAX)
205 return FT_Err_Array_Too_Large;
207 points_new = (FT_Vector*)realloc(base->points,
208 new_max * sizeof (FT_Vector));
209 if (!points_new)
210 return FT_Err_Out_Of_Memory;
211 base->points = points_new;
213 tags_new = (char*)realloc(base->tags,
214 new_max * sizeof (char));
215 if (!tags_new)
216 return FT_Err_Out_Of_Memory;
217 base->tags = tags_new;
219 if (loader->use_extra)
221 FT_Vector* extra_points_new;
224 extra_points_new =
225 (FT_Vector*)realloc(loader->base.extra_points,
226 new_max * 2 * sizeof (FT_Vector));
227 if (!extra_points_new)
228 return FT_Err_Out_Of_Memory;
229 loader->base.extra_points = extra_points_new;
231 memmove(loader->base.extra_points + new_max,
232 loader->base.extra_points + old_max,
233 old_max * sizeof (FT_Vector));
235 loader->base.extra_points2 = loader->base.extra_points + new_max;
238 adjust = 1;
239 loader->max_points = new_max;
242 /* check contours */
243 old_max = loader->max_contours;
244 new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours
245 + n_contours;
246 if (new_max > old_max)
248 short* contours_new;
251 new_max = TA_PAD_CEIL(new_max, 4);
253 if (new_max > FT_OUTLINE_CONTOURS_MAX)
254 return FT_Err_Array_Too_Large;
256 contours_new = (short*)realloc(base->contours,
257 new_max * sizeof (short));
258 if (!contours_new)
259 return FT_Err_Out_Of_Memory;
260 base->contours = contours_new;
262 adjust = 1;
263 loader->max_contours = new_max;
266 if (adjust)
267 TA_GlyphLoader_Adjust_Points(loader);
269 return FT_Err_Ok;
273 /* ensure that we can add `n_subglyphs' to our glyph -- */
274 /* this function reallocates its subglyphs table if necessary, */
275 /* but it DOES NOT change the number of subglyphs within the loader */
276 FT_Error
277 TA_GlyphLoader_CheckSubGlyphs(TA_GlyphLoader loader,
278 FT_UInt n_subs)
280 FT_UInt new_max, old_max;
282 TA_GlyphLoad base = &loader->base;
283 TA_GlyphLoad current = &loader->current;
286 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
287 old_max = loader->max_subglyphs;
288 if (new_max > old_max)
290 TA_SubGlyph subglyphs_new;
293 new_max = TA_PAD_CEIL(new_max, 2);
294 subglyphs_new = (TA_SubGlyph)realloc(base->subglyphs,
295 new_max * sizeof (TA_SubGlyphRec));
296 if (!subglyphs_new)
297 return FT_Err_Out_Of_Memory;
298 base->subglyphs = subglyphs_new;
300 loader->max_subglyphs = new_max;
302 TA_GlyphLoader_Adjust_Subglyphs(loader);
305 return FT_Err_Ok;
309 /* prepare loader for the addition of a new glyph on top of the base one */
310 void
311 TA_GlyphLoader_Prepare(TA_GlyphLoader loader)
313 TA_GlyphLoad current = &loader->current;
316 current->outline.n_points = 0;
317 current->outline.n_contours = 0;
318 current->num_subglyphs = 0;
320 TA_GlyphLoader_Adjust_Points (loader);
321 TA_GlyphLoader_Adjust_Subglyphs(loader);
325 /* add current glyph to the base image -- and prepare for another */
326 void
327 TA_GlyphLoader_Add(TA_GlyphLoader loader)
329 TA_GlyphLoad base;
330 TA_GlyphLoad current;
332 FT_Int n_curr_contours;
333 FT_Int n_base_points;
334 FT_Int n;
337 if (!loader)
338 return;
340 base = &loader->base;
341 current = &loader->current;
343 n_curr_contours = current->outline.n_contours;
344 n_base_points = base->outline.n_points;
346 base->outline.n_points =
347 (short)(base->outline.n_points + current->outline.n_points);
348 base->outline.n_contours =
349 (short)(base->outline.n_contours + current->outline.n_contours);
351 base->num_subglyphs += current->num_subglyphs;
353 /* adjust contours count in newest outline */
354 for (n = 0; n < n_curr_contours; n++)
355 current->outline.contours[n] =
356 (short)(current->outline.contours[n] + n_base_points);
358 /* prepare for another new glyph image */
359 TA_GlyphLoader_Prepare(loader);
363 FT_Error
364 TA_GlyphLoader_CopyPoints(TA_GlyphLoader target,
365 TA_GlyphLoader source)
367 FT_Error error;
368 FT_UInt num_points = (FT_UInt)source->base.outline.n_points;
369 FT_UInt num_contours = (FT_UInt)source->base.outline.n_contours;
372 error = TA_GlyphLoader_CheckPoints(target, num_points, num_contours);
373 if (!error)
375 FT_Outline* out = &target->base.outline;
376 FT_Outline* in = &source->base.outline;
379 memcpy(out->points, in->points, num_points * sizeof (FT_Vector));
380 memcpy(out->contours, in->contours, num_contours * sizeof (short));
381 memcpy(out->tags, in->tags, num_points * sizeof (char));
383 /* do we need to copy the extra points? */
384 if (target->use_extra && source->use_extra)
386 memcpy(target->base.extra_points, source->base.extra_points,
387 num_points * sizeof (FT_Vector));
388 memcpy(target->base.extra_points2, source->base.extra_points2,
389 num_points * sizeof (FT_Vector));
392 out->n_points = (short)num_points;
393 out->n_contours = (short)num_contours;
395 TA_GlyphLoader_Adjust_Points(target);
398 return error;
401 /* end of tagloadr.c */