1 /**************************************************************************** 2 * 3 * ftadvanc.c 4 * 5 * Quick computation of advance widths (body). 6 * 7 * Copyright (C) 2008-2019 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 ) 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 ) FT_Get_Advance(FT_Face face,FT_UInt gindex,FT_Int32 flags,FT_Fixed * padvance)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 ) FT_Get_Advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * padvances)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 */ 176