From 28534d616be45a45767e5cfa65164a863d068eea Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 1 Sep 2008 21:35:21 +0000 Subject: [PATCH] * include/freetype/ftadvanc.h, src/base/ftadvanc.c, include/freetype/config/ftheader.h, include/freetype/freetype.h, src/base/Jamfile, src/base/rules.mk, src/cff/cffdrivr.c, src/cff/cffgload.c, src/cff/cffgload.h, src/truetype/ttdriver.c, src/truetype/ttgload.h, src/truetype/ttgload.c, src/type1/t1driver.c, src/type1/t1gload.h, src/type1/t1gload.c: Add a new header named FT_ADVANCES_H declaring some new APIs to extract the advances of one or more glyphs without necessarily loading their outlines. Also provide 'fast loaders' for the TrueType, Type1 and CFF font drivers (more to come later) * autogen.sh: add checks for minimum version of the 'autotools' stuff. --- ChangeLog | 16 ++++ README.CVS | 16 ++-- autogen.sh | 120 ++++++++++++++++++++++++--- include/freetype/config/ftheader.h | 10 +++ include/freetype/freetype.h | 5 +- include/freetype/internal/ftdriver.h | 11 ++- src/base/Jamfile | 2 +- src/base/rules.mk | 4 +- src/cff/cffdrivr.c | 28 ++++++- src/cff/cffgload.c | 14 ++++ src/cff/cffgload.h | 4 + src/truetype/ttdriver.c | 40 ++++++++- src/truetype/ttgload.c | 44 +++++----- src/truetype/ttgload.h | 14 ++++ src/type1/t1driver.c | 2 +- src/type1/t1gload.c | 57 +++++++++++++ src/type1/t1gload.h | 7 ++ 17 files changed, 340 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5a6c7a53e..5210b3582 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2008-09-01 david turner + + * include/freetype/ftadvanc.h, src/base/ftadvanc.c, + include/freetype/config/ftheader.h, include/freetype/freetype.h, + src/base/Jamfile, src/base/rules.mk, src/cff/cffdrivr.c, + src/cff/cffgload.c, src/cff/cffgload.h, src/truetype/ttdriver.c, + src/truetype/ttgload.h, src/truetype/ttgload.c, src/type1/t1driver.c, + src/type1/t1gload.h, src/type1/t1gload.c: + Add a new header named FT_ADVANCES_H declaring some new APIs + to extract the advances of one or more glyphs without necessarily + loading their outlines. Also provide 'fast loaders' for the + TrueType, Type1 and CFF font drivers (more to come later) + + * autogen.sh: add checks for minimum version of the 'autotools' + stuff. + 2008-08-29 suzuki toshiya * src/sfnt/sfobjs.c (sfnt_open_font): Use TTAG_OTTO defined in diff --git a/README.CVS b/README.CVS index 2764ae95f..676578fc0 100644 --- a/README.CVS +++ b/README.CVS @@ -13,17 +13,13 @@ The versions given in parentheses are known to work. Newer versions should work too, of course. Note that autogen.sh also sets up proper file permissions for the `configure' and auxiliary scripts. -A very common problem is that this script complains that the `aclocal' -program doesn't accept a `--force' option: +The autogen.sh script now checks the version of your installed auto tools +to see if they match the numbers above. If not, it will complain and suggest +either upgrading or using an environment variable to point to a more recent +version of the required tool(s). - generating `configure.ac' - running `aclocal -I . --force' - aclocal: unrecognized option -- `--force' - Try `aclocal --help' for more information. - error while running `aclocal -I . --force' - -This means that your version of the automake package is too old. -Please update it before trying to build FreeType. +Note that 'aclocal' is provided by the 'automake' package on Linux, and +that 'libtoolize' is called 'glibtoolize' on Darwin (OS X) For static builds which don't use platform specific optimizations, no diff --git a/autogen.sh b/autogen.sh index 87f30a1ca..c167abb77 100644 --- a/autogen.sh +++ b/autogen.sh @@ -20,12 +20,119 @@ run () fi } +# extract major version +get_major_version () +{ + echo $1 | sed -e 's/\([0-9]\+\)\..*/\1/g' +} + +get_minor_version () +{ + echo $1 | sed -e 's/[0-9]\+\.\([0-9]\+\).*/\1/g' +} + +get_patch_version () +{ + # tricky, some version numbers don't include a patch + # separated with a point, but something like 1.4-p6 + # + patch=`echo $1 | sed -e 's/[0-9]\+\.[0-9]\+\.\([0-9]\+\).*/\1/g'` + if test "$patch" = "$1"; then + patch=`echo $1 | sed -e 's/[0-9]\+\.[0-9]\+\-p\([0-9]\+\).*/\1/g'` + # if there isn't any patch number, default to 0 + if test "$patch" = "$1"; then + patch=0 + fi + fi + echo $patch +} + +# $1: version to check +# $2: minimum version +compare_to_minimum_version () +{ + MAJOR1=`get_major_version $1` + MAJOR2=`get_major_version $2` + if test $MAJOR1 -lt $MAJOR2; then + echo 0 + return + else + if test $MAJOR1 -gt $MAJOR2; then + echo 1 + return + fi + fi + + MINOR1=`get_minor_version $1` + MINOR2=`get_minor_version $2` + if test $MINOR1 -lt $MINOR2; then + echo 0 + return + else + if test $MINOR1 -gt $MINOR2; then + echo 1 + return + fi + fi + + PATCH1=`get_patch_version $1` + PATCH2=`get_patch_version $2` + if test $PATCH1 -lt $PATCH2; then + echo 0 + else + echo 1 + fi +} + + +# check that version of a given tool against a minimum version number +# $1: tool path +# $2: tool usual name (e.g. 'aclocal') +# $3: tool variable (e.g. 'ACLOCAL') +# $4: minimum version to check against +# $5: option field index used to extract the tool version from the output of --version +# +check_tool_version () +{ + field=$5 + if test "$field"x = x; then + field=4 # default to 4 for all GNU autotools + fi + version=`$1 --version | head -1 | cut -d ' ' -f $field` + version_check=`compare_to_minimum_version $version $4` + if test "$version_check"x = 0x; then + echo "ERROR: You $2 version is too old. minimum version $4 is required (yours is $version)" + echo "please upgrade or use the $3 variable to point to a more recent one" + echo "" + exit 1 + fi +} + if test ! -f ./builds/unix/configure.raw; then - echo "You must be in the same directory as \`autogen.sh'." - echo "Bootstrapping doesn't work if srcdir != builddir." - exit 1 + echo "You must be in the same directory as \`autogen.sh'." + echo "Bootstrapping doesn't work if srcdir != builddir." + exit 1 fi +# On MacOS X, the GNU libtool is named `glibtool'. +HOSTOS=`uname` +LIBTOOLIZE=libtoolize +if test "$HOSTOS"x = Darwinx; then + LIBTOOLIZE=glibtoolize +fi + +if test "$ACLOCAL"x = x; then + ACLOCAL=aclocal +fi + +if test "$AUTOCONF"x = x; then + AUTOCONF=autoconf +fi + +check_tool_version $ACLOCAL aclocal ACLOCAL 1.10.1 +check_tool_version $LIBTOOLIZE libtoolize LIBTOOLIZE 2.2.4 +check_tool_version $AUTOCONF autoconf AUTOCONF 2.62 + # This sets freetype_major, freetype_minor, and freetype_patch. eval `sed -nf version.sed include/freetype/freetype.h` @@ -40,13 +147,6 @@ echo "generating \`configure.ac'" sed -e "s;@VERSION@;$freetype_major$freetype_minor$freetype_patch;" \ < configure.raw > configure.ac -# On MacOS X, the GNU libtool is named `glibtool'. -HOSTOS=`uname` -LIBTOOLIZE=libtoolize -if test "$HOSTOS"x = Darwinx; then - LIBTOOLIZE=glibtoolize -fi - run aclocal -I . --force run $LIBTOOLIZE --force --copy --install run autoconf --force diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h index dc5ad3fde..4c3ce0aaa 100644 --- a/include/freetype/config/ftheader.h +++ b/include/freetype/config/ftheader.h @@ -728,6 +728,16 @@ */ #define FT_GASP_H + /************************************************************************* + * + * @macro: + * FT_ADVANCES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which returns individual and ranged glyph advances + */ +#define FT_ADVANCES_H /* */ diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index 238eca679..b0193c71e 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -2431,8 +2431,11 @@ FT_BEGIN_HEADER #define FT_LOAD_IGNORE_TRANSFORM 0x800 #define FT_LOAD_MONOCHROME 0x1000 #define FT_LOAD_LINEAR_DESIGN 0x2000 -#define FT_LOAD_SBITS_ONLY 0x4000 /* temporary hack! */ #define FT_LOAD_NO_AUTOHINT 0x8000U +#define FT_LOAD_ADVANCE_ONLY 0x10000U + + /* used internally only by certain font drivers ! */ +#define FT_LOAD_SBITS_ONLY 0x4000 /* */ diff --git a/include/freetype/internal/ftdriver.h b/include/freetype/internal/ftdriver.h index e433e78da..611963040 100644 --- a/include/freetype/internal/ftdriver.h +++ b/include/freetype/internal/ftdriver.h @@ -97,18 +97,17 @@ FT_BEGIN_HEADER FT_UInt right_glyph, FT_Vector* kerning ); - typedef FT_Error (*FT_Face_AttachFunc)( FT_Face face, FT_Stream stream ); typedef FT_Error - (*FT_Face_GetAdvancesFunc)( FT_Face face, - FT_UInt first, - FT_UInt count, - FT_Bool vertical, - FT_UShort* advances ); + (*FT_Face_GetAdvancesFunc)( FT_Face face, + FT_UInt first, + FT_UInt count, + FT_UInt flags, + FT_Fixed* advances ); /*************************************************************************/ diff --git a/src/base/Jamfile b/src/base/Jamfile index aeffe388e..d13d9bfbc 100644 --- a/src/base/Jamfile +++ b/src/base/Jamfile @@ -34,7 +34,7 @@ SubDir FT2_TOP $(FT2_SRC_DIR) base ; local _sources = system init glyph mm bdf bbox debug xf86 type1 pfr stroke winfnt otval bitmap synth - gxval lcdfil gasp patent + gxval lcdfil gasp patent advanc ; Library $(FT2_LIB) : ft$(_sources).c ; diff --git a/src/base/rules.mk b/src/base/rules.mk index d6e441254..738264cbe 100644 --- a/src/base/rules.mk +++ b/src/base/rules.mk @@ -44,7 +44,9 @@ BASE_SRC := $(BASE_DIR)/ftcalc.c \ $(BASE_DIR)/ftrfork.c \ $(BASE_DIR)/ftstream.c \ $(BASE_DIR)/fttrigon.c \ - $(BASE_DIR)/ftutil.c + $(BASE_DIR)/ftutil.c \ + $(BASE_DIR)/ftadvanc.c + # Base layer `extensions' sources # diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index 6c3ff989f..4e96d6844 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -187,6 +187,32 @@ } + FT_CALLBACK_DEF(FT_Error) + cff_get_advances( FT_Face ftface, + FT_UInt start, + FT_UInt count, + FT_UInt flags, + FT_Fixed* advances ) + { + CFF_Face face = (CFF_Face) ftface; + FT_UInt nn; + FT_Error error = 0; + FT_GlyphSlot slot = face->root.glyph; + + flags |= FT_LOAD_ADVANCE_ONLY; + + for (nn = 0; nn < count; nn++) + { + error = Load_Glyph( slot, face->root.size, start+nn, flags ); + if (error) break; + + advances[nn] = (flags & FT_LOAD_VERTICAL_LAYOUT) + ? slot->advance.y + : slot->advance.x; + } + return error; + } + /* * GLYPH DICT SERVICE * @@ -570,7 +596,7 @@ cff_get_kerning, 0, /* FT_Face_AttachFunc */ - 0, /* FT_Face_GetAdvancesFunc */ + cff_get_advances, /* FT_Face_GetAdvancesFunc */ cff_size_request, diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 935239d32..1914983f4 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -384,6 +384,11 @@ decoder->hint_mode = hint_mode; } + FT_LOCAL_DEF( void ) + cff_decoder_set_width_only( CFF_Decoder* decoder ) + { + decoder->width_only = 1; + } /* this function is used to select the subfont */ /* and the locals subrs array */ @@ -1200,6 +1205,12 @@ decoder->glyph_width = decoder->nominal_width + ( stack[0] >> 16 ); + if (decoder->width_only) + { + /* we only want the advance width, stop here */ + break; + } + /* Consumed an argument. */ num_args--; } @@ -2559,6 +2570,9 @@ cff_decoder_init( &decoder, face, size, glyph, hinting, FT_LOAD_TARGET_MODE( load_flags ) ); + if ((load_flags & FT_LOAD_ADVANCE_ONLY) != 0) + cff_decoder_set_width_only( &decoder ); + decoder.builder.no_recurse = (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h index d661f9e70..bf2165411 100644 --- a/src/cff/cffgload.h +++ b/src/cff/cffgload.h @@ -139,6 +139,7 @@ FT_BEGIN_HEADER FT_Pos nominal_width; FT_Bool read_width; + FT_Bool width_only; FT_Int num_hints; FT_Fixed* buildchar; FT_Int len_buildchar; @@ -168,6 +169,9 @@ FT_BEGIN_HEADER FT_Bool hinting, FT_Render_Mode hint_mode ); + FT_LOCAL( void ) + cff_decoder_set_width_only( CFF_Decoder* decoder ); + FT_LOCAL( FT_Error ) cff_decoder_prepare( CFF_Decoder* decoder, CFF_Size size, diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index c2cf45298..2647cf50c 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -125,6 +125,44 @@ #undef PAIR_TAG + static FT_Error + tt_get_advances( FT_Face ttface, + FT_UInt start, + FT_UInt count, + FT_UInt flags, + FT_Fixed *advances ) + { + FT_UInt nn; + TT_Face face = (TT_Face) ttface; + FT_Bool check = FT_BOOL(!(flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)); + + /* XXX: TODO: check for sbits */ + + if (flags & FT_LOAD_VERTICAL_LAYOUT) + { + for (nn = 0; nn < count; nn++) + { + FT_Short tsb; + FT_UShort ah; + + TT_Get_VMetrics( face, start + nn, check, &tsb, &ah ); + advances[nn] = ah; + } + } + else + { + for (nn = 0; nn < count; nn++) + { + FT_Short lsb; + FT_UShort aw; + + TT_Get_HMetrics( face, start + nn, check, &lsb, &aw ); + advances[nn] = aw; + } + } + return 0; + } + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ @@ -404,7 +442,7 @@ tt_get_kerning, 0, /* FT_Face_AttachFunc */ - 0, /* FT_Face_GetAdvancesFunc */ + tt_get_advances, tt_size_request, #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index ed79b932c..56857a344 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -69,12 +69,12 @@ /* `check' is true, take care of monospaced fonts by returning the */ /* advance width maximum. */ /* */ - static void - Get_HMetrics( TT_Face face, - FT_UInt idx, - FT_Bool check, - FT_Short* lsb, - FT_UShort* aw ) + FT_LOCAL_DEF(void) + TT_Get_HMetrics( TT_Face face, + FT_UInt idx, + FT_Bool check, + FT_Short* lsb, + FT_UShort* aw ) { ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); @@ -96,12 +96,12 @@ /* The monospace `check' is probably not meaningful here, but we leave */ /* it in for a consistent interface. */ /* */ - static void - Get_VMetrics( TT_Face face, - FT_UInt idx, - FT_Bool check, - FT_Short* tsb, - FT_UShort* ah ) + FT_LOCAL_DEF(void) + TT_Get_VMetrics( TT_Face face, + FT_UInt idx, + FT_Bool check, + FT_Short* tsb, + FT_UShort* ah ) { FT_UNUSED( check ); @@ -1143,16 +1143,16 @@ FT_UShort advance_width = 0, advance_height = 0; - Get_HMetrics( face, glyph_index, - (FT_Bool)!( loader->load_flags & - FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), - &left_bearing, - &advance_width ); - Get_VMetrics( face, glyph_index, - (FT_Bool)!( loader->load_flags & - FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), - &top_bearing, - &advance_height ); + TT_Get_HMetrics( face, glyph_index, + (FT_Bool)!( loader->load_flags & + FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), + &left_bearing, + &advance_width ); + TT_Get_VMetrics( face, glyph_index, + (FT_Bool)!( loader->load_flags & + FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), + &top_bearing, + &advance_height ); #ifdef FT_CONFIG_OPTION_INCREMENTAL diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h index b261e97de..313bb145c 100644 --- a/src/truetype/ttgload.h +++ b/src/truetype/ttgload.h @@ -34,6 +34,20 @@ FT_BEGIN_HEADER FT_LOCAL( void ) TT_Init_Glyph_Loading( TT_Face face ); + FT_LOCAL(void) + TT_Get_HMetrics( TT_Face face, + FT_UInt idx, + FT_Bool check, + FT_Short* lsb, + FT_UShort* aw ); + + FT_LOCAL(void) + TT_Get_VMetrics( TT_Face face, + FT_UInt idx, + FT_Bool check, + FT_Short* tsb, + FT_UShort* ah ); + FT_LOCAL( FT_Error ) TT_Load_Glyph( TT_Size size, TT_GlyphSlot glyph, diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c index 3ca21dc17..42302e578 100644 --- a/src/type1/t1driver.c +++ b/src/type1/t1driver.c @@ -304,7 +304,7 @@ (FT_Face_GetKerningFunc) Get_Kerning, (FT_Face_AttachFunc) T1_Read_Metrics, #endif - (FT_Face_GetAdvancesFunc) 0, + (FT_Face_GetAdvancesFunc) T1_Get_Advances, (FT_Size_RequestFunc) T1_Size_Request, (FT_Size_SelectFunc) 0 }; diff --git a/src/type1/t1gload.c b/src/type1/t1gload.c index e08a42897..6d7420c79 100644 --- a/src/type1/t1gload.c +++ b/src/type1/t1gload.c @@ -202,6 +202,63 @@ } + FT_LOCAL_DEF( FT_Error ) + T1_Get_Advances( T1_Face face, + FT_UInt first, + FT_UInt count, + FT_ULong load_flags, + FT_Fixed* advances ) + { + T1_DecoderRec decoder; + T1_Font type1 = &face->type1; + PSAux_Service psaux = (PSAux_Service)face->psaux; + FT_UInt nn; + FT_Error error; + + if (load_flags & FT_LOAD_VERTICAL_LAYOUT) + { + for (nn = 0; nn < count; nn++) + advances[nn] = 0; + + return T1_Err_Ok; + } + + error = psaux->t1_decoder_funcs->init( &decoder, + (FT_Face)face, + 0, /* size */ + 0, /* glyph slot */ + (FT_Byte**)type1->glyph_names, + face->blend, + 0, + FT_RENDER_MODE_NORMAL, + T1_Parse_Glyph ); + if ( error ) + return error; + + FT_UNUSED(load_flags); + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + decoder.num_subrs = type1->num_subrs; + decoder.subrs = type1->subrs; + decoder.subrs_len = type1->subrs_len; + + decoder.buildchar = face->buildchar; + decoder.len_buildchar = face->len_buildchar; + + for ( nn = 0; nn < count; nn++ ) + { + error = T1_Parse_Glyph( &decoder, first + nn ); + if (!error) + advances[nn] = decoder.builder.advance.x; + else + advances[nn] = 0; + } + return T1_Err_Ok; + } + + FT_LOCAL_DEF( FT_Error ) T1_Load_Glyph( T1_GlyphSlot glyph, T1_Size size, diff --git a/src/type1/t1gload.h b/src/type1/t1gload.h index de87896dc..1638db81b 100644 --- a/src/type1/t1gload.h +++ b/src/type1/t1gload.h @@ -31,6 +31,13 @@ FT_BEGIN_HEADER T1_Compute_Max_Advance( T1_Face face, FT_Pos* max_advance ); + FT_LOCAL( FT_Error ) + T1_Get_Advances( T1_Face face, + FT_UInt first, + FT_UInt count, + FT_ULong load_flags, + FT_Fixed* advances ); + FT_LOCAL( FT_Error ) T1_Load_Glyph( T1_GlyphSlot glyph, T1_Size size,