(root)/
freetype-2.13.2/
src/
base/
ftglyph.c
       1  /****************************************************************************
       2   *
       3   * ftglyph.c
       4   *
       5   *   FreeType convenience functions to handle glyphs (body).
       6   *
       7   * Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h>
      32  
      33  #include <freetype/ftglyph.h>
      34  #include <freetype/ftoutln.h>
      35  #include <freetype/ftbitmap.h>
      36  #include <freetype/internal/ftobjs.h>
      37  #include <freetype/otsvg.h>
      38  
      39  #include "ftbase.h"
      40  
      41  
      42    /**************************************************************************
      43     *
      44     * The macro FT_COMPONENT is used in trace mode.  It is an implicit
      45     * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
      46     * messages during execution.
      47     */
      48  #undef  FT_COMPONENT
      49  #define FT_COMPONENT  glyph
      50  
      51  
      52    /*************************************************************************/
      53    /*************************************************************************/
      54    /****                                                                 ****/
      55    /****   FT_BitmapGlyph support                                        ****/
      56    /****                                                                 ****/
      57    /*************************************************************************/
      58    /*************************************************************************/
      59  
      60    FT_CALLBACK_DEF( FT_Error )
      61    ft_bitmap_glyph_init( FT_Glyph      bitmap_glyph,
      62                          FT_GlyphSlot  slot )
      63    {
      64      FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
      65      FT_Error        error   = FT_Err_Ok;
      66      FT_Library      library = FT_GLYPH( glyph )->library;
      67  
      68  
      69      if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
      70      {
      71        error = FT_THROW( Invalid_Glyph_Format );
      72        goto Exit;
      73      }
      74  
      75      glyph->left = slot->bitmap_left;
      76      glyph->top  = slot->bitmap_top;
      77  
      78      /* do lazy copying whenever possible */
      79      if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
      80      {
      81        glyph->bitmap          = slot->bitmap;
      82        slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
      83      }
      84      else
      85      {
      86        FT_Bitmap_Init( &glyph->bitmap );
      87        error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
      88      }
      89  
      90    Exit:
      91      return error;
      92    }
      93  
      94  
      95    FT_CALLBACK_DEF( FT_Error )
      96    ft_bitmap_glyph_copy( FT_Glyph  bitmap_source,
      97                          FT_Glyph  bitmap_target )
      98    {
      99      FT_Library      library = bitmap_source->library;
     100      FT_BitmapGlyph  source  = (FT_BitmapGlyph)bitmap_source;
     101      FT_BitmapGlyph  target  = (FT_BitmapGlyph)bitmap_target;
     102  
     103  
     104      target->left = source->left;
     105      target->top  = source->top;
     106  
     107      return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
     108    }
     109  
     110  
     111    FT_CALLBACK_DEF( void )
     112    ft_bitmap_glyph_done( FT_Glyph  bitmap_glyph )
     113    {
     114      FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
     115      FT_Library      library = FT_GLYPH( glyph )->library;
     116  
     117  
     118      FT_Bitmap_Done( library, &glyph->bitmap );
     119    }
     120  
     121  
     122    FT_CALLBACK_DEF( void )
     123    ft_bitmap_glyph_bbox( FT_Glyph  bitmap_glyph,
     124                          FT_BBox*  cbox )
     125    {
     126      FT_BitmapGlyph  glyph = (FT_BitmapGlyph)bitmap_glyph;
     127  
     128  
     129      cbox->xMin = glyph->left * 64;
     130      cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 );
     131      cbox->yMax = glyph->top * 64;
     132      cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 );
     133    }
     134  
     135  
     136    FT_DEFINE_GLYPH(
     137      ft_bitmap_glyph_class,
     138  
     139      sizeof ( FT_BitmapGlyphRec ),
     140      FT_GLYPH_FORMAT_BITMAP,
     141  
     142      ft_bitmap_glyph_init,    /* FT_Glyph_InitFunc       glyph_init      */
     143      ft_bitmap_glyph_done,    /* FT_Glyph_DoneFunc       glyph_done      */
     144      ft_bitmap_glyph_copy,    /* FT_Glyph_CopyFunc       glyph_copy      */
     145      NULL,                    /* FT_Glyph_TransformFunc  glyph_transform */
     146      ft_bitmap_glyph_bbox,    /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
     147      NULL                     /* FT_Glyph_PrepareFunc    glyph_prepare   */
     148    )
     149  
     150  
     151    /*************************************************************************/
     152    /*************************************************************************/
     153    /****                                                                 ****/
     154    /****   FT_OutlineGlyph support                                       ****/
     155    /****                                                                 ****/
     156    /*************************************************************************/
     157    /*************************************************************************/
     158  
     159  
     160    FT_CALLBACK_DEF( FT_Error )
     161    ft_outline_glyph_init( FT_Glyph      outline_glyph,
     162                           FT_GlyphSlot  slot )
     163    {
     164      FT_OutlineGlyph  glyph   = (FT_OutlineGlyph)outline_glyph;
     165      FT_Error         error   = FT_Err_Ok;
     166      FT_Library       library = FT_GLYPH( glyph )->library;
     167      FT_Outline*      source  = &slot->outline;
     168      FT_Outline*      target  = &glyph->outline;
     169  
     170  
     171      /* check format in glyph slot */
     172      if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
     173      {
     174        error = FT_THROW( Invalid_Glyph_Format );
     175        goto Exit;
     176      }
     177  
     178      /* allocate new outline */
     179      error = FT_Outline_New( library,
     180                              (FT_UInt)source->n_points,
     181                              source->n_contours,
     182                              &glyph->outline );
     183      if ( error )
     184        goto Exit;
     185  
     186      FT_Outline_Copy( source, target );
     187  
     188    Exit:
     189      return error;
     190    }
     191  
     192  
     193    FT_CALLBACK_DEF( void )
     194    ft_outline_glyph_done( FT_Glyph  outline_glyph )
     195    {
     196      FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
     197  
     198  
     199      FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
     200    }
     201  
     202  
     203    FT_CALLBACK_DEF( FT_Error )
     204    ft_outline_glyph_copy( FT_Glyph  outline_source,
     205                           FT_Glyph  outline_target )
     206    {
     207      FT_OutlineGlyph  source  = (FT_OutlineGlyph)outline_source;
     208      FT_OutlineGlyph  target  = (FT_OutlineGlyph)outline_target;
     209      FT_Error         error;
     210      FT_Library       library = FT_GLYPH( source )->library;
     211  
     212  
     213      error = FT_Outline_New( library,
     214                              (FT_UInt)source->outline.n_points,
     215                              source->outline.n_contours,
     216                              &target->outline );
     217      if ( !error )
     218        FT_Outline_Copy( &source->outline, &target->outline );
     219  
     220      return error;
     221    }
     222  
     223  
     224    FT_CALLBACK_DEF( void )
     225    ft_outline_glyph_transform( FT_Glyph          outline_glyph,
     226                                const FT_Matrix*  matrix,
     227                                const FT_Vector*  delta )
     228    {
     229      FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
     230  
     231  
     232      if ( matrix )
     233        FT_Outline_Transform( &glyph->outline, matrix );
     234  
     235      if ( delta )
     236        FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
     237    }
     238  
     239  
     240    FT_CALLBACK_DEF( void )
     241    ft_outline_glyph_bbox( FT_Glyph  outline_glyph,
     242                           FT_BBox*  bbox )
     243    {
     244      FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
     245  
     246  
     247      FT_Outline_Get_CBox( &glyph->outline, bbox );
     248    }
     249  
     250  
     251    FT_CALLBACK_DEF( FT_Error )
     252    ft_outline_glyph_prepare( FT_Glyph      outline_glyph,
     253                              FT_GlyphSlot  slot )
     254    {
     255      FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
     256  
     257  
     258      slot->format         = FT_GLYPH_FORMAT_OUTLINE;
     259      slot->outline        = glyph->outline;
     260      slot->outline.flags &= ~FT_OUTLINE_OWNER;
     261  
     262      return FT_Err_Ok;
     263    }
     264  
     265  
     266    FT_DEFINE_GLYPH(
     267      ft_outline_glyph_class,
     268  
     269      sizeof ( FT_OutlineGlyphRec ),
     270      FT_GLYPH_FORMAT_OUTLINE,
     271  
     272      ft_outline_glyph_init,      /* FT_Glyph_InitFunc       glyph_init      */
     273      ft_outline_glyph_done,      /* FT_Glyph_DoneFunc       glyph_done      */
     274      ft_outline_glyph_copy,      /* FT_Glyph_CopyFunc       glyph_copy      */
     275      ft_outline_glyph_transform, /* FT_Glyph_TransformFunc  glyph_transform */
     276      ft_outline_glyph_bbox,      /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
     277      ft_outline_glyph_prepare    /* FT_Glyph_PrepareFunc    glyph_prepare   */
     278    )
     279  
     280  
     281  #ifdef FT_CONFIG_OPTION_SVG
     282  
     283    /*************************************************************************/
     284    /*************************************************************************/
     285    /****                                                                 ****/
     286    /****   FT_SvgGlyph support                                           ****/
     287    /****                                                                 ****/
     288    /*************************************************************************/
     289    /*************************************************************************/
     290  
     291  
     292    FT_CALLBACK_DEF( FT_Error )
     293    ft_svg_glyph_init( FT_Glyph      svg_glyph,
     294                       FT_GlyphSlot  slot )
     295    {
     296      FT_ULong         doc_length;
     297      FT_SVG_Document  document;
     298      FT_SvgGlyph      glyph = (FT_SvgGlyph)svg_glyph;
     299  
     300      FT_Error   error  = FT_Err_Ok;
     301      FT_Memory  memory = FT_GLYPH( glyph )->library->memory;
     302  
     303  
     304      if ( slot->format != FT_GLYPH_FORMAT_SVG )
     305      {
     306        error = FT_THROW( Invalid_Glyph_Format );
     307        goto Exit;
     308      }
     309  
     310      if ( slot->other == NULL )
     311      {
     312        error = FT_THROW( Invalid_Slot_Handle );
     313        goto Exit;
     314      }
     315  
     316      document = (FT_SVG_Document)slot->other;
     317  
     318      if ( document->svg_document_length == 0 )
     319      {
     320        error = FT_THROW( Invalid_Slot_Handle );
     321        goto Exit;
     322      }
     323  
     324      /* allocate a new document */
     325      doc_length = document->svg_document_length;
     326      if ( FT_QALLOC( glyph->svg_document, doc_length ) )
     327        goto Exit;
     328      glyph->svg_document_length = doc_length;
     329  
     330      glyph->glyph_index = slot->glyph_index;
     331  
     332      glyph->metrics      = document->metrics;
     333      glyph->units_per_EM = document->units_per_EM;
     334  
     335      glyph->start_glyph_id = document->start_glyph_id;
     336      glyph->end_glyph_id   = document->end_glyph_id;
     337  
     338      glyph->transform = document->transform;
     339      glyph->delta     = document->delta;
     340  
     341      /* copy the document into glyph */
     342      FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length );
     343  
     344    Exit:
     345      return error;
     346    }
     347  
     348  
     349    FT_CALLBACK_DEF( void )
     350    ft_svg_glyph_done( FT_Glyph  svg_glyph )
     351    {
     352      FT_SvgGlyph  glyph  = (FT_SvgGlyph)svg_glyph;
     353      FT_Memory    memory = svg_glyph->library->memory;
     354  
     355  
     356      /* just free the memory */
     357      FT_FREE( glyph->svg_document );
     358    }
     359  
     360  
     361    FT_CALLBACK_DEF( FT_Error )
     362    ft_svg_glyph_copy( FT_Glyph  svg_source,
     363                       FT_Glyph  svg_target )
     364    {
     365      FT_SvgGlyph  source = (FT_SvgGlyph)svg_source;
     366      FT_SvgGlyph  target = (FT_SvgGlyph)svg_target;
     367  
     368      FT_Error   error  = FT_Err_Ok;
     369      FT_Memory  memory = FT_GLYPH( source )->library->memory;
     370  
     371  
     372      if ( svg_source->format != FT_GLYPH_FORMAT_SVG )
     373      {
     374        error = FT_THROW( Invalid_Glyph_Format );
     375        goto Exit;
     376      }
     377  
     378      if ( source->svg_document_length == 0 )
     379      {
     380        error = FT_THROW( Invalid_Slot_Handle );
     381        goto Exit;
     382      }
     383  
     384      target->glyph_index = source->glyph_index;
     385  
     386      target->svg_document_length = source->svg_document_length;
     387  
     388      target->metrics      = source->metrics;
     389      target->units_per_EM = source->units_per_EM;
     390  
     391      target->start_glyph_id = source->start_glyph_id;
     392      target->end_glyph_id   = source->end_glyph_id;
     393  
     394      target->transform = source->transform;
     395      target->delta     = source->delta;
     396  
     397      /* allocate space for the SVG document */
     398      if ( FT_QALLOC( target->svg_document, target->svg_document_length ) )
     399        goto Exit;
     400  
     401      /* copy the document */
     402      FT_MEM_COPY( target->svg_document,
     403                   source->svg_document,
     404                   target->svg_document_length );
     405  
     406    Exit:
     407      return error;
     408    }
     409  
     410  
     411    FT_CALLBACK_DEF( void )
     412    ft_svg_glyph_transform( FT_Glyph          svg_glyph,
     413                            const FT_Matrix*  _matrix,
     414                            const FT_Vector*  _delta )
     415    {
     416      FT_SvgGlyph  glyph  = (FT_SvgGlyph)svg_glyph;
     417      FT_Matrix*   matrix = (FT_Matrix*)_matrix;
     418      FT_Vector*   delta  = (FT_Vector*)_delta;
     419  
     420      FT_Matrix  tmp_matrix;
     421      FT_Vector  tmp_delta;
     422  
     423      FT_Matrix  a, b;
     424      FT_Pos     x, y;
     425  
     426  
     427      if ( !matrix )
     428      {
     429        tmp_matrix.xx = 0x10000;
     430        tmp_matrix.xy = 0;
     431        tmp_matrix.yx = 0;
     432        tmp_matrix.yy = 0x10000;
     433  
     434        matrix = &tmp_matrix;
     435      }
     436  
     437      if ( !delta )
     438      {
     439        tmp_delta.x = 0;
     440        tmp_delta.y = 0;
     441  
     442        delta = &tmp_delta;
     443      }
     444  
     445      a = glyph->transform;
     446      b = *matrix;
     447      FT_Matrix_Multiply( &b, &a );
     448  
     449      x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, glyph->delta.x ),
     450                              FT_MulFix( matrix->xy, glyph->delta.y ) ),
     451                    delta->x );
     452      y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, glyph->delta.x ),
     453                              FT_MulFix( matrix->yy, glyph->delta.y ) ),
     454                    delta->y );
     455  
     456      glyph->delta.x = x;
     457      glyph->delta.y = y;
     458  
     459      glyph->transform = a;
     460    }
     461  
     462  
     463    FT_CALLBACK_DEF( FT_Error )
     464    ft_svg_glyph_prepare( FT_Glyph      svg_glyph,
     465                          FT_GlyphSlot  slot )
     466    {
     467      FT_SvgGlyph  glyph = (FT_SvgGlyph)svg_glyph;
     468  
     469      FT_Error   error  = FT_Err_Ok;
     470      FT_Memory  memory = svg_glyph->library->memory;
     471  
     472      FT_SVG_Document  document = NULL;
     473  
     474  
     475      if ( FT_NEW( document ) )
     476        return error;
     477  
     478      document->svg_document        = glyph->svg_document;
     479      document->svg_document_length = glyph->svg_document_length;
     480  
     481      document->metrics      = glyph->metrics;
     482      document->units_per_EM = glyph->units_per_EM;
     483  
     484      document->start_glyph_id = glyph->start_glyph_id;
     485      document->end_glyph_id   = glyph->end_glyph_id;
     486  
     487      document->transform = glyph->transform;
     488      document->delta     = glyph->delta;
     489  
     490      slot->format      = FT_GLYPH_FORMAT_SVG;
     491      slot->glyph_index = glyph->glyph_index;
     492      slot->other       = document;
     493  
     494      return error;
     495    }
     496  
     497  
     498    FT_DEFINE_GLYPH(
     499      ft_svg_glyph_class,
     500  
     501      sizeof ( FT_SvgGlyphRec ),
     502      FT_GLYPH_FORMAT_SVG,
     503  
     504      ft_svg_glyph_init,      /* FT_Glyph_InitFunc       glyph_init      */
     505      ft_svg_glyph_done,      /* FT_Glyph_DoneFunc       glyph_done      */
     506      ft_svg_glyph_copy,      /* FT_Glyph_CopyFunc       glyph_copy      */
     507      ft_svg_glyph_transform, /* FT_Glyph_TransformFunc  glyph_transform */
     508      NULL,                   /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
     509      ft_svg_glyph_prepare    /* FT_Glyph_PrepareFunc    glyph_prepare   */
     510    )
     511  
     512  #endif /* FT_CONFIG_OPTION_SVG */
     513  
     514  
     515    /*************************************************************************/
     516    /*************************************************************************/
     517    /****                                                                 ****/
     518    /****   FT_Glyph class and API                                        ****/
     519    /****                                                                 ****/
     520    /*************************************************************************/
     521    /*************************************************************************/
     522  
     523     static FT_Error
     524     ft_new_glyph( FT_Library             library,
     525                   const FT_Glyph_Class*  clazz,
     526                   FT_Glyph*              aglyph )
     527     {
     528       FT_Memory  memory = library->memory;
     529       FT_Error   error;
     530       FT_Glyph   glyph  = NULL;
     531  
     532  
     533       *aglyph = NULL;
     534  
     535       if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
     536       {
     537         glyph->library = library;
     538         glyph->clazz   = clazz;
     539         glyph->format  = clazz->glyph_format;
     540  
     541         *aglyph = glyph;
     542       }
     543  
     544       return error;
     545     }
     546  
     547  
     548    /* documentation is in ftglyph.h */
     549  
     550    FT_EXPORT_DEF( FT_Error )
     551    FT_Glyph_Copy( FT_Glyph   source,
     552                   FT_Glyph  *target )
     553    {
     554      FT_Glyph               copy;
     555      FT_Error               error;
     556      const FT_Glyph_Class*  clazz;
     557  
     558  
     559      /* check arguments */
     560      if ( !target || !source || !source->clazz )
     561      {
     562        error = FT_THROW( Invalid_Argument );
     563        goto Exit;
     564      }
     565  
     566      *target = NULL;
     567  
     568      if ( !source || !source->clazz )
     569      {
     570        error = FT_THROW( Invalid_Argument );
     571        goto Exit;
     572      }
     573  
     574      clazz = source->clazz;
     575      error = ft_new_glyph( source->library, clazz, &copy );
     576      if ( error )
     577        goto Exit;
     578  
     579      copy->advance = source->advance;
     580      copy->format  = source->format;
     581  
     582      if ( clazz->glyph_copy )
     583        error = clazz->glyph_copy( source, copy );
     584  
     585      if ( error )
     586        FT_Done_Glyph( copy );
     587      else
     588        *target = copy;
     589  
     590    Exit:
     591      return error;
     592    }
     593  
     594  
     595    /* documentation is in ftglyph.h */
     596  
     597    FT_EXPORT( FT_Error )
     598    FT_New_Glyph( FT_Library       library,
     599                  FT_Glyph_Format  format,
     600                  FT_Glyph        *aglyph )
     601    {
     602      const FT_Glyph_Class*  clazz = NULL;
     603  
     604      if ( !library || !aglyph )
     605        return FT_THROW( Invalid_Argument );
     606  
     607      /* if it is a bitmap, that's easy :-) */
     608      if ( format == FT_GLYPH_FORMAT_BITMAP )
     609        clazz = &ft_bitmap_glyph_class;
     610  
     611      /* if it is an outline */
     612      else if ( format == FT_GLYPH_FORMAT_OUTLINE )
     613        clazz = &ft_outline_glyph_class;
     614  
     615  #ifdef FT_CONFIG_OPTION_SVG
     616      /* if it is an SVG glyph */
     617      else if ( format == FT_GLYPH_FORMAT_SVG )
     618        clazz = &ft_svg_glyph_class;
     619  #endif
     620  
     621      else
     622      {
     623        /* try to find a renderer that supports the glyph image format */
     624        FT_Renderer  render = FT_Lookup_Renderer( library, format, 0 );
     625  
     626  
     627        if ( render )
     628          clazz = &render->glyph_class;
     629      }
     630  
     631      if ( !clazz )
     632        return FT_THROW( Invalid_Glyph_Format );
     633  
     634      /* create FT_Glyph object */
     635      return ft_new_glyph( library, clazz, aglyph );
     636    }
     637  
     638  
     639    /* documentation is in ftglyph.h */
     640  
     641    FT_EXPORT_DEF( FT_Error )
     642    FT_Get_Glyph( FT_GlyphSlot  slot,
     643                  FT_Glyph     *aglyph )
     644    {
     645      FT_Error  error;
     646      FT_Glyph  glyph;
     647  
     648  
     649      if ( !slot )
     650        return FT_THROW( Invalid_Slot_Handle );
     651  
     652      if ( !aglyph )
     653        return FT_THROW( Invalid_Argument );
     654  
     655      /* create FT_Glyph object */
     656      error = FT_New_Glyph( slot->library, slot->format, &glyph );
     657      if ( error )
     658        goto Exit;
     659  
     660      /* copy advance while converting 26.6 to 16.16 format */
     661      if ( slot->advance.x >=  0x8000L * 64 ||
     662           slot->advance.x <= -0x8000L * 64 )
     663      {
     664        FT_ERROR(( "FT_Get_Glyph: advance width too large\n" ));
     665        error = FT_THROW( Invalid_Argument );
     666        goto Exit2;
     667      }
     668      if ( slot->advance.y >=  0x8000L * 64 ||
     669           slot->advance.y <= -0x8000L * 64 )
     670      {
     671        FT_ERROR(( "FT_Get_Glyph: advance height too large\n" ));
     672        error = FT_THROW( Invalid_Argument );
     673        goto Exit2;
     674      }
     675  
     676      glyph->advance.x = slot->advance.x * 1024;
     677      glyph->advance.y = slot->advance.y * 1024;
     678  
     679      /* now import the image from the glyph slot */
     680      error = glyph->clazz->glyph_init( glyph, slot );
     681  
     682    Exit2:
     683      /* if an error occurred, destroy the glyph */
     684      if ( error )
     685      {
     686        FT_Done_Glyph( glyph );
     687        *aglyph = NULL;
     688      }
     689      else
     690        *aglyph = glyph;
     691  
     692    Exit:
     693      return error;
     694    }
     695  
     696  
     697    /* documentation is in ftglyph.h */
     698  
     699    FT_EXPORT_DEF( FT_Error )
     700    FT_Glyph_Transform( FT_Glyph          glyph,
     701                        const FT_Matrix*  matrix,
     702                        const FT_Vector*  delta )
     703    {
     704      FT_Error  error = FT_Err_Ok;
     705  
     706  
     707      if ( !glyph || !glyph->clazz )
     708        error = FT_THROW( Invalid_Argument );
     709      else
     710      {
     711        const FT_Glyph_Class*  clazz = glyph->clazz;
     712  
     713  
     714        if ( clazz->glyph_transform )
     715        {
     716          /* transform glyph image */
     717          clazz->glyph_transform( glyph, matrix, delta );
     718  
     719          /* transform advance vector */
     720          if ( matrix )
     721            FT_Vector_Transform( &glyph->advance, matrix );
     722        }
     723        else
     724          error = FT_THROW( Invalid_Glyph_Format );
     725      }
     726      return error;
     727    }
     728  
     729  
     730    /* documentation is in ftglyph.h */
     731  
     732    FT_EXPORT_DEF( void )
     733    FT_Glyph_Get_CBox( FT_Glyph  glyph,
     734                       FT_UInt   bbox_mode,
     735                       FT_BBox  *acbox )
     736    {
     737      const FT_Glyph_Class*  clazz;
     738  
     739  
     740      if ( !acbox )
     741        return;
     742  
     743      acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
     744  
     745      if ( !glyph || !glyph->clazz )
     746        return;
     747  
     748      clazz = glyph->clazz;
     749      if ( !clazz->glyph_bbox )
     750        return;
     751  
     752      /* retrieve bbox in 26.6 coordinates */
     753      clazz->glyph_bbox( glyph, acbox );
     754  
     755      /* perform grid fitting if needed */
     756      if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
     757           bbox_mode == FT_GLYPH_BBOX_PIXELS  )
     758      {
     759        acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
     760        acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
     761        acbox->xMax = FT_PIX_CEIL_LONG( acbox->xMax );
     762        acbox->yMax = FT_PIX_CEIL_LONG( acbox->yMax );
     763      }
     764  
     765      /* convert to integer pixels if needed */
     766      if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
     767           bbox_mode == FT_GLYPH_BBOX_PIXELS   )
     768      {
     769        acbox->xMin >>= 6;
     770        acbox->yMin >>= 6;
     771        acbox->xMax >>= 6;
     772        acbox->yMax >>= 6;
     773      }
     774    }
     775  
     776  
     777    /* documentation is in ftglyph.h */
     778  
     779    FT_EXPORT_DEF( FT_Error )
     780    FT_Glyph_To_Bitmap( FT_Glyph*         the_glyph,
     781                        FT_Render_Mode    render_mode,
     782                        const FT_Vector*  origin,
     783                        FT_Bool           destroy )
     784    {
     785      FT_GlyphSlotRec           dummy;
     786      FT_GlyphSlot_InternalRec  dummy_internal;
     787      FT_Error                  error = FT_Err_Ok;
     788      FT_Glyph                  b, glyph;
     789      FT_BitmapGlyph            bitmap = NULL;
     790      const FT_Glyph_Class*     clazz;
     791  
     792      FT_Library                library;
     793  
     794  
     795      /* check argument */
     796      if ( !the_glyph )
     797        goto Bad;
     798      glyph = *the_glyph;
     799      if ( !glyph )
     800        goto Bad;
     801  
     802      clazz   = glyph->clazz;
     803      library = glyph->library;
     804      if ( !library || !clazz )
     805        goto Bad;
     806  
     807      /* when called with a bitmap glyph, do nothing and return successfully */
     808      if ( clazz == &ft_bitmap_glyph_class )
     809        goto Exit;
     810  
     811      if ( !clazz->glyph_prepare )
     812        goto Bad;
     813  
     814      /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
     815      /* then calling FT_Render_Glyph_Internal()                            */
     816  
     817      FT_ZERO( &dummy );
     818      FT_ZERO( &dummy_internal );
     819      dummy.internal = &dummy_internal;
     820      dummy.library  = library;
     821      dummy.format   = clazz->glyph_format;
     822  
     823      /* create result bitmap glyph */
     824      error = ft_new_glyph( library, &ft_bitmap_glyph_class, &b );
     825      if ( error )
     826        goto Exit;
     827      bitmap = (FT_BitmapGlyph)b;
     828  
     829  #if 1
     830      /* if `origin' is set, translate the glyph image */
     831      if ( origin )
     832        FT_Glyph_Transform( glyph, NULL, origin );
     833  #else
     834      FT_UNUSED( origin );
     835  #endif
     836  
     837      /* prepare dummy slot for rendering */
     838      error = clazz->glyph_prepare( glyph, &dummy );
     839      if ( !error )
     840        error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
     841  
     842  #ifdef FT_CONFIG_OPTION_SVG
     843      if ( clazz == &ft_svg_glyph_class )
     844      {
     845        FT_Memory  memory = library->memory;
     846  
     847  
     848        FT_FREE( dummy.other );
     849      }
     850  #endif
     851  
     852  #if 1
     853      if ( !destroy && origin )
     854      {
     855        FT_Vector  v;
     856  
     857  
     858        v.x = -origin->x;
     859        v.y = -origin->y;
     860        FT_Glyph_Transform( glyph, NULL, &v );
     861      }
     862  #endif
     863  
     864      if ( error )
     865        goto Exit;
     866  
     867      /* in case of success, copy the bitmap to the glyph bitmap */
     868      error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
     869      if ( error )
     870        goto Exit;
     871  
     872      /* copy advance */
     873      bitmap->root.advance = glyph->advance;
     874  
     875      if ( destroy )
     876        FT_Done_Glyph( glyph );
     877  
     878      *the_glyph = FT_GLYPH( bitmap );
     879  
     880    Exit:
     881      if ( error && bitmap )
     882        FT_Done_Glyph( FT_GLYPH( bitmap ) );
     883  
     884      return error;
     885  
     886    Bad:
     887      error = FT_THROW( Invalid_Argument );
     888      goto Exit;
     889    }
     890  
     891  
     892    /* documentation is in ftglyph.h */
     893  
     894    FT_EXPORT_DEF( void )
     895    FT_Done_Glyph( FT_Glyph  glyph )
     896    {
     897      if ( glyph )
     898      {
     899        FT_Memory              memory = glyph->library->memory;
     900        const FT_Glyph_Class*  clazz  = glyph->clazz;
     901  
     902  
     903        if ( clazz->glyph_done )
     904          clazz->glyph_done( glyph );
     905  
     906        FT_FREE( glyph );
     907      }
     908    }
     909  
     910  
     911  /* END */