diff options
Diffstat (limited to 'src/base/ftadvanc.c')
-rw-r--r-- | src/base/ftadvanc.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/base/ftadvanc.c b/src/base/ftadvanc.c new file mode 100644 index 0000000..626a0cf --- /dev/null +++ b/src/base/ftadvanc.c @@ -0,0 +1,127 @@ +#include <ft2build.h> +#include FT_ADVANCES_H +#include FT_INTERNAL_OBJECTS_H + + static FT_Error + _ft_face_scale_advances( FT_Face face, + FT_Fixed* advances, + FT_UInt count, + FT_UInt flags ) + { + FT_Fixed scale; + FT_UInt nn; + + if ( (flags & FT_LOAD_NO_SCALE) ) + return FT_Err_Ok; + + if ( face->size == NULL ) + return FT_Err_Invalid_Size_Handle; + + if ( !(flags & FT_LOAD_VERTICAL_LAYOUT) ) + scale = face->size->metrics.x_scale; + else + scale = face->size->metrics.y_scale; + + /* this must be the same computation than to get linearHori/VertAdvance + * (see FT_Load_Glyph() implementation in src/base/ftobjs.c */ + for (nn = 0; nn < count; nn++) + advances[nn] = FT_MulDiv( advances[nn], scale, 64 ); + + return 0; + } + + +/* at the moment, we can perform fast advance retrieval only in + the following cases: + + - unscaled load + - unhinted load + - light-hinted load + */ +#define LOAD_ADVANCE_FAST_CHECK(flags) \ + (((flags & (FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING)) != 0) || \ + FT_LOAD_TARGET_MODE(flags) == FT_RENDER_MODE_LIGHT) + + FT_EXPORT_DEF(FT_Error) + FT_Get_Advance( FT_Face face, + FT_UInt gindex, + FT_UInt flags, + FT_Fixed *padvance ) + { + FT_Face_GetAdvancesFunc func; + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + if (gindex >= (FT_UInt) face->num_glyphs ) + return FT_Err_Invalid_Glyph_Index; + + func = face->driver->clazz->get_advances; + if (func != NULL && LOAD_ADVANCE_FAST_CHECK(flags)) + { + FT_Error error; + + error = func( face, gindex, 1, flags, padvance ); + if (!error) + return _ft_face_scale_advances( face, padvance, 1, flags ); + + if (error != FT_Err_Unimplemented_Feature) + return error; + } + + return FT_Get_Advances( face, gindex, 1, flags, padvance ); + } + + + FT_EXPORT_DEF(FT_Error) + FT_Get_Advances( FT_Face face, + FT_UInt start, + FT_UInt count, + FT_UInt flags, + FT_Fixed *padvances ) + { + FT_Face_GetAdvancesFunc func; + FT_UInt num, end, nn; + FT_Error error = 0; + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + num = (FT_UInt) face->num_glyphs; + end = start + count; + if (start >= num || end < start || end > num) + return FT_Err_Invalid_Glyph_Index; + + if (count == 0) + return FT_Err_Ok; + + func = face->driver->clazz->get_advances; + if (func != NULL && LOAD_ADVANCE_FAST_CHECK(flags)) + { + error = func( face, start, count, flags, padvances ); + if (!error) goto Exit; + + if (error != FT_Err_Unimplemented_Feature) + return error; + } + + error = 0; + + if ((flags & FT_ADVANCE_FLAG_FAST_ONLY) != 0) + return FT_Err_Unimplemented_Feature; + + flags |= FT_LOAD_ADVANCE_ONLY; + for (nn = 0; nn < count; nn++) + { + error = FT_Load_Glyph( face, start+nn, flags ); + if (error) break; + + padvances[nn] = (flags & FT_LOAD_VERTICAL_LAYOUT) + ? face->glyph->advance.x + : face->glyph->advance.y; + } + if (error) return error; + + Exit: + return _ft_face_scale_advances( face, padvances, count, flags ); + } |