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