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