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 */