tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ftglyph.c (24220B)


      1 /****************************************************************************
      2 *
      3 * ftglyph.c
      4 *
      5 *   FreeType convenience functions to handle glyphs (body).
      6 *
      7 * Copyright (C) 1996-2025 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 */