diff options
7 files changed, 4784 insertions, 0 deletions
diff --git a/testing/freetype-infinality/APKBUILD b/testing/freetype-infinality/APKBUILD new file mode 100644 index 000000000..a5c134c92 --- /dev/null +++ b/testing/freetype-infinality/APKBUILD @@ -0,0 +1,56 @@ +# Contributor: Carlo Landmeter <clandmeter@gmail.com> +# Maintainer: +pkgname=freetype-infinality +pkgver=2.4.4 +pkgrel=0 +pkgdesc="TrueType font rendering library with infinality patch" +url="http://www.infinality.net" +arch="all" +license="GPL" +depends= +depends_dev="zlib-dev freetype-dev" +makedepends="$depends_dev" +install="" +subpackages="$pkgname-dev" +replaces="freetype" +source="http://downloads.sourceforge.net/sourceforge/freetype/freetype-$pkgver.tar.bz2 +freetype-add-subpixel-hinting-infinality-20101114-1.patch +freetype-enable-subpixel-hinting-infinality-20100909-1.patch +freetype-entire-infinality-patchset-20101114-1.patch +infinality-settings +freetype-2.2.1-enable-valid.patch +freetype2-infinality-protect_null_pointer-goddesse.patch" + +_builddir="$srcdir/freetype-$pkgver" + +prepare() { + local i + cd "$_builddir" + for i in $source; do + case $i in + *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;; + esac + done +} + +build() { + cd "$_builddir" + ./configure --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man + make || return 1 +} + +package() { + cd "$_builddir" + make DESTDIR="$pkgdir" install || return 1 + install -Dm644 "$srcdir/infinality-settings" "$pkgdir/etc/infinality-settings" +} + +md5sums="b3e2b6e2f1c3e0dffa1fd2a0f848b671 freetype-2.4.4.tar.bz2 +799a2d229c2997a5bb2d5b7c9f92fdba freetype-add-subpixel-hinting-infinality-20101114-1.patch +a88b1a66da44a90c1fdcdeaa39a2dc09 freetype-enable-subpixel-hinting-infinality-20100909-1.patch +6725774b17820f5413cb6a3cf7547f53 freetype-entire-infinality-patchset-20101114-1.patch +416154ff9eb8dfb27e46080f678785b8 infinality-settings +214119610444c9b02766ccee5e220680 freetype-2.2.1-enable-valid.patch +316d2986f9a08e7ceb51fb9d5a5cab38 freetype2-infinality-protect_null_pointer-goddesse.patch" diff --git a/testing/freetype-infinality/freetype-2.2.1-enable-valid.patch b/testing/freetype-infinality/freetype-2.2.1-enable-valid.patch new file mode 100644 index 000000000..c78b6b70f --- /dev/null +++ b/testing/freetype-infinality/freetype-2.2.1-enable-valid.patch @@ -0,0 +1,20 @@ +--- freetype-2.2.1/modules.cfg.orig 2006-07-07 21:01:09.000000000 -0400 ++++ freetype-2.2.1/modules.cfg 2006-07-07 21:01:54.000000000 -0400 +@@ -110,7 +110,7 @@ + AUX_MODULES += cache + + # TrueType GX/AAT table validation. Needs ftgxval.c below. +-# AUX_MODULES += gxvalid ++AUX_MODULES += gxvalid + + # Support for streams compressed with gzip (files with suffix .gz). + # +@@ -124,7 +124,7 @@ + + # OpenType table validation. Needs ftotval.c below. + # +-# AUX_MODULES += otvalid ++AUX_MODULES += otvalid + + # Auxiliary PostScript driver component to share common code. + # diff --git a/testing/freetype-infinality/freetype-add-subpixel-hinting-infinality-20101114-1.patch b/testing/freetype-infinality/freetype-add-subpixel-hinting-infinality-20101114-1.patch new file mode 100644 index 000000000..05e9c4414 --- /dev/null +++ b/testing/freetype-infinality/freetype-add-subpixel-hinting-infinality-20101114-1.patch @@ -0,0 +1,2776 @@ +Infinality Freetype Truetype Subpixel Hinting Patch +------------------------------------------------------------------- +Should patch cleanly to freetype-2.4.3 + + +Changes for 2010-11-14: + * Rule tweaks on various fonts. Fixed the Cyrillic y issue and e issue + with Trebuchet, and the ^ issue with Arial. Other issues + (firefox and @font-face) are still present to a degree. + + * A couple new rules to deal with various issues. (work in progress) + + * Additional commenting. + + * Some cleanup of obsolete code. + + * Added some debugging code for potential future enhancements. Please + ignore the mess. + + +Changes for 2010-10-22: + * I'm refocusing on just getting the subpixel looking nice, so I've stripped + back the rendering modes to just 2. The standard SUBPIXEL_HINTING and + the ADDITIONAL_TWEAKS. The rules structure is still in place. I recommend + using ADDITIONAL_TWEAKS mode. + + * Fixed an issue with monochrome rendering that made fonts look really bad. + There is still an issue with them, but they are at least tolerable to + look at now. + + * Added some testing code for detecting inline delta functions. Not sure + if this is useful yet. + + * Added more rules to deal with certain artifacts on various fonts, like the + issue with < > and ^. Created some "exception" rules for certain rules. + + * Reverted back to older rounding functions. The new experimental ones I + was trying were causing artifacts on some fonts. + + * Some code cleanup. + + +Changes for 2010-10-08: + * Fix PDF crashes. + +Changes for 2010-10-04: + * Update to freetype-2.4.3 + + +Changes for 2010-10-03: + * There are lots of changes for this one, some big, some small, and some + that still are not implemented. Not sure if I can remember them all + but I will try! THIS IS A POINT RELEASE THAT IS NOT + INTENDED TO WORK 100%. Some fonts and compile options may be broken + and the code may be inefficient and/or not syntactiacally correct. + That said, I do plan on using this on my system right away. + + * There are now "rendering modes" for the subpixel hinting, with the idea + that this will enventually be able to be controlled by fontconfig. The 4 + modes of enhanced hinting defined so far are: + 1) NATIVE HINTING - this is what freetype TT interpreter does by default. + 2) FIXED NATIVE HINTING - A slighly tweaked version of the above that + does "better" native rendering when displaying on LCD, for those + that still seem to like incorrect, thin fonts, which were only ever + there due to technical limitations. + 3) SUBPIXEL OPTIMIZED HINTING - this is straight up subpixel hinting with + very few tweaks. Just enough to get it working. + 4) COMPATIBILITY MODE HINTING - this is the sweet spot I'm working on + that will hopefully supplant #3 because it will work so well with all + fonts. The idea here is to tweak all available fonts so that each + renders well. + All of these modes either turn on or off switches in the interpreter + to make the fonts render properly for each mode. Right now these are only + compile-time options. + + * Subpixel-related code has been broken out into its own files, so as to not + clutter up the existing code. + + * The rasterizer now pays attention to the additional bits of MS rasterizer + v. 37, meaning that it can now indicate to fonts that it can handle + subpixel rendering. + + * The rounding functions have been adapted to accept a grid resolution + variable, which lets them work on pixel and subpixel boundaries + automatically. Y still needs to be implemented. + + * Additional conditions have been added to the switches, to further refine + how they are applied to different fonts. + + * What all this means qualitatively is that legacy fonts now render much + better. There are still some that need a bit of love, like Courier New. + + - Courier New has some fixes, and some breakage (Ghost pixels above bold + fonts, too thin on regular font) + - Times New Roman has some fixes and breakage (serifs, particularly) + - Tahoma and Trebuchet MS have been cleaned up + - Arial now snaps to grid better, but that causes breakage on a few glyphs + - Verdana 13 is now set to grid fit, but some glyhs are broken (mwxyz) + - Geneva and Geneva CY no longer look like turds + - Lucida Sans Unicode now looks arguably better than Lucida Grande + + + +Changes for 2010-09-16: + + * The changes from 2010-09-14 regarding subpixel when LIGHT hinting enabled + have been reverted due to problems. The old behavior is back. + + * Disable grayscale when subpixel is enabled. This results in better + behavior of some TT instructions within some fonts, like Times New Roman. + + * Some modification of the tweaks, in light of above. + + +Changes for 2010-09-14: + + /************************** NO LONGER IN PLACE *****************************/ + * Subpixel hinting is now used when the LIGHT hinting method and the TT + hinting is called. If FULL hinting is requested it will do the usual + behavior of the TT hinter. + + This allows for all previously existing behavior, plus the new subpixel + hinting behavior, all in the same compile, and it makes sense in that + the slight hinting of the autohinter is essentially doing the same thing + as this, which is not forcing X-direction hints. + + Previously, even if TT was selected, but LIGHT hinting was used, the + autohinter would still be forced. Other than this, autohint is not affected. + /***************************************************************************/ + + * Added a couple more conditionals around things to test whether subpixel + hinting is enabled. There were a few missing that ended up causing some + goofy hinting if subpixel was not enabled, but compiled in. + + + + + + + + + +diff -Nur freetype-2.4.3.orig/include/freetype/config/ftoption.h freetype-2.4.3.new/include/freetype/config/ftoption.h +--- freetype-2.4.3.orig/include/freetype/config/ftoption.h 2010-07-04 23:38:55.000000000 -0500 ++++ freetype-2.4.3.new/include/freetype/config/ftoption.h 2010-10-23 21:47:20.476211579 -0500 +@@ -501,6 +501,48 @@ + + /*************************************************************************/ + /* */ ++ /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile */ ++ /* EXPERIMENTAL subpixel hinting support into the TrueType driver. */ ++ /* This will replace the native TrueType hinting mechanism when */ ++ /* anything but FT_RENDER_MODE_MONO is requested. */ ++ /* */ ++ /* Enabling this causes the TrueType driver to ignore instructions */ ++ /* under certain conditions. This is done in accordance with the */ ++ /* guide here, with some minor differences: */ ++ /* */ ++ /* http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ ++ /* */ ++ /* By undefining this, you will only compile the code necessary to */ ++ /* hint TrueType glyphs with native TT hinting. */ ++ /* */ ++ /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */ ++ /* defined. */ ++ /* */ ++/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ ++ ++ /*************************************************************************/ ++ /* */ ++ /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS if you */ ++ /* want to enable additional subpixel hinting tweaks of individual fonts,*/ ++ /* glyphs, styles and sizes. The idea here is that some glyphs and */ ++ /* fonts still do not render in a desirable way with */ ++ /* TT_CONFIG_OPTION_SUBPIXEL_HINTING. */ ++ /* */ ++ /* This is disabled by default, as some people may not care, or may not */ ++ /* want the additional overhead involved in doing this. */ ++ /* */ ++ /* By undefining this, you will only compile the code necessary to */ ++ /* do subpixel hinting as defined above. */ ++ /* */ ++ /* This option requires TT_CONFIG_OPTION_SUBPIXEL_HINTING to be */ ++ /* defined. */ ++ /* */ ++/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */ ++ ++ ++ /*************************************************************************/ ++ /* */ + /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */ + /* of the TrueType bytecode interpreter is used that doesn't implement */ + /* any of the patented opcodes and algorithms. The patents related to */ +diff -Nur freetype-2.4.3.orig/include/freetype/internal/ftobjs.h freetype-2.4.3.new/include/freetype/internal/ftobjs.h +--- freetype-2.4.3.orig/include/freetype/internal/ftobjs.h 2010-07-18 11:07:31.000000000 -0500 ++++ freetype-2.4.3.new/include/freetype/internal/ftobjs.h 2010-11-07 11:18:19.681501081 -0600 +@@ -81,6 +81,14 @@ + #define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 ) + #define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 ) + ++ /* ++ * These are used in ttinterp.c for subpixel hinting with an ++ * adjustable grids-per-pixel value. ++ */ ++#define FT_PIX_FLOOR_GRID( x, n ) ( (x) & ~(64 / n - 1) ) ++#define FT_PIX_ROUND_GRID( x, n ) FT_PIX_FLOOR_GRID( (x) + 32 / n, n) ++#define FT_PIX_CEIL_GRID( x, n ) FT_PIX_FLOOR_GRID( (x) + 63 / n, n) ++ + + /* + * Return the highest power of 2 that is <= value; this correspond to +diff -Nur freetype-2.4.3.orig/src/truetype/rules.mk freetype-2.4.3.new/src/truetype/rules.mk +--- freetype-2.4.3.orig/src/truetype/rules.mk 2009-03-14 08:45:26.000000000 -0500 ++++ freetype-2.4.3.new/src/truetype/rules.mk 2010-10-22 19:25:46.060977607 -0500 +@@ -30,7 +30,8 @@ + $(TT_DIR)/ttgload.c \ + $(TT_DIR)/ttinterp.c \ + $(TT_DIR)/ttgxvar.c \ +- $(TT_DIR)/ttdriver.c ++ $(TT_DIR)/ttdriver.c \ ++ $(TT_DIR)/ttsubpixel.c + + # TrueType driver headers + # +diff -Nur freetype-2.4.3.orig/src/truetype/truetype.c freetype-2.4.3.new/src/truetype/truetype.c +--- freetype-2.4.3.orig/src/truetype/truetype.c 2009-07-03 08:28:24.000000000 -0500 ++++ freetype-2.4.3.new/src/truetype/truetype.c 2010-10-22 19:25:46.061853066 -0500 +@@ -27,6 +27,7 @@ + + #ifdef TT_USE_BYTECODE_INTERPRETER + #include "ttinterp.c" ++#include "ttsubpixel.c" + #endif + + #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +diff -Nur freetype-2.4.3.orig/src/truetype/ttgload.c freetype-2.4.3.new/src/truetype/ttgload.c +--- freetype-2.4.3.orig/src/truetype/ttgload.c 2010-09-14 02:00:35.000000000 -0500 ++++ freetype-2.4.3.new/src/truetype/ttgload.c 2010-11-14 09:07:50.835981062 -0600 +@@ -33,7 +33,7 @@ + #endif + + #include "tterrors.h" +- ++#include "ttsubpixel.h" + + /*************************************************************************/ + /* */ +@@ -166,6 +166,12 @@ + loader->top_bearing = top_bearing; + loader->vadvance = advance_height; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( loader->exec ) loader->exec->sph_tweak_flags = 0x00000; ++ /* this may not be the right place for this, but it works */ ++ if ( loader->exec && loader->exec->enhanced ) sph_set_tweaks( loader, glyph_index ); ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ + if ( !loader->linear_def ) + { + loader->linear_def = 1; +@@ -1683,13 +1689,23 @@ + IS_HINTED( loader->load_flags ) ) + { + FT_Byte* widthp; ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ FT_Bool enhanced; + ++ enhanced = ++ FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) ++ != FT_RENDER_MODE_MONO ); + ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + widthp = tt_face_get_device_metrics( face, + size->root.metrics.x_ppem, + glyph_index ); + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( ( !enhanced || BITMAP_WIDTHS ) && widthp ) ++#else + if ( widthp ) ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + glyph->metrics.horiAdvance = *widthp << 6; + } + +@@ -1883,8 +1899,13 @@ + { + TT_ExecContext exec; + FT_Bool grayscale; +- +- ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ FT_Bool subpixel_hinting; ++ FT_Bool grayscale_hinting; ++ /*FT_Bool compatible_widths; ++ FT_Bool symmetrical_smoothing; ++ FT_Bool bgr;*/ ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + if ( !size->cvt_ready ) + { + FT_Error error = tt_size_ready_bytecode( size ); +@@ -1898,20 +1919,75 @@ + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ subpixel_hinting = ++ FT_BOOL( (FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO) ++ && SET_SUBPIXEL ); ++ ++ if ( subpixel_hinting ) grayscale = grayscale_hinting = FALSE; ++ else if ( SET_GRAYSCALE ) ++ { ++ grayscale = grayscale_hinting = TRUE; ++ subpixel_hinting = FALSE; ++ } ++ ++ exec->enhanced = ( subpixel_hinting ++ || grayscale_hinting ); ++ ++ exec->rasterizer_version = SET_RASTERIZER_VERSION; ++ ++ exec->compatible_widths = SET_COMPATIBLE_WIDTHS; ++ /*FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) ++ != TT_LOAD_COMPATIBLE_WIDTHS );*/ ++ ++ exec->symmetrical_smoothing = FALSE; ++ /*FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) ++ != TT_LOAD_SYMMETRICAL_SMOOTHING );*/ ++ ++ exec->bgr = FALSE; ++ /*FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) ++ != TT_LOAD_BGR );*/ ++#else + grayscale = + FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO ); ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + TT_Load_Context( exec, face, size ); + +- /* a change from mono to grayscale rendering (and vice versa) */ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ ++ /* a change from mono to subpixel rendering (and vice versa) */ + /* requires a re-execution of the CVT program */ +- if ( grayscale != exec->grayscale ) ++ if ( subpixel_hinting != exec->subpixel_hinting ) ++ { ++ FT_UInt i; ++ ++ exec->subpixel_hinting = subpixel_hinting; ++ ++ for ( i = 0; i < size->cvt_size; i++ ) ++ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); ++ tt_size_run_prep( size ); ++ } ++ ++ /* a change from mono to grayscale rendering (and vice versa) */ ++ /* requires a re-execution of the CVT program */ ++ if ( grayscale != exec->grayscale_hinting ) + { + FT_UInt i; + ++ exec->grayscale_hinting = grayscale_hinting; + +- FT_TRACE4(( "tt_loader_init: grayscale change," +- " re-executing `prep' table\n" )); ++ for ( i = 0; i < size->cvt_size; i++ ) ++ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); ++ tt_size_run_prep( size ); ++ } ++#else ++ ++ /* a change from mono to grayscale rendering (and vice versa) */ ++ /* requires a re-execution of the CVT program */ ++ if ( grayscale != exec->grayscale ) ++ { ++ FT_UInt i; + + exec->grayscale = grayscale; + +@@ -1919,6 +1995,7 @@ + size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); + tt_size_run_prep( size ); + } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + /* see whether the cvt program has disabled hinting */ + if ( exec->GS.instruct_control & 1 ) +@@ -2050,6 +2127,7 @@ + if ( face->postscript.isFixedPitch && + ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 ) + glyph->linearHoriAdvance = face->horizontal.advance_Width_Max; ++ + } + + return TT_Err_Ok; +@@ -2125,6 +2203,9 @@ + } + else + glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; ++ ++ ++ + } + + #endif /* TT_USE_BYTECODE_INTERPRETER */ +diff -Nur freetype-2.4.3.orig/src/truetype/ttinterp.c freetype-2.4.3.new/src/truetype/ttinterp.c +--- freetype-2.4.3.orig/src/truetype/ttinterp.c 2010-10-01 01:08:19.000000000 -0500 ++++ freetype-2.4.3.new/src/truetype/ttinterp.c 2010-11-14 09:25:21.736322597 -0600 +@@ -27,10 +27,12 @@ + + #include "tterrors.h" + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++#include "ttsubpixel.h" ++#endif + + #ifdef TT_USE_BYTECODE_INTERPRETER + +- + #define TT_MULFIX FT_MulFix + #define TT_MULDIV FT_MulDiv + #define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round +@@ -150,11 +152,11 @@ + #define NORMalize( x, y, v ) \ + Normalize( EXEC_ARG_ x, y, v ) + +-#define SET_SuperRound( scale, flags ) \ +- SetSuperRound( EXEC_ARG_ scale, flags ) ++#define SET_SuperRound( scale, flags, res ) \ ++ SetSuperRound( EXEC_ARG_ scale, flags, res ) + +-#define ROUND_None( d, c ) \ +- Round_None( EXEC_ARG_ d, c ) ++#define ROUND_None( d, c, e ) \ ++ Round_None( EXEC_ARG_ d, c, e ) + + #define INS_Goto_CodeRange( range, ip ) \ + Ins_Goto_CodeRange( EXEC_ARG_ range, ip ) +@@ -165,8 +167,8 @@ + #define CUR_Func_move_orig( z, p, d ) \ + CUR.func_move_orig( EXEC_ARG_ z, p, d ) + +-#define CUR_Func_round( d, c ) \ +- CUR.func_round( EXEC_ARG_ d, c ) ++#define CUR_Func_round( d, c, e ) \ ++ CUR.func_round( EXEC_ARG_ d, c, e ) + + #define CUR_Func_read_cvt( index ) \ + CUR.func_read_cvt( EXEC_ARG_ index ) +@@ -246,6 +248,12 @@ + #define GUESS_VECTOR( V ) + #endif + ++ ++ /*FT_Int CUR.num_delta_funcs;*/ ++ /*FT_ULong inline_delta_funcs[5];*/ ++ /*FT_Long CUR.infunc;*/ ++ ++ + /*************************************************************************/ + /* */ + /* CODERANGE FUNCTIONS */ +@@ -1838,24 +1846,33 @@ + FT_ASSERT( !CUR.face->unpatented_hinting ); + #endif + +- v = CUR.GS.freeVector.x; +- +- if ( v != 0 ) ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( !CUR.enhanced || CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_DMOVE_FREEV ) + { +- zone->cur[point].x += TT_MULDIV( distance, ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ ++ v = CUR.GS.freeVector.x; ++ ++ if ( v != 0 ) ++ { ++ zone->cur[point].x += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + +- zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; ++ zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; ++ } ++ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + v = CUR.GS.freeVector.y; + + if ( v != 0 ) + { + zone->cur[point].y += TT_MULDIV( distance, +- v * 0x10000L, +- CUR.F_dot_P ); ++ v * 0x10000L, ++ CUR.F_dot_P ); + + zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; + } +@@ -1895,18 +1912,17 @@ + + if ( v != 0 ) + zone->org[point].x += TT_MULDIV( distance, +- v * 0x10000L, +- CUR.F_dot_P ); ++ v * 0x10000L, ++ CUR.F_dot_P ); + + v = CUR.GS.freeVector.y; + + if ( v != 0 ) + zone->org[point].y += TT_MULDIV( distance, +- v * 0x10000L, +- CUR.F_dot_P ); ++ v * 0x10000L, ++ CUR.F_dot_P ); + } + +- + /*************************************************************************/ + /* */ + /* Special versions of Direct_Move() */ +@@ -1923,9 +1939,16 @@ + FT_F26Dot6 distance ) + { + FT_UNUSED_EXEC; +- +- zone->cur[point].x += distance; +- zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( !CUR.enhanced ++ || ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_DMOVEX_FREEV ) ) ++ { ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ zone->cur[point].x += distance; ++ zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + } + + +@@ -1940,7 +1963,6 @@ + zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; + } + +- + /*************************************************************************/ + /* */ + /* Special versions of Direct_Move_Orig() */ +@@ -1959,6 +1981,7 @@ + FT_UNUSED_EXEC; + + zone->org[point].x += distance; ++ + } + + +@@ -1969,7 +1992,7 @@ + { + FT_UNUSED_EXEC; + +- zone->org[point].y += distance; ++ zone->org[point].y += distance; + } + + +@@ -1997,7 +2020,8 @@ + /* */ + static FT_F26Dot6 + Round_None( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + +@@ -2016,6 +2040,7 @@ + if ( val > 0 ) + val = 0; + } ++ + return val; + } + +@@ -2038,7 +2063,8 @@ + /* */ + static FT_F26Dot6 + Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + +@@ -2047,15 +2073,15 @@ + + if ( distance >= 0 ) + { +- val = distance + compensation + 32; ++ val = distance + compensation + 32 / resolution; + if ( distance && val > 0 ) +- val &= ~63; ++ val &= ~(64 / resolution - 1); + else + val = 0; + } + else + { +- val = -FT_PIX_ROUND( compensation - distance ); ++ val = -FT_PIX_ROUND_GRID( compensation - distance, resolution ); + if ( val > 0 ) + val = 0; + } +@@ -2082,22 +2108,22 @@ + /* */ + static FT_F26Dot6 + Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + +- + if ( distance >= 0 ) + { +- val = FT_PIX_FLOOR( distance + compensation ) + 32; ++ val = FT_PIX_FLOOR_GRID( distance + compensation, resolution ) + 32 / resolution; + if ( distance && val < 0 ) + val = 0; + } + else + { +- val = -( FT_PIX_FLOOR( compensation - distance ) + 32 ); ++ val = -( FT_PIX_FLOOR_GRID( compensation - distance, resolution ) + 32 / resolution ); + if ( val > 0 ) + val = 0; + } +@@ -2124,7 +2150,8 @@ + /* */ + static FT_F26Dot6 + Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + +@@ -2135,13 +2162,13 @@ + { + val = distance + compensation; + if ( distance && val > 0 ) +- val &= ~63; ++ val &= ~(64 / resolution - 1 ); + else + val = 0; + } + else + { +- val = -( ( compensation - distance ) & -64 ); ++ val = -( ( compensation - distance ) & -(64 / resolution) ); + if ( val > 0 ) + val = 0; + } +@@ -2168,7 +2195,8 @@ + /* */ + static FT_F26Dot6 + Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + +@@ -2177,15 +2205,15 @@ + + if ( distance >= 0 ) + { +- val = distance + compensation + 63; ++ val = distance + compensation + (64 / resolution - 1); + if ( distance && val > 0 ) +- val &= ~63; ++ val &= ~(64 / resolution - 1); + else + val = 0; + } + else + { +- val = - FT_PIX_CEIL( compensation - distance ); ++ val = - FT_PIX_CEIL_GRID( compensation - distance, resolution ); + if ( val > 0 ) + val = 0; + } +@@ -2212,24 +2240,26 @@ + /* */ + static FT_F26Dot6 + Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + +- if ( distance >= 0 ) ++ if ( distance >= 0 ) + { +- val = distance + compensation + 16; ++ val = distance + compensation + 16 / resolution ; + if ( distance && val > 0 ) +- val &= ~31; ++ val &= ~(32 / resolution - 1); + else + val = 0; + } + else + { +- val = -FT_PAD_ROUND( compensation - distance, 32 ); ++ ++ val = -FT_PAD_ROUND( compensation - distance, 32 / resolution ); + if ( val > 0 ) + val = 0; + } +@@ -2262,7 +2292,8 @@ + /* */ + static FT_F26Dot6 + Round_Super( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + +@@ -2310,7 +2341,8 @@ + /* */ + static FT_F26Dot6 + Round_Super_45( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ) ++ FT_F26Dot6 compensation, ++ FT_Int resolution ) + { + FT_F26Dot6 val; + +@@ -2401,7 +2433,8 @@ + /* */ + static void + SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod, +- FT_Long selector ) ++ FT_Long selector, ++ FT_Int resolution ) + { + switch ( (FT_Int)( selector & 0xC0 ) ) + { +@@ -3061,13 +3094,13 @@ + + + #define DO_SROUND \ +- SET_SuperRound( 0x4000, args[0] ); \ ++ SET_SuperRound( 0x4000, args[0], 1 ); \ + CUR.GS.round_state = TT_Round_Super; \ + CUR.func_round = (TT_Round_Func)Round_Super; + + + #define DO_S45ROUND \ +- SET_SuperRound( 0x2D41, args[0] ); \ ++ SET_SuperRound( 0x2D41, args[0], 1 ); \ + CUR.GS.round_state = TT_Round_Super_45; \ + CUR.func_round = (TT_Round_Func)Round_Super_45; + +@@ -3228,11 +3261,11 @@ + + + #define DO_ODD \ +- args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 ); ++ args[0] = ( ( CUR_Func_round( args[0], 0, 1 ) & 127 ) == 64 ); + + + #define DO_EVEN \ +- args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 ); ++ args[0] = ( ( CUR_Func_round( args[0], 0, 1 ) & 127 ) == 0 ); + + + #define DO_AND \ +@@ -3281,7 +3314,31 @@ + #define DO_CEILING \ + args[0] = FT_PIX_CEIL( args[0] ); + +- ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++#define DO_RS \ ++ { \ ++ FT_ULong I = (FT_ULong)args[0]; \ ++ \ ++ \ ++ if ( BOUNDSL( I, CUR.storeSize ) ) \ ++ { \ ++ if ( CUR.pedantic_hinting ) \ ++ { \ ++ ARRAY_BOUND_ERROR; \ ++ } \ ++ else \ ++ args[0] = 0; \ ++ } \ ++ else \ ++ /* Subpixel Hinting - Avoid Typeman Dstroke and Istroke \ ++ * and Vacuform Rounds */ \ ++ if ( CUR.enhanced \ ++ && ( I == 24 || I == 22 || I == 8 ) \ ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_DO_RS ) ) \ ++ args[0] = 0; \ ++ else args[0] = CUR.storage[I]; \ ++ } ++#else + #define DO_RS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ +@@ -3299,6 +3356,7 @@ + else \ + args[0] = CUR.storage[I]; \ + } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + + #define DO_WS \ +@@ -3378,12 +3436,12 @@ + #define DO_ROUND \ + args[0] = CUR_Func_round( \ + args[0], \ +- CUR.tt_metrics.compensations[CUR.opcode - 0x68] ); ++ CUR.tt_metrics.compensations[CUR.opcode - 0x68], 1 ); + + + #define DO_NROUND \ + args[0] = ROUND_None( args[0], \ +- CUR.tt_metrics.compensations[CUR.opcode - 0x6C] ); ++ CUR.tt_metrics.compensations[CUR.opcode - 0x6C], 1 ); + + + #define DO_MAX \ +@@ -4554,7 +4612,21 @@ + FT_ULong n; + TT_DefRecord* rec; + TT_DefRecord* limit; +- ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ int opcode_pattern[4][12]= { ++ /* VacuFormRound function */ ++ {0x45,0x23,0x46,0x60,0x20}, ++ /* inline delta function 1 */ ++ {0x4B,0x53,0x23,0x4B,0x51,0x5A,0x58,0x38,0x1B,0x21,0x21,0x59}, ++ /* inline delta function 2 */ ++ {0x4B,0x54,0x58,0x38,0x1B,0x5A,0x21,0x21,0x59}, ++ /* diagonal stroke function */ ++ {0x20,0x20,0x40,0x60,0x47,0x40,0x23,0x42}, ++ }; ++ int opcode_patterns = 4; ++ int i; ++ int opcode_pointer[4] = {0,0,0,0} ; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + /* some font programs are broken enough to redefine functions! */ + /* We will then parse the current table. */ +@@ -4592,6 +4664,7 @@ + rec->opc = (FT_UInt16)n; + rec->start = CUR.IP + 1; + rec->active = TRUE; ++ rec->inline = FALSE; + + if ( n > CUR.maxFunc ) + CUR.maxFunc = (FT_UInt16)n; +@@ -4601,20 +4674,63 @@ + + while ( SKIP_Code() == SUCCESS ) + { ++ /*printf ("%d ", CUR.opcode);*/ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ for ( i = 0; i < opcode_patterns; i++ ){ ++ if ( CUR.opcode == opcode_pattern[i][opcode_pointer[i]] ) ++ { ++ /*printf ("function %d, opcode ptrn: %d op# %d: %d FOUND -------------\n ", n, i, opcode_pointer[i], CUR.opcode);*/ ++ opcode_pointer[i] += 1; ++ ++ if (i == 0 && opcode_pointer[0] == 5){ ++ /*inline_delta_funcs[CUR.num_delta_funcs] = n; ++ CUR.num_delta_funcs++;*/ ++ /*printf ("Vacuform Round FUNCTION %d detected \n ", n);*/ ++ if (CUR.enhanced) /*rec->active = FALSE;*/ ++ opcode_pointer[i] = 0; ++ } ++ if (i == 1 && opcode_pointer[1] == 12){ ++ /*rec->active = FALSE;*/ ++ /*CUR.inline_delta_funcs[CUR.num_delta_funcs] = n; ++ CUR.num_delta_funcs++;*/ ++ rec->inline = TRUE; ++ /*printf ("inline delta FUNCTION1 %d detected \n ", n, CUR.num_delta_funcs);*/ ++ opcode_pointer[i] = 0; ++ } ++ if (i == 2 && opcode_pointer[1] == 9){ ++ /* CUR.inline_delta_funcs[CUR.num_delta_funcs] = n; ++ CUR.num_delta_funcs++;*/ ++ rec->inline = TRUE; ++ /*printf ("inline delta2 FUNCTION2 %d detected \n ", n, CUR.num_delta_funcs);*/ ++ opcode_pointer[i] = 0; ++ } ++ if (i == 4 && opcode_pointer[1] == 8){ ++ /* CUR.inline_delta_funcs[CUR.num_delta_funcs] = n; ++ CUR.num_delta_funcs++;*/ ++ /*rec->inline = TRUE;*/ ++ /*printf ("diagonal stroke function %d detected \n ", n, CUR.num_delta_funcs);*/ ++ opcode_pointer[i] = 0; ++ } ++ } ++ else { ++ opcode_pointer[i]=0; ++ } ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ + switch ( CUR.opcode ) + { +- case 0x89: /* IDEF */ +- case 0x2C: /* FDEF */ +- CUR.error = TT_Err_Nested_DEFS; +- return; ++ case 0x89: /* IDEF */ ++ case 0x2C: /* FDEF */ ++ CUR.error = TT_Err_Nested_DEFS; ++ return; + +- case 0x2D: /* ENDF */ +- return; ++ case 0x2D: /* ENDF */ ++ return; + } + } + } + +- + /*************************************************************************/ + /* */ + /* ENDF[]: END Function definition */ +@@ -4643,6 +4759,13 @@ + + CUR.step_ins = FALSE; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /* CUR.enhanced may be turned off prior to function calls. This ++ * ensures it is turned back on. ++ */ ++ CUR.enhanced = ( CUR.subpixel_hinting || CUR.grayscale_hinting ); ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ ++ + if ( pRec->Cur_Count > 0 ) + { + CUR.callTop++; +@@ -4675,8 +4798,9 @@ + FT_ULong F; + TT_CallRec* pCrec; + TT_DefRecord* def; +- +- ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ FT_Bool oldF; ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ + /* first of all, check the index */ + + F = args[0]; +@@ -4713,6 +4837,17 @@ + if ( !def->active ) + goto Fail; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /* This is test code used to detect inline delta functions */ ++ oldF = def->inline; ++ if (CUR.enhanced) ++ { ++ if ( def->inline ) { CUR.infunc = TRUE; } ++ } ++ ++ /* if ( F == 35 || F == 34 ){ CUR.enhanced = 0; printf ("ENTERING %d ", F); }*/ ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ ++ + /* check the call stack */ + if ( CUR.callTop >= CUR.callSize ) + { +@@ -4733,6 +4868,12 @@ + def->start ); + + CUR.step_ins = FALSE; ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ { ++ CUR.infunc = oldF; /*printf ("Leaving %d ", F);*/ ++ } ++ /*if ( F == 35 || F == 34 ){ CUR.enhanced = 1; printf ("Leaving %d ", F); }*/ ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ + return; + + Fail: +@@ -4752,7 +4893,9 @@ + FT_ULong F; + TT_CallRec* pCrec; + TT_DefRecord* def; +- ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ FT_Bool oldF; ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ + + /* first of all, check the index */ + F = args[1]; +@@ -4788,7 +4931,16 @@ + /* check that the function is active */ + if ( !def->active ) + goto Fail; +- ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ oldF=def->inline; ++ if (CUR.enhanced) ++ { ++ if ( def->inline ) ++ { ++ CUR.infunc = TRUE; ++ } ++ } ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ + /* check stack */ + if ( CUR.callTop >= CUR.callSize ) + { +@@ -4811,6 +4963,11 @@ + + CUR.step_ins = FALSE; + } ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ { ++ CUR.infunc = oldF; ++ } ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ + return; + + Fail: +@@ -5154,6 +5311,10 @@ + } + } + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */ ++ if ( CUR.enhanced && FT_ABS(D) == 64) D += 1; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + args[0] = D; + } + +@@ -5634,13 +5795,21 @@ + } + #endif + +- if ( CUR.GS.freeVector.x != 0 ) ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( !CUR.enhanced ++ || ( CUR.enhanced ++ && ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_MOVEZP2_FREEV ) )) + { +- CUR.zp2.cur[point].x += dx; +- if ( touch ) +- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ if ( CUR.GS.freeVector.x != 0 ) ++ { ++ CUR.zp2.cur[point].x += dx; ++ if ( touch ) ++ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; ++ } ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + } +- ++#endif + if ( CUR.GS.freeVector.y != 0 ) + { + CUR.zp2.cur[point].y += dy; +@@ -5649,7 +5818,6 @@ + } + } + +- + /*************************************************************************/ + /* */ + /* SHP[a]: SHift Point by the last point */ +@@ -5819,7 +5987,7 @@ + { + FT_F26Dot6 dx, dy; + FT_UShort point; +- ++ FT_Int B1, B2; + + if ( CUR.top < CUR.GS.loop + 1 ) + { +@@ -5863,11 +6031,64 @@ + } + } + else +- MOVE_Zp2_Point( point, dx, dy, TRUE ); ++ { ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /* The conditionals here still to not do a perfect job and need work. ++ * ++ * If not using enhanced rendering, allow ZP2 move. ++ * ++ * If using enhanced rendering, allow ZP2 point move if: ++ * - The glyph is composite ++ * - The glyph is specifically set to allow SHPIX moves ++ * - The move is in the Y direction on a previously touched point ++ * ++ * It seems that what qualifies as a previously touched point varies ++ * somewhat from font to font. Some render better when either X or Y ++ * must be touched ( SPH_TWEAK_SHPIX_CLASS_A ) and some render better ++ * when both must be touched. ++ */ ++ ++ if ( CUR.enhanced ) ++ { ++ B1 = CUR.zp2.cur[point].y; ++ if ( CUR.is_composite ++ || ( CUR.sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ++ || ( /*CUR.infunc && !(CUR.sph_tweak_flags ++ & SPH_TWEAK_SKIP_NONPIXEL_INLINE_MOVES) &&*/ /*CUR.infunc &&*/ ++ CUR.GS.freeVector.y != 0 ++ && CUR.iup_called == 0 ++ && CUR.iupy_called == 0 ++ && ( ++ ( (CUR.sph_tweak_flags & SPH_TWEAK_SHPIX_CLASS_A ) ++ && (( CUR.pts.tags[point] & FT_CURVE_TAG_TOUCH_X ) != 0 ++ || ( CUR.pts.tags[point] & FT_CURVE_TAG_TOUCH_Y ) != 0 )) ++ || ( !(CUR.sph_tweak_flags & SPH_TWEAK_SHPIX_CLASS_A ) ++ && (( CUR.pts.tags[point] & FT_CURVE_TAG_TOUCH_X ) != 0 ++ && ( CUR.pts.tags[point] & FT_CURVE_TAG_TOUCH_Y ) != 0 )) ++ ) ++ /*|| !CUR.infunc*/ ) ) ++ MOVE_Zp2_Point( point, dx, dy, TRUE ); ++ ++ B2 = CUR.zp2.cur[point].y; ++ ++ /* Reverse moves that move the point off a pixel boundary */ ++ if ((CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_INLINE_MOVES) ++ && B1 % 64 == 0 ++ && B2 % 64 != 0 ) ++ { ++ /*printf ("Reversing ZP2 move ");*/ ++ MOVE_Zp2_Point( point, -dx, -dy, TRUE ); ++ } ++ } ++ else ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ MOVE_Zp2_Point( point, dx, dy, TRUE ); ++ ++ } + + CUR.GS.loop--; + } +- ++ /*printf("SHPIX:%d ", CUR.infunc);*/ + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } +@@ -5884,7 +6105,17 @@ + { + FT_UShort point; + FT_F26Dot6 distance; ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ FT_Int resolution = 1; + ++ if ( CUR.enhanced ) ++ { ++ if ( CUR.GS.freeVector.x != 0 ) ++ resolution = Grids_Per_Pixel_X; ++ else if ( CUR.GS.freeVector.y != 0 ) ++ resolution = Grids_Per_Pixel_Y; ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + point = (FT_UShort)args[0]; + +@@ -5908,6 +6139,15 @@ + distance = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /* Subpixel Hinting - make MSIRP respect CVT cutin */ ++ /* Fixes "k" issue with Arial */ ++ if ( CUR.enhanced && CUR.GS.freeVector.x != 0 ++ && FT_ABS( distance - args[1]) ++ >= CUR.GS.control_value_cutin / resolution ) ++ distance = args[1]; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ + CUR_Func_move( &CUR.zp1, point, args[1] - distance ); + + CUR.GS.rp1 = CUR.GS.rp0; +@@ -5930,7 +6170,19 @@ + FT_UShort point; + FT_F26Dot6 cur_dist, + distance; ++ FT_Int resolution = 1; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( CUR.enhanced ) ++ { ++ if ( CUR.GS.freeVector.x != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MDAP )) ++ resolution = Grids_Per_Pixel_X; ++ else if ( CUR.GS.freeVector.y != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MDAP )) ++ resolution = Grids_Per_Pixel_Y; ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + point = (FT_UShort)args[0]; + +@@ -5946,8 +6198,8 @@ + if ( ( CUR.opcode & 1 ) != 0 ) + { + cur_dist = CUR_fast_project( &CUR.zp0.cur[point] ); +- distance = CUR_Func_round( cur_dist, +- CUR.tt_metrics.compensations[0] ) - cur_dist; ++ distance = CUR_Func_round( cur_dist, ++ CUR.tt_metrics.compensations[0], resolution ) - cur_dist; + } + else + distance = 0; +@@ -5972,7 +6224,19 @@ + FT_UShort point; + FT_F26Dot6 distance, + org_dist; ++ FT_Int resolution = 1; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( CUR.enhanced ) ++ { ++ if ( CUR.GS.freeVector.x != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MIAP )) ++ resolution = Grids_Per_Pixel_X; ++ else if ( CUR.GS.freeVector.y != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MIAP )) ++ resolution = Grids_Per_Pixel_Y; ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + cvtEntry = (FT_ULong)args[1]; + point = (FT_UShort)args[0]; +@@ -6020,10 +6284,13 @@ + + if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */ + { +- if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin ) +- distance = org_dist; +- +- distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] ); ++ { ++ if ( FT_ABS( distance - org_dist ) ++ > CUR.GS.control_value_cutin / resolution ) ++ distance = org_dist; ++ distance = CUR_Func_round( distance, ++ CUR.tt_metrics.compensations[0], resolution ); ++ } + } + + CUR_Func_move( &CUR.zp0, point, distance - org_dist ); +@@ -6044,6 +6311,24 @@ + { + FT_UShort point; + FT_F26Dot6 org_dist, distance; ++ FT_Int minimum_distance_factor = 64; ++ FT_Int resolution = 1; ++ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( CUR.enhanced ) ++ { ++ if ( CUR.GS.freeVector.x != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MDRP )) ++ { ++ resolution = Grids_Per_Pixel_X; ++ minimum_distance_factor = 64 - resolution / 3; ++ } ++ else if ( CUR.GS.freeVector.y != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MDRP )) ++ resolution = Grids_Per_Pixel_Y; ++ ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + + point = (FT_UShort)args[0]; +@@ -6107,13 +6392,15 @@ + /* round flag */ + + if ( ( CUR.opcode & 4 ) != 0 ) ++ { + distance = CUR_Func_round( + org_dist, +- CUR.tt_metrics.compensations[CUR.opcode & 3] ); ++ CUR.tt_metrics.compensations[CUR.opcode & 3], resolution ); ++ } + else + distance = ROUND_None( + org_dist, +- CUR.tt_metrics.compensations[CUR.opcode & 3] ); ++ CUR.tt_metrics.compensations[CUR.opcode & 3], resolution ); + + /* minimum distance flag */ + +@@ -6121,13 +6408,17 @@ + { + if ( org_dist >= 0 ) + { +- if ( distance < CUR.GS.minimum_distance ) +- distance = CUR.GS.minimum_distance; ++ if ( distance < FT_MulDiv(minimum_distance_factor, ++ CUR.GS.minimum_distance, 64) ) ++ distance = FT_MulDiv(minimum_distance_factor, ++ CUR.GS.minimum_distance, 64); + } + else + { +- if ( distance > -CUR.GS.minimum_distance ) +- distance = -CUR.GS.minimum_distance; ++ if ( distance > -FT_MulDiv( minimum_distance_factor, ++ CUR.GS.minimum_distance, 64 ) ) ++ distance = -FT_MulDiv( minimum_distance_factor, ++ CUR.GS.minimum_distance, 64 ); + } + } + +@@ -6163,10 +6454,30 @@ + cur_dist, + org_dist; + ++ FT_Int minimum_distance_factor = 64; ++ FT_Int B1, B2, resolution = 1; + + point = (FT_UShort)args[0]; + cvtEntry = (FT_ULong)( args[1] + 1 ); + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( CUR.enhanced ) ++ { ++ if ( CUR.GS.freeVector.x != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MIRP )) ++ { ++ resolution = Grids_Per_Pixel_X; ++ /* High value emboldens glyphs at lower ppems ( < 14 ) */ ++ /* Courier looks better with 52 */ ++ /* MS Cleartype Rasterizer supposedly uses 32 */ ++ minimum_distance_factor = 64 - resolution / 3; ++ } ++ else if ( CUR.GS.freeVector.y != 0 ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND_MIRP )) ++ resolution = Grids_Per_Pixel_Y; ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ + /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ + + if ( BOUNDS( point, CUR.zp1.n_points ) || +@@ -6230,36 +6541,55 @@ + /* refer to the same zone. */ + + if ( CUR.GS.gep0 == CUR.GS.gep1 ) +- if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin ) ++ if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin / resolution ) + cvt_dist = org_dist; + + distance = CUR_Func_round( + cvt_dist, +- CUR.tt_metrics.compensations[CUR.opcode & 3] ); ++ CUR.tt_metrics.compensations[CUR.opcode & 3], resolution ); + } + else + distance = ROUND_None( + cvt_dist, +- CUR.tt_metrics.compensations[CUR.opcode & 3] ); ++ CUR.tt_metrics.compensations[CUR.opcode & 3], resolution ); + + /* minimum distance test */ +- + if ( ( CUR.opcode & 8 ) != 0 ) + { + if ( org_dist >= 0 ) + { +- if ( distance < CUR.GS.minimum_distance ) +- distance = CUR.GS.minimum_distance; ++ if ( distance < FT_MulDiv( minimum_distance_factor, ++ CUR.GS.minimum_distance, 64 ) ) ++ distance = FT_MulDiv( minimum_distance_factor, ++ CUR.GS.minimum_distance, 64 ); + } + else + { +- if ( distance > -CUR.GS.minimum_distance ) +- distance = -CUR.GS.minimum_distance; ++ if ( distance > -FT_MulDiv( minimum_distance_factor, ++ CUR.GS.minimum_distance, 64 ) ) ++ distance = -FT_MulDiv( minimum_distance_factor, ++ CUR.GS.minimum_distance, 64 ); + } + } + ++ B1 = CUR.zp1.cur[point].y; ++ + CUR_Func_move( &CUR.zp1, point, distance - cur_dist ); + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( CUR.enhanced && CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_INLINE_MOVES) ++ { ++ B2 = CUR.zp1.cur[point].y; ++ ++ if ( ( CUR.GS.freeVector.x != 0 && B1 % 64 == 0 && B2 % 64 != 0 ) ++ || ( CUR.GS.freeVector.y != 0 && B2 % 64 != 0 ) ) ++ { ++ /* reverse the MIRP move. Ideally this could be implemented better */ ++ CUR_Func_move( &CUR.zp1, point, -(distance - cur_dist) ); ++ } ++ } ++#endif /*TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ ++ + CUR.GS.rp1 = CUR.GS.rp0; + + if ( ( CUR.opcode & 16 ) != 0 ) +@@ -6751,6 +7081,14 @@ + contour = 0; + point = 0; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( CUR.enhanced ) ++ { ++ CUR.iup_called = 1; ++ if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) return; ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ + do + { + end_point = CUR.pts.contours[contour] - CUR.pts.first_point; +@@ -6820,7 +7158,19 @@ + FT_UShort A; + FT_ULong C; + FT_Long B; +- ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ FT_Byte orig_round_state; ++ FT_Int resolution = 1; ++ FT_UShort B1, B2; ++ ++ if (CUR.enhanced ) ++ { ++ if ( CUR.GS.freeVector.x != 0 ) ++ resolution = Grids_Per_Pixel_X; ++ else if ( CUR.GS.freeVector.y != 0 ) ++ resolution = Grids_Per_Pixel_Y; ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + /* Delta hinting is covered by US Patent 5159668. */ +@@ -6889,8 +7239,81 @@ + if ( B >= 0 ) + B++; + B = B * 64 / ( 1L << CUR.GS.delta_shift ); ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS ++ /* Undocumented hack that will round the point prior to or instead ++ * of the delta move. Fixes glitches in various fonts due to bad ++ * y-hinting routines. ++ */ ++ if ( CUR.enhanced && CUR.GS.freeVector.y != 0 ) ++ { ++ orig_round_state= CUR.GS.round_state; ++ ++ if ( CUR.sph_tweak_flags & SPH_TWEAK_DELTAP_RDTG ) ++ { ++ COMPUTE_Round( TT_Round_Down_To_Grid ); ++ B = CUR_Func_round( B, CUR.tt_metrics.compensations[0], 1 ); ++ } ++ ++ else if ( CUR.sph_tweak_flags & SPH_TWEAK_DELTAP_RUTG ) ++ { ++ COMPUTE_Round( TT_Round_Up_To_Grid ); ++ B = CUR_Func_round( B, CUR.tt_metrics.compensations[0], 1 ); ++ } ++ ++ else if ( CUR.sph_tweak_flags & SPH_TWEAK_DELTAP_RTG ) ++ { ++ COMPUTE_Round( TT_Round_To_Grid ); ++ B = CUR_Func_round( B, CUR.tt_metrics.compensations[0], 1 ); ++ } ++ ++ COMPUTE_Round( orig_round_state ); ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */ ++ ++ /* Allow delta move if: ++ * - Not using enhanced rendering ++ * - Glyph is specifically set to allow it ++ * - Glyph is composite ++ */ ++ if ( !CUR.enhanced ++ || CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ++ || CUR.is_composite ) ++ CUR_Func_move( &CUR.zp0, A, B ); + ++ else if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) ) ++ { ++ /* Save the y value of the point now. Compare after move */ ++ B1 = CUR.zp0.cur[A].y; ++ ++ /* Allow delta move if using enhanced rendering, IUP has not ++ * been called, and point is touched on X or Y. ++ * ++ * Working code, but needs more features. ++ */ ++ if ( CUR.enhanced && CUR.GS.freeVector.y != 0 ++ && CUR.iup_called == 0 && CUR.iupy_called == 0 ++ && ( ( CUR.pts.tags[A] & FT_CURVE_TAG_TOUCH_X ) != 0 ++ || ( CUR.pts.tags[A] & FT_CURVE_TAG_TOUCH_Y ) != 0 ) ) ++ /* Should resolution always be 1 for this move ??? */ ++ CUR_Func_move( &CUR.zp0, A, B ); ++ ++ B2 = CUR.zp0.cur[A].y; ++ ++ /* Reverse this move if it results in a move off a pixel ++ * boundary. ++ */ ++ if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_INLINE_MOVES ) ++ && B1 % 64 == 0 ++ && B2 % 64 != 0 ) ++ { ++ CUR_Func_move( &CUR.zp0, A, -B ); ++ } ++ ++ } ++#else + CUR_Func_move( &CUR.zp0, A, B ); ++#endif /* *TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + } + } + else +@@ -7015,22 +7438,100 @@ + + K = 0; + +- /* We return MS rasterizer version 1.7 for the font scaler. */ +- if ( ( args[0] & 1 ) != 0 ) +- K = 35; +- +- /* Has the glyph been rotated? */ ++ /********************************/ ++ /* RASTERIZER VERSION */ ++ /* Selector Bit: 0 */ ++ /* Return Bit(s): 0-7 */ ++ /* */ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( ( args[0] & 1 ) != 0 ++ && CUR.enhanced ++ && !( CUR.sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) ){ ++ K = CUR.rasterizer_version; /*printf (" SETTING AS 37 \n" );*/ } ++ else ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ if ( ( args[0] & 1 ) != 0 ){ ++ K = 35; /*printf (" SETTING AS 35 \n" );*/ ++ } ++ /********************************/ ++ /* GLYPH ROTATED */ ++ /* Selector Bit: 1 */ ++ /* Return Bit(s): 8 */ ++ /* */ + if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated ) +- K |= 0x80; ++ K |= 1 << 8; + +- /* Has the glyph been stretched? */ ++ /********************************/ ++ /* GLYPH STRETCHED */ ++ /* Selector Bit: 2 */ ++ /* Return Bit(s): 9 */ ++ /* */ + if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched ) +- K |= 1 << 8; ++ /*K |= 1 << 8; Original value appears to be incorrect?? */ ++ K |= 1 << 9; + +- /* Are we hinting for grayscale? */ ++ /********************************/ ++ /* HINTING FOR GRAYSCALE */ ++ /* Selector Bit: 5 */ ++ /* Return Bit(s): 12 */ ++ /* */ + if ( ( args[0] & 32 ) != 0 && CUR.grayscale ) + K |= 1 << 12; + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ if ( CUR.enhanced && !( CUR.sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) ) ++ { ++ /********************************/ ++ /* HINTING FOR GRAYSCALE */ ++ /* Selector Bit: 5 */ ++ /* Return Bit(s): 12 */ ++ /* */ ++ if ( ( args[0] & 32 ) != 0 && CUR.grayscale_hinting ) ++ K |= 1 << 12; ++ ++ /********************************/ ++ /* HINTING FOR SUBPIXEL */ ++ /* Selector Bit: 6 */ ++ /* Return Bit(s): 13 */ ++ /* */ ++ if ( ( args[0] & 64 ) != 0 && CUR.subpixel_hinting ) ++ { ++ K |= 1 << 13; ++ ++ /* The below are irrelevant if subpixel_hinting is not set */ ++ ++ /********************************/ ++ /* COMPATIBLE WIDTHS ENABLED */ ++ /* Selector Bit: 7 */ ++ /* Return Bit(s): 14 */ ++ /* */ ++ /* Functionality still needs to be added */ ++ if ( ( args[0] & 128 ) != 0 && CUR.compatible_widths ) ++ { ++ K |= 1 << 14; ++ } ++ ++ /********************************/ ++ /* SYMMETRICAL SMOOTHING */ ++ /* Selector Bit: 8 */ ++ /* Return Bit(s): 15 */ ++ /* */ ++ /* Functionality still needs to be added */ ++ if ( ( args[0] & 256 ) != 0 && CUR.symmetrical_smoothing ) ++ K |= 1 << 15; ++ ++ /********************************/ ++ /* HINTING FOR BGR? */ ++ /* Selector Bit: 9 */ ++ /* Return Bit(s): 16 */ ++ /* */ ++ /* Functionality still needs to be added */ ++ if ( ( args[0] & 512 ) != 0 && CUR.bgr ) ++ K |= 1 << 16; ++ } ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ + args[0] = K; + } + +@@ -7405,6 +7906,14 @@ + cur = *exc; + #endif + ++ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /* Ensure some variables are set for this run */ ++ CUR.iup_called = FALSE; ++ CUR.iupy_called = FALSE; ++ CUR.infunc = FALSE; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ + /* set CVT functions */ + CUR.tt_metrics.ratio = 0; + if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem ) +@@ -7683,8 +8192,16 @@ + + + case 0x30: /* IUP */ ++ Ins_IUP( EXEC_ARG_ args ); ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ CUR.iup_called = TRUE; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ break; + case 0x31: /* IUP */ + Ins_IUP( EXEC_ARG_ args ); ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ CUR.iupy_called = TRUE; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING*/ + break; + + case 0x32: /* SHP */ +diff -Nur freetype-2.4.3.orig/src/truetype/ttinterp.h freetype-2.4.3.new/src/truetype/ttinterp.h +--- freetype-2.4.3.orig/src/truetype/ttinterp.h 2010-08-05 16:56:05.000000000 -0500 ++++ freetype-2.4.3.new/src/truetype/ttinterp.h 2010-10-23 14:00:05.553373908 -0500 +@@ -68,7 +68,8 @@ + /* Rounding function */ + typedef FT_F26Dot6 + (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance, +- FT_F26Dot6 compensation ); ++ FT_F26Dot6 compensation, ++ FT_Int resolution ); + + /* Point displacement along the freedom vector routine */ + typedef void +@@ -106,6 +107,24 @@ + } TT_CallRec, *TT_CallStack; + + ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /*************************************************************************/ ++ /* */ ++ /* This structure defines a rule used to tweak subpixel hinting for */ ++ /* various fonts. "", 0, "", NULL value indicates to match any value. */ ++ /* */ ++ ++ typedef struct SPH_TweakRule_ ++ { ++ const char family[32]; ++ const int ppem; ++ const char style[32]; ++ const char glyph; ++ } SPH_TweakRule; ++ ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ ++ + /*************************************************************************/ + /* */ + /* The main structure for the interpreter which collects all necessary */ +@@ -215,7 +234,32 @@ + TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */ + TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */ + +- FT_Bool grayscale; /* are we hinting for grayscale? */ ++ FT_Bool grayscale; /* are we hinting for grayscale? */ ++ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ TT_Round_Func func_round_sphn; /* subpixel rounding fuction */ ++ ++ FT_Bool grayscale_hinting; /* are we hinting for subpixel? */ ++ FT_Bool subpixel_hinting; /* are we hinting for subpixel? */ ++ FT_Bool enhanced; /* are we using enhanced rendering? */ ++ /* ( grayscale_hinting || subpixel_hinting ) */ ++ FT_Bool native_hinting; /* do native hinting when true */ ++ /* the following 3 are unimplemented but here for future reference */ ++ ++ FT_Bool compatible_widths; /* are we using compatible widths?*/ ++ FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */ ++ FT_Bool bgr; /* are we using bgr, not rgb? */ ++ FT_Int rasterizer_version;/* return ms rasterizer version */ ++ ++ FT_Bool iup_called; /* IUP[x] been called for glyph? */ ++ FT_Bool iupy_called; /* IUP[y] been called for glyph? */ ++ FT_Bool infunc; /* inside an inline delta func? */ ++ ++ FT_ULong sph_tweak_flags; /* flags to control hint tweaks */ ++ ++ FT_Int num_delta_funcs; ++ FT_ULong inline_delta_funcs[5]; ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + } TT_ExecContextRec; + +diff -Nur freetype-2.4.3.orig/src/truetype/ttobjs.h freetype-2.4.3.new/src/truetype/ttobjs.h +--- freetype-2.4.3.orig/src/truetype/ttobjs.h 2009-07-03 08:28:24.000000000 -0500 ++++ freetype-2.4.3.new/src/truetype/ttobjs.h 2010-10-22 19:25:46.075900111 -0500 +@@ -177,6 +177,7 @@ + FT_Long start; /* where does it start? */ + FT_UInt opc; /* function #, or instruction code */ + FT_Bool active; /* is it active? */ ++ FT_Bool inline; /* function that defines inline delta */ + + } TT_DefRecord, *TT_DefArray; + +diff -Nur freetype-2.4.3.orig/src/truetype/ttsubpixel.c freetype-2.4.3.new/src/truetype/ttsubpixel.c +--- freetype-2.4.3.orig/src/truetype/ttsubpixel.c 1969-12-31 18:00:00.000000000 -0600 ++++ freetype-2.4.3.new/src/truetype/ttsubpixel.c 2010-11-14 09:25:59.206993605 -0600 +@@ -0,0 +1,171 @@ ++/***************************************************************************/ ++/* */ ++/* ttsubpixel.c */ ++/* */ ++/* TrueType Subpixel Hinting. */ ++/* */ ++/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ ++/* 2010 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. */ ++/* */ ++/***************************************************************************/ ++ ++#include <ft2build.h> ++#include FT_INTERNAL_DEBUG_H ++#include FT_INTERNAL_CALC_H ++#include FT_INTERNAL_STREAM_H ++#include FT_INTERNAL_SFNT_H ++#include FT_TRUETYPE_TAGS_H ++#include FT_OUTLINE_H ++ ++#include "ttsubpixel.h" ++ ++ ++ /*************************************************************************/ ++ /* */ ++ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ ++ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ ++ /* messages during execution. */ ++ /* */ ++#undef FT_COMPONENT ++#define FT_COMPONENT trace_ttgload ++ ++ ++ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS ++ static FT_Bool ++ sph_test_tweak ( TT_Face face, ++ FT_String* family, ++ int ppem, ++ FT_String* style, ++ FT_UInt glyph_index, ++ SPH_TweakRule* rule, ++ int num_rules ) ++ { ++ FT_UInt i; ++ ++ /* rule checks may be able to be optimized further */ ++ for ( i = 0; i < num_rules; i++ ) ++ { ++ if ( family && ( strcmp( rule[i].family, "" ) == 0 ++ || strcmp ( rule[i].family, family ) == 0 ) ) ++ if ( rule[i].ppem == 0 ++ || (rule[i].ppem == ppem) ) ++ if ( ( style && strcmp ( rule[i].style, "" ) == 0 ) ++ || strcmp ( rule[i].style, style ) == 0 ) ++ if ( rule[i].glyph == 0 ++ || FT_Get_Char_Index( (FT_Face)face, rule[i].glyph ) ++ == glyph_index ) ++ { ++ /* printf ("%s,%d,%s,%c ", family, ppem, style, rule[i].glyph); */ ++ return TRUE; ++ } ++ } ++ return FALSE; ++ } ++ ++ static void ++ sph_set_tweaks( TT_Loader loader, ++ FT_UInt glyph_index ) ++ { ++ TT_Face face = (TT_Face)loader->face; ++ FT_String* family = face->root.family_name; ++ int ppem = loader->size->metrics.x_ppem; ++ FT_String* style = face->root.style_name; ++ ++ /* loader->exec->sph_tweak_flags = 0x0000; */ ++ ++ /*printf ("%s,%d,%s,%c ", family, ppem, style, glyph_index); */ ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ NORMAL_ROUND_MIRP_Rules, NORMAL_ROUND_MIRP_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_NORMAL_ROUND_MIRP; ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ NORMAL_ROUND_MDRP_Rules, NORMAL_ROUND_MDRP_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_NORMAL_ROUND_MDRP; ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ NORMAL_ROUND_MDAP_Rules, NORMAL_ROUND_MDAP_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_NORMAL_ROUND_MDAP; ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ NORMAL_ROUND_MIAP_Rules, NORMAL_ROUND_MIAP_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_NORMAL_ROUND_MIAP; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ SKIP_IUP_Rules, SKIP_IUP_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_SKIP_IUP; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALWAYS_SKIP_DELTAP_Rules, ALWAYS_SKIP_DELTAP_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_ALWAYS_SKIP_DELTAP; ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALWAYS_DO_DELTAP_Rules, ALWAYS_DO_DELTAP_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_ALWAYS_DO_DELTAP; ++ else if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ DELTAP_RTG_Rules, DELTAP_RTG_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_DELTAP_RTG; ++ else if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ DELTAP_RUTG_Rules, DELTAP_RUTG_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_DELTAP_RUTG; ++ else if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ DELTAP_RDTG_Rules, DELTAP_RDTG_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_DELTAP_RDTG; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALLOW_DMOVEX_FREEV_Rules, ALLOW_DMOVEX_FREEV_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_ALLOW_DMOVEX_FREEV; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALLOW_DMOVE_FREEV_Rules, ALLOW_DMOVE_FREEV_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_ALLOW_DMOVE_FREEV; ++ ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALLOW_DMOVEX_FREEV_Rules_Exceptions, ALLOW_DMOVEX_FREEV_RULES_EXCEPTIONS_SIZE ) ) ++ loader->exec->sph_tweak_flags &= ~SPH_TWEAK_ALLOW_DMOVEX_FREEV; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALLOW_DMOVE_FREEV_Rules_Exceptions, ALLOW_DMOVE_FREEV_RULES_EXCEPTIONS_SIZE ) ) ++ loader->exec->sph_tweak_flags &= ~SPH_TWEAK_ALLOW_DMOVE_FREEV; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ RASTERIZER_35_Rules, RASTERIZER_35_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_RASTERIZER_35; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALLOW_MOVEZP2_FREEV_Rules, ALLOW_MOVEZP2_FREEV_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_ALLOW_MOVEZP2_FREEV; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ ALLOW_MOVEZP2_FREEV_Rules_Exceptions, ALLOW_MOVEZP2_FREEV_RULES_EXCEPTIONS_SIZE ) ) ++ loader->exec->sph_tweak_flags &= ~SPH_TWEAK_ALLOW_MOVEZP2_FREEV; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ DO_RS_Rules, DO_RS_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_DO_RS; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ DO_SHPIX_Rules, DO_SHPIX_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_DO_SHPIX; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ SKIP_NONPIXEL_INLINE_MOVES_Rules, SKIP_NONPIXEL_INLINE_MOVES_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_SKIP_NONPIXEL_INLINE_MOVES; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ SHPIX_CLASS_A_Rules, SHPIX_CLASS_A_RULES_SIZE ) ) ++ loader->exec->sph_tweak_flags |= SPH_TWEAK_SHPIX_CLASS_A; ++ ++ if ( sph_test_tweak( face, family, ppem, style, glyph_index, ++ SHPIX_CLASS_A_Rules_Exceptions, SHPIX_CLASS_A_RULES_EXCEPTIONS_SIZE ) ) ++ loader->exec->sph_tweak_flags &= ~SPH_TWEAK_SHPIX_CLASS_A; ++ ++ } ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */ ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +diff -Nur freetype-2.4.3.orig/src/truetype/ttsubpixel.h freetype-2.4.3.new/src/truetype/ttsubpixel.h +--- freetype-2.4.3.orig/src/truetype/ttsubpixel.h 1969-12-31 18:00:00.000000000 -0600 ++++ freetype-2.4.3.new/src/truetype/ttsubpixel.h 2010-11-14 19:16:58.095874324 -0600 +@@ -0,0 +1,819 @@ ++/***************************************************************************/ ++/* */ ++/* ttsubpixel.h */ ++/* */ ++/* TrueType Subpixel Hinting. */ ++/* */ ++/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ ++/* 2010 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 __TTSUBPIXEL_H__ ++#define __TTSUBPIXEL_H__ ++ ++#include <ft2build.h> ++#include "ttobjs.h" ++ ++#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING ++ /*************************************************************************/ ++ /* */ ++ /* Tweak flags that are set for each glyph */ ++ /* */ ++ /* */ ++#define SPH_TWEAK_NORMAL_ROUND_MIRP 0x00001 ++#define SPH_TWEAK_NORMAL_ROUND_MDRP 0x00002 ++#define SPH_TWEAK_DELTAP_RDTG 0x00004 ++#define SPH_TWEAK_DELTAP_RTG 0x00008 ++#define SPH_TWEAK_DELTAP_RUTG 0x00010 ++#define SPH_TWEAK_ALLOW_DMOVEX_FREEV 0x00020 ++#define SPH_TWEAK_ALLOW_DMOVE_FREEV 0x00040 ++#define SPH_TWEAK_ALLOW_MOVEZP2_FREEV 0x00080 ++#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x00100 ++#define SPH_TWEAK_SKIP_IUP 0x00200 ++#define SPH_TWEAK_NORMAL_ROUND_MIAP 0x00400 ++#define SPH_TWEAK_NORMAL_ROUND_MDAP 0x00800 ++#define SPH_TWEAK_DO_RS 0x01000 ++#define SPH_TWEAK_DO_SHPIX 0x02000 ++#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x04000 ++#define SPH_TWEAK_SKIP_NONPIXEL_INLINE_MOVES 0x08000 ++#define SPH_TWEAK_SHPIX_CLASS_A 0x10000 ++#define SPH_TWEAK_RASTERIZER_35 0x20000 ++ ++ ++ static FT_Bool ++ sph_test_tweak ( TT_Face face, ++ FT_String* family, ++ int ppem, ++ FT_String* style, ++ FT_UInt glyph_index, ++ SPH_TweakRule* rule, ++ int num_rules ); ++ static void ++ sph_set_tweaks( TT_Loader loader, ++ FT_UInt glyph_index ); ++ ++ ++ /*************************************************************************/ ++ /* */ ++ /* These are groups of rules that affect how the TT Interpreter does */ ++ /* hinting. */ ++ /* */ ++ /* "" string or 0 int/char indicates to apply to all. */ ++ /* "-" used as dummy placeholders, but any non-matching string works */ ++ /* */ ++ /* Remaining rules are tweaks for various fonts / glyphs */ ++ /* Some of this could arguably be implemented in fontconfig, however: */ ++ /* */ ++ /* - Fontconfig can't set things on a glyph-by-glyph basis. */ ++ /* - The tweaks that happen here are very low-level, from an average */ ++ /* user's point of view and are best implemented in the hinter */ ++ /* */ ++ /* Ideally, some of these should be generalized across affected fonts, */ ++ /* and enabled by default in the code. The rule structure is designed so */ ++ /* that entirely new rules can easily be added when a new compatibility */ ++ /* feature is discovered. */ ++ /* */ ++ ++ /*************************************************************************/ ++ /* */ ++ /* TT_CONFIG_OPTION_SUBPIXEL_HINTING Rules */ ++ /* */ ++ /* Simply, this attempts to duplicate the fuctionality described here */ ++ /* and nothing more: */ ++ /* */ ++ /* http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ ++ /* */ ++ /* This mode is enabled when */ ++ /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */ ++ /* is undefined */ ++ /* */ ++ ++ ++#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS ++ ++#if FALSE /* THIS RULESET NOT CURRENTLY BEING USED */ ++ ++#define BITMAP_WIDTHS FALSE ++#define SET_SUBPIXEL FALSE ++#define SET_GRAYSCALE TRUE ++#define SET_MONOCHROME FALSE ++#define SET_COMPATIBLE_WIDTHS TRUE ++#define SET_RASTERIZER_VERSION 35 ++#define Grids_Per_Pixel_X 1 ++#define Grids_Per_Pixel_Y 1 ++ ++ ++/********** MOVE RULES *************/ ++ ++/* Allow a Direct_Move_X along freedom vector when matched */ ++#define ALLOW_DMOVEX_FREEV_RULES_SIZE 1 ++SPH_TweakRule ALLOW_DMOVEX_FREEV_Rules ++[ALLOW_DMOVEX_FREEV_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++/* Allow a Direct_Move along freedom vector when matched */ ++#define ALLOW_DMOVE_FREEV_RULES_SIZE 1 ++SPH_TweakRule ALLOW_DMOVE_FREEV_Rules ++[ALLOW_DMOVE_FREEV_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++/* Allow a ZP2 Move along freedom vector when matched */ ++#define ALLOW_MOVEZP2_FREEV_RULES_SIZE 1 ++SPH_TweakRule ALLOW_MOVEZP2_FREEV_Rules ++[ALLOW_MOVEZP2_FREEV_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++/* Don't skip RS calls */ ++#define DO_RS_RULES_SIZE 1 ++SPH_TweakRule DO_RS_Rules ++[DO_RS_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Force requested SHPIX operations when matched */ ++#define DO_SHPIX_RULES_SIZE 1 ++SPH_TweakRule DO_SHPIX_Rules ++[DO_SHPIX_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define SKIP_NONPIXEL_INLINE_MOVES_RULES_SIZE 1 ++SPH_TweakRule SKIP_NONPIXEL_INLINE_MOVES_Rules ++[SKIP_NONPIXEL_INLINE_MOVES_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MIRP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MIRP_Rules ++[NORMAL_ROUND_MIRP_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MIAP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MIAP_Rules ++[NORMAL_ROUND_MIAP_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MDRP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MDRP_Rules ++[NORMAL_ROUND_MDRP_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MDAP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MDAP_Rules ++[NORMAL_ROUND_MDAP_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++/* Indicates that SHPIX needs to match a touched point on x OR y */ ++#define SHPIX_CLASS_A_RULES_SIZE 1 ++SPH_TweakRule SHPIX_CLASS_A_Rules ++[SHPIX_CLASS_A_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Mystery rules that make SHPIX work on certain fonts/glyphs. */ ++/* Indicates that SHPIX needs to match a touched point on x AND y */ ++/* This is dirty and needs to be generalized and incorporated. */ ++#define SHPIX_CLASS_A_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule SHPIX_CLASS_A_Rules_Exceptions ++[SHPIX_CLASS_A_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define ALLOW_DMOVEX_FREEV_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule ALLOW_DMOVEX_FREEV_Rules_Exceptions ++[ALLOW_DMOVEX_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define ALLOW_DMOVE_FREEV_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule ALLOW_DMOVE_FREEV_Rules_Exceptions ++[ALLOW_DMOVE_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define ALLOW_MOVEZP2_FREEV_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule ALLOW_MOVEZP2_FREEV_Rules_Exceptions ++[ALLOW_MOVEZP2_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Skip IUP instructions when matched */ ++#define SKIP_IUP_RULES_SIZE 1 ++SPH_TweakRule SKIP_IUP_Rules ++[SKIP_IUP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Skip DELTAP instructions when matched */ ++#define ALWAYS_SKIP_DELTAP_RULES_SIZE 1 ++SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules ++[ALWAYS_SKIP_DELTAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Always do DELTAP instructions when matched */ ++#define ALWAYS_DO_DELTAP_RULES_SIZE 1 ++SPH_TweakRule ALWAYS_DO_DELTAP_Rules ++[ALWAYS_DO_DELTAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Do an extra RTG instruction in DELTAP when matched */ ++#define DELTAP_RTG_RULES_SIZE 1 ++SPH_TweakRule DELTAP_RTG_Rules ++[DELTAP_RTG_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Do an extra RUTG instruction in DELTAP when matched */ ++#define DELTAP_RUTG_RULES_SIZE 1 ++SPH_TweakRule DELTAP_RUTG_Rules ++[DELTAP_RUTG_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Do an extra RDTG instruction in DELTAP when matched */ ++#define DELTAP_RDTG_RULES_SIZE 1 ++SPH_TweakRule DELTAP_RDTG_Rules ++[DELTAP_RDTG_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Return MS rasterizer 35 when matched */ ++#define RASTERIZER_35_RULES_SIZE 1 ++SPH_TweakRule RASTERIZER_35_Rules ++[RASTERIZER_35_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++#endif ++ ++ ++#define BITMAP_WIDTHS FALSE ++#define SET_SUBPIXEL TRUE ++#define SET_GRAYSCALE FALSE ++#define SET_MONOCHROME FALSE ++#define SET_COMPATIBLE_WIDTHS FALSE ++#define SET_RASTERIZER_VERSION 37 ++#define Grids_Per_Pixel_X 64 ++#define Grids_Per_Pixel_Y 1 ++ ++ ++/********** MOVE RULES *************/ ++ ++/* Allow a Direct_Move_X along freedom vector when matched */ ++#define ALLOW_DMOVEX_FREEV_RULES_SIZE 1 ++SPH_TweakRule ALLOW_DMOVEX_FREEV_Rules ++[ALLOW_DMOVEX_FREEV_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Allow a Direct_Move along freedom vector when matched */ ++#define ALLOW_DMOVE_FREEV_RULES_SIZE 1 ++SPH_TweakRule ALLOW_DMOVE_FREEV_Rules ++[ALLOW_DMOVE_FREEV_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Allow a ZP2 Move along freedom vector when matched */ ++#define ALLOW_MOVEZP2_FREEV_RULES_SIZE 1 ++SPH_TweakRule ALLOW_MOVEZP2_FREEV_Rules ++[ALLOW_MOVEZP2_FREEV_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Don't skip RS calls */ ++#define DO_RS_RULES_SIZE 1 ++SPH_TweakRule DO_RS_Rules ++[DO_RS_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Force requested SHPIX operations when matched */ ++#define DO_SHPIX_RULES_SIZE 1 ++SPH_TweakRule DO_SHPIX_Rules ++[DO_SHPIX_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define SKIP_NONPIXEL_INLINE_MOVES_RULES_SIZE 1 ++SPH_TweakRule SKIP_NONPIXEL_INLINE_MOVES_Rules ++[SKIP_NONPIXEL_INLINE_MOVES_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MIRP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MIRP_Rules ++[NORMAL_ROUND_MIRP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MIAP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MIAP_Rules ++[NORMAL_ROUND_MIAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MDRP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MDRP_Rules ++[NORMAL_ROUND_MDRP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define NORMAL_ROUND_MDAP_RULES_SIZE 1 ++SPH_TweakRule NORMAL_ROUND_MDAP_Rules ++[NORMAL_ROUND_MDAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Indicates that SHPIX needs to match a touched point on x OR y */ ++#define SHPIX_CLASS_A_RULES_SIZE 1 ++SPH_TweakRule SHPIX_CLASS_A_Rules ++[SHPIX_CLASS_A_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Mystery rules that make SHPIX work on certain fonts/glyphs. */ ++/* Indicates that SHPIX needs to match a touched point on x AND y */ ++/* This is dirty and needs to be generalized and incorporated. */ ++#define SHPIX_CLASS_A_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule SHPIX_CLASS_A_Rules_Exceptions ++[SHPIX_CLASS_A_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define ALLOW_DMOVEX_FREEV_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule ALLOW_DMOVEX_FREEV_Rules_Exceptions ++[ALLOW_DMOVEX_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define ALLOW_DMOVE_FREEV_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule ALLOW_DMOVE_FREEV_Rules_Exceptions ++[ALLOW_DMOVE_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++#define ALLOW_MOVEZP2_FREEV_RULES_EXCEPTIONS_SIZE 1 ++SPH_TweakRule ALLOW_MOVEZP2_FREEV_Rules_Exceptions ++[ALLOW_MOVEZP2_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Skip IUP instructions when matched */ ++#define SKIP_IUP_RULES_SIZE 1 ++SPH_TweakRule SKIP_IUP_Rules ++[SKIP_IUP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Skip DELTAP instructions when matched */ ++#define ALWAYS_SKIP_DELTAP_RULES_SIZE 1 ++SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules ++[ALWAYS_SKIP_DELTAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Always do DELTAP instructions when matched */ ++#define ALWAYS_DO_DELTAP_RULES_SIZE 1 ++SPH_TweakRule ALWAYS_DO_DELTAP_Rules ++[ALWAYS_DO_DELTAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Do an extra RTG instruction in DELTAP when matched */ ++#define DELTAP_RTG_RULES_SIZE 1 ++SPH_TweakRule DELTAP_RTG_Rules ++[DELTAP_RTG_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Do an extra RUTG instruction in DELTAP when matched */ ++#define DELTAP_RUTG_RULES_SIZE 1 ++SPH_TweakRule DELTAP_RUTG_Rules ++[DELTAP_RUTG_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Do an extra RDTG instruction in DELTAP when matched */ ++#define DELTAP_RDTG_RULES_SIZE 1 ++SPH_TweakRule DELTAP_RDTG_Rules ++[DELTAP_RDTG_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++/* Return MS rasterizer 35 when matched */ ++#define RASTERIZER_35_RULES_SIZE 1 ++SPH_TweakRule RASTERIZER_35_Rules ++[RASTERIZER_35_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++ ++ /*************************************************************************/ ++ /* */ ++ /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS Rules */ ++ /* */ ++ /* This set of rules is an attempt at enhancing the basic subpixel rules */ ++ /* defined above, to fix visual problems with individual fonts and */ ++ /* glyphs. */ ++ /* */ ++ /* This mode is enabled when */ ++ /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */ ++ /* is defined */ ++ /* */ ++ /* ****************** WORK IN PROGRESS ******************* */ ++ /* */ ++ ++#else ++ ++#define BITMAP_WIDTHS FALSE ++#define SET_SUBPIXEL TRUE ++#define SET_GRAYSCALE FALSE ++#define SET_MONOCHROME FALSE ++#define SET_COMPATIBLE_WIDTHS FALSE ++#define SET_RASTERIZER_VERSION 37 ++#define Grids_Per_Pixel_X 64 ++#define Grids_Per_Pixel_Y 1 ++ ++ ++/* Don't avoid RS Rules (as the basic subpixel hinting does) */ ++#define DO_RS_RULES_SIZE 1 ++SPH_TweakRule DO_RS_Rules[DO_RS_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++}; ++ ++ ++/******************* DELTA RULES *********************/ ++ ++/* Do requested SHPIX operations when matched. This requires ZP2 moves */ ++/* to be enabled in order to get SHPIX moves in the X direction */ ++/* Do all "Optimized for Cleartype" fonts need to be here??. */ ++/* the below doesn't work because the bit is not set in MS cleartype fonts */ ++/* CUR.face->header.Flags & 0x10000 */ ++ ++#define DO_SHPIX_RULES_SIZE 7 ++SPH_TweakRule DO_SHPIX_Rules[DO_SHPIX_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-Verdana", 0, "Regular", 0 }, ++ { "-Verdana", 12, "Regular", 0 }, ++ { "Verdana", 13, "Regular", 0 }, ++ /* aligns to pixels nicely, but messes up some glyphs */ ++ { "-Times New Roman", 0, "Regular", 0 }, ++ { "+++Segoe UI", 0, "Regular", 0 }, ++ { "-Segoe UI", 0, "Semibold", 0 }, ++}; ++ ++/* Indicates that SHPIX needs to match a touched point on x OR y */ ++#define SHPIX_CLASS_A_RULES_SIZE 1 ++SPH_TweakRule SHPIX_CLASS_A_Rules[SHPIX_CLASS_A_RULES_SIZE] = { ++ { "", 0, "", 0 }, ++}; ++ ++/* Mystery rules that make SHPIX work on certain fonts/glyphs. */ ++/* Indicates that SHPIX needs to match a touched point on x AND y */ ++/* This is dirty and needs to be generalized and incorporated. */ ++#define SHPIX_CLASS_A_RULES_EXCEPTIONS_SIZE 2 ++SPH_TweakRule SHPIX_CLASS_A_Rules_Exceptions ++[SHPIX_CLASS_A_RULES_EXCEPTIONS_SIZE] = { ++ { "---", 0, "", 0 }, ++ { "Arial", 11, "Regular", 's' }, ++}; ++ ++/* Skip moves that don't align to a pixel in various functions. */ ++/* Fixes Tahoma, trebuchet oddities and some issues with $ */ ++#define SKIP_NONPIXEL_INLINE_MOVES_RULES_SIZE 4 ++SPH_TweakRule SKIP_NONPIXEL_INLINE_MOVES_Rules ++[SKIP_NONPIXEL_INLINE_MOVES_RULES_SIZE] = { ++ { "", 0, "Regular", 0 }, ++ /* keeps the weight in the center of the N */ ++ { "", 0, "Regular", 'N' }, ++ { "Tahoma", 0, "Regular", 0 }, ++ { "==Trebuchet MS", 0, "Regular", 0 }, ++}; ++ ++ ++/********** MOVE RULES *************/ ++ ++/* Allow a Direct_Move_X along X freedom vector when matched */ ++#define ALLOW_DMOVEX_FREEV_RULES_SIZE 20 ++SPH_TweakRule ALLOW_DMOVEX_FREEV_Rules[ALLOW_DMOVEX_FREEV_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-", 0, "Regular", 0 }, ++ { "-", 0, "Italic", 0 }, ++ { "-", 0, "Regular", 0 }, ++ { "-Verdana", 12, "Regular", 0 }, ++ { "-Geneva", 0, "", 0 }, ++ { "-Courier New", 0, "Regular", 0 }, ++ { "-Courier New", 0, "", 0 }, ++ { "-Arial", 0, "Bold", 0 }, ++ { "Verdana", 13, "Regular", 0 }, ++ { "-Times New Roman", 0, "Regular", 0 }, ++ { "Arial", 13, "Regular", 0 }, ++ { "Arial", 14, "Regular", 0 }, ++ { "-Tahoma", 0, "Regular", 0 }, ++ { "+++Trebuchet MS", 0, "Regular", 0 }, ++ { "-Trebuchet MS", 0, "Bold", 0 }, ++ { "-Segoe UI", 0, "Semibold", 0 }, ++ { "-Segoe UI", 12, "Regular", 'H' }, ++ { "Arial Narrow", 0, "Regular", 0 }, ++ { "+++Andale Mono", 17, "Regular", 0 }, ++}; ++ ++/* Allow a Direct_Move along X freedom vector when matched */ ++#define ALLOW_DMOVE_FREEV_RULES_SIZE 21 ++SPH_TweakRule ALLOW_DMOVE_FREEV_Rules ++[ALLOW_DMOVE_FREEV_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-", 0, "Regular", 0 }, ++ { "-", 0, "Italic", 0 }, ++ { "-Verdana", 12, "Regular", 0 }, ++ { "Verdana", 13, "Regular", 0 }, ++ { "-Courier New", 0, "Bold", 0 }, ++ { "-Times New Roman", 0, "Regular", 0 }, ++ { "Arial", 13, "Regular", 0 }, ++ { "Arial", 14, "Regular", 0 }, ++ { "-Arial", 0, "Bold", 0 }, ++ { "-Tahoma", 0, "Regular", 0 }, ++ { "+++Trebuchet MS", 0, "Regular", 0 }, ++ { "-Trebuchet MS", 0, "Bold", 0 }, ++ { "-Geneva", 0, "", 0 }, ++ { "-------", 0, "Regular", 0 }, ++ { "-Segoe UI", 0, "Semibold", 0 }, ++ { "+++Segoe UI", 12, "Regular", 'H' }, ++ { "-----", 0, "Regular", 0 }, ++ { "Arial Narrow", 0, "Regular", 0 }, ++ { "+++Andale Mono", 17, "Regular", 0 }, ++ { "-Courier New", 0, "", 0 }, ++}; ++ ++ ++#define ALLOW_DMOVEX_FREEV_RULES_EXCEPTIONS_SIZE 9 ++SPH_TweakRule ALLOW_DMOVEX_FREEV_Rules_Exceptions ++ [ALLOW_DMOVEX_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-Times New Roman", 0, "Regular", 'a' }, ++ { "-Times New Roman", 0, "Regular", 'q' }, ++ { "-Times New Roman", 0, "Regular", 'P' }, ++ { "-Times New Roman", 0, "Regular", 'R' }, ++ { "-Times New Roman", 0, "Regular", 'B' }, ++ { "Arial", 0, "Regular", '4' }, ++ { "Arial", 0, "Regular", 's' }, ++ { "Arial", 0, "Regular", '^' }, ++}; ++ ++#define ALLOW_DMOVE_FREEV_RULES_EXCEPTIONS_SIZE 9 ++SPH_TweakRule ALLOW_DMOVE_FREEV_Rules_Exceptions ++[ALLOW_DMOVE_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-Times New Roman", 0, "Regular", 'a' }, ++ { "-Times New Roman", 0, "Regular", 'q' }, ++ { "-Times New Roman", 0, "Regular", 'P' }, ++ { "-Times New Roman", 0, "Regular", 'R' }, ++ { "-Times New Roman", 0, "Regular", 'B' }, ++ { "Arial", 0, "Regular", '4' }, ++ { "Arial", 0, "Regular", 's' }, ++ { "Arial", 0, "Regular", '^' }, ++}; ++ ++ ++/* Allow a ZP2 Move along freedom vector when matched */ ++/* This is called from SHP, SHPIX, SHC, SHZ */ ++#define ALLOW_MOVEZP2_FREEV_RULES_SIZE 14 ++SPH_TweakRule ALLOW_MOVEZP2_FREEV_Rules[ALLOW_MOVEZP2_FREEV_RULES_SIZE] = { ++ { "-", 0, "Regular", 0 }, ++ { "-Verdana", 12, "Regular", 0 }, ++ { "Verdana", 13, "Regular", 0 }, ++ { "-Times New Roman", 0, "Regular", 0 }, ++ { "-Courier New", 0, "Bold", 0 }, ++ { "-Tahoma", 0, "Regular", 0 }, ++ { "-Courier New", 0, "", 0 }, ++ { "Arial", 13, "Regular", 0 }, ++ { "Arial", 14, "Regular", 0 }, ++ { "-Arial", 0, "Bold", 0 }, ++ { "+++Trebuchet MS", 0, "Regular", 0 }, ++ { "-Trebuchet MS", 0, "Bold", 0 }, ++ { "-Verdana", 13, "Regular", 0 }, ++ /* this needs a bit of work though */ ++ { "-Microsoft Sans Serif", 0, "Regular", 0 }, ++}; ++ ++/* Return MS rasterizer 35 when matched */ ++#define RASTERIZER_35_RULES_SIZE 1 ++SPH_TweakRule RASTERIZER_35_Rules ++[RASTERIZER_35_RULES_SIZE] = { ++ { "Times New Roman", 0, "Regular", 'i' }, ++}; ++ ++/************** DIRTY, DIRTY HACKS!!!!!!!! ***************/ ++ ++#define ALLOW_MOVEZP2_FREEV_RULES_EXCEPTIONS_SIZE 11 ++SPH_TweakRule ALLOW_MOVEZP2_FREEV_Rules_Exceptions ++[ALLOW_MOVEZP2_FREEV_RULES_EXCEPTIONS_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "Times New Roman", 0, "Regular", 'a' }, ++ { "Times New Roman", 0, "Regular", 'q' }, ++ { "Verdana", 13, "Regular", 'N' }, ++ { "Verdana", 13, "Regular", 'f' }, ++ { "Verdana", 13, "Regular", 'v' }, ++ { "-------", 13, "Regular", 'k' }, ++ { "Verdana", 13, "Regular", 'w' }, ++ { "Verdana", 13, "Regular", 'x' }, ++ { "Verdana", 13, "Regular", 'y' }, ++ { "Verdana", 13, "Regular", 'z' }, ++}; ++ ++/*********** ROUNDING ***************/ ++/* These only have an effect on fonts that are allowed to move X (above) */ ++/* It appears all MS cleartype fonts may be OK using normal rounds */ ++#define NORMAL_ROUND_MIRP_RULES_SIZE 16 ++SPH_TweakRule NORMAL_ROUND_MIRP_Rules[NORMAL_ROUND_MIRP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-Tahoma", 9, "Regular", 0 }, ++ { "-Courier New", 0, "Regular", 'W' }, ++ { "-Courier New", 0, "Regular", 'K' }, ++ { "-Courier New", 0, "Regular", 'k' }, ++ { "-Courier New", 0, "Regular", 'V' }, ++ { "-Courier New", 0, "Regular", 'O' }, ++ { "-Courier New", 0, "Regular", 'X' }, ++ { "-Courier New", 0, "Regular", 'Y' }, ++ { "-Courier New", 0, "Regular", 'A' }, ++ { "-Courier New", 0, "Regular", 'v' }, ++ { "-Courier New", 0, "Regular", 'z' }, ++ { "-Courier New", 0, "Regular", 'x' }, ++ { "-Courier New", 0, "Regular", 'y' }, ++ { "Calibri", 0, "Italic", 0 }, ++ { "Calibri", 0, "Bold Italic", 0 }, ++}; ++ ++#define NORMAL_ROUND_MIAP_RULES_SIZE 16 ++SPH_TweakRule NORMAL_ROUND_MIAP_Rules[NORMAL_ROUND_MIAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-Tahoma", 9, "Regular", 0 }, ++ { "-Courier New", 0, "Regular", 'W' }, ++ { "-Courier New", 0, "Regular", 'K' }, ++ { "-Courier New", 0, "Regular", 'k' }, ++ { "-Courier New", 0, "Regular", 'V' }, ++ { "-Courier New", 0, "Regular", 'O' }, ++ { "-Courier New", 0, "Regular", 'X' }, ++ { "-Courier New", 0, "Regular", 'Y' }, ++ { "-Courier New", 0, "Regular", 'A' }, ++ { "-Courier New", 0, "Regular", 'v' }, ++ { "-Courier New", 0, "Regular", 'z' }, ++ { "-Courier New", 0, "Regular", 'x' }, ++ { "-Courier New", 0, "Regular", 'y' }, ++ { "Calibri", 0, "Italic", 0 }, ++ { "Calibri", 0, "Bold Italic", 0 }, ++}; ++ ++#define NORMAL_ROUND_MDRP_RULES_SIZE 16 ++SPH_TweakRule NORMAL_ROUND_MDRP_Rules[NORMAL_ROUND_MDRP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-Tahoma", 9, "Regular", 0 }, ++ { "-Courier New", 0, "Regular", 'W' }, ++ { "-Courier New", 0, "Regular", 'K' }, ++ { "-Courier New", 0, "Regular", 'k' }, ++ { "-Courier New", 0, "Regular", 'V' }, ++ { "-Courier New", 0, "Regular", 'O' }, ++ { "-Courier New", 0, "Regular", 'X' }, ++ { "-Courier New", 0, "Regular", 'Y' }, ++ { "-Courier New", 0, "Regular", 'A' }, ++ { "-Courier New", 0, "Regular", 'v' }, ++ { "-Courier New", 0, "Regular", 'z' }, ++ { "-Courier New", 0, "Regular", 'x' }, ++ { "-Courier New", 0, "Regular", 'y' }, ++ { "Calibri", 0, "Italic", 0 }, ++ { "Calibri", 0, "Bold Italic", 0 }, ++}; ++ ++#define NORMAL_ROUND_MDAP_RULES_SIZE 16 ++SPH_TweakRule NORMAL_ROUND_MDAP_Rules[NORMAL_ROUND_MDAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "-Tahoma", 9, "Regular", 0 }, ++ { "-Courier New", 0, "Regular", 'W' }, ++ { "-Courier New", 0, "Regular", 'K' }, ++ { "-Courier New", 0, "Regular", 'k' }, ++ { "-Courier New", 0, "Regular", 'V' }, ++ { "-Courier New", 0, "Regular", 'O' }, ++ { "-Courier New", 0, "Regular", 'X' }, ++ { "-Courier New", 0, "Regular", 'Y' }, ++ { "-Courier New", 0, "Regular", 'A' }, ++ { "-Courier New", 0, "Regular", 'v' }, ++ { "-Courier New", 0, "Regular", 'z' }, ++ { "-Courier New", 0, "Regular", 'x' }, ++ { "-Courier New", 0, "Regular", 'y' }, ++ { "Calibri", 0, "Italic", 0 }, ++ { "Calibri", 0, "Bold Italic", 0 }, ++}; ++ ++ ++/* Skip IUP instructions when matched */ ++#define SKIP_IUP_RULES_SIZE 6 ++SPH_TweakRule SKIP_IUP_Rules[SKIP_IUP_RULES_SIZE] = { ++ { "Arial", 13, "Regular", 'a' }, ++ { "-", 0, "Regular", '2' }, ++ { "-", 0, "", 0 }, ++ { "-", 0, "Regular", 'a' }, ++ { "-", 0, "Regular", 'V' }, ++ { "-", 0, "Light", 0 }, ++}; ++ ++/* Skip DELTAP instructions when matched */ ++#define ALWAYS_SKIP_DELTAP_RULES_SIZE 19 ++SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules[ALWAYS_SKIP_DELTAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "--Courier New", 0, "Regular", 'V' }, ++ { "Verdana", 10, "Regular", 0 }, ++ { "-Trebuchet MS", 0, "Regular", 'W' }, ++ { "-Trebuchet MS", 0, "Regular", 'w' }, ++ { "-Verdana", 0, "Italic", 'v' }, ++ { "-Verdana", 0, "Italic", 'w' }, ++ { "-Verdana", 0, "Italic", 'x' }, ++ { "-Verdana", 0, "Italic", 'y' }, ++ { "-Verdana", 0, "Italic", 'z' }, ++ { "-Verdana", 0, "Regular", 'v' }, ++ { "-Verdana", 10, "Regular", 'w' }, ++ { "-Verdana", 0, "Regular", 'y' }, ++ { "-Verdana", 0, "Regular", 'z' }, ++ { "-Arial Bold", 0, "Bold", 's' }, ++ { "Trebuchet MS", 14, "Regular", 'e' }, ++ { "Trebuchet MS", 0, "Italic", 0 }, ++ { "-Arial", 0, "Italic", 0 }, ++ { "-", 0, "Italic", 0 }, ++}; ++ ++/* Always do DELTAP instructions when matched */ ++#define ALWAYS_DO_DELTAP_RULES_SIZE 3 ++SPH_TweakRule ALWAYS_DO_DELTAP_Rules[ALWAYS_DO_DELTAP_RULES_SIZE] = { ++ { "-", 0, "", 0 }, ++ { "DejaVu Sans", 14, "Regular", 'k' }, ++ { "DejaVu Sans", 14, "Regular", 'K' }, ++}; ++ ++/* Do an extra RTG instruction in DELTAP when matched */ ++#define DELTAP_RTG_RULES_SIZE 4 ++SPH_TweakRule DELTAP_RTG_Rules[DELTAP_RTG_RULES_SIZE] = { ++ { "-Arial Unicode MS", 0, "Regular", 0 }, ++ { "-Microsoft Sans Serif", 0, "Regular", '0' }, ++ { "--Verdana", 0, "", 0 }, ++ { "-Trebuchet MS", 14, "Regular", 'e' }, ++}; ++ ++/* Do an extra RUTG instruction in DELTAP when matched */ ++#define DELTAP_RUTG_RULES_SIZE 2 ++SPH_TweakRule DELTAP_RUTG_Rules[DELTAP_RUTG_RULES_SIZE] = { ++ { "-", 14, "Regular", 'e' }, ++ { "-", 0, "", 0 }, ++}; ++ ++/* Do an extra RDTG instruction in DELTAP when matched */ ++#define DELTAP_RDTG_RULES_SIZE 28 ++SPH_TweakRule DELTAP_RDTG_Rules[DELTAP_RDTG_RULES_SIZE] = { ++ { "Calibri", 0, "Italic", 0 }, ++ { "Comic Sans MS", 0, "Regular", 0 }, ++ { "Lucida Grande", 0, "Regular", 'e' }, ++ { "Lucida Grande", 12, "Bold", 0 }, ++ { "Microsoft Sans Serif", 0, "Regular", '7' }, ++ { "Microsoft Sans Serif", 0, "Regular", 'O' }, ++ { "Microsoft Sans Serif", 0, "Regular", 'Q' }, ++ { "Microsoft Sans Serif", 0, "Regular", 'X' }, ++ { "Microsoft Sans Serif", 0, "Regular", 'e' }, ++ { "Microsoft Sans Serif", 0, "Regular", 'o' }, ++ { "-", 0, "", 0 }, ++ { "-", 0, "Regular", 'O' }, ++ { "-", 0, "Regular", 'U' }, ++ { "-", 0, "Regular", 'e' }, ++ { "-", 0, "Regular", 'g' }, ++ { "Tahoma", 0, "Bold", '0' }, ++ { "Tahoma", 16, "Bold", 'C' }, ++ { "Tahoma", 16, "Bold Italic", 'C' }, ++ { "Trebuchet MS", 0, "", '0' }, ++ { "-", 9, "", 'w' }, ++ { "Verdana", 0, "", '0' }, ++ { "Verdana", 0, "Bold Italic", '7' }, ++ { "Verdana", 0, "Bold Italic", 'v' }, ++ { "Verdana", 0, "Bold Italic", 'w' }, ++ { "Verdana", 0, "Bold", 0 }, ++ { "Verdana", 0, "Italic", 'o' }, ++ { "Verdana", 0, "Regular", 'x' }, ++ { "Trebuchet MS", 14, "Regular", 'e' }, ++}; ++ ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */ ++#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++ ++#endif /* __TTSUBPIXEL_H__ */ diff --git a/testing/freetype-infinality/freetype-enable-subpixel-hinting-infinality-20100909-1.patch b/testing/freetype-infinality/freetype-enable-subpixel-hinting-infinality-20100909-1.patch new file mode 100644 index 000000000..08416afed --- /dev/null +++ b/testing/freetype-infinality/freetype-enable-subpixel-hinting-infinality-20100909-1.patch @@ -0,0 +1,29 @@ +--- freetype-2.4.2.subpixel-patched/include/freetype/config/ftoption.h 2010-09-09 18:08:11.375855632 -0500 ++++ freetype-2.4.2.subpixel-enabled/include/freetype/config/ftoption.h 2010-09-09 18:09:48.491864607 -0500 +@@ -93,7 +93,7 @@ + /* This is done to allow FreeType clients to run unmodified, forcing */ + /* them to display normal gray-level anti-aliased glyphs. */ + /* */ +-/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ ++#define FT_CONFIG_OPTION_SUBPIXEL_RENDERING + + + /*************************************************************************/ +@@ -510,7 +510,7 @@ + /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */ + /* defined. */ + /* */ +-/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++#define TT_CONFIG_OPTION_SUBPIXEL_HINTING + + + /*************************************************************************/ +@@ -527,7 +527,7 @@ + /* This option requires TT_CONFIG_OPTION_SUBPIXEL_HINTING to be */ + /* defined. */ + /* */ +-/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */ ++#define TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS + + + /*************************************************************************/ diff --git a/testing/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch b/testing/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch new file mode 100644 index 000000000..aae5fadde --- /dev/null +++ b/testing/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch @@ -0,0 +1,1602 @@ +freetype-entire-infinality-patchset (excludes the TT subpixel patches) +------------------------------------------------------------------- + +This patch contains all the patches I used to distribute separately. +It made more sense to lump these all together into a single file +now that there are runtime options. It's also easier for me to maintain. ;) + +I recommend that if you are using this patch that you use + + /etc/fonts/local.conf + +that I provide at: http://www.infinality.net/files/local.conf +You will also need: http://www.infinality.net/files/infinality-settings + +The second one will need to be included in your profile with something like: + + . ~/path/to/the/file/infinality-settings + +It should be adjusted to your personal tastes as an end-user. + + +DISCLAIMERS: + +This patch will almost certainly result in a performance hit when +freetype is rendering the glyphs. The good news is that fontconfig +caches the glyphs so it's only the first time they are displayed that there +could be a performance issue. + +I expect that if you compile freetype with this patch along with my +TT subpixel hinting patch, you will have a complete build that works the +way I expect it to. However, I have not tested all compile configurations +for errors. I intend to at some point. This patch may make your system crash, +have memory leaks, not compile, or render fonts in a way that you don't like. +Either way, when you use this patch, you should recognize that it +is ALPHA / BETA quality. That said, I intend to run these patches on my +personal system, so they had better be pretty stable! + + +Changelog + +2010-11-14 + - All patches can now be enabled at runtime with ENVIRONMENT_VARIABLES. + See the file infinality-settings (and below) for how to enable these. + Effects that used to work now **REQUIRE** these in order to be turned on + at runtime. This lets end users have full control over what they want + without requiring different compiles. + + - Added option to auto-embolden thin/light fonts. + + - Further refinement of the stem calculations for enhanced autohint. + + - Adjustable FIR filter at runtime. + + - Stem alignment ability to align glyph bitmaps to pixel boundaries. + + - Adjustable gamma correction prior to the FIR filter for LCD rendering. + This can be used to make small ppem text more readable, or for whatever + else you want to use it for. + + - A height tweak on the enhanced autohint that makes Arial, Segoe, Times + and others render more similarly to Windows. + + - Separated out the option to maintain the original width of glyphs + when doing fake emboldening. + + + +################################################################## +# The environment variables below should be copied to a file in +# /etc/profile.d/ for system-wide effects and/or included in +# ~/.bashrc or ~/.bash_profile for per-user effects: +# +# . ~/path/to/the/file/infinality-settings +# +# Of course, the per-user settings will override the system-wide +# settings. + + + +################################################################## +# INFINALITY_FT_FILTER_PARAMS +# +# This is a modified version of the patch here: +# http://levelsofdetail.kendeeter.com/2008/12/dynamic_fir_filter_patch.html +# +# Allows you to adjust the FIR filter at runtime instead of at +# compile time. The idea is to have values add up to one, and be +# symmetrical around the middle value. Here are some samples +# of various filter parameters: +# +# Strong Extra Smooth "0.15 0.2 0.3 0.2 0.15" (extra smooth, natural weight) +# Extra Smooth "0.20 0.20 0.30 0.20 0.20" (extra smooth, extra weight) +# Smooth "0.15 0.20 0.32 0.20 0.15" (smooth, natural weight) +# Stronger Gibson "0.11 0.22 0.38 0.22 0.11" (smooth, extra weight) +# Gibson "0.11 0.22 0.33 0.22 0.11" (smooth, natural weight) +# Freetype Light "0.00 0.33 0.34 0.33 0.00" (sharp, natural weight) +# Freetype Default "0.06 0.25 0.44 0.25 0.06" (sharp, extra weight) *default +# Extra Sharp "0.00 0.35 0.35 0.35 0.00" (extra sharp, extra weight) +# +# Default: [Freetype's default] +# Recommended: "0.11 0.22 0.38 0.22 0.11" +# +# Example 1: export INFINALITY_FT_FILTER_PARAMS="0.11 0.22 0.38 0.22 0.11" +# + +export INFINALITY_FT_FILTER_PARAMS="0.11 0.22 0.38 0.22 0.11" + + + + +################################################################## +# INFINALITY_FT_STEM_ALIGNMENT_TYPE +# +# This performs analysis on each glyph and determines the best +# subpixel orientation for the glyph. The glyph is not scaled in +# any way, just moved left or right by a subpixel amount. This +# results in subtley cleaner looking fonts, at the expense of +# proper distances between glyphs. This is only active for sizes +# 10 px or greater and does not apply to bold or italic fonts. +# +# Possible values: +# full - Allows a glyph to be moved to the LEFT or RIGHT by 1 subpixel +# Best alignment, Worst positioning +# medium,medium1 - Only allows a glyph to be moved to the LEFT by 1 subpixel +# Good alignment, Good positioning +# medium2 - Only allows a glyph to be moved to the RIGHT by 1 subpixel +# Good alignment, Good positioning +# slight,slight1 - A stricter version of medium +# Minor alignment, Best positioning +# slight2 - A stricter version of medium2 +# Minor alignment, Best positioning +# infinality - medium1 when stem < 5 subpixels, full when >= 5 subpixels +# none - Don't do any alignment +# +# Default: none +# Recommended: medium + +export INFINALITY_FT_STEM_ALIGNMENT_TYPE=medium + + + + + +################################################################## +# INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT +# +# Cause the height of horizontal stems to snap to integer pixels +# when using light auto-hinting. (This happens automatically +# when using full auto-hinting) +# +# This produces an effect similar to the way Windows renders fonts +# without requiring the font to contain bytecode instructions. +# +# Possible values: +# true - enable stem snapping +# false - do not enable stem snapping +# +# Default: false +# Recommended: true + +export INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT=true + + + + +################################################################## +# INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT +# +# Embolden particularly light or thin fonts, like DejaVu Sans Light, +# Inconsolata, Freemono, Courier New, etc. up until stem width is +# 1 pixel wide. This makes these fonts easier to read at lower +# ppems. Only applies when the autohinter is being used. +# +# Possible values: +# true - enable emboldening of light fonts +# false - do not enable emboldening of light fonts +# +# Default: false +# Recommended: true + +export INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT=true + + + + +################################################################## +# INFINALITY_FT_PSEUDO_GAMMA +# +# This does a weighted gamma correction at the LCD filter phase +# prior to the LCD filter. +# +# The first value indicates a px value, the second indicates a +# "gamma" value. All sizes < the px value will be corrected +# on a weighted scale based on the second value. +# +# Values .1 < 1.0 will darken the glyph +# Values > 1.0 will lighten the glyph +# +# Example 1: Darken glyphs that are less than 10 px. With some fonts +# even 5 or 6px is readable! +# export INFINALITY_FT_PSEUDO_GAMMA="10 .6" +# +# Example 2: Lighten all glyphs (below 100px) +# export INFINALITY_FT_PSEUDO_GAMMA="100 1.5" +# +# Default: [No gamma correction] +# Recommended: "9 .7" + +export INFINALITY_FT_PSEUDO_GAMMA="9 .7" + + + + +################################################################## +# INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS +# +# This will slightly stretch some glyphs vertically between 9px +# and 14px (inclusive). Some people may find this more +# aesthetically pleasing. This only applies to fonts that are +# using autohint. +# +# Possible values: +# true - enable height adjustment +# false - do not enable height adjustment +# +# Default: false + +export INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS=true + + + + +################################################################## +# INFINALITY_FT_ENHANCED_EMBOLDEN +# +# When doing artificial emboldening, only embolden in the X +# direction, skipping the Y direction. Most people will find this +# more aesthetically pleasing than the default behavior. +# +# Possible values: +# true - enable enhanced emboldening +# false - no not enable enhanced emboldening +# +# Default: false +# Recommended: true + +export INFINALITY_FT_ENHANCED_EMBOLDEN=true + + + + +################################################################## +# INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH +# +# When doing artificial emboldening, don't change the glyph width. +# +# Possible values: +# true - maintain width +# false - do not maintain width +# +# Default: false +# Recommended: true + +export INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH=true + + + + +################################################################## +# INFINALITY_FT_AUTO_AUTOHINT +# +# Automatically use autohint when rendering a font that contains +# no truetype instructions, regardless of what the calling +# program asks for. The truetype hinter will not do a good job +# on these. +# +# Possible values: +# true - automatically use autohint +# false - do not automatically use autohint +# +# Default: false +# Recommended: true + +export INFINALITY_FT_AUTO_AUTOHINT=true + + + + + + +INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT details +--------------------------------------------- + +This patch is intended to make freetype's autohinter round down widths of +horizontal stems to whole pixel values. This dramatically reduces the +graininess of the rendering at small sizes, at the expense of being true to the +glyph. + +Put simply, it makes freetype's autohinter render fonts similarly +to well-hinted TrueType fonts, even on fonts that contain no instructions. +So, as far as I can tell, this makes it 100% patent-free. + +The most dramatic results are on sans-serif fonts like Lucida Grande, +Arial, Helvetica Neue, Inconsolata, Droid Sans, Trebuchet MS, etc. + + +It is recommended to use this with antialiasing on, and fonts set to +slight hinting: + + <match target="font" > + <edit mode="assign" name="rgba" > + <const>rgb</const> + </edit> + <edit mode="assign" name="hinting" > + <bool>true</bool> + </edit> + <edit mode="assign" name="autohint" > + <bool>true</bool> + </edit> + <edit mode="assign" name="antialias" > + <bool>true</bool> + </edit> + <edit mode="assign" name="hintstyle" > + <const>hintslight</const> + </edit> + <edit name="lcdfilter" mode="assign"> + <const>lcddefault</const> + </edit> + </match> + + + + +diff -Nur freetype-2.4.3.orig/configure freetype-2.4.3.new/configure +--- freetype-2.4.3.orig/configure 2010-10-03 13:05:26.000000000 -0500 ++++ freetype-2.4.3.new/configure 2010-11-14 18:17:36.593491866 -0600 +@@ -13,6 +13,8 @@ + # Call the `configure' script located in `builds/unix'. + # + ++export LDFLAGS="$LDFLAGS -lm" ++ + rm -f config.mk builds/unix/unix-def.mk builds/unix/unix-cc.mk + + if test "x$GNUMAKE" = x; then +diff -Nur freetype-2.4.3.orig/include/freetype/internal/ftobjs.h freetype-2.4.3.new/include/freetype/internal/ftobjs.h +--- freetype-2.4.3.orig/include/freetype/internal/ftobjs.h 2010-07-18 11:07:31.000000000 -0500 ++++ freetype-2.4.3.new/include/freetype/internal/ftobjs.h 2010-11-07 11:18:19.681501081 -0600 +@@ -762,6 +770,10 @@ + FT_Library library ); + + ++ typedef void (*FT_Bitmap_LcdStemAlignFunc)( FT_Bitmap* bitmap, ++ FT_Render_Mode render_mode, ++ FT_GlyphSlot slot ); ++ + /*************************************************************************/ + /* */ + /* <Struct> */ +@@ -862,6 +874,7 @@ + FT_Int lcd_extra; /* number of extra pixels */ + FT_Byte lcd_weights[7]; /* filter weights, if any */ + FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ ++ FT_Bitmap_LcdStemAlignFunc lcd_stem_align_func; + #endif + + #ifdef FT_CONFIG_OPTION_PIC +diff -Nur freetype-2.4.3.orig/src/autofit/aflatin.c freetype-2.4.3.new/src/autofit/aflatin.c +--- freetype-2.4.3.orig/src/autofit/aflatin.c 2010-09-11 01:23:02.000000000 -0500 ++++ freetype-2.4.3.new/src/autofit/aflatin.c 2010-11-14 18:55:57.678647844 -0600 +@@ -21,6 +21,7 @@ + + #include "aflatin.h" + #include "aferrors.h" ++#include "strings.h" + + + #ifdef AF_USE_WARPER +@@ -495,6 +496,29 @@ + AF_LatinAxis axis; + FT_UInt nn; + ++ int checked_adjust_heights_env = 0; ++ FT_Bool adjust_heights = FALSE; ++ ++ if ( checked_adjust_heights_env == 0 ) ++ { ++ char *adjust_heights_env = getenv( "INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS" ); ++ if ( adjust_heights_env != NULL ) ++ { ++ if ( strcasecmp(adjust_heights_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(adjust_heights_env, "true") == 0) ++ adjust_heights = TRUE; ++ else if ( strcasecmp(adjust_heights_env, "1") == 0) ++ adjust_heights = TRUE; ++ else if ( strcasecmp(adjust_heights_env, "on") == 0) ++ adjust_heights = TRUE; ++ else if ( strcasecmp(adjust_heights_env, "yes") == 0) ++ adjust_heights = TRUE; ++ } ++ } ++ checked_adjust_heights_env = 1; ++ } ++ + + if ( dim == AF_DIMENSION_HORZ ) + { +@@ -522,21 +546,46 @@ + { + AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT]; + AF_LatinBlue blue = NULL; +- ++ int threshold = 40; + + for ( nn = 0; nn < Axis->blue_count; nn++ ) + { +- if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ) ++ if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ++ || ( adjust_heights && Axis->blues[nn].flags & AF_LATIN_BLUE_TOP ) ++ ) + { + blue = &Axis->blues[nn]; + break; + } + } + ++ if ( adjust_heights ++ && metrics->root.scaler.face->size->metrics.x_ppem < 15 ++ && metrics->root.scaler.face->size->metrics.x_ppem > 8 ) ++ threshold = 52; ++ ++ /* NEED TO FIND A WAY TO ADJUST CAPS AND LOWER SEPARATELY */ ++ /* The below does not work */ ++ /* if (Axis->blues[nn].flags & AF_LATIN_BLUE_SMALL_TOP ) ++ { ++ if (metrics->root.scaler.face->size->metrics.x_ppem < 15) ++ threshold = 22; ++ else threshold = 40; ++ break; ++ } ++ if ( Axis->blues[nn].flags & AF_LATIN_BLUE_CAPITAL_TOP ) ++ { ++ if (metrics->root.scaler.face->size->metrics.x_ppem < 15) ++ threshold = 40; ++ else threshold = 40; ++ break; ++ } ++ */ ++ + if ( blue ) + { + FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); +- FT_Pos fitted = ( scaled + 40 ) & ~63; ++ FT_Pos fitted = ( scaled + threshold ) & ~63; + + + if ( scaled != fitted ) +@@ -1340,7 +1389,8 @@ + if ( dist < 0 ) + dist = -dist; + +- dist = FT_MulFix( dist, scale ); ++ /* round down to pixels */ ++ dist = FT_MulFix( dist, scale ) & ~63; + if ( dist < best_dist ) + { + best_dist = dist; +@@ -1500,9 +1550,33 @@ + FT_Int vertical = ( dim == AF_DIMENSION_VERT ); + + +- if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || +- axis->extra_light ) +- return width; ++ int checked_stem_snap_env = 0; ++ FT_Bool stem_snap_light = FALSE; ++ ++ if ( checked_stem_snap_env == 0 ) ++ { ++ char *stem_snap_env = getenv( "INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT" ); ++ if ( stem_snap_env != NULL ) ++ { ++ if ( strcasecmp(stem_snap_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(stem_snap_env, "true") == 0) ++ stem_snap_light = TRUE; ++ else if ( strcasecmp(stem_snap_env, "1") == 0) ++ stem_snap_light = TRUE; ++ else if ( strcasecmp(stem_snap_env, "on") == 0) ++ stem_snap_light = TRUE; ++ else if ( strcasecmp(stem_snap_env, "yes") == 0) ++ stem_snap_light = TRUE; ++ } ++ } ++ checked_stem_snap_env = 1; ++ } ++ ++ if ( !stem_snap_light ) ++ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || ++ axis->extra_light ) ++ return width; + + if ( dist < 0 ) + { +@@ -1510,8 +1584,67 @@ + sign = 1; + } + +- if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || +- ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) ++ if ( stem_snap_light ++ && ( ++ ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ++ || ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) ) ++ { ++ dist = af_latin_snap_width( axis->widths, axis->width_count, dist ); ++ ++ if ( metrics->root.scaler.face->size->metrics.x_ppem > 9 ++ && axis->width_count > 0 ++ && abs ( axis->widths[0].cur - dist ) < 32 ++ && axis->widths[0].cur > 52 ) ++ { ++ if ( strstr(metrics->root.scaler.face->style_name, "Regular") ++ || strstr(metrics->root.scaler.face->style_name, "Book") ++ || strstr(metrics->root.scaler.face->style_name, "Medium") ++ || strcmp(metrics->root.scaler.face->style_name, "Italic") == 0 ++ || strcmp(metrics->root.scaler.face->style_name, "Oblique") == 0 ) ++ { ++ /* regular weight */ ++ if ( axis->widths[0].cur < 64 ) dist = 64 ; ++ else if (axis->widths[0].cur < 88) dist = 64; ++ else if (axis->widths[0].cur < 160) dist = 128; ++ else if (axis->widths[0].cur < 240) dist = 190; ++ else dist = ( dist ) & ~63; ++ } ++ else ++ { ++ /* bold gets a different threshold */ ++ if ( axis->widths[0].cur < 64 ) dist = 64 ; ++ else if (axis->widths[0].cur < 108) dist = 64; ++ else if (axis->widths[0].cur < 160) dist = 128; ++ else if (axis->widths[0].cur < 222) dist = 190; ++ else if (axis->widths[0].cur < 288) dist = 254; ++ else dist = ( dist + 16 ) & ~63; ++ } ++ ++ /* fix any unusually low values */ ++ if (dist < ( axis->widths[0].cur & ~63 ) ) ++ dist = (axis->widths[0].cur & ~63); ++ ++ /* fix any unusually high values */ ++ if (dist > ( ( axis->widths[0].cur + 64 ) & ~63 ) ) ++ dist = ( ( axis->widths[0].cur + 64 ) & ~63 ); ++ ++ if (dist < 64 ) dist = 64 ; ++ ++ } ++ if (dist < 52) ++ { ++ if (metrics->root.scaler.face->size->metrics.x_ppem < 9 ) ++ { ++ /*dist = 64 - (64 - dist) / 2 ;*/ ++ if (dist < 31) dist = 31; ++ } ++ else ++ dist = 52; ++ } ++ ++ } ++ else if ( !stem_snap_light && (( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || ++ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) ) + { + /* smooth hinting process: very lightly quantize the stem width */ + +@@ -1569,7 +1702,7 @@ + dist = ( dist + 32 ) & ~63; + } + } +- else ++ else if (!stem_snap_light) + { + /* strong hinting process: snap the stem width to integer pixels */ + FT_Pos org_dist = dist; +@@ -1577,6 +1710,8 @@ + + dist = af_latin_snap_width( axis->widths, axis->width_count, dist ); + ++ if ( stem_snap_light ) goto Done_Width; ++ + if ( vertical ) + { + /* in the case of vertical hinting, always round */ +@@ -2100,7 +2235,30 @@ + { + FT_Error error; + int dim; ++ int e_strength = 0; ++ ++ int checked_embolden_light_env = 0; ++ FT_Bool embolden_light = FALSE; + ++ if ( checked_embolden_light_env == 0 ) ++ { ++ char *embolden_light_env = getenv( "INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT" ); ++ if ( embolden_light_env != NULL ) ++ { ++ if ( strcasecmp(embolden_light_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(embolden_light_env, "true") == 0) ++ embolden_light = TRUE; ++ else if ( strcasecmp(embolden_light_env, "1") == 0) ++ embolden_light = TRUE; ++ else if ( strcasecmp(embolden_light_env, "on") == 0) ++ embolden_light = TRUE; ++ else if ( strcasecmp(embolden_light_env, "yes") == 0) ++ embolden_light = TRUE; ++ } ++ } ++ checked_embolden_light_env = 1; ++ } + + error = af_glyph_hints_reload( hints, outline ); + if ( error ) +@@ -2146,8 +2304,15 @@ + } + #endif + +- if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || +- ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) ++ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ) ++ { ++ af_latin_hint_edges( hints, (AF_Dimension)dim ); ++ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim ); ++ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); ++ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); ++ } ++ ++ if ( ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) + { + af_latin_hint_edges( hints, (AF_Dimension)dim ); + af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim ); +@@ -2157,6 +2322,34 @@ + } + af_glyph_hints_save( hints, outline ); + ++ /* if the font is particularly thin, embolden it, up to 1 px */ ++ if ( embolden_light ++ && metrics->axis->widths[0].cur <= 80 ++ && !( dim == AF_DIMENSION_VERT ) ++ && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ++ { ++ if ( metrics->axis->widths[0].cur ++ / metrics->root.scaler.face->size->metrics.x_ppem < 5 ) ++ { ++ /* weakest at width 80, stronger at lower widths */ ++ e_strength = 40 * ( 80 - metrics->axis->widths[0].cur)/80 ; ++ /* Don't do low ppems as much */ ++ if ( metrics->root.scaler.face->size->metrics.x_ppem < 9 ) ++ e_strength -= ++ ( 9 - metrics->root.scaler.face->size->metrics.x_ppem ) * 10; ++ } ++ ++ /* Embolden small fonts on a sliding scale. Better readability. */ ++ if ( e_strength > 0 ++ && ( strstr(metrics->root.scaler.face->style_name, "Regular") ++ || strstr(metrics->root.scaler.face->style_name, "Book") ++ || strstr(metrics->root.scaler.face->style_name, "Light") ++ || strstr(metrics->root.scaler.face->style_name, "Medium") ++ || strcmp(metrics->root.scaler.face->style_name, "Italic") == 0 ++ || strcmp(metrics->root.scaler.face->style_name, "Oblique") == 0 ) ) ++ FT_Outline_Embolden(outline,e_strength); ++ } ++ + Exit: + return error; + } +diff -Nur freetype-2.4.3.orig/src/autofit/afloader.c freetype-2.4.3.new/src/autofit/afloader.c +--- freetype-2.4.3.orig/src/autofit/afloader.c 2009-07-03 08:28:24.000000000 -0500 ++++ freetype-2.4.3.new/src/autofit/afloader.c 2010-10-22 22:22:04.073099288 -0500 +@@ -180,8 +180,8 @@ + AF_Edge edge2 = edge1 + + axis->num_edges - 1; /* rightmost edge */ + +- +- if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) ) ++/* dont hint metrics - temporary until different hinting can be done */ ++ if ( FALSE && axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) ) + { + old_rsb = loader->pp2.x - edge2->opos; + old_lsb = edge1->opos; +@@ -214,7 +214,8 @@ + slot->lsb_delta = loader->pp1.x - pp1x_uh; + slot->rsb_delta = loader->pp2.x - pp2x_uh; + } +- else ++/* dont hint metrics - temporary until different hinting can be done */ ++ else if (FALSE) + { + FT_Pos pp1x = loader->pp1.x; + FT_Pos pp2x = loader->pp2.x; +diff -Nur freetype-2.4.3.orig/src/base/ftlcdfil.c freetype-2.4.3.new/src/base/ftlcdfil.c +--- freetype-2.4.3.orig/src/base/ftlcdfil.c 2010-04-01 03:18:57.000000000 -0500 ++++ freetype-2.4.3.new/src/base/ftlcdfil.c 2010-11-14 18:33:58.300770778 -0600 +@@ -21,9 +21,659 @@ + #include FT_IMAGE_H + #include FT_INTERNAL_OBJECTS_H + ++#include <math.h> ++#include <string.h> ++#include <strings.h> + + #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + ++/* ++int sinc( int val ) { ++ if (val == 0.0) ++ return(1.0); ++ return 256.0 * (sin(3.14*(double) (val/256.0))/(3.14*(double) (val/256.0))); ++} ++ ++int sigmoidal( int val ) { ++ int val2; ++ val2 = 256.0 /(1.0+exp(-(10.0*(val/256.0-.5)))); ++ return window(val2); ++} ++ ++int window ( int val ) ++{ ++ if (val < 0 ) return 0; ++ if (val > 255) return 255; ++ else return val; ++} ++*/ ++int gamma2 ( int val, float value ) { ++ return 256 * (1.0 - pow((1.0 - (float)val/ 256.0) , 1.0/value)); ++} ++/* ++int gamma3 ( int val, float value ) { ++ 1- (x-1)^10 ++} ++*/ ++/* ++int gamma ( int val ) { ++ return 256 * (1.0 - pow((1.0 - (float)val/ 256.0) , 1.5)); ++} ++ ++int brick (int val) { ++ if (val > 50) return val; ++ else return 0; ++} ++ ++int brick2 (int val) { ++ if (val > 100) return val; ++ if (val > 50) return 100; ++ else return 0; ++} ++ ++int none (int val) { ++ return val; ++} ++ ++float pixmoid (int val1, int val2, int val3, int testval) ++{ ++ int avg; ++ int result; ++ ++ avg = (val1 + val2 + val3)/3; ++ ++ if ( avg < 128 ) ++ { ++ if (testval > 128) result = avg; ++ else result = testval; ++ } ++ else ++ { ++ if (testval < 128) result = avg; ++ else result = testval; ++ } ++ ++ return none(result); ++} ++ ++float pixmoid2 (int val1, int val2, int val3, int testval) ++{ ++ int avg; ++ int result; ++ ++ avg = (val1 + val2 + val3)/3; ++ ++ if ( avg > 160 ) return 255; ++ else if ( avg < 100 ) return 0; ++ else return testval; ++ ++ return none(result); ++ ++} ++*/ ++/* ++bool Resample(FT_Byte* line, int newWidth, int newHeight) ++{ ++ ++ unsigned char* newData = new unsigned char [newWidth * newHeight * 3]; ++ ++ double scaleWidth = (double)newWidth / (double)_width; ++ double scaleHeight = (double)newHeight / (double)_height; ++ ++ for(int cy = 0; cy < newHeight; cy++) ++ { ++ for(int cx = 0; cx < newWidth; cx++) ++ { ++ int pixel = (cy * (newWidth *3)) + (cx*3); ++ int nearestMatch = (((int)(cy / scaleHeight) ++ * (_width *3)) + ((int)(cx / scaleWidth) *3) ); ++ ++ newData[pixel ] = _data[nearestMatch ]; ++ newData[pixel + 1] = _data[nearestMatch + 1]; ++ newData[pixel + 2] = _data[nearestMatch + 2]; ++ } ++ } ++ ++ delete[] _data; ++ _data = newData; ++ _width = newWidth; ++ _height = newHeight; ++ ++ return true; ++}*/ ++ ++ ++ /* Stem alignment for bitmaps; A hack with very nice results */ ++ /* Ideally this could be implemented on the outline, prior to ++ * rasterization */ ++ static void ++ _lcd_stem_align ( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_GlyphSlot slot ) ++ { ++ /*FT_Byte* weights = library->lcd_weights;*/ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ ++ FT_UInt h; ++ ++ FT_UInt alignment_type = 0; ++ FT_UInt checked_alignment_type = 0; ++ float pseudo_gamma_value = 1; ++ float pseudo_gamma_lt = 0; ++ FT_UInt checked_pseudo_gamma_value = 0; ++ ++ if ( checked_alignment_type == 0) ++ { ++ char *alignment_type_env = getenv( "INFINALITY_FT_STEM_ALIGNMENT_TYPE" ); ++ if ( alignment_type_env != NULL ) ++ { ++ /*sscanf ( alignment_type_env, "%d", &alignment_type );*/ ++ if (strcasecmp(alignment_type_env, "full") == 0) alignment_type = 1; ++ else if (strcasecmp(alignment_type_env, "medium") == 0) alignment_type = 2; ++ else if (strcasecmp(alignment_type_env, "medium1") == 0) alignment_type = 2; ++ else if (strcasecmp(alignment_type_env, "slight") == 0) alignment_type = 3; ++ else if (strcasecmp(alignment_type_env, "slight1") == 0) alignment_type = 3; ++ else if (strcasecmp(alignment_type_env, "medium2") == 0) alignment_type = 4; ++ else if (strcasecmp(alignment_type_env, "slight2") == 0) alignment_type = 5; ++ else if (strcasecmp(alignment_type_env, "infinality") == 0) alignment_type = 6; ++ else if (strcasecmp(alignment_type_env, "infinality1") == 0) alignment_type = 6; ++ else alignment_type = 0; ++ ++ if ( /*strstr(slot.metrics->root.scaler.face->style_name, "Regular") ++ || strstr(slot.metrics->root.scaler.face->style_name, "Book") ++ || strstr(slot.metrics->root.scaler.face->style_name, "Medium") ++ ||*/ strcasestr(slot->face->style_name, "Italic") ++ || strcasestr(slot->face->style_name, "Oblique") ) ++ alignment_type = 0; ++ if ( strcasestr(slot->face->style_name, "Bold") ) ++ alignment_type = 0; ++ } ++ checked_alignment_type = 1; ++ } ++ ++ if ( checked_pseudo_gamma_value == 0 ) ++ { ++ char *pseudo_gamma_value_env = getenv( "INFINALITY_FT_PSEUDO_GAMMA" ); ++ if ( pseudo_gamma_value_env != NULL ) ++ { ++ float f1, f2; ++ ++ if ( strcasecmp(pseudo_gamma_value_env, "default" ) != 0) ++ { ++ sscanf ( pseudo_gamma_value_env, "%f %f", &f1, &f2 ); ++ pseudo_gamma_lt = f1; ++ pseudo_gamma_value = f2; ++ } ++ if ( pseudo_gamma_value < .1 ) pseudo_gamma_value = 1; ++ if ( pseudo_gamma_lt < 0 ) pseudo_gamma_lt = 1; ++ } ++ checked_pseudo_gamma_value = 1; ++ } ++ ++ /*printf("%s,%s ", slot->face->family_name, slot->face->style_name);*/ ++ /*printf("%d ", slot->face->size->metrics.x_ppem);*/ ++ ++ /* set gamma value to 1 if out of range */ ++ if ( slot->face->size->metrics.x_ppem >= pseudo_gamma_lt ) ++ { ++ pseudo_gamma_value = 1; ++ } ++ ++ /* don't do alignment for < 10 */ ++ if ( slot->face->size->metrics.x_ppem < 10 ) ++ { ++ alignment_type = 0; ++ } ++ ++ if ( mode == FT_RENDER_MODE_LCD ) ++ { ++ if (width >= 4 && alignment_type != 0 ) ++ { ++ FT_Byte* line = bitmap->buffer; ++ FT_Byte* lineabove = bitmap->buffer; ++ FT_Byte* linebelow = bitmap->buffer; ++ ++ FT_UInt vsums[width], vtotals[width], offsetruns[width / 2][width/2]; ++ FT_UInt offsetrank[width/2], offsetchosen, stemwidths[width], stemwidthsmax; ++ FT_UInt stemwidth, vstems = 0; ++ ++ FT_UInt shift = 0; ++ FT_UInt xx; ++ ++ FT_ULong rtotal = 0, vweight = 0, wtotal = 0; ++ FT_UInt lreached = 0, rreached = 0, rr = 0, ll = 0, testwidth; ++ FT_UInt lwidth = 0, loffset = 0, offset = 0, htotal = 0, windowstart; ++ FT_UInt windowelement; ++ ++ line = bitmap->buffer; ++ rreached = 0; lreached = width, ll = width; ++ ++ lwidth = 0; ++ loffset = 0; ++ ++ ++ /* initialize variables - can this be done inline??? */ ++ for ( testwidth = 3; testwidth < 4; testwidth += 1 ) ++ { ++ for ( offset = 0; offset < 3; offset +=1 ) ++ { ++ offsetruns[offset][testwidth] = 0; ++ offsetrank[offset] = 0; ++ } ++ } ++ for ( xx = 0; xx < width; xx += 1 ) ++ { ++ stemwidths[xx] = 0; ++ } ++ ++ ++ for ( h = (FT_UInt)bitmap->rows; h > 0; h--, line += bitmap->pitch ) ++ { ++ ++ if (rr > rreached) rreached = rr; ++ if (ll < lreached) lreached = ll; ++ ++ rr = width; ++ ll = 0; ++ rtotal = 0; ++ htotal = 0; ++ ++ /*stemwidthsmax = 0;*/ ++ stemwidth = 0; ++ ++ ++ /* Calculate various sums and stem widths of glyph */ ++ for ( xx = 0; xx < width; xx += 1 ) ++ { ++ if (line[xx] >= 128) ++ { ++ stemwidth += 1; ++ /*if (stemwidth > stemwidthsmax) stemwidthsmax = stemwidth;*/ /* necessary ? */ ++ } ++ else ++ { ++ if (xx > 0 && line[xx - 1] >= 128) stemwidths[stemwidth] += 1; ++ stemwidth = 0; ++ } ++ ++ if (h == (FT_UInt)bitmap->rows) vsums[xx] = 0; ++ if ( h == (FT_UInt)bitmap->rows ) vtotals[xx] = 0; ++ ++ if (line[xx] == 0) vsums[xx] -= 255; ++ else vsums[xx] += line[xx]; ++ if (vsums[xx] < 0) vsums[xx] = 0; ++ ++ if (ll == 0 && line[xx] != 0) ll = (xx); ++ ++ if (line[xx] != 0) rr = (xx); ++ ++ if (xx < width / 2) vweight -= line[xx]; ++ else vweight += line[xx]; ++ ++ htotal += line [xx]; ++ vtotals[xx] += line[xx]; ++ } ++ ++ if ( h < (FT_UInt)bitmap->rows ) lineabove = line - bitmap->pitch; ++ if ( h > 1 ) linebelow = line + bitmap->pitch; ++ ++ ++ /* Determine the offset at which the most weight of the glyph exists */ ++ /* This is currently hard-coded at 3, but the code is here to adjust */ ++ for ( testwidth = 3; testwidth < 4; testwidth += 1 ) ++ { ++ /* test the widths at each of these offsets */ ++ for ( offset = 0; offset < 3; offset +=1 ) ++ { ++ /* test window of size testwidth, starting at offset */ ++ rtotal = 0; ++ for ( windowstart = offset; windowstart < width; ++ windowstart += testwidth ) ++ { ++ /* calculate total for this window */ ++ wtotal = 0; ++ for ( windowelement = windowstart; ++ windowelement < windowstart + testwidth; windowelement += 1 ) ++ if ( windowelement < width) ++ { ++ wtotal += line[windowelement]; ++ ++ /* Assign extra value to this subpixel under certain conditions */ ++ if ( line[windowelement] == 255 ) ++ { ++ /* favor if full pixels above and below */ ++ if ( h < (FT_UInt)bitmap->rows ++ && lineabove[windowelement] == 255 ) ++ wtotal += 10; ++ if ( h > 1 && linebelow[windowelement] == 255 ) ++ wtotal += 10; ++ ++ /* favor if full pixels next to them */ ++ if ( windowelement > 0 && line[windowelement-1] == 255 ) ++ { ++ wtotal += 10; ++ if ( windowelement > 1 && line[windowelement-2] == 255 ) ++ { ++ wtotal += 10; ++ if ( windowelement > 2 && line[windowelement-3] == 255 ) ++ wtotal += 10; ++ } ++ } ++ if ( windowelement < width - 1 && line[windowelement+1] == 255 ) ++ { ++ wtotal += 10; ++ if ( windowelement < width - 2 && line[windowelement+2] == 255 ) ++ { ++ wtotal += 10; ++ if ( windowelement < width - 3 && line[windowelement+3] == 255 ) ++ wtotal += 10; ++ } ++ } ++ } ++ } ++ /* divide window total by number of subpixel samples */ ++ /* add to total for this run */ ++ rtotal += (wtotal * wtotal) / testwidth; ++ } ++ /* dont count horizontal stems */ ++ /*if (rtotal < ( 255 * testwidth ) * (255 * testwidth) * (width / testwidth) / (testwidth * 2) )*/ ++ if ( rtotal < ( 255 * 255 * width / 2 ) ) ++ offsetruns[offset][testwidth] += rtotal; ++ } ++ ++ /* determine the best offset for this width and increment its counter */ ++ offsetchosen = 0; ++ for ( offset = 0; offset < 2; offset +=1 ) ++ { ++ if ( offsetruns[offset][testwidth] < offsetruns[offset + 1][testwidth] ){ ++ offsetrank[offset + 1] += 1; ++ offsetchosen = offset; ++ } ++ } ++ if (offsetchosen == 0) offsetrank[0] += 1; ++ } ++ } ++ ++ /* Use the best offset */ ++ loffset = 0; ++ for ( offset = 0; offset < 2; offset +=1 ) ++ { ++ if ( offsetrank[offset] < offsetrank[offset + 1] ){ ++ loffset = offset + 1; ++ } ++ } ++ ++ /* Use the best width */ ++ lwidth = 0; ++ stemwidthsmax = 0; ++ ++ for ( xx = 0; xx < width - 1; xx +=1 ) ++ { ++ if ( stemwidthsmax < stemwidths[xx + 1] ){ ++ lwidth = xx + 1; ++ stemwidthsmax = stemwidths[xx + 1]; ++ } ++ } ++ ++ /* currently unused */ ++ rreached = width - rreached; ++ ++ /* Set the number of vertical stem components */ ++ for ( xx = 0; xx < width; xx += 1 ) ++ { ++ if ( height > 0 && vsums[xx] / height > 110 ) ++ vstems++; ++ } ++ ++ ++ /******************** CALCULATE GLYPH ALIGNMENT *********************/ ++ /*printf(" %d,%d,%d,%d,%d,%d,%d\n", width, height, lreached, ++ rreached, lwidth,vstems,alignment_type );*/ ++ ++ shift = 0; ++ ++ /* infinality1 alignment - combination of below */ ++ if ( alignment_type == 6 ) ++ { ++ if ( lwidth < 5 ) alignment_type = 2; ++ else alignment_type = 1; ++ } ++ ++ /* strong alignment - shift glyph left or right one subpixel */ ++ if ( alignment_type == 1 /*&& vstems > 0*/ ) ++ { ++ if ( lwidth < 5) ++ { ++ /* lower widths should use this */ ++ if (loffset % 3 == 0) shift = -1; ++ if (loffset % 3 == 1) shift = 1; ++ if (loffset % 3 == 2) shift = 0; ++ } ++ else if ( lwidth < 6 ) ++ { ++ /* medium widths should use this */ ++ if (loffset % 3 == 0) shift = 1; ++ if (loffset % 3 == 1) shift = 0; ++ if (loffset % 3 == 2) shift = -1; ++ } ++ else if ( lwidth < 20 ) ++ { ++ /* higher widths should use this */ ++ if (loffset % 3 == 0) shift = 1; ++ if (loffset % 3 == 1) shift = -1; ++ if (loffset % 3 == 2) shift = 0; ++ } ++ } ++ ++ /* medium alignment - shift glyph ONLY LEFT one subpixel ++ * - a compromise to prevent spacing issues */ ++ else if ( alignment_type == 2 /*&& vstems > 0*/ ){ ++ ++ if ( lwidth < 5 ) ++ { ++ /* medium alignment - use next highest value instead */ ++ if ( loffset == 1 && offsetrank[0] > offsetrank[2] ) loffset = 0; ++ ++ if ( loffset % 3 == 0 ) shift = -1; ++ /*if (loffset % 3 == 1 ) shift = 1;*/ ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ else if (lwidth < 6 ) ++ { ++ /* medium alignment - use next highest value instead */ ++ if ( loffset == 0 && offsetrank[2] > offsetrank[1] ) loffset = 2; ++ /*if (loffset % 3 == 0 ) shift = 1;*/ ++ if ( loffset % 3 == 1 ) shift = 0; ++ if ( loffset % 3 == 2 ) shift = -1; ++ } ++ else if ( lwidth < 20 ) ++ { ++ /* medium alignment - use next highest value instead */ ++ if ( loffset == 0 && offsetrank[1] > offsetrank[2] ) loffset = 1; ++ /*if (loffset % 3 == 0 ) shift = 1;*/ ++ if ( loffset % 3 == 1 ) shift = -1; ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ } ++ ++ /* medium alignment 2 - shift glyph ONLY RIGHT one subpixel ++ * - a compromise to prevent spacing issues */ ++ else if ( alignment_type == 4 ){ ++ if ( lwidth < 5 ) ++ { ++ /* medium alignment - use next highest value instead */ ++ if ( loffset == 0 && offsetrank[1] > offsetrank[2] ) loffset = 1; ++ ++ /*if ( loffset % 3 == 0 ) shift = -1;*/ ++ if ( loffset % 3 == 1 ) shift = 1; ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ else if ( lwidth < 6 ) ++ { ++ /* medium alignment - use next highest value instead */ ++ if ( loffset == 2 && offsetrank[0] > offsetrank[1] ) loffset = 0; ++ if ( loffset % 3 == 0 ) shift = 1; ++ if ( loffset % 3 == 1 ) shift = 0; ++ /*if ( loffset % 3 == 2 ) shift = -1;*/ ++ } ++ else if ( lwidth < 20 ) ++ { ++ /* medium alignment - use next highest value instead */ ++ if ( loffset == 1 && offsetrank[0] > offsetrank[2] ) loffset = 0; ++ if ( loffset % 3 == 0 ) shift = 1; ++ /*if (loffset % 3 == 1 ) shift = -1;*/ ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ } ++ ++ /* light alignment - shift glyph ONLY LEFT one subpixel ++ * - a compromise to prevent spacing issues */ ++ else if ( alignment_type == 3 ){ ++ if ( lwidth < 5 ) ++ { ++ if ( loffset % 3 == 0 ) shift = -1; ++ /*if ( loffset % 3 == 1 ) shift = 1;*/ ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ else if ( lwidth < 6 ) ++ { ++ /*if ( loffset % 3 == 0 ) shift = 1;*/ ++ if ( loffset % 3 == 1 ) shift = 0; ++ if ( loffset % 3 == 2 ) shift = -1; ++ } ++ else if ( lwidth < 20 ) ++ { ++ /*if ( loffset % 3 == 0 ) shift = 1;*/ ++ if ( loffset % 3 == 1 ) shift = -1; ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ } ++ ++ /* light alignment 2 - shift glyph ONLY RIGHT one subpixel ++ * - a compromise to prevent spacing issues */ ++ else if ( alignment_type == 5 ){ ++ if ( lwidth < 5 ) ++ { ++ /*if ( loffset % 3 == 0 ) shift = -1;*/ ++ if ( loffset % 3 == 1 ) shift = 1; ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ else if ( lwidth < 6 ) ++ { ++ if ( loffset % 3 == 0 ) shift = 1; ++ if ( loffset % 3 == 1 ) shift = 0; ++ /*if ( loffset % 3 == 2 ) shift = -1;*/ ++ } ++ else if ( lwidth < 20 ) ++ { ++ if ( loffset % 3 == 0 ) shift = 1; ++ /*if ( loffset % 3 == 1 ) shift = -1;*/ ++ if ( loffset % 3 == 2 ) shift = 0; ++ } ++ } ++ ++ /******************** ALIGN GLYPHS *********************/ ++ if (shift == -1) ++ { ++ line = bitmap->buffer; ++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--, ++ line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ for ( xx = 0; xx < width - 1; xx += 1 ) ++ { ++ line[xx] = line[xx+1]; ++ } ++ line[width - 1] = 1; ++ } ++ } ++ ++ else if (shift == -2) ++ { ++ line = bitmap->buffer; ++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--, ++ line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ for ( xx = 0; xx < width - 2; xx += 1 ) ++ { ++ line[xx] = line[xx+2]; ++ } ++ line[width - 2] = 1; ++ line[width - 1] = 1; ++ } ++ } ++ else if (shift == 1) ++ { ++ line = bitmap->buffer; ++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--, ++ line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ for ( xx = width - 1; xx > 0; xx -= 1 ) ++ { ++ line[xx] = line[xx-1]; ++ } ++ line[0] = 1; ++ } ++ } ++ else if (shift == 2) ++ { ++ line = bitmap->buffer; ++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--, ++ line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ for ( xx = width; xx > 1; xx -= 1 ) ++ { ++ line[xx] = line[xx-2]; ++ } ++ line[0] = 1; ++ line[1] = 1; ++ } ++ } ++ } ++ ++ if ( pseudo_gamma_value != 1 ) ++ { ++ FT_Byte* line = bitmap->buffer; ++ float ppem = (float)slot->face->size->metrics.x_ppem; ++ ++ if (ppem >= 5 ) ++ for (height = (FT_UInt)bitmap->rows; height > 0; height--, line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ for ( xx = 0; xx < width; xx += 1 ) ++ { ++ /*normal*/ ++ /*line[xx] = gamma2 ( line[xx], pseudo_gamma_value );*/ ++ ++ /* sloped */ ++ /*line[xx] = gamma2 ( line[xx], pseudo_gamma_value - 5 ++ * (1-pseudo_gamma_value)/(pseudo_gamma_lt -5) ++ + ((1-pseudo_gamma_value)/(pseudo_gamma_lt -5)) * ppem );*/ ++ ++ /* 1/3-sloped */ ++ line[xx] = gamma2 ( line[xx], pseudo_gamma_value - 5 ++ * ((1-pseudo_gamma_value)/(3*(pseudo_gamma_lt -5))) ++ * + ((1-pseudo_gamma_value)/(3*(pseudo_gamma_lt -5))) * ppem ); ++ } ++ } ++ } ++ } ++ } ++ ++ ++ ++ ++ ++ + /* define USE_LEGACY to implement the legacy filter */ + #define USE_LEGACY + +@@ -287,9 +1017,31 @@ + { 0x00, 0x55, 0x56, 0x55, 0x00 }; + /* the values here sum up to a value larger than 256, */ + /* providing a cheap gamma correction */ +- static const FT_Byte default_filter[5] = ++ static FT_Byte default_filter[5] = + { 0x10, 0x40, 0x70, 0x40, 0x10 }; + ++ int checked_filter_params_env = 0; ++ ++ if ( checked_filter_params_env == 0 ) ++ { ++ char *filter_params = getenv( "INFINALITY_FT_FILTER_PARAMS" ); ++ if ( filter_params != NULL ) ++ { ++ float f1, f2, f3, f4, f5; ++ ++ if ( strcasecmp(filter_params, "default" ) != 0) ++ { ++ sscanf ( filter_params, "%f %f %f %f %f", &f1, &f2, &f3, &f4, &f5 ); ++ ++ default_filter[0] = (FT_Byte) (f1 * 255.0f + 0.5f); ++ default_filter[1] = (FT_Byte) (f2 * 255.0f + 0.5f); ++ default_filter[2] = (FT_Byte) (f3 * 255.0f + 0.5f); ++ default_filter[3] = (FT_Byte) (f4 * 255.0f + 0.5f); ++ default_filter[4] = (FT_Byte) (f5 * 255.0f + 0.5f); ++ } ++ } ++ checked_filter_params_env = 1; ++ } + + if ( !library ) + return FT_Err_Invalid_Argument; +@@ -304,17 +1056,20 @@ + case FT_LCD_FILTER_DEFAULT: + #if defined( FT_FORCE_LEGACY_LCD_FILTER ) + ++ library->lcd_stem_align_func = _lcd_stem_align; + library->lcd_filter_func = _ft_lcd_filter_legacy; + library->lcd_extra = 0; + + #elif defined( FT_FORCE_LIGHT_LCD_FILTER ) + ++ library->lcd_stem_align_func = _lcd_stem_align; + ft_memcpy( library->lcd_weights, light_filter, 5 ); + library->lcd_filter_func = _ft_lcd_filter_fir; + library->lcd_extra = 2; + + #else + ++ library->lcd_stem_align_func = _lcd_stem_align; + ft_memcpy( library->lcd_weights, default_filter, 5 ); + library->lcd_filter_func = _ft_lcd_filter_fir; + library->lcd_extra = 2; +@@ -325,6 +1080,7 @@ + + case FT_LCD_FILTER_LIGHT: + ft_memcpy( library->lcd_weights, light_filter, 5 ); ++ library->lcd_stem_align_func = _lcd_stem_align; + library->lcd_filter_func = _ft_lcd_filter_fir; + library->lcd_extra = 2; + break; +@@ -332,6 +1088,7 @@ + #ifdef USE_LEGACY + + case FT_LCD_FILTER_LEGACY: ++ library->lcd_stem_align_func = _lcd_stem_align; + library->lcd_filter_func = _ft_lcd_filter_legacy; + library->lcd_extra = 0; + break; +diff -Nur freetype-2.4.3.orig/src/base/ftobjs.c freetype-2.4.3.new/src/base/ftobjs.c +--- freetype-2.4.3.orig/src/base/ftobjs.c 2010-08-06 13:02:15.000000000 -0500 ++++ freetype-2.4.3.new/src/base/ftobjs.c 2010-11-14 15:43:02.906303324 -0600 +@@ -562,6 +562,45 @@ + FT_Bool autohint = FALSE; + FT_Module hinter; + ++ TT_Face face2=(TT_Face)face; ++ int checked_auto_autohint_env; ++ FT_Bool auto_autohint = FALSE; ++ ++ if ( !checked_auto_autohint_env ) ++ { ++ char *auto_autohint_env = getenv( "INFINALITY_FT_AUTO_AUTOHINT" ); ++ if ( auto_autohint_env != NULL ) ++ { ++ if ( strcasecmp(auto_autohint_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(auto_autohint_env, "true") == 0) auto_autohint = TRUE; ++ else if ( strcasecmp(auto_autohint_env, "1") == 0) auto_autohint = TRUE; ++ else if ( strcasecmp(auto_autohint_env, "on") == 0) auto_autohint = TRUE; ++ else if ( strcasecmp(auto_autohint_env, "yes") == 0) auto_autohint = TRUE; ++ } ++ } ++ checked_auto_autohint_env = 1; ++ } ++/*printf("%d,%d ", load_flags, FT_LOAD_TARGET_NORMAL); ++10000001000101000 ++0#define FT_LOAD_DEFAULT 0x0 ++0#define FT_LOAD_NO_SCALE 0x1 ++0#define FT_LOAD_NO_HINTING 0x2 ++1#define FT_LOAD_RENDER 0x4 ++0#define FT_LOAD_NO_BITMAP 0x8 ++1#define FT_LOAD_VERTICAL_LAYOUT 0x10 ++0#define FT_LOAD_FORCE_AUTOHINT 0x20 ++0#define FT_LOAD_CROP_BITMAP 0x40 ++0#define FT_LOAD_PEDANTIC 0x80 ++1#define FT_LOAD_ADVANCE_ONLY 0x100 ++0#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200 ++0#define FT_LOAD_NO_RECURSE 0x400 ++0#define FT_LOAD_IGNORE_TRANSFORM 0x800 ++0#define FT_LOAD_MONOCHROME 0x1000 ++0#define FT_LOAD_LINEAR_DESIGN 0x2000 ++0#define FT_LOAD_SBITS_ONLY 0x4000 ++1#define FT_LOAD_NO_AUTOHINT 0x8000U ++*/ + + if ( !face || !face->size || !face->glyph ) + return FT_Err_Invalid_Face_Handle; +@@ -627,8 +666,11 @@ + + + if ( mode == FT_RENDER_MODE_LIGHT || +- face->internal->ignore_unpatented_hinter ) ++ face->internal->ignore_unpatented_hinter || ++ ( auto_autohint && face2->max_profile.maxSizeOfInstructions == 0 ) ) ++ { + autohint = TRUE; ++ } + } + } + +diff -Nur freetype-2.4.3.orig/src/base/ftoutln.c freetype-2.4.3.new/src/base/ftoutln.c +--- freetype-2.4.3.orig/src/base/ftoutln.c 2010-06-27 08:03:58.000000000 -0500 ++++ freetype-2.4.3.new/src/base/ftoutln.c 2010-11-14 09:06:38.779916717 -0600 +@@ -888,6 +888,28 @@ + FT_Int c, n, first; + FT_Int orientation; + ++ int checked_enhanced_embolden_env = 0; ++ FT_Bool enhanced_embolden = FALSE; ++ ++ if ( checked_enhanced_embolden_env == 0 ) ++ { ++ char *enhanced_embolden_env = getenv( "INFINALITY_FT_ENHANCED_EMBOLDEN" ); ++ if ( enhanced_embolden_env != NULL ) ++ { ++ if ( strcasecmp(enhanced_embolden_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(enhanced_embolden_env, "true") == 0) ++ enhanced_embolden = TRUE; ++ else if ( strcasecmp(enhanced_embolden_env, "1") == 0) ++ enhanced_embolden = TRUE; ++ else if ( strcasecmp(enhanced_embolden_env, "on") == 0) ++ enhanced_embolden = TRUE; ++ else if ( strcasecmp(enhanced_embolden_env, "yes") == 0) ++ enhanced_embolden = TRUE; ++ } ++ } ++ checked_enhanced_embolden_env = 1; ++ } + + if ( !outline ) + return FT_Err_Invalid_Argument; +@@ -957,7 +979,8 @@ + } + + outline->points[n].x = v_cur.x + strength + in.x; +- outline->points[n].y = v_cur.y + strength + in.y; ++ if ( !enhanced_embolden ) ++ outline->points[n].y = v_cur.y + strength + in.y; + + v_prev = v_cur; + v_cur = v_next; +diff -Nur freetype-2.4.3.orig/src/base/ftsynth.c freetype-2.4.3.new/src/base/ftsynth.c +--- freetype-2.4.3.orig/src/base/ftsynth.c 2010-09-11 01:28:32.000000000 -0500 ++++ freetype-2.4.3.new/src/base/ftsynth.c 2010-11-14 09:19:16.860168106 -0600 +@@ -88,9 +88,28 @@ + FT_Error error; + FT_Pos xstr, ystr; + ++ int checked_enhanced_embolden_env = 0; ++ FT_Bool enhanced_embolden = FALSE; ++ ++ if ( checked_enhanced_embolden_env == 0 ) ++ { ++ char *enhanced_embolden_env = getenv( "INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH" ); ++ if ( enhanced_embolden_env != NULL ) ++ { ++ if ( strcasecmp(enhanced_embolden_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(enhanced_embolden_env, "true") == 0) enhanced_embolden = TRUE; ++ else if ( strcasecmp(enhanced_embolden_env, "1") == 0) enhanced_embolden = TRUE; ++ else if ( strcasecmp(enhanced_embolden_env, "on") == 0) enhanced_embolden = TRUE; ++ else if ( strcasecmp(enhanced_embolden_env, "yes") == 0) enhanced_embolden = TRUE; ++ } ++ } ++ checked_enhanced_embolden_env = 1; ++ } ++ + + if ( slot->format != FT_GLYPH_FORMAT_OUTLINE && +- slot->format != FT_GLYPH_FORMAT_BITMAP ) ++ slot->format != FT_GLYPH_FORMAT_BITMAP ) + return; + + /* some reasonable strength */ +@@ -108,7 +127,7 @@ + xstr = xstr * 2; + ystr = xstr; + } +- else /* slot->format == FT_GLYPH_FORMAT_BITMAP */ ++ else if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) + { + /* round to full pixels */ + xstr &= ~63; +@@ -146,7 +165,8 @@ + slot->metrics.width += xstr; + slot->metrics.height += ystr; + slot->metrics.horiBearingY += ystr; +- slot->metrics.horiAdvance += xstr; ++ /* Don't add any horiAdvance - Personal preference */ ++ if ( !enhanced_embolden ) slot->metrics.horiAdvance += xstr; + slot->metrics.vertBearingX -= xstr / 2; + slot->metrics.vertBearingY += ystr; + slot->metrics.vertAdvance += ystr; +diff -Nur freetype-2.4.3.orig/src/smooth/ftsmooth.c freetype-2.4.3.new/src/smooth/ftsmooth.c +--- freetype-2.4.3.orig/src/smooth/ftsmooth.c 2010-08-09 19:47:47.000000000 -0500 ++++ freetype-2.4.3.new/src/smooth/ftsmooth.c 2010-11-07 11:17:08.693652341 -0600 +@@ -283,6 +283,9 @@ + vec->y /= 3; + } + ++ if ( slot->library->lcd_stem_align_func ) ++ slot->library->lcd_stem_align_func ( bitmap, mode, slot ); ++ + if ( slot->library->lcd_filter_func ) + slot->library->lcd_filter_func( bitmap, mode, slot->library ); diff --git a/testing/freetype-infinality/freetype2-infinality-protect_null_pointer-goddesse.patch b/testing/freetype-infinality/freetype2-infinality-protect_null_pointer-goddesse.patch new file mode 100644 index 000000000..43143e69e --- /dev/null +++ b/testing/freetype-infinality/freetype2-infinality-protect_null_pointer-goddesse.patch @@ -0,0 +1,71 @@ +Contributed by goddesse +https://bbs.archlinux.org/viewtopic.php?pid=864901#p864901 + +diff -Naur freetype-2.4.4/src/base/ftlcdfil.c freetype-2.4.4.new/src/base/ftlcdfil.c +--- freetype-2.4.4/src/base/ftlcdfil.c 2010-12-12 12:05:21.606671258 -0600 ++++ freetype-2.4.4.new/src/base/ftlcdfil.c 2010-12-12 12:08:17.726671242 -0600 +@@ -180,14 +180,17 @@ + else if (strcasecmp(alignment_type_env, "infinality1") == 0) alignment_type = 6; + else alignment_type = 0; + +- if ( /*strstr(slot.metrics->root.scaler.face->style_name, "Regular") +- || strstr(slot.metrics->root.scaler.face->style_name, "Book") +- || strstr(slot.metrics->root.scaler.face->style_name, "Medium") +- ||*/ strcasestr(slot->face->style_name, "Italic") +- || strcasestr(slot->face->style_name, "Oblique") ) +- alignment_type = 0; +- if ( strcasestr(slot->face->style_name, "Bold") ) +- alignment_type = 0; ++ if ( slot->face != NULL && slot->face->style_name != NULL ) ++ { ++ if ( /*strstr(slot.metrics->root.scaler.face->style_name, "Regular") ++ || strstr(slot.metrics->root.scaler.face->style_name, "Book") ++ || strstr(slot.metrics->root.scaler.face->style_name, "Medium") ++ ||*/ strcasestr(slot->face->style_name, "Italic") ++ || strcasestr(slot->face->style_name, "Oblique") ) ++ alignment_type = 0; ++ if ( strcasestr(slot->face->style_name, "Bold") ) ++ alignment_type = 0; ++ } + } + checked_alignment_type = 1; + } +@@ -214,16 +217,19 @@ + /*printf("%s,%s ", slot->face->family_name, slot->face->style_name);*/ + /*printf("%d ", slot->face->size->metrics.x_ppem);*/ + +- /* set gamma value to 1 if out of range */ +- if ( slot->face->size->metrics.x_ppem >= pseudo_gamma_lt ) ++ if ( slot->face && slot->face->size ) + { +- pseudo_gamma_value = 1; +- } ++ /* set gamma value to 1 if out of range */ ++ if ( slot->face->size->metrics.x_ppem >= pseudo_gamma_lt ) ++ { ++ pseudo_gamma_value = 1; ++ } + +- /* don't do alignment for < 10 */ +- if ( slot->face->size->metrics.x_ppem < 10 ) +- { +- alignment_type = 0; ++ /* don't do alignment for < 10 */ ++ if ( slot->face->size->metrics.x_ppem < 10 ) ++ { ++ alignment_type = 0; ++ } + } + + if ( mode == FT_RENDER_MODE_LCD ) +@@ -642,7 +648,9 @@ + if ( pseudo_gamma_value != 1 ) + { + FT_Byte* line = bitmap->buffer; +- float ppem = (float)slot->face->size->metrics.x_ppem; ++ float ppem = 0; ++ if ( slot->face && slot->face->size ) ++ ppem = (float)slot->face->size->metrics.x_ppem; + + if (ppem >= 5 ) + for (height = (FT_UInt)bitmap->rows; height > 0; height--, line += bitmap->pitch ) diff --git a/testing/freetype-infinality/infinality-settings b/testing/freetype-infinality/infinality-settings new file mode 100644 index 000000000..f6fca1aac --- /dev/null +++ b/testing/freetype-infinality/infinality-settings @@ -0,0 +1,230 @@ +################################################################## +# INFINALITY ENVIRONMENT VARIABLES FOR EXTRA RUN-TIME OPTIONS +################################################################## +# +# These environment variables require that their respective patches +# from http://www.infinality.net have been applied to the Freetype +# installation you are using. They will do abolutely +# nothing otherwise! +# + +# This file should be copied to /etc/profile.d/ for system-wide +# effects and/or included in ~/.bashrc or ~/.bash_profile for per-user +# effects: +# +# . ~/path/to/this/file/infinality-settings +# +# Of course, the per-user settings will override the system-wide +# settings. Default values indicated below will be used when the +# environment variables below are not defined. + + + +################################################################## +# INFINALITY_FT_FILTER_PARAMS +# +# This is a modified version of the patch here: +# http://levelsofdetail.kendeeter.com/2008/12/dynamic_fir_filter_patch.html +# +# Allows you to adjust the FIR filter at runtime instead of at +# compile time. The idea is to have values add up to one, and be +# symmetrical around the middle value. Here are some samples +# of various filter parameters: +# +# Strong Extra Smooth "15e-2 20e-2 30e-2 20e-2 15e-2" (extra smooth, natural weight) +# Extra Smooth "20e-2 20e-2 30e-2 20e-2 20e-2" (extra smooth, extra weight) +# Smooth "15e-2 20e-2 32e-2 20e-2 15e-2" (smooth, natural weight) +# Stronger Gibson "11e-2 22e-2 38e-2 22e-2 11e-2" (smooth, extra weight) +# Gibson "11e-2 22e-2 33e-2 22e-2 11e-2" (smooth, natural weight) +# Freetype Light "00e-2 33e-2 34e-2 33e-2 00e-2" (sharp, natural weight) +# Freetype Default "06e-2 25e-2 44e-2 25e-2 06e-2" (sharp, extra weight) *default +# Extra Sharp "00e-2 35e-2 35e-2 35e-2 00e-2" (extra sharp, extra weight) +# +# Default: [Freetype's default] +# Recommended: "11e-2 22e-2 38e-2 22e-2 11e-2" +# +# Example 1: export INFINALITY_FT_FILTER_PARAMS="11e-2 22e-2 38e-2 22e-2 11e-2" +# + +export INFINALITY_FT_FILTER_PARAMS="11e-2 22e-2 38e-2 22e-2 11e-2" + + + + +################################################################## +# INFINALITY_FT_STEM_ALIGNMENT_TYPE +# +# This performs analysis on each glyph and determines the best +# subpixel orientation for the glyph. The glyph is not scaled in +# any way, just moved left or right by a subpixel amount. This +# results in subtley cleaner looking fonts, at the expense of +# proper distances between glyphs. This is only active for sizes +# 10 px or greater and does not apply to bold or italic fonts. +# +# Possible values: +# full - Allows a glyph to be moved to the LEFT or RIGHT by 1 subpixel +# Best alignment, Worst positioning +# medium,medium1 - Only allows a glyph to be moved to the LEFT by 1 subpixel +# Good alignment, Good positioning +# medium2 - Only allows a glyph to be moved to the RIGHT by 1 subpixel +# Good alignment, Good positioning +# slight,slight1 - A stricter version of medium +# Minor alignment, Best positioning +# slight2 - A stricter version of medium2 +# Minor alignment, Best positioning +# infinality - medium1 when stem < 5 subpixels, full when >= 5 subpixels +# none - Don't do any alignment +# +# Default: none +# Recommended: medium + +export INFINALITY_FT_STEM_ALIGNMENT_TYPE=medium + + + + +################################################################## +# INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT +# +# Cause the height of horizontal stems to snap to integer pixels +# when using light auto-hinting. (This happens automatically +# when using full auto-hinting) +# +# This produces an effect similar to the way Windows renders fonts +# without requiring the font to contain bytecode instructions. +# +# Possible values: +# true - enable stem snapping +# false - do not enable stem snapping +# +# Default: false +# Recommended: true + +export INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT=true + + + + +################################################################## +# INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT +# +# Embolden particularly light or thin fonts, like DejaVu Sans Light, +# Inconsolata, Freemono, Courier New, etc. up until stem width is +# 1 pixel wide. This makes these fonts easier to read at lower +# ppems. Only applies when the autohinter is being used. +# +# Possible values: +# true - enable emboldening of light fonts +# false - do not enable emboldening of light fonts +# +# Default: false +# Recommended: true + +export INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT=true + + + + +################################################################## +# INFINALITY_FT_PSEUDO_GAMMA +# +# This does a weighted gamma correction at the LCD filter phase +# prior to the LCD filter. +# +# The first value indicates a px value, the second indicates a +# "gamma" value. All sizes < the px value will be corrected +# on a weighted scale based on the second value. +# +# Values .1 < 1.0 will darken the glyph +# Values > 1.0 will lighten the glyph +# +# Example 1: Darken glyphs that are less than 10 px. With some fonts +# even 5 or 6px is readable! +# export INFINALITY_FT_PSEUDO_GAMMA="10 6e-1" +# +# Example 2: Lighten all glyphs (below 100px) +# export INFINALITY_FT_PSEUDO_GAMMA="100 15e-1" +# +# Default: [No gamma correction] +# Recommended: "9 5e-1" + +export INFINALITY_FT_PSEUDO_GAMMA="9 7e-1" + + + + +################################################################## +# INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS +# +# This will slightly stretch some glyphs vertically between 9px +# and 14px (inclusive). Some people may find this more +# aesthetically pleasing. This only applies to fonts that are +# using autohint. +# +# Possible values: +# true - enable height adjustment +# false - do not enable height adjustment +# +# Default: false + +export INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS=true + + + + +################################################################## +# INFINALITY_FT_ENHANCED_EMBOLDEN +# +# When doing artificial emboldening, only embolden in the X +# direction, skipping the Y direction. Most people will find this +# more aesthetically pleasing than the default behavior. +# +# Possible values: +# true - enable enhanced emboldening +# false - no not enable enhanced emboldening +# +# Default: false +# Recommended: true + +export INFINALITY_FT_ENHANCED_EMBOLDEN=true + + + + +################################################################## +# INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH +# +# When doing artificial emboldening, don't change the glyph width. +# +# Possible values: +# true - maintain width +# false - do not maintain width +# +# Default: false +# Recommended: true + +export INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH=true + + + + +################################################################## +# INFINALITY_FT_AUTO_AUTOHINT +# +# Automatically use autohint when rendering a font that contains +# no truetype instructions, regardless of what the calling +# program asks for. The truetype hinter will not do a good job +# on these. +# +# Possible values: +# true - automatically use autohint +# false - do not automatically use autohint +# +# Default: false +# Recommended: true + +export INFINALITY_FT_AUTO_AUTOHINT=true + + + + |