#include #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 ); }