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 _ft_face_scale_advances(FT_Face face,FT_Fixed * advances,FT_UInt count,FT_Int32 flags)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 ) FT_Get_Advance(FT_Face face,FT_UInt gindex,FT_Int32 flags,FT_Fixed * padvance)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 ) FT_Get_Advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * padvances)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