misc/libfreetype/src/base/ftglyph.c
branchwebgl
changeset 9521 8054d9d775fd
parent 9282 92af50454cf2
parent 9519 b8b5c82eb61b
child 9950 2759212a27de
equal deleted inserted replaced
9282:92af50454cf2 9521:8054d9d775fd
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ftglyph.c                                                              */
       
     4 /*                                                                         */
       
     5 /*    FreeType convenience functions to handle glyphs (body).              */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008, 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   /*                                                                       */
       
    20   /*  This file contains the definition of several convenience functions   */
       
    21   /*  that can be used by client applications to easily retrieve glyph     */
       
    22   /*  bitmaps and outlines from a given face.                              */
       
    23   /*                                                                       */
       
    24   /*  These functions should be optional if you are writing a font server  */
       
    25   /*  or text layout engine on top of FreeType.  However, they are pretty  */
       
    26   /*  handy for many other simple uses of the library.                     */
       
    27   /*                                                                       */
       
    28   /*************************************************************************/
       
    29 
       
    30 
       
    31 #include <ft2build.h>
       
    32 #include FT_GLYPH_H
       
    33 #include FT_OUTLINE_H
       
    34 #include FT_BITMAP_H
       
    35 #include FT_INTERNAL_OBJECTS_H
       
    36 
       
    37 #include "basepic.h"
       
    38 
       
    39   /*************************************************************************/
       
    40   /*                                                                       */
       
    41   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    42   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    43   /* messages during execution.                                            */
       
    44   /*                                                                       */
       
    45 #undef  FT_COMPONENT
       
    46 #define FT_COMPONENT  trace_glyph
       
    47 
       
    48 
       
    49   /*************************************************************************/
       
    50   /*************************************************************************/
       
    51   /****                                                                 ****/
       
    52   /****   FT_BitmapGlyph support                                        ****/
       
    53   /****                                                                 ****/
       
    54   /*************************************************************************/
       
    55   /*************************************************************************/
       
    56 
       
    57   FT_CALLBACK_DEF( FT_Error )
       
    58   ft_bitmap_glyph_init( FT_Glyph      bitmap_glyph,
       
    59                         FT_GlyphSlot  slot )
       
    60   {
       
    61     FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
       
    62     FT_Error        error   = FT_Err_Ok;
       
    63     FT_Library      library = FT_GLYPH( glyph )->library;
       
    64 
       
    65 
       
    66     if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
       
    67     {
       
    68       error = FT_Err_Invalid_Glyph_Format;
       
    69       goto Exit;
       
    70     }
       
    71 
       
    72     glyph->left = slot->bitmap_left;
       
    73     glyph->top  = slot->bitmap_top;
       
    74 
       
    75     /* do lazy copying whenever possible */
       
    76     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
       
    77     {
       
    78       glyph->bitmap = slot->bitmap;
       
    79       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
       
    80     }
       
    81     else
       
    82     {
       
    83       FT_Bitmap_New( &glyph->bitmap );
       
    84       error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
       
    85     }
       
    86 
       
    87   Exit:
       
    88     return error;
       
    89   }
       
    90 
       
    91 
       
    92   FT_CALLBACK_DEF( FT_Error )
       
    93   ft_bitmap_glyph_copy( FT_Glyph  bitmap_source,
       
    94                         FT_Glyph  bitmap_target )
       
    95   {
       
    96     FT_Library      library = bitmap_source->library;
       
    97     FT_BitmapGlyph  source  = (FT_BitmapGlyph)bitmap_source;
       
    98     FT_BitmapGlyph  target  = (FT_BitmapGlyph)bitmap_target;
       
    99 
       
   100 
       
   101     target->left = source->left;
       
   102     target->top  = source->top;
       
   103 
       
   104     return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
       
   105   }
       
   106 
       
   107 
       
   108   FT_CALLBACK_DEF( void )
       
   109   ft_bitmap_glyph_done( FT_Glyph  bitmap_glyph )
       
   110   {
       
   111     FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
       
   112     FT_Library      library = FT_GLYPH( glyph )->library;
       
   113 
       
   114 
       
   115     FT_Bitmap_Done( library, &glyph->bitmap );
       
   116   }
       
   117 
       
   118 
       
   119   FT_CALLBACK_DEF( void )
       
   120   ft_bitmap_glyph_bbox( FT_Glyph  bitmap_glyph,
       
   121                         FT_BBox*  cbox )
       
   122   {
       
   123     FT_BitmapGlyph  glyph = (FT_BitmapGlyph)bitmap_glyph;
       
   124 
       
   125 
       
   126     cbox->xMin = glyph->left << 6;
       
   127     cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
       
   128     cbox->yMax = glyph->top << 6;
       
   129     cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
       
   130   }
       
   131 
       
   132 
       
   133   FT_DEFINE_GLYPH(ft_bitmap_glyph_class,
       
   134     sizeof ( FT_BitmapGlyphRec ),
       
   135     FT_GLYPH_FORMAT_BITMAP,
       
   136 
       
   137     ft_bitmap_glyph_init,
       
   138     ft_bitmap_glyph_done,
       
   139     ft_bitmap_glyph_copy,
       
   140     0,                          /* FT_Glyph_TransformFunc */
       
   141     ft_bitmap_glyph_bbox,
       
   142     0                           /* FT_Glyph_PrepareFunc   */
       
   143   )
       
   144 
       
   145 
       
   146   /*************************************************************************/
       
   147   /*************************************************************************/
       
   148   /****                                                                 ****/
       
   149   /****   FT_OutlineGlyph support                                       ****/
       
   150   /****                                                                 ****/
       
   151   /*************************************************************************/
       
   152   /*************************************************************************/
       
   153 
       
   154 
       
   155   FT_CALLBACK_DEF( FT_Error )
       
   156   ft_outline_glyph_init( FT_Glyph      outline_glyph,
       
   157                          FT_GlyphSlot  slot )
       
   158   {
       
   159     FT_OutlineGlyph  glyph   = (FT_OutlineGlyph)outline_glyph;
       
   160     FT_Error         error   = FT_Err_Ok;
       
   161     FT_Library       library = FT_GLYPH( glyph )->library;
       
   162     FT_Outline*      source  = &slot->outline;
       
   163     FT_Outline*      target  = &glyph->outline;
       
   164 
       
   165 
       
   166     /* check format in glyph slot */
       
   167     if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
       
   168     {
       
   169       error = FT_Err_Invalid_Glyph_Format;
       
   170       goto Exit;
       
   171     }
       
   172 
       
   173     /* allocate new outline */
       
   174     error = FT_Outline_New( library, source->n_points, source->n_contours,
       
   175                             &glyph->outline );
       
   176     if ( error )
       
   177       goto Exit;
       
   178 
       
   179     FT_Outline_Copy( source, target );
       
   180 
       
   181   Exit:
       
   182     return error;
       
   183   }
       
   184 
       
   185 
       
   186   FT_CALLBACK_DEF( void )
       
   187   ft_outline_glyph_done( FT_Glyph  outline_glyph )
       
   188   {
       
   189     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
       
   190 
       
   191 
       
   192     FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
       
   193   }
       
   194 
       
   195 
       
   196   FT_CALLBACK_DEF( FT_Error )
       
   197   ft_outline_glyph_copy( FT_Glyph  outline_source,
       
   198                          FT_Glyph  outline_target )
       
   199   {
       
   200     FT_OutlineGlyph  source  = (FT_OutlineGlyph)outline_source;
       
   201     FT_OutlineGlyph  target  = (FT_OutlineGlyph)outline_target;
       
   202     FT_Error         error;
       
   203     FT_Library       library = FT_GLYPH( source )->library;
       
   204 
       
   205 
       
   206     error = FT_Outline_New( library, source->outline.n_points,
       
   207                             source->outline.n_contours, &target->outline );
       
   208     if ( !error )
       
   209       FT_Outline_Copy( &source->outline, &target->outline );
       
   210 
       
   211     return error;
       
   212   }
       
   213 
       
   214 
       
   215   FT_CALLBACK_DEF( void )
       
   216   ft_outline_glyph_transform( FT_Glyph          outline_glyph,
       
   217                               const FT_Matrix*  matrix,
       
   218                               const FT_Vector*  delta )
       
   219   {
       
   220     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
       
   221 
       
   222 
       
   223     if ( matrix )
       
   224       FT_Outline_Transform( &glyph->outline, matrix );
       
   225 
       
   226     if ( delta )
       
   227       FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
       
   228   }
       
   229 
       
   230 
       
   231   FT_CALLBACK_DEF( void )
       
   232   ft_outline_glyph_bbox( FT_Glyph  outline_glyph,
       
   233                          FT_BBox*  bbox )
       
   234   {
       
   235     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
       
   236 
       
   237 
       
   238     FT_Outline_Get_CBox( &glyph->outline, bbox );
       
   239   }
       
   240 
       
   241 
       
   242   FT_CALLBACK_DEF( FT_Error )
       
   243   ft_outline_glyph_prepare( FT_Glyph      outline_glyph,
       
   244                             FT_GlyphSlot  slot )
       
   245   {
       
   246     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
       
   247 
       
   248 
       
   249     slot->format         = FT_GLYPH_FORMAT_OUTLINE;
       
   250     slot->outline        = glyph->outline;
       
   251     slot->outline.flags &= ~FT_OUTLINE_OWNER;
       
   252 
       
   253     return FT_Err_Ok;
       
   254   }
       
   255 
       
   256 
       
   257   FT_DEFINE_GLYPH( ft_outline_glyph_class, 
       
   258     sizeof ( FT_OutlineGlyphRec ),
       
   259     FT_GLYPH_FORMAT_OUTLINE,
       
   260 
       
   261     ft_outline_glyph_init,
       
   262     ft_outline_glyph_done,
       
   263     ft_outline_glyph_copy,
       
   264     ft_outline_glyph_transform,
       
   265     ft_outline_glyph_bbox,
       
   266     ft_outline_glyph_prepare
       
   267   )
       
   268 
       
   269 
       
   270   /*************************************************************************/
       
   271   /*************************************************************************/
       
   272   /****                                                                 ****/
       
   273   /****   FT_Glyph class and API                                        ****/
       
   274   /****                                                                 ****/
       
   275   /*************************************************************************/
       
   276   /*************************************************************************/
       
   277 
       
   278    static FT_Error
       
   279    ft_new_glyph( FT_Library             library,
       
   280                  const FT_Glyph_Class*  clazz,
       
   281                  FT_Glyph*              aglyph )
       
   282    {
       
   283      FT_Memory  memory = library->memory;
       
   284      FT_Error   error;
       
   285      FT_Glyph   glyph  = NULL;
       
   286 
       
   287 
       
   288      *aglyph = 0;
       
   289 
       
   290      if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
       
   291      {
       
   292        glyph->library = library;
       
   293        glyph->clazz   = clazz;
       
   294        glyph->format  = clazz->glyph_format;
       
   295 
       
   296        *aglyph = glyph;
       
   297      }
       
   298 
       
   299      return error;
       
   300    }
       
   301 
       
   302 
       
   303   /* documentation is in ftglyph.h */
       
   304 
       
   305   FT_EXPORT_DEF( FT_Error )
       
   306   FT_Glyph_Copy( FT_Glyph   source,
       
   307                  FT_Glyph  *target )
       
   308   {
       
   309     FT_Glyph               copy;
       
   310     FT_Error               error;
       
   311     const FT_Glyph_Class*  clazz;
       
   312 
       
   313 
       
   314     /* check arguments */
       
   315     if ( !target )
       
   316     {
       
   317       error = FT_Err_Invalid_Argument;
       
   318       goto Exit;
       
   319     }
       
   320 
       
   321     *target = 0;
       
   322 
       
   323     if ( !source || !source->clazz )
       
   324     {
       
   325       error = FT_Err_Invalid_Argument;
       
   326       goto Exit;
       
   327     }
       
   328 
       
   329     clazz = source->clazz;
       
   330     error = ft_new_glyph( source->library, clazz, &copy );
       
   331     if ( error )
       
   332       goto Exit;
       
   333 
       
   334     copy->advance = source->advance;
       
   335     copy->format  = source->format;
       
   336 
       
   337     if ( clazz->glyph_copy )
       
   338       error = clazz->glyph_copy( source, copy );
       
   339 
       
   340     if ( error )
       
   341       FT_Done_Glyph( copy );
       
   342     else
       
   343       *target = copy;
       
   344 
       
   345   Exit:
       
   346     return error;
       
   347   }
       
   348 
       
   349 
       
   350   /* documentation is in ftglyph.h */
       
   351 
       
   352   FT_EXPORT_DEF( FT_Error )
       
   353   FT_Get_Glyph( FT_GlyphSlot  slot,
       
   354                 FT_Glyph     *aglyph )
       
   355   {
       
   356     FT_Library  library;
       
   357     FT_Error    error;
       
   358     FT_Glyph    glyph;
       
   359 
       
   360     const FT_Glyph_Class*  clazz = 0;
       
   361 
       
   362 
       
   363     if ( !slot )
       
   364       return FT_Err_Invalid_Slot_Handle;
       
   365 
       
   366     library = slot->library;
       
   367 
       
   368     if ( !aglyph )
       
   369       return FT_Err_Invalid_Argument;
       
   370 
       
   371     /* if it is a bitmap, that's easy :-) */
       
   372     if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
       
   373       clazz = FT_BITMAP_GLYPH_CLASS_GET;
       
   374 
       
   375     /* if it is an outline */
       
   376     else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
       
   377       clazz = FT_OUTLINE_GLYPH_CLASS_GET;
       
   378 
       
   379     else
       
   380     {
       
   381       /* try to find a renderer that supports the glyph image format */
       
   382       FT_Renderer  render = FT_Lookup_Renderer( library, slot->format, 0 );
       
   383 
       
   384 
       
   385       if ( render )
       
   386         clazz = &render->glyph_class;
       
   387     }
       
   388 
       
   389     if ( !clazz )
       
   390     {
       
   391       error = FT_Err_Invalid_Glyph_Format;
       
   392       goto Exit;
       
   393     }
       
   394 
       
   395     /* create FT_Glyph object */
       
   396     error = ft_new_glyph( library, clazz, &glyph );
       
   397     if ( error )
       
   398       goto Exit;
       
   399 
       
   400     /* copy advance while converting it to 16.16 format */
       
   401     glyph->advance.x = slot->advance.x << 10;
       
   402     glyph->advance.y = slot->advance.y << 10;
       
   403 
       
   404     /* now import the image from the glyph slot */
       
   405     error = clazz->glyph_init( glyph, slot );
       
   406 
       
   407     /* if an error occurred, destroy the glyph */
       
   408     if ( error )
       
   409       FT_Done_Glyph( glyph );
       
   410     else
       
   411       *aglyph = glyph;
       
   412 
       
   413   Exit:
       
   414     return error;
       
   415   }
       
   416 
       
   417 
       
   418   /* documentation is in ftglyph.h */
       
   419 
       
   420   FT_EXPORT_DEF( FT_Error )
       
   421   FT_Glyph_Transform( FT_Glyph    glyph,
       
   422                       FT_Matrix*  matrix,
       
   423                       FT_Vector*  delta )
       
   424   {
       
   425     const FT_Glyph_Class*  clazz;
       
   426     FT_Error               error = FT_Err_Ok;
       
   427 
       
   428 
       
   429     if ( !glyph || !glyph->clazz )
       
   430       error = FT_Err_Invalid_Argument;
       
   431     else
       
   432     {
       
   433       clazz = glyph->clazz;
       
   434       if ( clazz->glyph_transform )
       
   435       {
       
   436         /* transform glyph image */
       
   437         clazz->glyph_transform( glyph, matrix, delta );
       
   438 
       
   439         /* transform advance vector */
       
   440         if ( matrix )
       
   441           FT_Vector_Transform( &glyph->advance, matrix );
       
   442       }
       
   443       else
       
   444         error = FT_Err_Invalid_Glyph_Format;
       
   445     }
       
   446     return error;
       
   447   }
       
   448 
       
   449 
       
   450   /* documentation is in ftglyph.h */
       
   451 
       
   452   FT_EXPORT_DEF( void )
       
   453   FT_Glyph_Get_CBox( FT_Glyph  glyph,
       
   454                      FT_UInt   bbox_mode,
       
   455                      FT_BBox  *acbox )
       
   456   {
       
   457     const FT_Glyph_Class*  clazz;
       
   458 
       
   459 
       
   460     if ( !acbox )
       
   461       return;
       
   462 
       
   463     acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
       
   464 
       
   465     if ( !glyph || !glyph->clazz )
       
   466       return;
       
   467     else
       
   468     {
       
   469       clazz = glyph->clazz;
       
   470       if ( !clazz->glyph_bbox )
       
   471         return;
       
   472       else
       
   473       {
       
   474         /* retrieve bbox in 26.6 coordinates */
       
   475         clazz->glyph_bbox( glyph, acbox );
       
   476 
       
   477         /* perform grid fitting if needed */
       
   478         if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
       
   479              bbox_mode == FT_GLYPH_BBOX_PIXELS  )
       
   480         {
       
   481           acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
       
   482           acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
       
   483           acbox->xMax = FT_PIX_CEIL( acbox->xMax );
       
   484           acbox->yMax = FT_PIX_CEIL( acbox->yMax );
       
   485         }
       
   486 
       
   487         /* convert to integer pixels if needed */
       
   488         if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
       
   489              bbox_mode == FT_GLYPH_BBOX_PIXELS   )
       
   490         {
       
   491           acbox->xMin >>= 6;
       
   492           acbox->yMin >>= 6;
       
   493           acbox->xMax >>= 6;
       
   494           acbox->yMax >>= 6;
       
   495         }
       
   496       }
       
   497     }
       
   498     return;
       
   499   }
       
   500 
       
   501 
       
   502   /* documentation is in ftglyph.h */
       
   503 
       
   504   FT_EXPORT_DEF( FT_Error )
       
   505   FT_Glyph_To_Bitmap( FT_Glyph*       the_glyph,
       
   506                       FT_Render_Mode  render_mode,
       
   507                       FT_Vector*      origin,
       
   508                       FT_Bool         destroy )
       
   509   {
       
   510     FT_GlyphSlotRec           dummy;
       
   511     FT_GlyphSlot_InternalRec  dummy_internal;
       
   512     FT_Error                  error = FT_Err_Ok;
       
   513     FT_Glyph                  glyph;
       
   514     FT_BitmapGlyph            bitmap = NULL;
       
   515 
       
   516     const FT_Glyph_Class*     clazz;
       
   517 
       
   518 #ifdef FT_CONFIG_OPTION_PIC
       
   519     FT_Library                library = FT_GLYPH( glyph )->library;
       
   520 #endif
       
   521 
       
   522 
       
   523     /* check argument */
       
   524     if ( !the_glyph )
       
   525       goto Bad;
       
   526 
       
   527     /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
       
   528     /* then calling FT_Render_Glyph_Internal()                            */
       
   529 
       
   530     glyph = *the_glyph;
       
   531     if ( !glyph )
       
   532       goto Bad;
       
   533 
       
   534     clazz = glyph->clazz;
       
   535 
       
   536     /* when called with a bitmap glyph, do nothing and return successfully */
       
   537     if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
       
   538       goto Exit;
       
   539 
       
   540     if ( !clazz || !clazz->glyph_prepare )
       
   541       goto Bad;
       
   542 
       
   543     FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
       
   544     FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
       
   545     dummy.internal = &dummy_internal;
       
   546     dummy.library  = glyph->library;
       
   547     dummy.format   = clazz->glyph_format;
       
   548 
       
   549     /* create result bitmap glyph */
       
   550     error = ft_new_glyph( glyph->library, FT_BITMAP_GLYPH_CLASS_GET,
       
   551                           (FT_Glyph*)(void*)&bitmap );
       
   552     if ( error )
       
   553       goto Exit;
       
   554 
       
   555 #if 1
       
   556     /* if `origin' is set, translate the glyph image */
       
   557     if ( origin )
       
   558       FT_Glyph_Transform( glyph, 0, origin );
       
   559 #else
       
   560     FT_UNUSED( origin );
       
   561 #endif
       
   562 
       
   563     /* prepare dummy slot for rendering */
       
   564     error = clazz->glyph_prepare( glyph, &dummy );
       
   565     if ( !error )
       
   566       error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
       
   567 
       
   568 #if 1
       
   569     if ( !destroy && origin )
       
   570     {
       
   571       FT_Vector  v;
       
   572 
       
   573 
       
   574       v.x = -origin->x;
       
   575       v.y = -origin->y;
       
   576       FT_Glyph_Transform( glyph, 0, &v );
       
   577     }
       
   578 #endif
       
   579 
       
   580     if ( error )
       
   581       goto Exit;
       
   582 
       
   583     /* in case of success, copy the bitmap to the glyph bitmap */
       
   584     error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
       
   585     if ( error )
       
   586       goto Exit;
       
   587 
       
   588     /* copy advance */
       
   589     bitmap->root.advance = glyph->advance;
       
   590 
       
   591     if ( destroy )
       
   592       FT_Done_Glyph( glyph );
       
   593 
       
   594     *the_glyph = FT_GLYPH( bitmap );
       
   595 
       
   596   Exit:
       
   597     if ( error && bitmap )
       
   598       FT_Done_Glyph( FT_GLYPH( bitmap ) );
       
   599 
       
   600     return error;
       
   601 
       
   602   Bad:
       
   603     error = FT_Err_Invalid_Argument;
       
   604     goto Exit;
       
   605   }
       
   606 
       
   607 
       
   608   /* documentation is in ftglyph.h */
       
   609 
       
   610   FT_EXPORT_DEF( void )
       
   611   FT_Done_Glyph( FT_Glyph  glyph )
       
   612   {
       
   613     if ( glyph )
       
   614     {
       
   615       FT_Memory              memory = glyph->library->memory;
       
   616       const FT_Glyph_Class*  clazz  = glyph->clazz;
       
   617 
       
   618 
       
   619       if ( clazz->glyph_done )
       
   620         clazz->glyph_done( glyph );
       
   621 
       
   622       FT_FREE( glyph );
       
   623     }
       
   624   }
       
   625 
       
   626 
       
   627 /* END */