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-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     const FT_Glyph_Class*     clazz;
    516 
    517     /* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */
    518     FT_Library                library;
    519 
    520 
    521     /* check argument */
    522     if ( !the_glyph )
    523       goto Bad;
    524     glyph = *the_glyph;
    525     if ( !glyph )
    526       goto Bad;
    527 
    528     clazz   = glyph->clazz;
    529     library = glyph->library;
    530     if ( !library || !clazz )
    531       goto Bad;
    532 
    533     /* when called with a bitmap glyph, do nothing and return successfully */
    534     if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
    535       goto Exit;
    536 
    537     if ( !clazz->glyph_prepare )
    538       goto Bad;
    539 
    540     /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
    541     /* then calling FT_Render_Glyph_Internal()                            */
    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  = library;
    547     dummy.format   = clazz->glyph_format;
    548 
    549     /* create result bitmap glyph */
    550     error = ft_new_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 */
    628