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