ftgloadr.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftgloadr.c                                                             */
00004 /*                                                                         */
00005 /*    The FreeType glyph loader (body).                                    */
00006 /*                                                                         */
00007 /*  Copyright 2002, 2003, 2004, 2005, 2006 by                              */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg                       */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_GLYPH_LOADER_H
00021 #include FT_INTERNAL_MEMORY_H
00022 #include FT_INTERNAL_OBJECTS_H
00023 
00024 #undef  FT_COMPONENT
00025 #define FT_COMPONENT  trace_gloader
00026 
00027 
00028   /*************************************************************************/
00029   /*************************************************************************/
00030   /*************************************************************************/
00031   /*****                                                               *****/
00032   /*****                                                               *****/
00033   /*****                    G L Y P H   L O A D E R                    *****/
00034   /*****                                                               *****/
00035   /*****                                                               *****/
00036   /*************************************************************************/
00037   /*************************************************************************/
00038   /*************************************************************************/
00039 
00040   /*************************************************************************/
00041   /*                                                                       */
00042   /* The glyph loader is a simple object which is used to load a set of    */
00043   /* glyphs easily.  It is critical for the correct loading of composites. */
00044   /*                                                                       */
00045   /* Ideally, one can see it as a stack of abstract `glyph' objects.       */
00046   /*                                                                       */
00047   /*   loader.base     Is really the bottom of the stack.  It describes a  */
00048   /*                   single glyph image made of the juxtaposition of     */
00049   /*                   several glyphs (those `in the stack').              */
00050   /*                                                                       */
00051   /*   loader.current  Describes the top of the stack, on which a new      */
00052   /*                   glyph can be loaded.                                */
00053   /*                                                                       */
00054   /*   Rewind          Clears the stack.                                   */
00055   /*   Prepare         Set up `loader.current' for addition of a new glyph */
00056   /*                   image.                                              */
00057   /*   Add             Add the `current' glyph image to the `base' one,    */
00058   /*                   and prepare for another one.                        */
00059   /*                                                                       */
00060   /* The glyph loader is now a base object.  Each driver used to           */
00061   /* re-implement it in one way or the other, which wasted code and        */
00062   /* energy.                                                               */
00063   /*                                                                       */
00064   /*************************************************************************/
00065 
00066 
00067   /* create a new glyph loader */
00068   FT_BASE_DEF( FT_Error )
00069   FT_GlyphLoader_New( FT_Memory        memory,
00070                       FT_GlyphLoader  *aloader )
00071   {
00072     FT_GlyphLoader  loader;
00073     FT_Error        error;
00074 
00075 
00076     if ( !FT_NEW( loader ) )
00077     {
00078       loader->memory = memory;
00079       *aloader       = loader;
00080     }
00081     return error;
00082   }
00083 
00084 
00085   /* rewind the glyph loader - reset counters to 0 */
00086   FT_BASE_DEF( void )
00087   FT_GlyphLoader_Rewind( FT_GlyphLoader  loader )
00088   {
00089     FT_GlyphLoad  base    = &loader->base;
00090     FT_GlyphLoad  current = &loader->current;
00091 
00092 
00093     base->outline.n_points   = 0;
00094     base->outline.n_contours = 0;
00095     base->num_subglyphs      = 0;
00096 
00097     *current = *base;
00098   }
00099 
00100 
00101   /* reset the glyph loader, frees all allocated tables */
00102   /* and starts from zero                               */
00103   FT_BASE_DEF( void )
00104   FT_GlyphLoader_Reset( FT_GlyphLoader  loader )
00105   {
00106     FT_Memory memory = loader->memory;
00107 
00108 
00109     FT_FREE( loader->base.outline.points );
00110     FT_FREE( loader->base.outline.tags );
00111     FT_FREE( loader->base.outline.contours );
00112     FT_FREE( loader->base.extra_points );
00113     FT_FREE( loader->base.subglyphs );
00114 
00115     loader->base.extra_points2 = NULL;
00116 
00117     loader->max_points    = 0;
00118     loader->max_contours  = 0;
00119     loader->max_subglyphs = 0;
00120 
00121     FT_GlyphLoader_Rewind( loader );
00122   }
00123 
00124 
00125   /* delete a glyph loader */
00126   FT_BASE_DEF( void )
00127   FT_GlyphLoader_Done( FT_GlyphLoader  loader )
00128   {
00129     if ( loader )
00130     {
00131       FT_Memory memory = loader->memory;
00132 
00133 
00134       FT_GlyphLoader_Reset( loader );
00135       FT_FREE( loader );
00136     }
00137   }
00138 
00139 
00140   /* re-adjust the `current' outline fields */
00141   static void
00142   FT_GlyphLoader_Adjust_Points( FT_GlyphLoader  loader )
00143   {
00144     FT_Outline*  base    = &loader->base.outline;
00145     FT_Outline*  current = &loader->current.outline;
00146 
00147 
00148     current->points   = base->points   + base->n_points;
00149     current->tags     = base->tags     + base->n_points;
00150     current->contours = base->contours + base->n_contours;
00151 
00152     /* handle extra points table - if any */
00153     if ( loader->use_extra )
00154     {
00155       loader->current.extra_points  = loader->base.extra_points +
00156                                       base->n_points;
00157 
00158       loader->current.extra_points2 = loader->base.extra_points2 +
00159                                       base->n_points;
00160     }
00161   }
00162 
00163 
00164   FT_BASE_DEF( FT_Error )
00165   FT_GlyphLoader_CreateExtra( FT_GlyphLoader  loader )
00166   {
00167     FT_Error   error;
00168     FT_Memory  memory = loader->memory;
00169 
00170 
00171     if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )
00172     {
00173       loader->use_extra          = 1;
00174       loader->base.extra_points2 = loader->base.extra_points +
00175                                    loader->max_points;
00176 
00177       FT_GlyphLoader_Adjust_Points( loader );
00178     }
00179     return error;
00180   }
00181 
00182 
00183   /* re-adjust the `current' subglyphs field */
00184   static void
00185   FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader  loader )
00186   {
00187     FT_GlyphLoad  base    = &loader->base;
00188     FT_GlyphLoad  current = &loader->current;
00189 
00190 
00191     current->subglyphs = base->subglyphs + base->num_subglyphs;
00192   }
00193 
00194 
00195   /* Ensure that we can add `n_points' and `n_contours' to our glyph.      */
00196   /* This function reallocates its outline tables if necessary.  Note that */
00197   /* it DOESN'T change the number of points within the loader!             */
00198   /*                                                                       */
00199   FT_BASE_DEF( FT_Error )
00200   FT_GlyphLoader_CheckPoints( FT_GlyphLoader  loader,
00201                               FT_UInt         n_points,
00202                               FT_UInt         n_contours )
00203   {
00204     FT_Memory    memory  = loader->memory;
00205     FT_Error     error   = FT_Err_Ok;
00206     FT_Outline*  base    = &loader->base.outline;
00207     FT_Outline*  current = &loader->current.outline;
00208     FT_Bool      adjust  = 0;
00209 
00210     FT_UInt      new_max, old_max;
00211 
00212 
00213     /* check points & tags */
00214     new_max = base->n_points + current->n_points + n_points;
00215     old_max = loader->max_points;
00216 
00217     if ( new_max > old_max )
00218     {
00219       new_max = FT_PAD_CEIL( new_max, 8 );
00220 
00221       if ( new_max > FT_OUTLINE_POINTS_MAX )
00222         return FT_Err_Array_Too_Large;
00223 
00224       if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
00225            FT_RENEW_ARRAY( base->tags,   old_max, new_max ) )
00226         goto Exit;
00227 
00228       if ( loader->use_extra )
00229       {
00230         if ( FT_RENEW_ARRAY( loader->base.extra_points,
00231                              old_max * 2, new_max * 2 ) )
00232           goto Exit;
00233 
00234         FT_ARRAY_MOVE( loader->base.extra_points + new_max,
00235                        loader->base.extra_points + old_max,
00236                        old_max );
00237 
00238         loader->base.extra_points2 = loader->base.extra_points + new_max;
00239       }
00240 
00241       adjust = 1;
00242       loader->max_points = new_max;
00243     }
00244 
00245     /* check contours */
00246     old_max = loader->max_contours;
00247     new_max = base->n_contours + current->n_contours +
00248               n_contours;
00249     if ( new_max > old_max )
00250     {
00251       new_max = FT_PAD_CEIL( new_max, 4 );
00252 
00253       if ( new_max > FT_OUTLINE_CONTOURS_MAX )
00254         return FT_Err_Array_Too_Large;
00255 
00256       if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
00257         goto Exit;
00258 
00259       adjust = 1;
00260       loader->max_contours = new_max;
00261     }
00262 
00263     if ( adjust )
00264       FT_GlyphLoader_Adjust_Points( loader );
00265 
00266   Exit:
00267     return error;
00268   }
00269 
00270 
00271   /* Ensure that we can add `n_subglyphs' to our glyph. this function */
00272   /* reallocates its subglyphs table if necessary.  Note that it DOES */
00273   /* NOT change the number of subglyphs within the loader!            */
00274   /*                                                                  */
00275   FT_BASE_DEF( FT_Error )
00276   FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader  loader,
00277                                  FT_UInt         n_subs )
00278   {
00279     FT_Memory     memory = loader->memory;
00280     FT_Error      error  = FT_Err_Ok;
00281     FT_UInt       new_max, old_max;
00282 
00283     FT_GlyphLoad  base    = &loader->base;
00284     FT_GlyphLoad  current = &loader->current;
00285 
00286 
00287     new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
00288     old_max = loader->max_subglyphs;
00289     if ( new_max > old_max )
00290     {
00291       new_max = FT_PAD_CEIL( new_max, 2 );
00292       if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )
00293         goto Exit;
00294 
00295       loader->max_subglyphs = new_max;
00296 
00297       FT_GlyphLoader_Adjust_Subglyphs( loader );
00298     }
00299 
00300   Exit:
00301     return error;
00302   }
00303 
00304 
00305   /* prepare loader for the addition of a new glyph on top of the base one */
00306   FT_BASE_DEF( void )
00307   FT_GlyphLoader_Prepare( FT_GlyphLoader  loader )
00308   {
00309     FT_GlyphLoad  current = &loader->current;
00310 
00311 
00312     current->outline.n_points   = 0;
00313     current->outline.n_contours = 0;
00314     current->num_subglyphs      = 0;
00315 
00316     FT_GlyphLoader_Adjust_Points   ( loader );
00317     FT_GlyphLoader_Adjust_Subglyphs( loader );
00318   }
00319 
00320 
00321   /* add current glyph to the base image - and prepare for another */
00322   FT_BASE_DEF( void )
00323   FT_GlyphLoader_Add( FT_GlyphLoader  loader )
00324   {
00325     FT_GlyphLoad  base;
00326     FT_GlyphLoad  current;
00327 
00328     FT_UInt       n_curr_contours;
00329     FT_UInt       n_base_points;
00330     FT_UInt       n;
00331 
00332 
00333     if ( !loader )
00334       return;
00335 
00336     base    = &loader->base;
00337     current = &loader->current;
00338 
00339     n_curr_contours = current->outline.n_contours;
00340     n_base_points   = base->outline.n_points;
00341 
00342     base->outline.n_points =
00343       (short)( base->outline.n_points + current->outline.n_points );
00344     base->outline.n_contours =
00345       (short)( base->outline.n_contours + current->outline.n_contours );
00346 
00347     base->num_subglyphs += current->num_subglyphs;
00348 
00349     /* adjust contours count in newest outline */
00350     for ( n = 0; n < n_curr_contours; n++ )
00351       current->outline.contours[n] =
00352         (short)( current->outline.contours[n] + n_base_points );
00353 
00354     /* prepare for another new glyph image */
00355     FT_GlyphLoader_Prepare( loader );
00356   }
00357 
00358 
00359   FT_BASE_DEF( FT_Error )
00360   FT_GlyphLoader_CopyPoints( FT_GlyphLoader  target,
00361                              FT_GlyphLoader  source )
00362   {
00363     FT_Error  error;
00364     FT_UInt   num_points   = source->base.outline.n_points;
00365     FT_UInt   num_contours = source->base.outline.n_contours;
00366 
00367 
00368     error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );
00369     if ( !error )
00370     {
00371       FT_Outline*  out = &target->base.outline;
00372       FT_Outline*  in  = &source->base.outline;
00373 
00374 
00375       FT_ARRAY_COPY( out->points, in->points,
00376                      num_points );
00377       FT_ARRAY_COPY( out->tags, in->tags,
00378                      num_points );
00379       FT_ARRAY_COPY( out->contours, in->contours,
00380                      num_contours );
00381 
00382       /* do we need to copy the extra points? */
00383       if ( target->use_extra && source->use_extra )
00384       {
00385         FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points,
00386                        num_points );
00387         FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2,
00388                        num_points );
00389       }
00390 
00391       out->n_points   = (short)num_points;
00392       out->n_contours = (short)num_contours;
00393 
00394       FT_GlyphLoader_Adjust_Points( target );
00395     }
00396 
00397     return error;
00398   }
00399 
00400 
00401 /* END */

Generated on Tue Jul 5 14:13:42 2011 for ROOT_528-00b_version by  doxygen 1.5.1