Home | History | Annotate | Download | only in base
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftadvanc.c                                                             */
      4 /*                                                                         */
      5 /*    Quick computation of advance widths (body).                          */
      6 /*                                                                         */
      7 /*  Copyright 2008-2018 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 )
     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    /*  - if a variations font, it must have an `HVAR' or `VVAR'    */
     64    /*    table (thus the old MM or GX fonts don't qualify; this    */
     65    /*    gets checked by the driver-specific functions)            */
     66 
     67 #define LOAD_ADVANCE_FAST_CHECK( face, flags )                      \
     68           ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    || \
     69             FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
     70 
     71 
     72   /* documentation is in ftadvanc.h */
     73 
     74   FT_EXPORT_DEF( FT_Error )
     75   FT_Get_Advance( FT_Face    face,
     76                   FT_UInt    gindex,
     77                   FT_Int32   flags,
     78                   FT_Fixed  *padvance )
     79   {
     80     FT_Face_GetAdvancesFunc  func;
     81 
     82 
     83     if ( !face )
     84       return FT_THROW( Invalid_Face_Handle );
     85 
     86     if ( !padvance )
     87       return FT_THROW( Invalid_Argument );
     88 
     89     if ( gindex >= (FT_UInt)face->num_glyphs )
     90       return FT_THROW( Invalid_Glyph_Index );
     91 
     92     func = face->driver->clazz->get_advances;
     93     if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
     94     {
     95       FT_Error  error;
     96 
     97 
     98       error = func( face, gindex, 1, flags, padvance );
     99       if ( !error )
    100         return _ft_face_scale_advances( face, padvance, 1, flags );
    101 
    102       if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
    103         return error;
    104     }
    105 
    106     return FT_Get_Advances( face, gindex, 1, flags, padvance );
    107   }
    108 
    109 
    110   /* documentation is in ftadvanc.h */
    111 
    112   FT_EXPORT_DEF( FT_Error )
    113   FT_Get_Advances( FT_Face    face,
    114                    FT_UInt    start,
    115                    FT_UInt    count,
    116                    FT_Int32   flags,
    117                    FT_Fixed  *padvances )
    118   {
    119     FT_Error  error = FT_Err_Ok;
    120 
    121     FT_Face_GetAdvancesFunc  func;
    122 
    123     FT_UInt  num, end, nn;
    124     FT_Int   factor;
    125 
    126 
    127     if ( !face )
    128       return FT_THROW( Invalid_Face_Handle );
    129 
    130     if ( !padvances )
    131       return FT_THROW( Invalid_Argument );
    132 
    133     num = (FT_UInt)face->num_glyphs;
    134     end = start + count;
    135     if ( start >= num || end < start || end > num )
    136       return FT_THROW( Invalid_Glyph_Index );
    137 
    138     if ( count == 0 )
    139       return FT_Err_Ok;
    140 
    141     func = face->driver->clazz->get_advances;
    142     if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
    143     {
    144       error = func( face, start, count, flags, padvances );
    145       if ( !error )
    146         return _ft_face_scale_advances( face, padvances, count, flags );
    147 
    148       if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
    149         return error;
    150     }
    151 
    152     error = FT_Err_Ok;
    153 
    154     if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
    155       return FT_THROW( Unimplemented_Feature );
    156 
    157     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
    158     factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024;
    159     for ( nn = 0; nn < count; nn++ )
    160     {
    161       error = FT_Load_Glyph( face, start + nn, flags );
    162       if ( error )
    163         break;
    164 
    165       /* scale from 26.6 to 16.16, unless NO_SCALE was requested */
    166       padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
    167                       ? face->glyph->advance.y * factor
    168                       : face->glyph->advance.x * factor;
    169     }
    170 
    171     return error;
    172   }
    173 
    174 
    175 /* END */
    176