Home | History | Annotate | Download | only in base
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftadvanc.c                                                             */
      4 /*                                                                         */
      5 /*    Quick computation of advance widths (body).                          */
      6 /*                                                                         */
      7 /*  Copyright 2008, 2009 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 #include <ft2build.h>
     20 #include FT_ADVANCES_H
     21 #include FT_INTERNAL_OBJECTS_H
     22 
     23 
     24   static FT_Error
     25   _ft_face_scale_advances( FT_Face    face,
     26                            FT_Fixed*  advances,
     27                            FT_UInt    count,
     28                            FT_Int32   flags )
     29   {
     30     FT_Fixed  scale;
     31     FT_UInt   nn;
     32 
     33 
     34     if ( flags & FT_LOAD_NO_SCALE )
     35       return FT_Err_Ok;
     36 
     37     if ( face->size == NULL )
     38       return FT_Err_Invalid_Size_Handle;
     39 
     40     if ( flags & FT_LOAD_VERTICAL_LAYOUT )
     41       scale = face->size->metrics.y_scale;
     42     else
     43       scale = face->size->metrics.x_scale;
     44 
     45     /* this must be the same scaling as to get linear{Hori,Vert}Advance */
     46     /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c)        */
     47 
     48     for ( nn = 0; nn < count; nn++ )
     49       advances[nn] = FT_MulDiv( advances[nn], scale, 64 );
     50 
     51     return FT_Err_Ok;
     52   }
     53 
     54 
     55    /* at the moment, we can perform fast advance retrieval only in */
     56    /* the following cases:                                         */
     57    /*                                                              */
     58    /*  - unscaled load                                             */
     59    /*  - unhinted load                                             */
     60    /*  - light-hinted load                                         */
     61 
     62 #define LOAD_ADVANCE_FAST_CHECK( flags )                            \
     63           ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    || \
     64             FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
     65 
     66 
     67   /* documentation is in ftadvanc.h */
     68 
     69   FT_EXPORT_DEF( FT_Error )
     70   FT_Get_Advance( FT_Face    face,
     71                   FT_UInt    gindex,
     72                   FT_Int32   flags,
     73                   FT_Fixed  *padvance )
     74   {
     75     FT_Face_GetAdvancesFunc  func;
     76 
     77 
     78     if ( !face )
     79       return FT_Err_Invalid_Face_Handle;
     80 
     81     if ( gindex >= (FT_UInt)face->num_glyphs )
     82       return FT_Err_Invalid_Glyph_Index;
     83 
     84     func = face->driver->clazz->get_advances;
     85     if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
     86     {
     87       FT_Error  error;
     88 
     89 
     90       error = func( face, gindex, 1, flags, padvance );
     91       if ( !error )
     92         return _ft_face_scale_advances( face, padvance, 1, flags );
     93 
     94       if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
     95         return error;
     96     }
     97 
     98     return FT_Get_Advances( face, gindex, 1, flags, padvance );
     99   }
    100 
    101 
    102   /* documentation is in ftadvanc.h */
    103 
    104   FT_EXPORT_DEF( FT_Error )
    105   FT_Get_Advances( FT_Face    face,
    106                    FT_UInt    start,
    107                    FT_UInt    count,
    108                    FT_Int32   flags,
    109                    FT_Fixed  *padvances )
    110   {
    111     FT_Face_GetAdvancesFunc  func;
    112     FT_UInt                  num, end, nn;
    113     FT_Error                 error = FT_Err_Ok;
    114 
    115 
    116     if ( !face )
    117       return FT_Err_Invalid_Face_Handle;
    118 
    119     num = (FT_UInt)face->num_glyphs;
    120     end = start + count;
    121     if ( start >= num || end < start || end > num )
    122       return FT_Err_Invalid_Glyph_Index;
    123 
    124     if ( count == 0 )
    125       return FT_Err_Ok;
    126 
    127     func = face->driver->clazz->get_advances;
    128     if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
    129     {
    130       error = func( face, start, count, flags, padvances );
    131       if ( !error )
    132         goto Exit;
    133 
    134       if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
    135         return error;
    136     }
    137 
    138     error = FT_Err_Ok;
    139 
    140     if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
    141       return FT_Err_Unimplemented_Feature;
    142 
    143     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
    144     for ( nn = 0; nn < count; nn++ )
    145     {
    146       error = FT_Load_Glyph( face, start + nn, flags );
    147       if ( error )
    148         break;
    149 
    150       padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
    151                       ? face->glyph->advance.y
    152                       : face->glyph->advance.x;
    153     }
    154 
    155     if ( error )
    156       return error;
    157 
    158   Exit:
    159     return _ft_face_scale_advances( face, padvances, count, flags );
    160   }
    161 
    162 
    163 /* END */
    164