1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* ftgloadr.c */ |
|
4 /* */ |
|
5 /* The FreeType glyph loader (body). */ |
|
6 /* */ |
|
7 /* Copyright 2002, 2003, 2004, 2005, 2006, 2010 by */ |
|
8 /* David Turner, Robert Wilhelm, and Werner Lemberg */ |
|
9 /* */ |
|
10 /* This file is part of the FreeType project, and may only be used, */ |
|
11 /* modified, and distributed under the terms of the FreeType project */ |
|
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
|
13 /* this file you indicate that you have read the license and */ |
|
14 /* understand and accept it fully. */ |
|
15 /* */ |
|
16 /***************************************************************************/ |
|
17 |
|
18 |
|
19 #include <ft2build.h> |
|
20 #include FT_INTERNAL_GLYPH_LOADER_H |
|
21 #include FT_INTERNAL_MEMORY_H |
|
22 #include FT_INTERNAL_OBJECTS_H |
|
23 |
|
24 #undef FT_COMPONENT |
|
25 #define FT_COMPONENT trace_gloader |
|
26 |
|
27 |
|
28 /*************************************************************************/ |
|
29 /*************************************************************************/ |
|
30 /*************************************************************************/ |
|
31 /***** *****/ |
|
32 /***** *****/ |
|
33 /***** G L Y P H L O A D E R *****/ |
|
34 /***** *****/ |
|
35 /***** *****/ |
|
36 /*************************************************************************/ |
|
37 /*************************************************************************/ |
|
38 /*************************************************************************/ |
|
39 |
|
40 /*************************************************************************/ |
|
41 /* */ |
|
42 /* The glyph loader is a simple object which is used to load a set of */ |
|
43 /* glyphs easily. It is critical for the correct loading of composites. */ |
|
44 /* */ |
|
45 /* Ideally, one can see it as a stack of abstract `glyph' objects. */ |
|
46 /* */ |
|
47 /* loader.base Is really the bottom of the stack. It describes a */ |
|
48 /* single glyph image made of the juxtaposition of */ |
|
49 /* several glyphs (those `in the stack'). */ |
|
50 /* */ |
|
51 /* loader.current Describes the top of the stack, on which a new */ |
|
52 /* glyph can be loaded. */ |
|
53 /* */ |
|
54 /* Rewind Clears the stack. */ |
|
55 /* Prepare Set up `loader.current' for addition of a new glyph */ |
|
56 /* image. */ |
|
57 /* Add Add the `current' glyph image to the `base' one, */ |
|
58 /* and prepare for another one. */ |
|
59 /* */ |
|
60 /* The glyph loader is now a base object. Each driver used to */ |
|
61 /* re-implement it in one way or the other, which wasted code and */ |
|
62 /* energy. */ |
|
63 /* */ |
|
64 /*************************************************************************/ |
|
65 |
|
66 |
|
67 /* create a new glyph loader */ |
|
68 FT_BASE_DEF( FT_Error ) |
|
69 FT_GlyphLoader_New( FT_Memory memory, |
|
70 FT_GlyphLoader *aloader ) |
|
71 { |
|
72 FT_GlyphLoader loader = NULL; |
|
73 FT_Error error; |
|
74 |
|
75 |
|
76 if ( !FT_NEW( loader ) ) |
|
77 { |
|
78 loader->memory = memory; |
|
79 *aloader = loader; |
|
80 } |
|
81 return error; |
|
82 } |
|
83 |
|
84 |
|
85 /* rewind the glyph loader - reset counters to 0 */ |
|
86 FT_BASE_DEF( void ) |
|
87 FT_GlyphLoader_Rewind( FT_GlyphLoader loader ) |
|
88 { |
|
89 FT_GlyphLoad base = &loader->base; |
|
90 FT_GlyphLoad current = &loader->current; |
|
91 |
|
92 |
|
93 base->outline.n_points = 0; |
|
94 base->outline.n_contours = 0; |
|
95 base->num_subglyphs = 0; |
|
96 |
|
97 *current = *base; |
|
98 } |
|
99 |
|
100 |
|
101 /* reset the glyph loader, frees all allocated tables */ |
|
102 /* and starts from zero */ |
|
103 FT_BASE_DEF( void ) |
|
104 FT_GlyphLoader_Reset( FT_GlyphLoader loader ) |
|
105 { |
|
106 FT_Memory memory = loader->memory; |
|
107 |
|
108 |
|
109 FT_FREE( loader->base.outline.points ); |
|
110 FT_FREE( loader->base.outline.tags ); |
|
111 FT_FREE( loader->base.outline.contours ); |
|
112 FT_FREE( loader->base.extra_points ); |
|
113 FT_FREE( loader->base.subglyphs ); |
|
114 |
|
115 loader->base.extra_points2 = NULL; |
|
116 |
|
117 loader->max_points = 0; |
|
118 loader->max_contours = 0; |
|
119 loader->max_subglyphs = 0; |
|
120 |
|
121 FT_GlyphLoader_Rewind( loader ); |
|
122 } |
|
123 |
|
124 |
|
125 /* delete a glyph loader */ |
|
126 FT_BASE_DEF( void ) |
|
127 FT_GlyphLoader_Done( FT_GlyphLoader loader ) |
|
128 { |
|
129 if ( loader ) |
|
130 { |
|
131 FT_Memory memory = loader->memory; |
|
132 |
|
133 |
|
134 FT_GlyphLoader_Reset( loader ); |
|
135 FT_FREE( loader ); |
|
136 } |
|
137 } |
|
138 |
|
139 |
|
140 /* re-adjust the `current' outline fields */ |
|
141 static void |
|
142 FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader ) |
|
143 { |
|
144 FT_Outline* base = &loader->base.outline; |
|
145 FT_Outline* current = &loader->current.outline; |
|
146 |
|
147 |
|
148 current->points = base->points + base->n_points; |
|
149 current->tags = base->tags + base->n_points; |
|
150 current->contours = base->contours + base->n_contours; |
|
151 |
|
152 /* handle extra points table - if any */ |
|
153 if ( loader->use_extra ) |
|
154 { |
|
155 loader->current.extra_points = loader->base.extra_points + |
|
156 base->n_points; |
|
157 |
|
158 loader->current.extra_points2 = loader->base.extra_points2 + |
|
159 base->n_points; |
|
160 } |
|
161 } |
|
162 |
|
163 |
|
164 FT_BASE_DEF( FT_Error ) |
|
165 FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader ) |
|
166 { |
|
167 FT_Error error; |
|
168 FT_Memory memory = loader->memory; |
|
169 |
|
170 |
|
171 if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) ) |
|
172 { |
|
173 loader->use_extra = 1; |
|
174 loader->base.extra_points2 = loader->base.extra_points + |
|
175 loader->max_points; |
|
176 |
|
177 FT_GlyphLoader_Adjust_Points( loader ); |
|
178 } |
|
179 return error; |
|
180 } |
|
181 |
|
182 |
|
183 /* re-adjust the `current' subglyphs field */ |
|
184 static void |
|
185 FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader ) |
|
186 { |
|
187 FT_GlyphLoad base = &loader->base; |
|
188 FT_GlyphLoad current = &loader->current; |
|
189 |
|
190 |
|
191 current->subglyphs = base->subglyphs + base->num_subglyphs; |
|
192 } |
|
193 |
|
194 |
|
195 /* Ensure that we can add `n_points' and `n_contours' to our glyph. */ |
|
196 /* This function reallocates its outline tables if necessary. Note that */ |
|
197 /* it DOESN'T change the number of points within the loader! */ |
|
198 /* */ |
|
199 FT_BASE_DEF( FT_Error ) |
|
200 FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, |
|
201 FT_UInt n_points, |
|
202 FT_UInt n_contours ) |
|
203 { |
|
204 FT_Memory memory = loader->memory; |
|
205 FT_Error error = FT_Err_Ok; |
|
206 FT_Outline* base = &loader->base.outline; |
|
207 FT_Outline* current = &loader->current.outline; |
|
208 FT_Bool adjust = 0; |
|
209 |
|
210 FT_UInt new_max, old_max; |
|
211 |
|
212 |
|
213 /* check points & tags */ |
|
214 new_max = base->n_points + current->n_points + n_points; |
|
215 old_max = loader->max_points; |
|
216 |
|
217 if ( new_max > old_max ) |
|
218 { |
|
219 new_max = FT_PAD_CEIL( new_max, 8 ); |
|
220 |
|
221 if ( new_max > FT_OUTLINE_POINTS_MAX ) |
|
222 return FT_Err_Array_Too_Large; |
|
223 |
|
224 if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) || |
|
225 FT_RENEW_ARRAY( base->tags, old_max, new_max ) ) |
|
226 goto Exit; |
|
227 |
|
228 if ( loader->use_extra ) |
|
229 { |
|
230 if ( FT_RENEW_ARRAY( loader->base.extra_points, |
|
231 old_max * 2, new_max * 2 ) ) |
|
232 goto Exit; |
|
233 |
|
234 FT_ARRAY_MOVE( loader->base.extra_points + new_max, |
|
235 loader->base.extra_points + old_max, |
|
236 old_max ); |
|
237 |
|
238 loader->base.extra_points2 = loader->base.extra_points + new_max; |
|
239 } |
|
240 |
|
241 adjust = 1; |
|
242 loader->max_points = new_max; |
|
243 } |
|
244 |
|
245 /* check contours */ |
|
246 old_max = loader->max_contours; |
|
247 new_max = base->n_contours + current->n_contours + |
|
248 n_contours; |
|
249 if ( new_max > old_max ) |
|
250 { |
|
251 new_max = FT_PAD_CEIL( new_max, 4 ); |
|
252 |
|
253 if ( new_max > FT_OUTLINE_CONTOURS_MAX ) |
|
254 return FT_Err_Array_Too_Large; |
|
255 |
|
256 if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) ) |
|
257 goto Exit; |
|
258 |
|
259 adjust = 1; |
|
260 loader->max_contours = new_max; |
|
261 } |
|
262 |
|
263 if ( adjust ) |
|
264 FT_GlyphLoader_Adjust_Points( loader ); |
|
265 |
|
266 Exit: |
|
267 return error; |
|
268 } |
|
269 |
|
270 |
|
271 /* Ensure that we can add `n_subglyphs' to our glyph. this function */ |
|
272 /* reallocates its subglyphs table if necessary. Note that it DOES */ |
|
273 /* NOT change the number of subglyphs within the loader! */ |
|
274 /* */ |
|
275 FT_BASE_DEF( FT_Error ) |
|
276 FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, |
|
277 FT_UInt n_subs ) |
|
278 { |
|
279 FT_Memory memory = loader->memory; |
|
280 FT_Error error = FT_Err_Ok; |
|
281 FT_UInt new_max, old_max; |
|
282 |
|
283 FT_GlyphLoad base = &loader->base; |
|
284 FT_GlyphLoad current = &loader->current; |
|
285 |
|
286 |
|
287 new_max = base->num_subglyphs + current->num_subglyphs + n_subs; |
|
288 old_max = loader->max_subglyphs; |
|
289 if ( new_max > old_max ) |
|
290 { |
|
291 new_max = FT_PAD_CEIL( new_max, 2 ); |
|
292 if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) ) |
|
293 goto Exit; |
|
294 |
|
295 loader->max_subglyphs = new_max; |
|
296 |
|
297 FT_GlyphLoader_Adjust_Subglyphs( loader ); |
|
298 } |
|
299 |
|
300 Exit: |
|
301 return error; |
|
302 } |
|
303 |
|
304 |
|
305 /* prepare loader for the addition of a new glyph on top of the base one */ |
|
306 FT_BASE_DEF( void ) |
|
307 FT_GlyphLoader_Prepare( FT_GlyphLoader loader ) |
|
308 { |
|
309 FT_GlyphLoad current = &loader->current; |
|
310 |
|
311 |
|
312 current->outline.n_points = 0; |
|
313 current->outline.n_contours = 0; |
|
314 current->num_subglyphs = 0; |
|
315 |
|
316 FT_GlyphLoader_Adjust_Points ( loader ); |
|
317 FT_GlyphLoader_Adjust_Subglyphs( loader ); |
|
318 } |
|
319 |
|
320 |
|
321 /* add current glyph to the base image - and prepare for another */ |
|
322 FT_BASE_DEF( void ) |
|
323 FT_GlyphLoader_Add( FT_GlyphLoader loader ) |
|
324 { |
|
325 FT_GlyphLoad base; |
|
326 FT_GlyphLoad current; |
|
327 |
|
328 FT_UInt n_curr_contours; |
|
329 FT_UInt n_base_points; |
|
330 FT_UInt n; |
|
331 |
|
332 |
|
333 if ( !loader ) |
|
334 return; |
|
335 |
|
336 base = &loader->base; |
|
337 current = &loader->current; |
|
338 |
|
339 n_curr_contours = current->outline.n_contours; |
|
340 n_base_points = base->outline.n_points; |
|
341 |
|
342 base->outline.n_points = |
|
343 (short)( base->outline.n_points + current->outline.n_points ); |
|
344 base->outline.n_contours = |
|
345 (short)( base->outline.n_contours + current->outline.n_contours ); |
|
346 |
|
347 base->num_subglyphs += current->num_subglyphs; |
|
348 |
|
349 /* adjust contours count in newest outline */ |
|
350 for ( n = 0; n < n_curr_contours; n++ ) |
|
351 current->outline.contours[n] = |
|
352 (short)( current->outline.contours[n] + n_base_points ); |
|
353 |
|
354 /* prepare for another new glyph image */ |
|
355 FT_GlyphLoader_Prepare( loader ); |
|
356 } |
|
357 |
|
358 |
|
359 FT_BASE_DEF( FT_Error ) |
|
360 FT_GlyphLoader_CopyPoints( FT_GlyphLoader target, |
|
361 FT_GlyphLoader source ) |
|
362 { |
|
363 FT_Error error; |
|
364 FT_UInt num_points = source->base.outline.n_points; |
|
365 FT_UInt num_contours = source->base.outline.n_contours; |
|
366 |
|
367 |
|
368 error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours ); |
|
369 if ( !error ) |
|
370 { |
|
371 FT_Outline* out = &target->base.outline; |
|
372 FT_Outline* in = &source->base.outline; |
|
373 |
|
374 |
|
375 FT_ARRAY_COPY( out->points, in->points, |
|
376 num_points ); |
|
377 FT_ARRAY_COPY( out->tags, in->tags, |
|
378 num_points ); |
|
379 FT_ARRAY_COPY( out->contours, in->contours, |
|
380 num_contours ); |
|
381 |
|
382 /* do we need to copy the extra points? */ |
|
383 if ( target->use_extra && source->use_extra ) |
|
384 { |
|
385 FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points, |
|
386 num_points ); |
|
387 FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2, |
|
388 num_points ); |
|
389 } |
|
390 |
|
391 out->n_points = (short)num_points; |
|
392 out->n_contours = (short)num_contours; |
|
393 |
|
394 FT_GlyphLoader_Adjust_Points( target ); |
|
395 } |
|
396 |
|
397 return error; |
|
398 } |
|
399 |
|
400 |
|
401 /* END */ |
|