From 11187206791326f7e851b62e13107723ce2c6505 Mon Sep 17 00:00:00 2001 From: David Turner Date: Fri, 26 May 2000 17:13:23 +0000 Subject: [PATCH] finalised the multiple masters support fixed some nasty little bugs too --- CHANGES | 9 ++ include/freetype/freetype.h | 15 +++- include/freetype/ftmm.h | 163 ++++++++++++++++++++++++++++++++++++ src/base/ftmm.c | 66 +++++++++++++++ src/base/ftobjs.c | 6 ++ src/base/rules.mk | 1 + src/sfnt/sfdriver.c | 1 + src/type1z/t1driver.c | 22 +++-- src/type1z/t1load.c | 132 +++++++++++++++++++++++++++++ src/type1z/t1load.h | 12 +++ 10 files changed, 419 insertions(+), 8 deletions(-) create mode 100644 include/freetype/ftmm.h create mode 100644 src/base/ftmm.c diff --git a/CHANGES b/CHANGES index 4013727a6..8ec03eed0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,14 @@ LATEST_CHANGES + - added support for Multiple Master fonts in "type1z". There is also + a new file named which defines functions to + manage them from client applications. + + The new file "src/base/ftmm.c" is also optional to the engine.. + + - various formatting changes (e.g. EXPORT_DEF -> FT_EXPORT_DEF) + + small bug fixes in FT_Load_Glyph, the "type1" driver, etc.. + - a minor fix to the Type 1 driver to let them apply the font matrix correctly (used for many oblique fonts..) diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index 4a4174fd8..470083031 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -733,6 +733,17 @@ /* */ #define FT_FACE_FLAG_FAST_GLYPHS 0x80 + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS */ + /* */ + /* */ + /* A bit-field constant, used to indicate that the font contains */ + /* multiple masters and is capable of interpolating between them.. */ + /* */ +#define FT_FACE_FLAG_MULTIPLE_MASTERS 0x100 + #define FT_HAS_HORIZONTAL(face) (face->face_flags & FT_FACE_FLAG_HORIZONTAL) #define FT_HAS_VERTICAL(face) (face->face_flags & FT_FACE_FLAG_VERTICAL) @@ -743,6 +754,8 @@ #define FT_HAS_FIXED_SIZES(face) (face->face_flags & FT_FACE_FLAG_FIXED_SIZES) #define FT_HAS_FAST_GLYPHS(face) (face->face_flags & FT_FACE_FLAG_FAST_GLYPHS) +#define FT_HAS_MULTIPLE_MASTERS(face) \ + (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) /*************************************************************************/ /* */ @@ -1964,7 +1977,7 @@ /* application if you want something simpler. */ /* */ FT_EXPORT_DEF(FT_Error) FT_Outline_Done( FT_Library library, - FT_Outline* outline ); + FT_Outline* outline ); /*************************************************************************/ /* */ diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h new file mode 100644 index 000000000..ae3d352ec --- /dev/null +++ b/include/freetype/ftmm.h @@ -0,0 +1,163 @@ +/***************************************************************************/ +/* */ +/* ftmm.h */ +/* */ +/* FreeType Multiple-Master interface. */ +/* */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#ifndef FTMM_H +#define FTMM_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + /********************************************************************** + * + * + * FT_MM_Axis + * + * + * A simple structure used to model a given axis in design space + * for multiple masters fonts.. + * + * + * name :: axis' name + * minimum :: axis' minimum design coordinate + * maximum :: axis's maximum design coordinate + * + */ + typedef struct FT_MM_Axis_ + { + FT_String* name; + FT_Long minimum; + FT_Long maximum; + + } FT_MM_Axis; + + /********************************************************************** + * + * + * FT_Multi_Master + * + * + * A structure used to model the axis and space of a multiple + * masters font. + * + * + * num_axis :: number of axis. cannot exceed 4 + * + * num_designs :: number of designs, should ne normally 2^num_axis + * even though the Type 1 specification strangely + * allows for intermediate designs to be present + * this number cannot exceed 16 + * + * axis :: an table of axis descriptors.. + * + */ + typedef struct FT_Multi_Master_ + { + FT_UInt num_axis; + FT_UInt num_designs; + FT_MM_Axis axis[ T1_MAX_MM_AXIS ]; + + } FT_Multi_Master; + + + typedef FT_Error (*FT_Get_MM_Func)( FT_Face face, FT_Multi_Master* master ); + + typedef FT_Error (*FT_Set_MM_Design_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + typedef FT_Error (*FT_Set_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + /************************************************************************* + * + * + * FT_Get_Multi_Master + * + * + * Retrieves the multiple master descriptor of a given font + * + * + * face :: handle to source face + * + * + * master :: multiple masters descriptor + * + * + * Error code. 0 means success. + * + */ + FT_EXPORT_DEF(FT_Error) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ); + + + /************************************************************************* + * + * + * FT_Set_MM_Design_Coordinates + * + * + * For multiple masters fonts, choose an interpolated font design + * through design coordinates + * + * + * face :: handle to source face + * num_coords :: number of design coordinates (must be equal to the + * number of axis in the font). + * coords :: design coordinates + * + * + * Error code. 0 means success. + * + */ + FT_EXPORT_DEF(FT_Error) FT_Set_MM_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + /************************************************************************* + * + * + * FT_Set_MM_Blend_Coordinates + * + * + * For multiple masters fonts, choose an interpolated font design + * through normalized blend coordinates + * + * + * face :: handle to source face + * num_coords :: number of design coordinates (must be equal to the + * number of axis in the font). + * coords :: design coordinates (each one must be between 0 and 1.0) + * + * + * Error code. 0 means success. + * + */ + FT_EXPORT_DEF(FT_Error) FT_Set_MM_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + +#ifdef __cplusplus + } +#endif + +#endif /* FTMM_H */ +/* END */ diff --git a/src/base/ftmm.c b/src/base/ftmm.c new file mode 100644 index 000000000..f9943bff1 --- /dev/null +++ b/src/base/ftmm.c @@ -0,0 +1,66 @@ +#include +#include + + FT_EXPORT_FUNC(FT_Error) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ) + { + FT_Error error; + + error = FT_Err_Invalid_Argument; + if (face && FT_HAS_MULTIPLE_MASTERS(face)) + { + FT_Driver driver = face->driver; + FT_Get_MM_Func func; + + func = (FT_Get_MM_Func)driver->interface.get_interface( + driver, "get_mm" ); + if (func) + error = func(face,master); + } + + return error; + } + + + FT_EXPORT_FUNC(FT_Error) FT_Set_MM_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ) + { + FT_Error error; + + error = FT_Err_Invalid_Argument; + if (face && FT_HAS_MULTIPLE_MASTERS(face)) + { + FT_Driver driver = face->driver; + FT_Set_MM_Design_Func func; + + func = (FT_Set_MM_Design_Func)driver->interface.get_interface( + driver, "set_mm_design" ); + if (func) + error = func(face,num_coords,coords); + } + + return error; + } + + FT_EXPORT_FUNC(FT_Error) FT_Set_MM_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error; + + error = FT_Err_Invalid_Argument; + if (face && FT_HAS_MULTIPLE_MASTERS(face)) + { + FT_Driver driver = face->driver; + FT_Set_MM_Blend_Func func; + + func = (FT_Set_MM_Blend_Func)driver->interface.get_interface( + driver, "set_mm_blend" ); + if (func) + error = func(face,num_coords,coords); + } + + return error; + } + diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index dbaac4dee..e51556275 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -1638,6 +1638,12 @@ memory = driver->memory; /* default processing - this can be overriden by the driver */ + if (pixel_width == 0) + pixel_width = pixel_height; + + else if (pixel_height == 0) + pixel_height = pixel_width; + if ( pixel_width < 1 ) pixel_width = 1; if ( pixel_height < 1 ) pixel_height = 1; diff --git a/src/base/rules.mk b/src/base/rules.mk index dd0f1a6d9..367f34b2f 100644 --- a/src/base/rules.mk +++ b/src/base/rules.mk @@ -56,6 +56,7 @@ BASE_H := $(INTERNAL_)ftcalc.h \ # BASE_EXT_SRC := $(BASE_)ftraster.c \ $(BASE_)ftglyph.c \ + $(BASE_)ftmm.c \ $(BASE_)ftgrays.c # Base layer extensions headers diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index dcc163bef..3c6b889bd 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/src/type1z/t1driver.c b/src/type1z/t1driver.c index c6dba1a5a..b086d53bf 100644 --- a/src/type1z/t1driver.c +++ b/src/type1z/t1driver.c @@ -26,7 +26,6 @@ #undef FT_COMPONENT #define FT_COMPONENT trace_t1driver -#ifndef T1_CONFIG_OPTION_NO_AFM /*************************************************************************/ /* */ /* */ @@ -59,15 +58,28 @@ const FT_String* interface ) { UNUSED(driver); - + UNUSED(interface); + +#ifndef T1_CONFIG_OPTION_NO_AFM if ( strcmp( (const char*)interface, "attach_file" ) == 0 ) return (FTDriver_Interface)T1_Read_AFM; +#endif +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + if ( strcmp( (const char*)interface, "get_mm" ) == 0 ) + return (FTDriver_Interface)T1_Get_Multi_Master; + + if ( strcmp( (const char*)interface, "set_mm_design") == 0 ) + return (FTDriver_Interface)T1_Set_MM_Design; + + if ( strcmp( (const char*)interface, "set_mm_blend") == 0 ) + return (FTDriver_Interface)T1_Set_MM_Blend; +#endif return 0; } - +#ifndef T1_CONFIG_OPTION_NO_AFM /*************************************************************************/ /* */ /* */ @@ -375,11 +387,7 @@ (FTDriver_initDriver) T1_Init_Driver, (FTDriver_doneDriver) T1_Done_Driver, -#ifdef T1_CONFIG_OPTION_NO_AFM - (FTDriver_getInterface) 0, -#else (FTDriver_getInterface) Get_Interface, -#endif (FTDriver_initFace) T1_Init_Face, (FTDriver_doneFace) T1_Done_Face, diff --git a/src/type1z/t1load.c b/src/type1z/t1load.c index b3beb3e8d..f1de8dc38 100644 --- a/src/type1z/t1load.c +++ b/src/type1z/t1load.c @@ -61,6 +61,7 @@ #include #include +#include #include #include @@ -70,6 +71,7 @@ #undef FT_COMPONENT #define FT_COMPONENT trace_t1load +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT /***************************************************************************/ /***************************************************************************/ /***** *****/ @@ -146,7 +148,135 @@ goto Exit; } + LOCAL_FUNC FT_Error T1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ) + { + T1_Blend* blend = face->blend; + T1_UInt n; + FT_Error error; + + error = FT_Err_Invalid_Argument; + if (blend) + { + master->num_axis = blend->num_axis; + master->num_designs = blend->num_designs; + for ( n = 0; n < blend->num_axis; n++ ) + { + FT_MM_Axis* axis = master->axis + n; + T1_DesignMap* map = blend->design_map + n; + + axis->name = blend->axis_names[n]; + axis->minimum = map->design_points[0]; + axis->maximum = map->design_points[map->num_points-1]; + } + error = 0; + } + return error; + } + + LOCAL_FUNC FT_Error T1_Set_MM_Blend( T1_Face face, + T1_UInt num_coords, + T1_Fixed* coords ) + { + T1_Blend* blend = face->blend; + FT_Error error; + T1_UInt n, m; + + error = FT_Err_Invalid_Argument; + if (blend && blend->num_axis == num_coords) + { + /* recompute the weight vector from the blend coordinates */ + error = 0; + for ( n = 0; n < blend->num_designs; n++ ) + { + FT_Fixed result = 0x10000L; /* 1.0 fixed */ + for ( m = 0; m < blend->num_axis; m++ ) + { + FT_Fixed factor; + + /* get current blend axis position */ + factor = coords[m]; + if (factor < 0) factor = 0; + if (factor > 0x10000L) factor = 0x10000L; + + if ((n & (1 << m)) == 0) + factor = 0x10000L - factor; + + result = FT_MulFix( result, factor ); + } + blend->weight_vector[n] = result; + } + error = 0; + } + return error; + } + + + LOCAL_FUNC FT_Error T1_Set_MM_Design( T1_Face face, + T1_UInt num_coords, + T1_Long* coords ) + { + T1_Blend* blend = face->blend; + FT_Error error; + T1_UInt n, p; + + error = FT_Err_Invalid_Argument; + if (blend && blend->num_axis == num_coords) + { + /* compute the blend coordinates through the blend design map */ + T1_Fixed final_blends[ T1_MAX_MM_DESIGNS ]; + + for ( n = 0; n < blend->num_axis; n++ ) + { + T1_Long design = coords[n]; + T1_Fixed the_blend; + T1_DesignMap* map = blend->design_map + n; + T1_Fixed* designs = map->design_points; + T1_Fixed* blends = map->blend_points; + T1_Int before = -1, after = -1; + + for ( p = 0; p < map->num_points; p++ ) + { + T1_Fixed p_design = designs[p]; + + /* exact match ? */ + if (design == p_design) + { + the_blend = blends[p]; + goto Found; + } + + if (design < p_design) + { + after = p; + break; + } + + before = p; + } + + /* now, interpolate if needed */ + if (before < 0) + the_blend = blends[0]; + + else if (after < 0) + the_blend = blends[map->num_points-1]; + + else + the_blend = FT_MulDiv( design - designs[before], + blends [after] - blends [before], + designs[after] - designs[before] ); + Found: + final_blends[n] = the_blend; + } + + error = T1_Set_MM_Blend( face, num_coords, final_blends ); + } + return error; + } + + LOCAL_FUNC void T1_Done_Blend( T1_Face face ) { FT_Memory memory = face->root.memory; @@ -193,6 +323,7 @@ } + static void parse_blend_axis_types( T1_Face face, T1_Loader* loader ) { T1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ]; @@ -446,6 +577,7 @@ parser->cursor = parser->limit; parser->error = 0; } +#endif /***************************************************************************/ /***************************************************************************/ diff --git a/src/type1z/t1load.h b/src/type1z/t1load.h index 47ca78b39..853559731 100644 --- a/src/type1z/t1load.h +++ b/src/type1z/t1load.h @@ -47,6 +47,18 @@ T1_Error T1_Open_Face( T1_Face face ); #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + LOCAL_DEF + FT_Error T1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ); + + LOCAL_DEF FT_Error T1_Set_MM_Blend( T1_Face face, + T1_UInt num_coords, + T1_Fixed* coords ); + + LOCAL_DEF FT_Error T1_Set_MM_Design( T1_Face face, + T1_UInt num_coords, + T1_Long* coords ); + LOCAL_DEF void T1_Done_Blend( T1_Face face ); #endif