1 /**************************************************************************** 2 * 3 * ftadvanc.c 4 * 5 * Quick computation of advance widths (body). 6 * 7 * Copyright (C) 2008-2022 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 <freetype/internal/ftdebug.h> 20 21 #include <freetype/ftadvanc.h> 22 #include <freetype/internal/ftobjs.h> 23 24 25 static FT_Error _ft_face_scale_advances(FT_Face face,FT_Fixed * advances,FT_UInt count,FT_Int32 flags)26 _ft_face_scale_advances( FT_Face face, 27 FT_Fixed* advances, 28 FT_UInt count, 29 FT_Int32 flags ) 30 { 31 FT_Fixed scale; 32 FT_UInt nn; 33 34 35 if ( flags & FT_LOAD_NO_SCALE ) 36 return FT_Err_Ok; 37 38 if ( !face->size ) 39 return FT_THROW( Invalid_Size_Handle ); 40 41 if ( flags & FT_LOAD_VERTICAL_LAYOUT ) 42 scale = face->size->metrics.y_scale; 43 else 44 scale = face->size->metrics.x_scale; 45 46 /* this must be the same scaling as to get linear{Hori,Vert}Advance */ 47 /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */ 48 49 for ( nn = 0; nn < count; nn++ ) 50 advances[nn] = FT_MulDiv( advances[nn], scale, 64 ); 51 52 return FT_Err_Ok; 53 } 54 55 56 /* at the moment, we can perform fast advance retrieval only in */ 57 /* the following cases: */ 58 /* */ 59 /* - unscaled load */ 60 /* - unhinted load */ 61 /* - light-hinted load */ 62 /* - if a variations font, it must have an `HVAR' or `VVAR' */ 63 /* table (thus the old MM or GX fonts don't qualify; this */ 64 /* gets checked by the driver-specific functions) */ 65 66 #define LOAD_ADVANCE_FAST_CHECK( face, flags ) \ 67 ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) || \ 68 FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT ) 69 70 71 /* documentation is in ftadvanc.h */ 72 73 FT_EXPORT_DEF( FT_Error ) FT_Get_Advance(FT_Face face,FT_UInt gindex,FT_Int32 flags,FT_Fixed * padvance)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 ) FT_Get_Advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * padvances)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_Error error = FT_Err_Ok; 119 120 FT_Face_GetAdvancesFunc func; 121 122 FT_UInt num, end, nn; 123 FT_Int factor; 124 125 126 if ( !face ) 127 return FT_THROW( Invalid_Face_Handle ); 128 129 if ( !padvances ) 130 return FT_THROW( Invalid_Argument ); 131 132 num = (FT_UInt)face->num_glyphs; 133 end = start + count; 134 if ( start >= num || end < start || end > num ) 135 return FT_THROW( Invalid_Glyph_Index ); 136 137 if ( count == 0 ) 138 return FT_Err_Ok; 139 140 func = face->driver->clazz->get_advances; 141 if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) ) 142 { 143 error = func( face, start, count, flags, padvances ); 144 if ( !error ) 145 return _ft_face_scale_advances( face, padvances, count, flags ); 146 147 if ( FT_ERR_NEQ( error, Unimplemented_Feature ) ) 148 return error; 149 } 150 151 error = FT_Err_Ok; 152 153 if ( flags & FT_ADVANCE_FLAG_FAST_ONLY ) 154 return FT_THROW( Unimplemented_Feature ); 155 156 flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; 157 factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024; 158 for ( nn = 0; nn < count; nn++ ) 159 { 160 error = FT_Load_Glyph( face, start + nn, flags ); 161 if ( error ) 162 break; 163 164 /* scale from 26.6 to 16.16, unless NO_SCALE was requested */ 165 padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) 166 ? face->glyph->advance.y * factor 167 : face->glyph->advance.x * factor; 168 } 169 170 return error; 171 } 172 173 174 /* END */ 175