Home | History | Annotate | Download | only in base
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftadvanc.c                                                             */
      4 /*                                                                         */
      5 /*    Quick computation of advance widths (body).                          */
      6 /*                                                                         */
      7 /*  Copyright 2008-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 #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 ( !padvance )
     84       return FT_THROW( Invalid_Argument );
     85 
     86     if ( gindex >= (FT_UInt)face->num_glyphs )
     87       return FT_THROW( Invalid_Glyph_Index );
     88 
     89     func = face->driver->clazz->get_advances;
     90     if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
     91     {
     92       FT_Error  error;
     93 
     94 
     95       error = func( face, gindex, 1, flags, padvance );
     96       if ( !error )
     97         return _ft_face_scale_advances( face, padvance, 1, flags );
     98 
     99       if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
    100         return error;
    101     }
    102 
    103     return FT_Get_Advances( face, gindex, 1, flags, padvance );
    104   }
    105 
    106 
    107   /* documentation is in ftadvanc.h */
    108 
    109   FT_EXPORT_DEF( FT_Error )
    110   FT_Get_Advances( FT_Face    face,
    111                    FT_UInt    start,
    112                    FT_UInt    count,
    113                    FT_Int32   flags,
    114                    FT_Fixed  *padvances )
    115   {
    116     FT_Face_GetAdvancesFunc  func;
    117     FT_UInt                  num, end, nn;
    118     FT_Error                 error = FT_Err_Ok;
    119 
    120 
    121     if ( !face )
    122       return FT_THROW( Invalid_Face_Handle );
    123 
    124     if ( !padvances )
    125       return FT_THROW( Invalid_Argument );
    126 
    127     num = (FT_UInt)face->num_glyphs;
    128     end = start + count;
    129     if ( start >= num || end < start || end > num )
    130       return FT_THROW( Invalid_Glyph_Index );
    131 
    132     if ( count == 0 )
    133       return FT_Err_Ok;
    134 
    135     func = face->driver->clazz->get_advances;
    136     if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
    137     {
    138       error = func( face, start, count, flags, padvances );
    139       if ( !error )
    140         return _ft_face_scale_advances( face, padvances, count, flags );
    141 
    142       if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
    143         return error;
    144     }
    145 
    146     error = FT_Err_Ok;
    147 
    148     if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
    149       return FT_THROW( Unimplemented_Feature );
    150 
    151     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
    152     for ( nn = 0; nn < count; nn++ )
    153     {
    154       error = FT_Load_Glyph( face, start + nn, flags );
    155       if ( error )
    156         break;
    157 
    158       /* scale from 26.6 to 16.16 */
    159       padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
    160                       ? face->glyph->advance.y << 10
    161                       : face->glyph->advance.x << 10;
    162     }
    163 
    164     return error;
    165   }
    166 
    167 
    168 /* END */
    169