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