1 /***************************************************************************/ 2 /* */ 3 /* ftadvanc.c */ 4 /* */ 5 /* Quick computation of advance widths (body). */ 6 /* */ 7 /* Copyright 2008, 2009 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_ADVANCES_H 21 #include FT_INTERNAL_OBJECTS_H 22 23 24 static FT_Error _ft_face_scale_advances(FT_Face face,FT_Fixed * advances,FT_UInt count,FT_Int32 flags)25 _ft_face_scale_advances( FT_Face face, 26 FT_Fixed* advances, 27 FT_UInt count, 28 FT_Int32 flags ) 29 { 30 FT_Fixed scale; 31 FT_UInt nn; 32 33 34 if ( flags & FT_LOAD_NO_SCALE ) 35 return FT_Err_Ok; 36 37 if ( face->size == NULL ) 38 return FT_Err_Invalid_Size_Handle; 39 40 if ( flags & FT_LOAD_VERTICAL_LAYOUT ) 41 scale = face->size->metrics.y_scale; 42 else 43 scale = face->size->metrics.x_scale; 44 45 /* this must be the same scaling as to get linear{Hori,Vert}Advance */ 46 /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */ 47 48 for ( nn = 0; nn < count; nn++ ) 49 advances[nn] = FT_MulDiv( advances[nn], scale, 64 ); 50 51 return FT_Err_Ok; 52 } 53 54 55 /* at the moment, we can perform fast advance retrieval only in */ 56 /* the following cases: */ 57 /* */ 58 /* - unscaled load */ 59 /* - unhinted load */ 60 /* - light-hinted load */ 61 62 #define LOAD_ADVANCE_FAST_CHECK( flags ) \ 63 ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) || \ 64 FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT ) 65 66 67 /* documentation is in ftadvanc.h */ 68 69 FT_EXPORT_DEF( FT_Error ) FT_Get_Advance(FT_Face face,FT_UInt gindex,FT_Int32 flags,FT_Fixed * padvance)70 FT_Get_Advance( FT_Face face, 71 FT_UInt gindex, 72 FT_Int32 flags, 73 FT_Fixed *padvance ) 74 { 75 FT_Face_GetAdvancesFunc func; 76 77 78 if ( !face ) 79 return FT_Err_Invalid_Face_Handle; 80 81 if ( gindex >= (FT_UInt)face->num_glyphs ) 82 return FT_Err_Invalid_Glyph_Index; 83 84 func = face->driver->clazz->get_advances; 85 if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) ) 86 { 87 FT_Error error; 88 89 90 error = func( face, gindex, 1, flags, padvance ); 91 if ( !error ) 92 return _ft_face_scale_advances( face, padvance, 1, flags ); 93 94 if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) ) 95 return error; 96 } 97 98 return FT_Get_Advances( face, gindex, 1, flags, padvance ); 99 } 100 101 102 /* documentation is in ftadvanc.h */ 103 104 FT_EXPORT_DEF( FT_Error ) FT_Get_Advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * padvances)105 FT_Get_Advances( FT_Face face, 106 FT_UInt start, 107 FT_UInt count, 108 FT_Int32 flags, 109 FT_Fixed *padvances ) 110 { 111 FT_Face_GetAdvancesFunc func; 112 FT_UInt num, end, nn; 113 FT_Error error = FT_Err_Ok; 114 115 116 if ( !face ) 117 return FT_Err_Invalid_Face_Handle; 118 119 num = (FT_UInt)face->num_glyphs; 120 end = start + count; 121 if ( start >= num || end < start || end > num ) 122 return FT_Err_Invalid_Glyph_Index; 123 124 if ( count == 0 ) 125 return FT_Err_Ok; 126 127 func = face->driver->clazz->get_advances; 128 if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) ) 129 { 130 error = func( face, start, count, flags, padvances ); 131 if ( !error ) 132 goto Exit; 133 134 if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) ) 135 return error; 136 } 137 138 error = FT_Err_Ok; 139 140 if ( flags & FT_ADVANCE_FLAG_FAST_ONLY ) 141 return FT_Err_Unimplemented_Feature; 142 143 flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; 144 for ( nn = 0; nn < count; nn++ ) 145 { 146 error = FT_Load_Glyph( face, start + nn, flags ); 147 if ( error ) 148 break; 149 150 padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) 151 ? face->glyph->advance.y 152 : face->glyph->advance.x; 153 } 154 155 if ( error ) 156 return error; 157 158 Exit: 159 return _ft_face_scale_advances( face, padvances, count, flags ); 160 } 161 162 163 /* END */ 164