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,