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