1 /****************************************************************************
5 * Quick computation of advance widths (body).
7 * Copyright (C) 2008-2023 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
19 #include <freetype/internal/ftdebug.h>
21 #include <freetype/ftadvanc.h>
22 #include <freetype/internal/ftobjs.h>
26 ft_face_scale_advances_( FT_Face face,
35 if ( flags & FT_LOAD_NO_SCALE )
39 return FT_THROW( Invalid_Size_Handle );
41 if ( flags & FT_LOAD_VERTICAL_LAYOUT )
42 scale = face->size->metrics.y_scale;
44 scale = face->size->metrics.x_scale;
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) */
49 for ( nn = 0; nn < count; nn++ )
50 advances[nn] = FT_MulDiv( advances[nn], scale, 64 );
56 /* at the moment, we can perform fast advance retrieval only in */
57 /* the following cases: */
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) */
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 )
71 /* documentation is in ftadvanc.h */
73 FT_EXPORT_DEF( FT_Error )
74 FT_Get_Advance( FT_Face face,
79 FT_Face_GetAdvancesFunc func;
83 return FT_THROW( Invalid_Face_Handle );
86 return FT_THROW( Invalid_Argument );
88 if ( gindex >= (FT_UInt)face->num_glyphs )
89 return FT_THROW( Invalid_Glyph_Index );
91 func = face->driver->clazz->get_advances;
92 if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
97 error = func( face, gindex, 1, flags, padvance );
99 return ft_face_scale_advances_( face, padvance, 1, flags );
101 if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
105 return FT_Get_Advances( face, gindex, 1, flags, padvance );
109 /* documentation is in ftadvanc.h */
111 FT_EXPORT_DEF( FT_Error )
112 FT_Get_Advances( FT_Face face,
116 FT_Fixed *padvances )
118 FT_Error error = FT_Err_Ok;
120 FT_Face_GetAdvancesFunc func;
122 FT_UInt num, end, nn;
127 return FT_THROW( Invalid_Face_Handle );
130 return FT_THROW( Invalid_Argument );
132 num = (FT_UInt)face->num_glyphs;
134 if ( start >= num || end < start || end > num )
135 return FT_THROW( Invalid_Glyph_Index );
140 func = face->driver->clazz->get_advances;
141 if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
143 error = func( face, start, count, flags, padvances );
145 return ft_face_scale_advances_( face, padvances, count, flags );
147 if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
153 if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
154 return FT_THROW( Unimplemented_Feature );
156 flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
157 factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024;
158 for ( nn = 0; nn < count; nn++ )
160 error = FT_Load_Glyph( face, start + nn, flags );
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;