Introduce point hints and provide framework for them.
[ttfautohint.git] / src / tagloadr.c
blob554d7e2693f9b32fe24e7fa6bad53034fc96781a
1 /* tagloadr.c */
3 /* originally file `ftgloadr.c' (2011-Mar-28) from FreeType */
5 /* heavily modified 2011 by Werner Lemberg <wl@gnu.org> */
7 #include <stdlib.h>
8 #include <string.h>
10 #include "tatypes.h"
11 #include "tagloadr.h"
14 /*************************************************************************/
15 /* */
16 /* The glyph loader is a simple object which is used to load a set of */
17 /* glyphs easily. It is critical for the correct loading of composites. */
18 /* */
19 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
20 /* */
21 /* loader.base Is really the bottom of the stack. It describes a */
22 /* single glyph image made of the juxtaposition of */
23 /* several glyphs (those `in the stack'). */
24 /* */
25 /* loader.current Describes the top of the stack, on which a new */
26 /* glyph can be loaded. */
27 /* */
28 /* Rewind Clears the stack. */
29 /* Prepare Set up `loader.current' for addition of a new glyph */
30 /* image. */
31 /* Add Add the `current' glyph image to the `base' one, */
32 /* and prepare for another one. */
33 /* */
34 /*************************************************************************/
37 /* create a new glyph loader */
38 FT_Error
39 TA_GlyphLoader_New(TA_GlyphLoader *aloader)
41 TA_GlyphLoader loader;
44 loader = (TA_GlyphLoader)calloc(1, sizeof (TA_GlyphLoaderRec));
46 if (!loader)
47 return FT_Err_Out_Of_Memory;
49 *aloader = loader;
50 return FT_Err_Ok;
54 /* rewind the glyph loader - reset counters to 0 */
55 void
56 TA_GlyphLoader_Rewind(TA_GlyphLoader loader)
58 TA_GlyphLoad base = &loader->base;
59 TA_GlyphLoad current = &loader->current;
62 base->outline.n_points = 0;
63 base->outline.n_contours = 0;
64 base->num_subglyphs = 0;
66 *current = *base;
70 /* reset the glyph loader, frees all allocated tables */
71 /* and starts from zero */
72 void
73 TA_GlyphLoader_Reset(TA_GlyphLoader loader)
75 free(loader->base.outline.points);
76 free(loader->base.outline.tags);
77 free(loader->base.outline.contours);
78 free(loader->base.extra_points);
79 free(loader->base.subglyphs);
81 loader->base.outline.points = NULL;
82 loader->base.outline.tags = NULL;
83 loader->base.outline.contours = NULL;
84 loader->base.extra_points = NULL;
85 loader->base.subglyphs = NULL;
87 loader->base.extra_points2 = NULL;
89 loader->max_points = 0;
90 loader->max_contours = 0;
91 loader->max_subglyphs = 0;
93 TA_GlyphLoader_Rewind(loader);
97 /* delete a glyph loader */
98 void
99 TA_GlyphLoader_Done(TA_GlyphLoader loader)
101 if (loader)
103 TA_GlyphLoader_Reset(loader);
104 free(loader);
109 /* re-adjust the `current' outline fields */
110 static void
111 TA_GlyphLoader_Adjust_Points(TA_GlyphLoader loader)
113 FT_Outline* base = &loader->base.outline;
114 FT_Outline* current = &loader->current.outline;
117 current->points = base->points + base->n_points;
118 current->tags = base->tags + base->n_points;
119 current->contours = base->contours + base->n_contours;
121 /* handle extra points table - if any */
122 if (loader->use_extra)
124 loader->current.extra_points = loader->base.extra_points
125 + base->n_points;
127 loader->current.extra_points2 = loader->base.extra_points2
128 + base->n_points;
133 FT_Error
134 TA_GlyphLoader_CreateExtra(TA_GlyphLoader loader)
136 loader->base.extra_points =
137 (FT_Vector*)calloc(1, 2 * loader->max_points * sizeof (FT_Vector));
138 if (!loader->base.extra_points)
139 return FT_Err_Out_Of_Memory;
141 loader->use_extra = 1;
142 loader->base.extra_points2 = loader->base.extra_points
143 + loader->max_points;
145 TA_GlyphLoader_Adjust_Points(loader);
147 return FT_Err_Ok;
151 /* re-adjust the `current' subglyphs field */
152 static void
153 TA_GlyphLoader_Adjust_Subglyphs(TA_GlyphLoader loader)
155 TA_GlyphLoad base = &loader->base;
156 TA_GlyphLoad current = &loader->current;
159 current->subglyphs = base->subglyphs + base->num_subglyphs;
163 /* ensure that we can add `n_points' and `n_contours' to our glyph -- */
164 /* this function reallocates its outline tables if necessary, */
165 /* but it DOESN'T change the number of points within the loader */
166 FT_Error
167 TA_GlyphLoader_CheckPoints(TA_GlyphLoader loader,
168 FT_UInt n_points,
169 FT_UInt n_contours)
171 FT_Outline* base = &loader->base.outline;
172 FT_Outline* current = &loader->current.outline;
173 FT_Bool adjust = 0;
175 FT_UInt new_max, old_max;
178 /* check points & tags */
179 new_max = base->n_points + current->n_points + n_points;
180 old_max = loader->max_points;
182 if (new_max > old_max)
184 FT_Vector* points_new;
185 char* tags_new;
188 new_max = TA_PAD_CEIL(new_max, 8);
190 if (new_max > FT_OUTLINE_POINTS_MAX)
191 return FT_Err_Array_Too_Large;
193 points_new = (FT_Vector*)realloc(base->points,
194 new_max * sizeof (FT_Vector));
195 if (!points_new)
196 return FT_Err_Out_Of_Memory;
197 base->points = points_new;
199 tags_new = (char*)realloc(base->tags,
200 new_max * sizeof (char));
201 if (!tags_new)
202 return FT_Err_Out_Of_Memory;
203 base->tags = tags_new;
205 if (loader->use_extra)
207 FT_Vector* extra_points_new;
210 extra_points_new =
211 (FT_Vector*)realloc(loader->base.extra_points,
212 new_max * 2 * sizeof (FT_Vector));
213 if (!extra_points_new)
214 return FT_Err_Out_Of_Memory;
215 loader->base.extra_points = extra_points_new;
217 memmove(loader->base.extra_points + new_max,
218 loader->base.extra_points + old_max,
219 old_max * sizeof (FT_Vector));
221 loader->base.extra_points2 = loader->base.extra_points + new_max;
224 adjust = 1;
225 loader->max_points = new_max;
228 /* check contours */
229 old_max = loader->max_contours;
230 new_max = base->n_contours + current->n_contours + n_contours;
231 if (new_max > old_max)
233 short* contours_new;
236 new_max = TA_PAD_CEIL(new_max, 4);
238 if (new_max > FT_OUTLINE_CONTOURS_MAX)
239 return FT_Err_Array_Too_Large;
241 contours_new = (short*)realloc(base->contours,
242 new_max * sizeof (short));
243 if (!contours_new)
244 return FT_Err_Out_Of_Memory;
245 base->contours = contours_new;
247 adjust = 1;
248 loader->max_contours = new_max;
251 if (adjust)
252 TA_GlyphLoader_Adjust_Points(loader);
254 return FT_Err_Ok;
258 /* ensure that we can add `n_subglyphs' to our glyph -- */
259 /* this function reallocates its subglyphs table if necessary, */
260 /* but it DOES NOT change the number of subglyphs within the loader */
261 FT_Error
262 TA_GlyphLoader_CheckSubGlyphs(TA_GlyphLoader loader,
263 FT_UInt n_subs)
265 FT_UInt new_max, old_max;
267 TA_GlyphLoad base = &loader->base;
268 TA_GlyphLoad current = &loader->current;
271 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
272 old_max = loader->max_subglyphs;
273 if (new_max > old_max)
275 TA_SubGlyph subglyphs_new;
278 new_max = TA_PAD_CEIL(new_max, 2);
279 subglyphs_new = (TA_SubGlyph)realloc(base->subglyphs,
280 new_max * sizeof (TA_SubGlyphRec));
281 if (!subglyphs_new)
282 return FT_Err_Out_Of_Memory;
283 base->subglyphs = subglyphs_new;
285 loader->max_subglyphs = new_max;
287 TA_GlyphLoader_Adjust_Subglyphs(loader);
290 return FT_Err_Ok;
294 /* prepare loader for the addition of a new glyph on top of the base one */
295 void
296 TA_GlyphLoader_Prepare(TA_GlyphLoader loader)
298 TA_GlyphLoad current = &loader->current;
301 current->outline.n_points = 0;
302 current->outline.n_contours = 0;
303 current->num_subglyphs = 0;
305 TA_GlyphLoader_Adjust_Points (loader);
306 TA_GlyphLoader_Adjust_Subglyphs(loader);
310 /* add current glyph to the base image -- and prepare for another */
311 void
312 TA_GlyphLoader_Add(TA_GlyphLoader loader)
314 TA_GlyphLoad base;
315 TA_GlyphLoad current;
317 FT_UInt n_curr_contours;
318 FT_UInt n_base_points;
319 FT_UInt n;
322 if (!loader)
323 return;
325 base = &loader->base;
326 current = &loader->current;
328 n_curr_contours = current->outline.n_contours;
329 n_base_points = base->outline.n_points;
331 base->outline.n_points =
332 (short)(base->outline.n_points + current->outline.n_points);
333 base->outline.n_contours =
334 (short)(base->outline.n_contours + current->outline.n_contours);
336 base->num_subglyphs += current->num_subglyphs;
338 /* adjust contours count in newest outline */
339 for (n = 0; n < n_curr_contours; n++)
340 current->outline.contours[n] =
341 (short)(current->outline.contours[n] + n_base_points);
343 /* prepare for another new glyph image */
344 TA_GlyphLoader_Prepare(loader);
348 FT_Error
349 TA_GlyphLoader_CopyPoints(TA_GlyphLoader target,
350 TA_GlyphLoader source)
352 FT_Error error;
353 FT_UInt num_points = source->base.outline.n_points;
354 FT_UInt num_contours = source->base.outline.n_contours;
357 error = TA_GlyphLoader_CheckPoints(target, num_points, num_contours);
358 if (!error)
360 FT_Outline* out = &target->base.outline;
361 FT_Outline* in = &source->base.outline;
364 memcpy(out->points, in->points, num_points * sizeof (FT_Vector));
365 memcpy(out->contours, in->contours, num_contours * sizeof (short));
366 memcpy(out->tags, in->tags, num_points * sizeof (char));
368 /* do we need to copy the extra points? */
369 if (target->use_extra && source->use_extra)
371 memcpy(target->base.extra_points, source->base.extra_points,
372 num_points * sizeof (FT_Vector));
373 memcpy(target->base.extra_points2, source->base.extra_points2,
374 num_points * sizeof (FT_Vector));
377 out->n_points = (short)num_points;
378 out->n_contours = (short)num_contours;
380 TA_GlyphLoader_Adjust_Points(target);
383 return error;
386 /* end of tagloadr.c */