Fix OTS warning about `maxp.maxSizeOfInstructions`.
[ttfautohint.git] / lib / tagloadr.c
blob7bbb714ab593705db7c4188db5a9663e8d1ff89d
1 /* tagloadr.c */
3 /*
4 * Copyright (C) 2011-2022 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 #if 0
147 FT_Error
148 TA_GlyphLoader_CreateExtra(TA_GlyphLoader loader)
150 loader->base.extra_points =
151 (FT_Vector*)calloc(1, 2 * loader->max_points * sizeof (FT_Vector));
152 if (!loader->base.extra_points)
153 return FT_Err_Out_Of_Memory;
155 loader->use_extra = 1;
156 loader->base.extra_points2 = loader->base.extra_points
157 + loader->max_points;
159 TA_GlyphLoader_Adjust_Points(loader);
161 return FT_Err_Ok;
163 #endif
166 /* re-adjust the `current' subglyphs field */
167 static void
168 TA_GlyphLoader_Adjust_Subglyphs(TA_GlyphLoader loader)
170 TA_GlyphLoad base = &loader->base;
171 TA_GlyphLoad current = &loader->current;
174 current->subglyphs = base->subglyphs + base->num_subglyphs;
178 /* ensure that we can add `n_points' and `n_contours' to our glyph -- */
179 /* this function reallocates its outline tables if necessary, */
180 /* but it DOESN'T change the number of points within the loader */
181 FT_Error
182 TA_GlyphLoader_CheckPoints(TA_GlyphLoader loader,
183 FT_UInt n_points,
184 FT_UInt n_contours)
186 FT_Outline* base = &loader->base.outline;
187 FT_Outline* current = &loader->current.outline;
188 FT_Bool adjust = 0;
190 FT_UInt new_max, old_max;
193 /* check points & tags */
194 new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points
195 + n_points;
196 old_max = loader->max_points;
198 if (new_max > old_max)
200 FT_Vector* points_new;
201 char* tags_new;
204 new_max = TA_PAD_CEIL(new_max, 8);
206 if (new_max > FT_OUTLINE_POINTS_MAX)
207 return FT_Err_Array_Too_Large;
209 points_new = (FT_Vector*)realloc(base->points,
210 new_max * sizeof (FT_Vector));
211 if (!points_new)
212 return FT_Err_Out_Of_Memory;
213 base->points = points_new;
215 tags_new = (char*)realloc(base->tags,
216 new_max * sizeof (char));
217 if (!tags_new)
218 return FT_Err_Out_Of_Memory;
219 base->tags = tags_new;
221 if (loader->use_extra)
223 FT_Vector* extra_points_new;
226 extra_points_new =
227 (FT_Vector*)realloc(loader->base.extra_points,
228 new_max * 2 * sizeof (FT_Vector));
229 if (!extra_points_new)
230 return FT_Err_Out_Of_Memory;
231 loader->base.extra_points = extra_points_new;
233 memmove(loader->base.extra_points + new_max,
234 loader->base.extra_points + old_max,
235 old_max * sizeof (FT_Vector));
237 loader->base.extra_points2 = loader->base.extra_points + new_max;
240 adjust = 1;
241 loader->max_points = new_max;
244 /* check contours */
245 old_max = loader->max_contours;
246 new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours
247 + n_contours;
248 if (new_max > old_max)
250 short* contours_new;
253 new_max = TA_PAD_CEIL(new_max, 4);
255 if (new_max > FT_OUTLINE_CONTOURS_MAX)
256 return FT_Err_Array_Too_Large;
258 contours_new = (short*)realloc(base->contours,
259 new_max * sizeof (short));
260 if (!contours_new)
261 return FT_Err_Out_Of_Memory;
262 base->contours = contours_new;
264 adjust = 1;
265 loader->max_contours = new_max;
268 if (adjust)
269 TA_GlyphLoader_Adjust_Points(loader);
271 return FT_Err_Ok;
275 /* ensure that we can add `n_subglyphs' to our glyph -- */
276 /* this function reallocates its subglyphs table if necessary, */
277 /* but it DOES NOT change the number of subglyphs within the loader */
278 FT_Error
279 TA_GlyphLoader_CheckSubGlyphs(TA_GlyphLoader loader,
280 FT_UInt n_subs)
282 FT_UInt new_max, old_max;
284 TA_GlyphLoad base = &loader->base;
285 TA_GlyphLoad current = &loader->current;
288 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
289 old_max = loader->max_subglyphs;
290 if (new_max > old_max)
292 TA_SubGlyph subglyphs_new;
295 new_max = TA_PAD_CEIL(new_max, 2);
296 subglyphs_new = (TA_SubGlyph)realloc(base->subglyphs,
297 new_max * sizeof (TA_SubGlyphRec));
298 if (!subglyphs_new)
299 return FT_Err_Out_Of_Memory;
300 base->subglyphs = subglyphs_new;
302 loader->max_subglyphs = new_max;
304 TA_GlyphLoader_Adjust_Subglyphs(loader);
307 return FT_Err_Ok;
311 /* prepare loader for the addition of a new glyph on top of the base one */
312 void
313 TA_GlyphLoader_Prepare(TA_GlyphLoader loader)
315 TA_GlyphLoad current = &loader->current;
318 current->outline.n_points = 0;
319 current->outline.n_contours = 0;
320 current->num_subglyphs = 0;
322 TA_GlyphLoader_Adjust_Points (loader);
323 TA_GlyphLoader_Adjust_Subglyphs(loader);
327 /* add current glyph to the base image -- and prepare for another */
328 void
329 TA_GlyphLoader_Add(TA_GlyphLoader loader)
331 TA_GlyphLoad base;
332 TA_GlyphLoad current;
334 FT_Int n_curr_contours;
335 FT_Int n_base_points;
336 FT_Int n;
339 if (!loader)
340 return;
342 base = &loader->base;
343 current = &loader->current;
345 n_curr_contours = current->outline.n_contours;
346 n_base_points = base->outline.n_points;
348 base->outline.n_points =
349 (short)(base->outline.n_points + current->outline.n_points);
350 base->outline.n_contours =
351 (short)(base->outline.n_contours + current->outline.n_contours);
353 base->num_subglyphs += current->num_subglyphs;
355 /* adjust contours count in newest outline */
356 for (n = 0; n < n_curr_contours; n++)
357 current->outline.contours[n] =
358 (short)(current->outline.contours[n] + n_base_points);
360 /* prepare for another new glyph image */
361 TA_GlyphLoader_Prepare(loader);
365 #if 0
366 FT_Error
367 TA_GlyphLoader_CopyPoints(TA_GlyphLoader target,
368 TA_GlyphLoader source)
370 FT_Error error;
371 FT_UInt num_points = (FT_UInt)source->base.outline.n_points;
372 FT_UInt num_contours = (FT_UInt)source->base.outline.n_contours;
375 error = TA_GlyphLoader_CheckPoints(target, num_points, num_contours);
376 if (!error)
378 FT_Outline* out = &target->base.outline;
379 FT_Outline* in = &source->base.outline;
382 memcpy(out->points, in->points, num_points * sizeof (FT_Vector));
383 memcpy(out->contours, in->contours, num_contours * sizeof (short));
384 memcpy(out->tags, in->tags, num_points * sizeof (char));
386 /* do we need to copy the extra points? */
387 if (target->use_extra && source->use_extra)
389 memcpy(target->base.extra_points, source->base.extra_points,
390 num_points * sizeof (FT_Vector));
391 memcpy(target->base.extra_points2, source->base.extra_points2,
392 num_points * sizeof (FT_Vector));
395 out->n_points = (short)num_points;
396 out->n_contours = (short)num_contours;
398 TA_GlyphLoader_Adjust_Points(target);
401 return error;
403 #endif
405 /* end of tagloadr.c */