PageRenderTime 36ms CodeModel.GetById 14ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/freetype/src/base/ftgloadr.c

https://bitbucket.org/cabalistic/ogredeps/
C | 401 lines | 230 code | 95 blank | 76 comment | 20 complexity | 89ecad8dc6136fc7176ab0d25e30989e MD5 | raw file
  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 */