misc/libfreetype/src/base/ftgloadr.c
changeset 5172 88f2e05288ba
equal deleted inserted replaced
5171:f9283dc4860d 5172:88f2e05288ba
       
     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 */