diff --git a/ChangeLog b/ChangeLog index 3fc63c4a2..03fbc029b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2003-01-07 David Turner + + * src/base/ftstroker.c: probably the last bug-fixes to the stroker, + the API is likely to change however. + + * src/base/fttrigon.c (FT_Angle_Diff): fixing function, it returned + invalid values for large negative angle differences (resulting in + incorrect stroker computations, among other things) + + * src/cache/ftccache.c (ftc_node_unlink): removing incorrect + assertion, and changing code to avoid hash table size contraction + + * src/base/Jamfile, src/base/rules.mk, src/base/descrip.mms: + adding "ftstroker.obj" to default build, as optional component + 2002-12-26 David Turner * src/gzip/adler32.c, src/gzip/infblock.c, src/gzip/inflate.c, diff --git a/Jamfile.in b/Jamfile.in index 65dd0640a..64ead8b56 100644 --- a/Jamfile.in +++ b/Jamfile.in @@ -1,6 +1,21 @@ -# FreeType 2 top Jamfile (c) 2001, 2002 David Turner +# FreeType 2 top Jamfile (c) 2001-2002 David Turner # +# The HDRMACRO is already defined in FTJam and is used to add +# the content of certain macros to the list of included header +# files. +# +# we can compile FreeType 2 with classic Jam however thanks to +# the following code +# +if ! $(JAM_TOOLSET) +{ + rule HDRMACRO + { + # nothing !! + } +} + # We need to invoke a SubDir rule if the FT2 source directory top is not the # current directory. This allows us to build FreeType 2 as part of a larger # project easily. @@ -10,17 +25,72 @@ if $(FT2_TOP) != $(DOT) SubDir FT2_TOP ; } -FT2_INCLUDE = [ FT2_SubDir include ] ; -FT2_SRC = [ FT2_SubDir src ] ; - -FT2_LIB = $(LIBPREFIX)freetype ; - - -# We don't support libtool just yet. It seems that this is not -# so simple with Jam, but I'll study this topic later. +# +# The following macros define the include directory, the source directory +# and the final library name (without library extensions). They can be +# replaced by other definitions when the library is compiled as part of +# a larger project. # -# used only when trying to debug the hinter(s) +# name of FreeType include directory during compilation. +# relative to FT2_TOP +# +FT2_INCLUDE_DIR ?= include ; + +# name of FreeType source directory during compilation. +# relative to FT2_TOP +# +FT2_SRC_DIR ?= src ; + +# name of final library, without extension +# +FT2_LIB ?= $(LIBPREFIX)freetype ; + + +# define FT2_BUILD_INCLUDE to point to your build-specific directory +# this is prepended to FT2_INCLUDE_DIR. This can be used to specify +# the location of a custom which will point to custom +# versions of "ftmodule.h" and "ftoption.h", for example +# +FT2_BUILD_INCLUDE ?= ; + +# the list of modules to compile on any given build of the library +# by default, this will contain _all_ modules defined in FT2_SRC_DIR +# +# IMPORTANT: You'll need to change the content of "ftmodule.h" as well +# if you modify this list or provide your own. +# +FT2_COMPONENTS ?= gzip # support for gzip-compressed files. + autohint # auto-hinter + base # base component (public APIs) + bdf # BDF font driver + cache # cache sub-system + ccg # Chinese Character Generator font driver + cff # CFF/CEF font driver + cid # Postscript CID-keyed font driver + pcf # PCF font driver + pfr # PFR/TrueDoc font driver + psaux # Common Postscript routines module + pshinter # Postscript hinter module + psnames # Postscript names handling + raster # Monochrome rasterizer + smooth # Anti-aliased rasterizer + sfnt # SFNT-based format support routines + truetype # TrueType font driver + type1 # Postscript Type 1 font driver + type42 # Postscript Type 42 (embedded TrueType) driver + winfonts # Windows FON/FNT font driver + ; + + +# don't touch +# +FT2_INCLUDE = $(FT2_BUILD_INCLUDE) + [ FT2_SubDir $(FT2_INCLUDE_DIR) ] ; + +FT2_SRC = [ FT2_SubDir $(FT2_SRC_DIR) ] ; + +# only used by FreeType developers # if $(DEBUG_HINTER) { @@ -31,7 +101,7 @@ if $(DEBUG_HINTER) # We need "freetype2/include" in the current include path in order to # compile any part of FreeType 2. # -SubDirHdr += $(FT2_INCLUDE) ; +SubDirHdr += $(FT2_INCLUDE) ; # Uncomment the following line if you want to build individual source files # for each FreeType 2 module. @@ -51,7 +121,7 @@ HDRMACRO [ FT2_SubDir include freetype internal internal.h ] ; SubInclude FT2_TOP $(FT2_SRC_DIR) ; -# tests files (hinter debugging) +# tests files (hinter debugging). only used by FreeType developers # if $(DEBUG_HINTER) { diff --git a/src/base/Jamfile b/src/base/Jamfile index 8e52df632..bc4c71dcd 100644 --- a/src/base/Jamfile +++ b/src/base/Jamfile @@ -22,7 +22,8 @@ SubDir FT2_TOP $(FT2_SRC_DIR) base ; # Add the optional/replaceable files. # Library $(FT2_LIB) : ftsystem.c ftinit.c ftglyph.c ftmm.c ftbdf.c - ftbbox.c ftdebug.c ftxf86.c fttype1.c ftpfr.c ; + ftbbox.c ftdebug.c ftxf86.c fttype1.c ftpfr.c + ftstroker.c ; # Add Macintosh-specific file to the library when necessary. # diff --git a/src/base/descrip.mms b/src/base/descrip.mms index ac304d0aa..895da06a2 100644 --- a/src/base/descrip.mms +++ b/src/base/descrip.mms @@ -15,7 +15,7 @@ CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.builds.vms],[--.include],[--.src.base]) -OBJS=ftbase.obj,ftinit.obj,ftglyph.obj,ftdebug.obj,ftbdf.obj,ftmm.obj,fttype1.obj,ftxf86.obj,ftpfr.obj +OBJS=ftbase.obj,ftinit.obj,ftglyph.obj,ftdebug.obj,ftbdf.obj,ftmm.obj,fttype1.obj,ftxf86.obj,ftpfr.obj, ftstroker.obj all : $(OBJS) library [--.lib]freetype.olb $(OBJS) diff --git a/src/base/ftstroker.c b/src/base/ftstroker.c index c019be7dd..712020e78 100644 --- a/src/base/ftstroker.c +++ b/src/base/ftstroker.c @@ -233,8 +233,12 @@ { FT_ASSERT( border->start >= 0 ); - border->tags[ border->start ] |= FT_STROKE_TAG_BEGIN; - border->tags[ border->num_points-1 ] |= FT_STROKE_TAG_END; + /* don't record empty paths !! */ + if ( border->num_points > (FT_UInt)border->start ) + { + border->tags[ border->start ] |= FT_STROKE_TAG_BEGIN; + border->tags[ border->num_points-1 ] |= FT_STROKE_TAG_END; + } border->start = -1; border->movable = 0; @@ -469,7 +473,7 @@ FT_Byte* tags = border->tags; FT_Int in_contour = 0; - for ( ; count > 0; count--, point++, tags++ ) + for ( ; count > 0; count--, num_points++, point++, tags++ ) { if ( tags[0] & FT_STROKE_TAG_BEGIN ) { @@ -538,7 +542,7 @@ FT_Short* write = outline->contours + outline->n_contours; FT_Short index = (FT_Short) outline->n_points; - for ( ; count > 0; count--, tags++, write++, index++ ) + for ( ; count > 0; count--, tags++, index++ ) { if ( *tags & FT_STROKE_TAG_END ) { @@ -787,9 +791,15 @@ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); if (theta == FT_ANGLE_PI) + { theta = rotate; + phi = stroker->angle_in; + } else + { theta = theta/2; + phi = stroker->angle_in + theta + rotate; + } thcos = FT_Cos( theta ); sigma = FT_MulFix( stroker->miter_limit, thcos ); @@ -797,7 +807,6 @@ if ( sigma >= 0x10000L ) miter = 0; - phi = stroker->angle_in + theta + rotate; if (miter) /* this is a miter (broken angle) */ { @@ -1362,3 +1371,207 @@ ft_stroke_border_export( stroker->borders+1, outline ); } } + + + + + + /* + * the following is very similar to FT_Outline_Decompose, except + * that we do support opened paths, and do not scale the outline + */ + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_ParseOutline( FT_Stroker stroker, + FT_Outline* outline, + FT_Bool opened ) + { + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + FT_Error error; + + FT_Int n; /* index of contour in outline */ + FT_UInt first; /* index of first point in contour */ + FT_Int tag; /* current point's state */ + FT_Int in_path; + + if ( !outline || !stroker ) + return FT_Err_Invalid_Argument; + + first = 0; + + in_path = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + FT_Int last; /* index of last point in contour */ + + + last = outline->contours[n]; + limit = outline->points + last; + + v_start = outline->points[first]; + v_last = outline->points[last]; + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_CURVE_TAG_CONIC ) + { + /* first point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + error = FT_Stroker_BeginSubPath( stroker, &v_start, opened ); + if ( error ) + goto Exit; + + in_path = 1; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + switch ( tag ) + { + case FT_CURVE_TAG_ON: /* emit a single line_to */ + { + FT_Vector vec; + + + vec.x = point->x; + vec.y = point->y; + + error = FT_Stroker_LineTo( stroker, &vec ); + if ( error ) + goto Exit; + continue; + } + + case FT_CURVE_TAG_CONIC: /* consume conic arcs */ + v_control.x = point->x; + v_control.y = point->y; + + Do_Conic: + if ( point < limit ) + { + FT_Vector vec; + FT_Vector v_middle; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + vec = point[0]; + + if ( tag == FT_CURVE_TAG_ON ) + { + error = FT_Stroker_ConicTo( stroker, &v_control, &vec ); + if ( error ) + goto Exit; + continue; + } + + if ( tag != FT_CURVE_TAG_CONIC ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + vec.x ) / 2; + v_middle.y = ( v_control.y + vec.y ) / 2; + + error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle ); + if ( error ) + goto Exit; + + v_control = vec; + goto Do_Conic; + } + + error = FT_Stroker_ConicTo( stroker, &v_control, &v_start ); + goto Close; + + default: /* FT_CURVE_TAG_CUBIC */ + { + FT_Vector vec1, vec2; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + vec1 = point[-2]; + vec2 = point[-1]; + + if ( point <= limit ) + { + FT_Vector vec; + + + vec = point[0]; + + error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec ); + if ( error ) + goto Exit; + continue; + } + + error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start ); + goto Close; + } + } + } + + Close: + if ( error ) + goto Exit; + + error = FT_Stroker_EndSubPath( stroker ); + if ( error ) + goto Exit; + + first = last + 1; + } + + return 0; + + Exit: + return error; + + Invalid_Outline: + return FT_Err_Invalid_Outline; + } diff --git a/src/base/fttrigon.c b/src/base/fttrigon.c index 744f9a9b5..c16fa2468 100644 --- a/src/base/fttrigon.c +++ b/src/base/fttrigon.c @@ -474,6 +474,8 @@ FT_Angle delta = angle2 - angle1; delta %= FT_ANGLE_2PI; + if ( delta < 0 ) + delta += FT_ANGLE_2PI; if ( delta > FT_ANGLE_PI ) delta -= FT_ANGLE_2PI; diff --git a/src/base/rules.mk b/src/base/rules.mk index 0a38faefa..d83b1e478 100644 --- a/src/base/rules.mk +++ b/src/base/rules.mk @@ -49,12 +49,13 @@ BASE_SRC := $(BASE_)ftcalc.c \ # object. It will then be linked to the final executable only if one of its # symbols is used by the application. # -BASE_EXT_SRC := $(BASE_)ftglyph.c \ - $(BASE_)ftmm.c \ - $(BASE_)ftbdf.c \ - $(BASE_)fttype1.c \ - $(BASE_)ftxf86.c \ - $(BASE_)ftpfr.c \ +BASE_EXT_SRC := $(BASE_)ftglyph.c \ + $(BASE_)ftmm.c \ + $(BASE_)ftbdf.c \ + $(BASE_)fttype1.c \ + $(BASE_)ftxf86.c \ + $(BASE_)ftpfr.c \ + $(BASE_)ftstroker.c \ $(BASE_)ftbbox.c # Default extensions objects diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c index 14cb725b2..343f08eac 100644 --- a/src/cache/ftccache.c +++ b/src/cache/ftccache.c @@ -196,7 +196,8 @@ FTC_Node* pold; - FT_ASSERT( old_index >= FTC_HASH_INITIAL_SIZE ); + if ( old_index+1 <= FTC_HASH_INITIAL_SIZE ) + goto Exit; if ( p == 0 ) {