diff options
author | Maarten de Boer | 2015-08-31 17:31:56 +0200 |
---|---|---|
committer | Maarten de Boer | 2015-08-31 19:20:13 +0200 |
commit | b5e7833b99c67854a9f8db663edd825dd87831e7 (patch) | |
tree | a32d718daf84ee480e2663dad11530fe4e80a8d6 | |
parent | 619a79ad7ef869b81ee83ce63247db2300594337 (diff) | |
download | aur-b5e7833b99c67854a9f8db663edd825dd87831e7.tar.gz |
Updated to 2.6 with patches from github
-rw-r--r-- | .SRCINFO | 46 | ||||
-rw-r--r-- | 01-freetype-2.6-enable-valid.patch | 20 | ||||
-rw-r--r-- | 02-upstream-2015.08.24.patch.xz | bin | 0 -> 231920 bytes | |||
-rw-r--r-- | 03-infinality-2.6-2015.08.24.patch | 4839 | ||||
-rw-r--r-- | PKGBUILD | 58 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9657.patch | 40 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9658.patch | 23 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9660.patch | 29 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9663.patch | 34 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9667.patch | 47 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9669.patch | 117 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9670.patch | 30 | ||||
-rw-r--r-- | freetype-2.4.11-CVE-2014-9671.patch | 36 | ||||
-rw-r--r-- | freetype-2.4.11-ft-strncmp.patch | 228 | ||||
-rw-r--r-- | freetype-2.5.0-CVE-2014-2240.patch | 25 | ||||
-rw-r--r-- | freetype-2.5.0-CVE-2014-2241.patch | 52 | ||||
-rwxr-xr-x | infinality-settings.sh | 48 |
17 files changed, 4942 insertions, 730 deletions
@@ -1,8 +1,8 @@ pkgbase = freetype2-infinality pkgdesc = TrueType font rendering library with infinality patch - pkgver = 2.4.12 - pkgrel = 4 - url = http://www.infinality.net/blog/infinality-freetype-patches/ + pkgver = 2.6 + pkgrel = 1 + url = https://github.com/bohoomil/fontconfig-ultimate install = install.sh arch = i686 arch = x86_64 @@ -11,38 +11,20 @@ pkgbase = freetype2-infinality depends = bzip2 depends = sh optdepends = fontconfig-infinality: Infinality package for fontconfig (required) - provides = freetype2=2.4.12 + provides = freetype2=2.6 conflicts = freetype2 options = !libtool backup = etc/profile.d/infinality-settings.sh - source = http://downloads.sourceforge.net/sourceforge/freetype/freetype-2.4.12.tar.bz2 - source = http://www.infinality.net/fedora/linux/zips/freetype-infinality-2.4.12-20130514_01-x86_64.tar.bz2 - source = freetype-2.2.1-enable-valid.patch::https://projects.archlinux.org/svntogit/packages.git/plain/trunk/freetype-2.2.1-enable-valid.patch?h=packages/freetype2 - source = freetype-2.5.0-CVE-2014-2240.patch - source = freetype-2.5.0-CVE-2014-2241.patch - source = freetype-2.4.11-ft-strncmp.patch - source = freetype-2.4.11-CVE-2014-9657.patch - source = freetype-2.4.11-CVE-2014-9658.patch - source = freetype-2.4.11-CVE-2014-9660.patch - source = freetype-2.4.11-CVE-2014-9663.patch - source = freetype-2.4.11-CVE-2014-9667.patch - source = freetype-2.4.11-CVE-2014-9669.patch - source = freetype-2.4.11-CVE-2014-9670.patch - source = freetype-2.4.11-CVE-2014-9671.patch - md5sums = 3463102764315eb86c0d3c2e1f3ffb7d - md5sums = 4f5ff3fd3e3e56310953e25eade4a2d3 - md5sums = 214119610444c9b02766ccee5e220680 - md5sums = e29654122be7dbfbc828b1f890257f40 - md5sums = 54d52c143c5e399972f2928d17b0f28e - md5sums = 451163e82887b59f0c0fad72a652f316 - md5sums = d8c69d190a81133d40b92d1d2ab81c98 - md5sums = 82055b1adb096766cf4269658ce5a68b - md5sums = 79e695ff3714fb66dcdadd2a4b82f418 - md5sums = 817ff425988e4f91dbd08b1f4bfaf5b4 - md5sums = a1560e1032cd0fb113aee6ce7b0c951e - md5sums = c5cbf68b7b2f3beeb766e8d97d9f723e - md5sums = 1bf2b83b8623ac4fed57dbe4e4f7714c - md5sums = f543132d39f801a230768dc133fd4870 + source = http://downloads.sourceforge.net/sourceforge/freetype/freetype-2.6.tar.bz2 + source = infinality-settings.sh + source = 01-freetype-2.6-enable-valid.patch + source = 02-upstream-2015.08.24.patch.xz + source = 03-infinality-2.6-2015.08.24.patch + sha256sums = 8469fb8124764f85029cc8247c31e132a2c5e51084ddce2a44ea32ee4ae8347e + sha256sums = 21192ce47be46ccd44e8aeea99754d4e5e38cb52717f752d67c319c74fea2716 + sha256sums = 086c9874ba5217dab419ac03dbc5ad6480aaa67b3c9d802f7181d8a3e007f8eb + sha256sums = 62eaa124f09916e237be994890178fb041b3648223f08429566df3a962971d8a + sha256sums = 241de84ca25d7ff106a3ebd5121d12a315abe5a72771957bd674e8b2e41c97d2 pkgname = freetype2-infinality diff --git a/01-freetype-2.6-enable-valid.patch b/01-freetype-2.6-enable-valid.patch new file mode 100644 index 000000000000..df81058b16da --- /dev/null +++ b/01-freetype-2.6-enable-valid.patch @@ -0,0 +1,20 @@ +--- a/modules.cfg 2013-11-12 13:02:26.000000000 +0100 ++++ b/modules.cfg 2014-03-07 19:18:00.546655169 +0100 +@@ -110,7 +110,7 @@ RASTER_MODULES += smooth + 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). + # +@@ -129,7 +129,7 @@ AUX_MODULES += bzip2 + + # OpenType table validation. Needs ftotval.c below. + # +-# AUX_MODULES += otvalid ++AUX_MODULES += otvalid + + # Auxiliary PostScript driver component to share common code. + # diff --git a/02-upstream-2015.08.24.patch.xz b/02-upstream-2015.08.24.patch.xz Binary files differnew file mode 100644 index 000000000000..4d2493b9eb05 --- /dev/null +++ b/02-upstream-2015.08.24.patch.xz diff --git a/03-infinality-2.6-2015.08.24.patch b/03-infinality-2.6-2015.08.24.patch new file mode 100644 index 000000000000..0b01a13db306 --- /dev/null +++ b/03-infinality-2.6-2015.08.24.patch @@ -0,0 +1,4839 @@ +diff --git a/builds/freetype.mk b/builds/freetype.mk +index 1cc7e29..c73ae68 100644 +--- a/builds/freetype.mk ++++ b/builds/freetype.mk +@@ -161,6 +161,7 @@ FT_CFLAGS = $(CPPFLAGS) \ + $(CFLAGS) \ + $DFT2_BUILD_LIBRARY \ + $DFT_CONFIG_MODULES_H="<ftmodule.h>" \ ++ $D_GNU_SOURCE \ + $(FTOPTION_FLAG) + + +diff --git a/configure b/configure +index fd52581..bb81fb8 100755 +--- a/configure ++++ b/configure +@@ -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 + + # respect GNUMAKE environment variable for backwards compatibility +diff --git a/devel/ftoption.h b/devel/ftoption.h +index eda772e..d408a5d 100644 +--- a/devel/ftoption.h ++++ b/devel/ftoption.h +@@ -607,6 +607,17 @@ FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ ++ /* Define FT_CONFIG_OPTION_INFINALITY_PATCHSET if you want to enable */ ++ /* all additional infinality patches, which are configured via env */ ++ /* variables. */ ++ /* */ ++ /* This option requires TT_CONFIG_OPTION_SUBPIXEL_HINTING to */ ++ /* defined. */ ++ /* */ ++#define FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ ++ /*************************************************************************/ ++ /* */ + /* 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 --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h +index 4970945..3df05be 100644 +--- a/include/freetype/config/ftoption.h ++++ b/include/freetype/config/ftoption.h +@@ -92,7 +92,7 @@ FT_BEGIN_HEADER + /* 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 + + + /*************************************************************************/ +@@ -602,11 +602,22 @@ FT_BEGIN_HEADER + /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */ + /* defined. */ + /* */ +-/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */ ++#define TT_CONFIG_OPTION_SUBPIXEL_HINTING + + + /*************************************************************************/ + /* */ ++ /* Define FT_CONFIG_OPTION_INFINALITY_PATCHSET if you want to enable */ ++ /* all additional infinality patches, which are configured via env */ ++ /* variables. */ ++ /* */ ++ /* This option requires TT_CONFIG_OPTION_SUBPIXEL_HINTING to */ ++ /* defined. */ ++ /* */ ++#define FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ ++ /*************************************************************************/ ++ /* */ + /* 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 --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c +index 3065895..214c217 100644 +--- a/src/autofit/aflatin.c ++++ b/src/autofit/aflatin.c +@@ -24,6 +24,7 @@ + #include "afpic.h" + #include "aflatin.h" + #include "aferrors.h" ++#include "strings.h" + + + #ifdef AF_CONFIG_OPTION_USE_WARPER +@@ -40,6 +41,10 @@ + #undef FT_COMPONENT + #define FT_COMPONENT trace_aflatin + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++FT_Pos infinality_cur_width = 0; ++#endif ++ + + /* needed for computation of round vs. flat segments */ + #define FLAT_THRESHOLD( x ) ( x / 14 ) +@@ -899,8 +904,33 @@ + FT_Pos delta; + AF_LatinAxis axis; + FT_UInt nn; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ int checked_adjust_heights_env = 0; ++ FT_Bool adjust_heights = FALSE; + + ++ if ( checked_adjust_heights_env == 0 ) ++ { ++ char *adjust_heights_env = ++ getenv( "INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_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; ++ } ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ ++ + if ( dim == AF_DIMENSION_HORZ ) + { + scale = scaler->x_scale; +@@ -927,7 +957,7 @@ + { + AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT]; + AF_LatinBlue blue = NULL; +- ++ int threshold = 40; + + for ( nn = 0; nn < Axis->blue_count; nn++ ) + { +@@ -937,7 +967,12 @@ + break; + } + } +- ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( adjust_heights && ++ metrics->root.scaler.face->size->metrics.x_ppem < 15 && ++ metrics->root.scaler.face->size->metrics.x_ppem > 5 ) ++ threshold = 52; ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + if ( blue ) + { + FT_Pos scaled; +@@ -1056,7 +1091,13 @@ + + /* a blue zone is only active if it is less than 3/4 pixels tall */ + dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale ); ++ ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ /* Do at low ppems ( ~< 200 ), in order to prevent fringes */ ++ if ( dist <= 256 && dist >= -256 ) ++#else + if ( dist <= 48 && dist >= -48 ) ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + { + #if 0 + FT_Pos delta1; +@@ -1107,7 +1148,12 @@ + delta2 = -delta2; + + blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ /* Round to prevent fringes */ ++ blue->shoot.fit = FT_PIX_ROUND( blue->ref.fit - delta2 ); ++#else + blue->shoot.fit = blue->ref.fit - delta2; ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + + #endif + +@@ -1945,7 +1991,10 @@ + dist = edge->fpos - blue->shoot.org; + if ( dist < 0 ) + dist = -dist; +- ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ /* round down to pixels */ ++ /*dist = FT_MulFix( dist, scale ) & ~63;*/ ++#endif + dist = FT_MulFix( dist, scale ); + if ( dist < best_dist ) + { +@@ -2120,8 +2169,31 @@ + FT_Pos dist = width; + FT_Int sign = 0; + FT_Int vertical = ( dim == AF_DIMENSION_VERT ); ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ FT_Int infinality_dist = 0; ++ FT_UInt autohint_snap_stem_height = 0; ++ FT_UInt checked_autohint_snap_stem_height = 0; + + ++ if ( checked_autohint_snap_stem_height == 0 ) ++ { ++ char *autohint_snap_stem_height_env = ++ getenv( "INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT" ); ++ if ( autohint_snap_stem_height_env != NULL ) ++ { ++ sscanf ( autohint_snap_stem_height_env, "%u", ++ &autohint_snap_stem_height ); ++ ++ if ( autohint_snap_stem_height > 100 ) ++ autohint_snap_stem_height = 100; ++ else if ( autohint_snap_stem_height < 0 ) ++ autohint_snap_stem_height = 0; ++ } ++ checked_autohint_snap_stem_height = 1; ++ } ++ ++ if ( autohint_snap_stem_height == 0 ) ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || + axis->extra_light ) + return width; +@@ -2131,9 +2203,73 @@ + dist = -width; + sign = 1; + } ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ /* Calculate snap value differently than standard freetype */ ++ if ( autohint_snap_stem_height > 0 && ++ ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || ++ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) ) ++ { ++ infinality_dist = af_latin_snap_width( axis->widths, ++ axis->width_count, dist ); + +- if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || ++ if ( metrics->root.scaler.face->size->metrics.x_ppem > 9 && ++ axis->width_count > 0 && ++ abs( axis->widths[0].cur - infinality_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 ) ++ infinality_dist = 64; ++ else if ( axis->widths[0].cur < 88 ) ++ infinality_dist = 64; ++ else if ( axis->widths[0].cur < 160 ) ++ infinality_dist = 128; ++ else if ( axis->widths[0].cur < 240 ) ++ infinality_dist = 190; ++ else infinality_dist = ( infinality_dist ) & ~63; ++ } ++ else ++ { ++ /* bold gets a different threshold */ ++ if ( axis->widths[0].cur < 64 ) ++ infinality_dist = 64 ; ++ else if ( axis->widths[0].cur < 108 ) ++ infinality_dist = 64; ++ else if ( axis->widths[0].cur < 160 ) ++ infinality_dist = 128; ++ else if ( axis->widths[0].cur < 222 ) ++ infinality_dist = 190; ++ else if ( axis->widths[0].cur < 288 ) ++ infinality_dist = 254; ++ else infinality_dist = ( infinality_dist + 16 ) & ~63; ++ } ++ ++ } ++ if ( infinality_dist < 52 ) ++ { ++ if ( metrics->root.scaler.face->size->metrics.x_ppem < 9 ) ++ { ++ if ( infinality_dist < 32 ) ++ infinality_dist = 32; ++ } ++ else ++ infinality_dist = 64; ++ } ++ } ++ else if ( autohint_snap_stem_height < 100 && ++ ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || ++ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) ) ++#else ++ ++ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || + ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + { + /* smooth hinting process: very lightly quantize the stem width */ + +@@ -2193,6 +2329,9 @@ + } + } + else ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( autohint_snap_stem_height < 100 ) ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + { + /* strong hinting process: snap the stem width to integer pixels */ + +@@ -2200,7 +2339,10 @@ + + + dist = af_latin_snap_width( axis->widths, axis->width_count, dist ); +- ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( autohint_snap_stem_height > 0 ) ++ goto Done_Width; ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + if ( vertical ) + { + /* in the case of vertical hinting, always round */ +@@ -2263,6 +2405,32 @@ + } + + Done_Width: ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( axis->widths[0].cur > 42 ) ++ /* weighted average */ ++ dist = (dist * ( 100 - autohint_snap_stem_height ) ++ + infinality_dist * autohint_snap_stem_height ) / 100; ++ ++ { ++ int factor = 100; ++ if ( axis->standard_width < 100 ) ++ factor = axis->standard_width; ++ ++ if ( metrics->root.scaler.face->size->metrics.x_ppem >= 9 && dist < 52 ) ++ dist += ( (52 - dist) * factor ) / 100; ++ if ( metrics->root.scaler.face->size->metrics.x_ppem < 9 && dist < 32 ) ++ dist += ( (32 - dist) * factor ) / 100; ++ ++ if ( axis->standard_width > 100 && ++ metrics->root.scaler.face->size->metrics.x_ppem >= 11 && ++ dist < 64 ) ++ dist = 64; ++ if ( axis->standard_width > 100 && ++ metrics->root.scaler.face->size->metrics.x_ppem >= 9 && ++ dist < 52 ) ++ dist = 52; ++ } ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + if ( sign ) + dist = -dist; + +@@ -2284,6 +2452,8 @@ + base_edge->flags, + stem_edge->flags ); + ++/* if fitted_width causes stem_edge->pos to land basically on top of an existing ++ * stem_edge->pos, then add or remove 64. Need to figure out a way to do this */ + + stem_edge->pos = base_edge->pos + fitted_width; + +@@ -2844,8 +3014,32 @@ + int dim; + + AF_LatinAxis axis; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ FT_Int emboldening_strength = 0; ++ FT_Bool checked_use_various_tweaks_env = FALSE; ++ FT_Bool use_various_tweaks = FALSE; + +- ++ if ( !checked_use_various_tweaks_env ) ++ { ++ char *use_various_tweaks_env = ++ getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" ); ++ if ( use_various_tweaks_env != NULL ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "true") == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "1") == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "on") == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "yes") == 0 ) ++ use_various_tweaks = TRUE; ++ } ++ } ++ checked_use_various_tweaks_env = TRUE; ++ } ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + error = af_glyph_hints_reload( hints, outline ); + if ( error ) + goto Exit; +@@ -2913,7 +3107,11 @@ + } + + af_glyph_hints_save( hints, outline ); +- ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ { ++ infinality_cur_width = metrics->axis->widths[0].cur; ++ } ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + Exit: + return error; + } +diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h +index 6855492..736f251 100644 +--- a/src/autofit/aflatin.h ++++ b/src/autofit/aflatin.h +@@ -62,6 +62,9 @@ FT_BEGIN_HEADER + + #define AF_LATIN_MAX_WIDTHS 16 + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ extern FT_Pos infinality_cur_width; ++#endif + + #define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */ + #define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */ +diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c +index ff6f7e9..7b91443 100644 +--- a/src/base/ftlcdfil.c ++++ b/src/base/ftlcdfil.c +@@ -23,6 +23,9 @@ + #include FT_IMAGE_H + #include FT_INTERNAL_OBJECTS_H + ++#include <math.h> ++#include <string.h> ++#include <strings.h> + + #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + +@@ -309,10 +312,53 @@ + { 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 }; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ int checked_filter_params_env = 0; + ++ if ( checked_filter_params_env == 0 ) ++ { ++ char *filter_params = getenv( "INFINALITY_FT_FILTER_PARAMS" ); ++ if ( filter_params != NULL && strcmp( filter_params, "" ) != 0 ) ++ { ++ float f1, f2, f3, f4, f5; + ++ if ( strcasecmp( filter_params, "default" ) != 0 ) ++ { ++ int args_assigned = 0; ++ args_assigned = sscanf ( filter_params, ++ "%f %f %f %f %f", ++ &f1, &f2, &f3, &f4, &f5 ); ++ ++ if ( args_assigned == 5 ) ++ { ++ if ( f1 + f2 + f3 + f4 + f5 > 5 ) ++ { ++ /* Assume we were given integers instead of floats */ ++ /* 0 to 100 */ ++ default_filter[0] = (FT_Byte) ( f1 * 2.55f + 0.5f ); ++ default_filter[1] = (FT_Byte) ( f2 * 2.55f + 0.5f ); ++ default_filter[2] = (FT_Byte) ( f3 * 2.55f + 0.5f ); ++ default_filter[3] = (FT_Byte) ( f4 * 2.55f + 0.5f ); ++ default_filter[4] = (FT_Byte) ( f5 * 2.55f + 0.5f ); ++ } ++ else ++ { ++ /* Assume we were given floating point values */ ++ /* 0 to 1.0 */ ++ 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; ++ } ++#endif + if ( !library ) + return FT_THROW( Invalid_Library_Handle ); + +diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c +index 926ac0a..8a166a5 100644 +--- a/src/base/ftobjs.c ++++ b/src/base/ftobjs.c +@@ -67,6 +67,11 @@ + + #define GRID_FIT_METRICS + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++#include <strings.h> ++#include <stdlib.h> ++#include "../autofit/aflatin.h" ++#endif + + FT_BASE_DEF( FT_Pointer ) + ft_service_list_lookup( FT_ServiceDesc service_descriptors, +@@ -543,6 +548,25 @@ + ft_lookup_glyph_renderer( FT_GlyphSlot slot ); + + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ static void ++ ft_glyphslot_enlarge_metrics( FT_GlyphSlot slot, ++ FT_Render_Mode mode ) ++ { ++ FT_Glyph_Metrics* metrics = &slot->metrics; ++ FT_Pos enlarge_cbox = 0; ++ ++ ++ /* enlarge for grayscale rendering */ ++ if ( mode == FT_RENDER_MODE_NORMAL ) ++ enlarge_cbox = 64; ++ ++ metrics->horiBearingX -= enlarge_cbox; ++ metrics->width += 2 * enlarge_cbox; ++ } ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ ++ ++ + #ifdef GRID_FIT_METRICS + static void + ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot, +@@ -601,8 +625,40 @@ + FT_Bool autohint = FALSE; + FT_Module hinter; + TT_Face ttface = (TT_Face)face; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET + ++ int checked_use_various_tweaks_env = FALSE; ++ FT_Bool use_various_tweaks = FALSE; ++ ++ if ( !checked_use_various_tweaks_env ) ++ { ++ char *use_various_tweaks_env = ++ getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" ); ++ ++ if ( use_various_tweaks_env != NULL ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "true") == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "1") == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "on") == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "yes") == 0 ) ++ use_various_tweaks = TRUE; ++ } ++ } ++ checked_use_various_tweaks_env = 1; ++ } + ++ /* Force autohint if no tt instructions */ ++ /* NOTE: NEEDS TO BE RUN LATER IN CODE???? */ ++ /*if ( use_various_tweaks && ++ ttface->num_locations && ++ ttface->max_profile.maxSizeOfInstructions == 0 ) ++ load_flags |= FT_LOAD_FORCE_AUTOHINT;*/ ++#endif + if ( !face || !face->size || !face->glyph ) + return FT_THROW( Invalid_Face_Handle ); + +@@ -690,6 +746,18 @@ + { + FT_AutoHinter_Interface hinting; + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( use_various_tweaks ) ++ { ++ /* Force slight hinting over full hinting always */ ++ load_flags &= ~FT_LOAD_TARGET_LCD; ++ load_flags &= ~FT_LOAD_TARGET_LCD_V; ++ load_flags &= ~FT_LOAD_TARGET_MONO; ++ load_flags &= ~FT_LOAD_TARGET_NORMAL; ++ load_flags |= FT_LOAD_TARGET_LIGHT; ++ /*printf("%d ", load_flags);*/ ++ } ++#endif + + /* try to load embedded bitmaps first if available */ + /* */ +@@ -735,6 +803,18 @@ + if ( error ) + goto Exit; + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ infinality_cur_width = 0; ++ ++ { ++ /* fix for sdl_ttf */ ++ FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); ++ ++ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) ++ ft_glyphslot_enlarge_metrics( slot, mode ); ++ } ++#endif ++ + if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) + { + /* check that the loaded outline is correct */ +diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c +index ef66b3c..c3e4c71 100644 +--- a/src/base/ftoutln.c ++++ b/src/base/ftoutln.c +@@ -910,7 +910,34 @@ + FT_Vector* points; + FT_Int c, first, last; + FT_Int orientation; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ int checked_use_various_tweaks_env = 0; ++ FT_Bool use_various_tweaks = FALSE; + ++ if ( checked_use_various_tweaks_env == 0 ) ++ { ++ char *use_various_tweaks_env ++ = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" ); ++ if ( use_various_tweaks_env != NULL ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "true" ) == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "1" ) == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "on" ) == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "yes" ) == 0 ) ++ use_various_tweaks = TRUE; ++ } ++ } ++ checked_use_various_tweaks_env = 1; ++ } ++ ++ if ( use_various_tweaks ) ++ ystrength = FT_PIX_FLOOR ( ystrength ); ++#endif + + if ( !outline ) + return FT_THROW( Invalid_Outline ); +diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c +index cd68533..62352e1 100644 +--- a/src/base/ftsynth.c ++++ b/src/base/ftsynth.c +@@ -93,7 +93,32 @@ + FT_Face face; + FT_Error error; + FT_Pos xstr, ystr; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ int checked_use_various_tweaks_env = 0; ++ FT_Bool use_various_tweaks = FALSE; ++ ++ if ( checked_use_various_tweaks_env == 0 ) ++ { ++ char *use_various_tweaks_env ++ = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" ); ++ if ( use_various_tweaks_env != NULL ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp(use_various_tweaks_env, "true" ) == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "1" ) == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "on" ) == 0 ) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp(use_various_tweaks_env, "yes" ) == 0 ) ++ use_various_tweaks = TRUE; ++ } + ++ } ++ checked_use_various_tweaks_env = 1; ++ } ++#endif + + if ( !slot ) + return; +@@ -111,8 +136,16 @@ + ystr = xstr; + + if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) ++ { ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( use_various_tweaks ) ++ (void)FT_Outline_EmboldenXY( &slot->outline, ++ xstr, ++ FT_PIX_FLOOR( ystr ) ); ++ else ++#endif + FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); +- ++ } + else /* slot->format == FT_GLYPH_FORMAT_BITMAP */ + { + /* round to full pixels */ +@@ -150,6 +183,9 @@ + + slot->metrics.width += xstr; + slot->metrics.height += ystr; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( !use_various_tweaks ) ++#endif + slot->metrics.horiAdvance += xstr; + slot->metrics.vertAdvance += ystr; + slot->metrics.horiBearingY += ystr; +diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c +index 3620550..a92e003 100644 +--- a/src/smooth/ftsmooth.c ++++ b/src/smooth/ftsmooth.c +@@ -26,102 +26,3575 @@ + + #include "ftsmerrs.h" + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++#include <math.h> ++#include FT_BITMAP_H ++#include <strings.h> ++#include "../autofit/aflatin.h" ++#include FT_OUTLINE_H ++ ++#define verbose FALSE ++#define STVALUES if (verbose) \ ++ printf ( "scale:%f translate:%ld ", *scale_value, *translate_value ); ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ ++ ++ /* initialize renderer -- init its raster */ ++ static FT_Error ++ ft_smooth_init( FT_Renderer render ) ++ { ++ FT_Library library = FT_MODULE_LIBRARY( render ); ++ ++ ++ render->clazz->raster_class->raster_reset( render->raster, ++ library->raster_pool, ++ library->raster_pool_size ); ++ ++ return 0; ++ } ++ ++ ++ /* sets render-specific mode */ ++ static FT_Error ++ ft_smooth_set_mode( FT_Renderer render, ++ FT_ULong mode_tag, ++ FT_Pointer data ) ++ { ++ /* we simply pass it to the raster */ ++ return render->clazz->raster_class->raster_set_mode( render->raster, ++ mode_tag, ++ data ); ++ } ++ ++ /* transform a given glyph image */ ++ static FT_Error ++ ft_smooth_transform( FT_Renderer render, ++ FT_GlyphSlot slot, ++ const FT_Matrix* matrix, ++ const FT_Vector* delta ) ++ { ++ FT_Error error = FT_Err_Ok; ++ ++ ++ if ( slot->format != render->glyph_format ) ++ { ++ error = FT_THROW( Invalid_Argument ); ++ goto Exit; ++ } ++ ++ if ( matrix ) ++ FT_Outline_Transform( &slot->outline, matrix ); ++ ++ if ( delta ) ++ FT_Outline_Translate( &slot->outline, delta->x, delta->y ); ++ ++ Exit: ++ return error; ++ } ++ ++ ++ /* return the glyph's control box */ ++ static void ++ ft_smooth_get_cbox( FT_Renderer render, ++ FT_GlyphSlot slot, ++ FT_BBox* cbox ) ++ { ++ FT_MEM_ZERO( cbox, sizeof ( *cbox ) ); ++ ++ if ( slot->format == render->glyph_format ) ++ FT_Outline_Get_CBox( &slot->outline, cbox ); ++ } ++ ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ static FT_Fixed FT_FixedFromFloat(float f) ++ { ++ short value = f; ++ unsigned short fract = (f - value) * 0xFFFF; ++ ++ ++ return (FT_Fixed)((long)value << 16 | (unsigned long)fract ); ++ } ++ ++ ++ /* ChromeOS sharpening algorithm */ ++ /* soften the sub-pixel anti-aliasing and sharpen */ ++ static void ++ _ft_lcd_chromeos_sharpen( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_Byte cutoff, ++ double gamma_value ) ++ { ++ static FT_Bool initialized_gamma = FALSE; ++ static unsigned short gamma_ramp[256]; ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ int ii; ++ ++ if ( !initialized_gamma ) ++ { ++ initialized_gamma = TRUE; ++ /* linear to voltage */ ++ for ( ii = 0; ii < 256; ii++ ) ++ { ++ gamma_ramp[ii] = (unsigned char) ++ ( pow( (double)ii / 255.0, gamma_value ) * 255.0f ); ++ if ( gamma_ramp[ii] < cutoff ) ++ gamma_ramp[ii] = 0; ++ } ++ } ++ ++ /* horizontal in-place sub-pixel sharpening filter */ ++ if ( mode == FT_RENDER_MODE_LCD ) ++ { ++ FT_Byte* line = bitmap->buffer; ++ ++ ++ for ( ; height > 0; height--, line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ ++ for ( xx = 0; xx < width; xx++ ) ++ line[xx] = gamma_ramp[line[xx]]; ++ } ++ } ++ } ++ ++ /* simple linear scale to handle various sliding values */ ++ float ++ sliding_scale ( int min_value, ++ int max_value, ++ float min_amount, ++ float max_amount, ++ int cur_value ) ++ { ++ ++ float m = ( min_amount - max_amount ) / (float)( min_value - max_value ); ++ float result = ( ( (float)cur_value * m) + ( max_amount - max_value * m ) ) ; ++ ++ if ( min_amount < max_amount ) ++ { ++ if ( result < min_amount ) ++ return min_amount; ++ if ( result > max_amount ) ++ return max_amount; ++ } ++ else ++ { ++ if ( result < max_amount ) ++ return max_amount; ++ if ( result > min_amount ) ++ return min_amount; ++ } ++ ++ return result; ++ } ++ ++ ++ /* brightness and contrast adjustment on the bitmap */ ++ static FT_Bool ++ _ft_bitmap_bc ( FT_Bitmap* bitmap, ++ float brightness, ++ float contrast ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* line = bitmap->buffer; ++ FT_UInt xx; ++ ++ ++ if ( brightness == 0 && contrast == 0 ) ++ return FALSE; ++ ++ for ( height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch ) ++ { ++ for ( xx = 0; xx < width - 1; xx += 1 ) ++ { ++ if ( line[xx] > 0) ++ { ++ float value = (float)( 255 - line[xx] ) / 256.0; ++ FT_Int result = 0; ++ ++ if ( brightness < 0.0 ) ++ value = value * ( 1.0 + brightness ); ++ else ++ value = value + ( ( 1.0 - value ) * brightness ); ++ ++ value = ( value - 0.5 ) * ++ ( tan ( ( contrast + 1.0 ) * 3.141592/4.0 ) ) + 0.5; ++ ++ result = (FT_Int)( 255.0 - value * 256.0 ); ++ ++ if ( result < 0 ) ++ result = 0; ++ if ( result > 255 ) ++ result = 255; ++ ++ line[xx] = result; ++ } ++ } ++ } ++ return TRUE; ++ } ++ ++ ++ /* Filter to mimic Windows-style sharpening */ ++ /* Determined via 100% experimentation. */ ++ static void ++ _ft_lcd_windows_sharpen( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_UInt strength, ++ FT_Library library ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* new_line; ++ FT_Byte* line = bitmap->buffer; ++ FT_Bitmap new_bitmap; ++ ++ ++ FT_Bitmap_New( &new_bitmap ); ++ FT_Bitmap_Copy( library, bitmap, &new_bitmap ); ++ new_line = (&new_bitmap)->buffer; ++ ++ if (strength > 0) ++ for (height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch, new_line += bitmap->pitch ) ++ { ++ FT_UInt xx, threshold = 128; ++ FT_Byte* prevline = line - bitmap->pitch; ++ FT_Byte* nextline = line + bitmap->pitch; ++ FT_Byte* new_prevline = new_line - bitmap->pitch; ++ FT_Byte* new_nextline = new_line + bitmap->pitch; ++ ++ for ( xx = 1; xx < width - 1; xx += 1 ) ++ { ++ /* subpixel grid sp11 sp21 sp31 */ ++ /* where sp22 is sp12 sp22 sp32 */ ++ /* current subpixel. sp13 sp23 sp33 */ ++ ++ FT_Int prevtotal, nexttotal, lefttotal, righttotal, sidesdiff, ++ prevdiff, nextdiff, sp11, sp21, sp31, sp12, sp22, sp32, ++ sp13, sp23, sp33; ++ ++ sp12 = line [xx-1]; ++ sp22 = line [xx]; ++ sp32 = line [xx+1]; ++ ++ if ( height == bitmap->rows ) ++ { ++ prevtotal = sp11 = sp21 = sp31 = 0; ++ prevdiff = sp22; ++ lefttotal = sp12 + sp13; ++ righttotal = sp32 + sp33; ++ } ++ else ++ { ++ prevtotal = prevline[xx-1] + prevline[xx] + prevline[xx+1]; ++ sp11 = prevline [xx-1]; ++ sp21 = prevline [xx]; ++ sp31 = prevline [xx+1]; ++ prevdiff = sp22 - sp21; ++ lefttotal = sp11 + sp12 + sp13; ++ righttotal = sp31 + sp32 + sp33; ++ } ++ ++ if ( height == 1 ) ++ { ++ nexttotal = sp13 = sp23 = sp33 = 0; ++ nextdiff = sp22; ++ lefttotal = sp11 + sp12; ++ righttotal = sp31 + sp32; ++ } ++ else ++ { ++ nexttotal = nextline[xx-1] + nextline[xx] + nextline[xx+1]; ++ sp13 = nextline [xx-1]; ++ sp23 = nextline [xx]; ++ sp33 = nextline [xx+1]; ++ nextdiff = sp23 - sp22; ++ lefttotal = sp11 + sp12 + sp13; ++ righttotal = sp31 + sp32 + sp33; ++ } ++ ++ sidesdiff = lefttotal - righttotal; ++ ++ if ( sidesdiff < 0 ) ++ sidesdiff *= -1; ++ ++ if ( prevdiff < 0 ) ++ prevdiff *= -1; ++ ++ if ( nextdiff < 0 ) ++ nextdiff *= -1; ++ ++ /* if the current pixel is less than threshold, and greater than 0 */ ++ if ( sp22 <= threshold && sp22 > 0 ) ++ { ++ /* A pixel is horizontally isolated if: */ ++ /* 1: All upper adjecent pixels are >= threshold */ ++ if ( prevtotal >= nexttotal && ++ abs( sp11 - sp12 ) > 5 && ++ abs( sp21 - sp22 ) > 5 && ++ abs( sp31 - sp32 ) > 5 && /* not a vert stem end */ ++ sp11 >= threshold && ++ sp21 >= threshold && ++ sp31 >= threshold && ++ abs( sp23 - sp22 ) > 15 ) /* not on a vert stem */ ++ { ++ /* darken upper adjacent subpixel; lighten current */ ++ if ( height != (FT_UInt)bitmap->rows ) ++ new_prevline[xx] += ( ( 255 - new_prevline[xx] ) ++ * strength ) / 100 ; ++ ++ new_line[xx] -= ( new_line[xx] * strength ) / 100; ++ ++ if ( height != 1 && height != (FT_UInt)bitmap->rows ) ++ if ( new_nextline[xx] > 155 + ( 100 - strength ) ) ++ new_prevline[xx] = 255; ++ ++ } ++ else if ( nexttotal > prevtotal && ++ abs( sp13 - sp12 ) > 5 && ++ abs( sp23 - sp22 ) > 5 && ++ abs( sp33 - sp32 ) > 5 && ++ /* 2: All lower adjecent pixels are >= threshold */ ++ sp13 >= threshold && ++ sp23 >= threshold && ++ sp33 >= threshold && ++ abs( sp22 - sp21 ) > 15 ) ++ { ++ /* darken lower adjacent subpixel; lighten current */ ++ if ( height != 1 ) ++ new_nextline[xx] += ( 255 - new_nextline[xx] ) * strength / 100; ++ ++ new_line[xx] -= ( new_line[xx] * strength ) / 100; ++ ++ if ( height != 1 ) ++ if ( new_nextline[xx] > 155 + ( 100 - strength ) ) ++ new_nextline[xx] = 255; ++ ++ } ++ } ++ else if ( sp22 > threshold && sp22 < 255 ) ++ { ++ if ( sp11 <= threshold && ++ abs( sp13 - sp12 ) > 5 && ++ abs( sp23 - sp22 ) > 5 && ++ abs( sp33 - sp32 ) > 5 && ++ sp21 <= threshold && ++ sp31 <= threshold && ++ prevtotal <= nexttotal && ++ abs( sp22 - sp21 ) > 15 ) ++ { ++ /* bring this subpixel 1/3 of the way to 255 at 100% strength */ ++ new_line[xx] += ( strength * ( 255 - new_line[xx] ) ) / 100; ++ ++ if ( height != (FT_UInt)bitmap->rows ) ++ new_prevline[xx] -= ( new_prevline[xx] * strength ) / 300; ++ } ++ else if ( sp13 <= threshold && ++ abs( sp11 - sp12 ) > 5 && ++ abs( sp21 - sp22 ) > 5 && ++ abs( sp31 - sp32 ) > 5 && ++ sp23 <= threshold && ++ sp33 <= threshold && ++ nexttotal < prevtotal && ++ abs( sp23 - sp22 ) > 15 ) ++ { ++ new_line[xx] += ( strength * ( 255 - new_line[xx] ) ) / 100; ++ ++ if ( height != 1 ) ++ new_nextline[xx] -= ( new_nextline[xx] * strength ) / 300; ++ } ++ } ++ } ++ } ++ FT_Bitmap_Copy( library, &new_bitmap, bitmap); ++ FT_Bitmap_Done( library, &new_bitmap ); ++ } ++ ++ ++ static void ++ _ft_lcd_darken_x ( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_UInt strength, ++ FT_Library library ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* new_line; ++ FT_Byte* line = bitmap->buffer; ++ FT_Bitmap new_bitmap; ++ int factor1, factor2; ++ int bias = 0; ++ ++ FT_Bitmap_New( &new_bitmap ); ++ ++ FT_Bitmap_Copy( library, bitmap, &new_bitmap ); ++ new_line = (&new_bitmap)->buffer; ++ ++ if ( strength > 0 ) ++ for ( height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch, new_line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ FT_Byte* prevline = line - bitmap->pitch; ++ FT_Byte* nextline = line + bitmap->pitch; ++ ++ for ( xx = 1; xx < width - 1; xx += 1 ) ++ { ++ /* subpixel grid sp11 sp21 sp31 */ ++ /* where sp22 is sp12 sp22 sp32 */ ++ /* current subpixel. sp13 sp23 sp33 */ ++ ++ FT_Int sp21, sp12, sp22, sp32, sp23; ++ ++ sp12 = line [xx-1]; ++ sp22 = line [xx]; ++ sp32 = line [xx+1]; ++ ++ if ( height == bitmap->rows ) ++ sp21 = 0; ++ else ++ sp21 = prevline [xx]; ++ ++ if ( height == 1 ) ++ sp23 = 0; ++ else ++ sp23 = nextline [xx]; ++ ++ /* darken subpixel if neighbor above and below are much less than */ ++ /* safer but less effective */ ++ factor1 = 5; ++ factor2 = 5; ++ ++ /* make matches in the middle of glyph slightly darker */ ++ /*if (height > 1 && height < (FT_UInt)bitmap->rows) bias = 1;*/ ++ ++ if ( sp22 > factor1 * sp21 && ++ sp22 > factor1 * sp23 && ++ sp22 > factor2 && ++ sp12 > 16 && ++ sp32 > 16 ) ++ if ( new_line[xx] < ( strength * 255 ) / 100 ) ++ new_line[xx] = (strength * 255 ) / 100 ++ + bias * ( 255 - ( strength * 255 ) / 100 ) / 3; ++ ++ } ++ } ++ FT_Bitmap_Copy( library, &new_bitmap, bitmap ); ++ FT_Bitmap_Done( library, &new_bitmap ); ++ } ++ ++ ++ static void ++ _ft_lcd_darken_y ( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_UInt strength, ++ FT_Library library ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* new_line; ++ FT_Byte* line = bitmap->buffer; ++ FT_Bitmap new_bitmap; ++ ++ ++ FT_Bitmap_New( &new_bitmap ); ++ FT_Bitmap_Copy( library, bitmap, &new_bitmap ); ++ new_line = (&new_bitmap)->buffer; ++ ++ if ( strength > 0 ) ++ for ( height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch, new_line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ ++ for ( xx = 1; xx < width - 1; xx += 1 ) ++ { ++ if ( line[xx] > line[xx-1] && line[xx] > line[xx+1] ) ++ { ++ if (new_line[xx] > 0) ++ new_line[xx] += ( strength * ( 255 - new_line[xx] ) ) / 100; ++ new_line[xx-1] += ( strength * ( 255 - line[xx-1] ) ) / 100; ++ new_line[xx+1] += ( strength * ( 255 - line[xx+1] ) ) / 100; ++ } ++ } ++ } ++ FT_Bitmap_Copy( library, &new_bitmap, bitmap ); ++ FT_Bitmap_Done( library, &new_bitmap ); ++ } ++ ++ ++ static void ++ _ft_bitmap_cap ( FT_Bitmap* bitmap, ++ FT_UInt strength, ++ FT_Library library ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* new_line; ++ FT_Byte* line = bitmap->buffer; ++ FT_UInt cur_value = 0; ++ FT_Bitmap new_bitmap; ++ ++ ++ FT_Bitmap_New( &new_bitmap ); ++ FT_Bitmap_Copy( library, bitmap, &new_bitmap ); ++ new_line = (&new_bitmap)->buffer; ++ ++ if ( strength > 0 ) ++ for ( height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch, new_line += bitmap->pitch ) ++ { ++ FT_UInt xx; ++ ++ ++ for ( xx = 1; xx < width - 1; xx += 1 ) ++ { ++ cur_value = ( new_line[xx-1] + new_line[xx] + new_line[xx+1] ) / 3; ++ if ( cur_value > ( strength * 255 ) / 100 ) ++ { ++ FT_UInt new_factor = ( strength * 255 ) / 100; ++ new_line[xx] = ( new_line[xx] * new_factor ) / cur_value; ++ new_line[xx+1] = ( new_line[xx+1] * new_factor ) / cur_value; ++ new_line[xx-1] = ( new_line[xx-1] * new_factor ) / cur_value; ++ } ++ } ++ } ++ FT_Bitmap_Copy( library, &new_bitmap, bitmap ); ++ FT_Bitmap_Done( library, &new_bitmap ); ++ } ++ ++ ++ int ++ pseudo_gamma ( int val, float value ) ++ { ++ return 256 * ( 1.0 - pow( ( 1.0 - (float)val / 256.0 ), 1.0 / value ) ); ++ } ++ ++ ++ ++ static void ++ _ft_bitmap_embolden ( FT_Bitmap* bitmap, ++ FT_UInt strength, ++ FT_Library library ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* new_line; ++ FT_Byte* line = bitmap->buffer; ++ FT_Bitmap new_bitmap; ++ FT_UInt xx; ++ ++ ++ FT_Bitmap_New(&new_bitmap); ++ FT_Bitmap_Copy(library, bitmap, &new_bitmap); ++ new_line = (&new_bitmap)->buffer; ++ ++ if ( strength > 0 ) ++ for ( height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch, new_line += bitmap->pitch ) ++ { ++ for ( xx = 1; xx < width - 1; xx += 1 ) ++ { ++ FT_Int new_value = 0; ++ ++ ++ new_value = ( strength * line [xx-1] ) / 100 ++ + pseudo_gamma( line [xx], .75 ) ++ + (strength * line [xx+1] ) / 100; ++ if ( new_value > 255 ) ++ new_value = 255; ++ ++ new_line[xx] = new_value; ++ } ++ } ++ FT_Bitmap_Copy( library, &new_bitmap, bitmap ); ++ FT_Bitmap_Done( library, &new_bitmap ); ++ } ++ ++ ++ ++ static void ++ _ft_bitmap_gamma ( FT_Bitmap* bitmap, ++ float strength ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* line = bitmap->buffer; ++ FT_UInt xx; ++ ++ ++ if ( strength > 0 ) ++ for ( height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch ) ++ { ++ ++ for ( xx = 1; xx < width - 1; xx += 1 ) ++ { ++ if ( abs( line[xx-1] - line[xx] ) < 20 || ++ abs( line[xx+1] - line[xx] ) < 20 ) ++ line [xx] = pseudo_gamma( line [xx], strength ) ; ++ } ++ } ++ } ++ ++ ++ /* Fringe filter */ ++ static void ++ _ft_lcd_fringe_filter ( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_UInt strength, ++ FT_Library library ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* new_line; ++ FT_Byte* line = bitmap->buffer; ++ FT_Bitmap new_bitmap; ++ ++ ++ FT_Bitmap_New(&new_bitmap); ++ ++ line = bitmap->buffer; ++ FT_Bitmap_Copy( library, bitmap, &new_bitmap ); ++ new_line = (&new_bitmap)->buffer; ++ ++ for ( height = (FT_UInt)bitmap->rows; ++ height > 0; ++ height--, line += bitmap->pitch, new_line += bitmap->pitch ) ++ { ++ /* Threshold set to 1/2 pixel intensity */ ++ FT_UInt xx, threshold = 128; ++ ++ /* Hack to make this work when bitmap is at first or last line */ ++ FT_Int fudge = bitmap->pitch * (height == (FT_UInt)bitmap->rows); ++ ++ FT_Byte* prevline = line - bitmap->pitch + fudge; ++ FT_Byte* nextline = line + bitmap->pitch; ++ ++ ++ for ( xx = 1; xx < width - 1; xx += 1 ) ++ { ++ /* subpixel grid sp11 sp21 sp31 */ ++ /* where sp22 is sp12 sp22 sp32 */ ++ /* current subpixel. sp13 sp23 sp33 */ ++ ++ FT_Int prevtotal, nexttotal, lefttotal, righttotal, sidesdiff, ++ leftdiff, rightdiff, prevdiff, nextdiff, sp11, sp21, sp31, ++ sp12, sp22, sp32, sp13, sp23, sp33; ++ ++ sp12 = line [xx-1]; ++ sp22 = line [xx]; ++ sp32 = line [xx+1]; ++ ++ /* if at max height fake out some values */ ++ if ( height == (FT_UInt)bitmap->rows ) ++ { ++ prevtotal = sp11 = sp21 = sp31 = 0; ++ prevdiff = sp22; ++ lefttotal = sp12 + sp13; ++ righttotal = sp32 + sp33; ++ } ++ else ++ { ++ prevtotal = prevline[xx-1] + prevline[xx] + prevline[xx+1]; ++ sp11 = prevline [xx-1]; ++ sp21 = prevline [xx]; ++ sp31 = prevline [xx+1]; ++ prevdiff = sp22 - sp21; ++ lefttotal = sp11 + sp12 + sp13; ++ righttotal = sp31 + sp32 + sp33; ++ } ++ ++ /* if at min height fake out some values */ ++ if ( height == 1 ) ++ { ++ nexttotal = sp13 = sp23 = sp33 = 0; ++ nextdiff = sp22; ++ lefttotal = sp11 + sp12; ++ righttotal = sp31 + sp32; ++ } ++ else ++ { ++ nexttotal = nextline[xx-1] + nextline[xx] + nextline[xx+1]; ++ sp13 = nextline [xx-1]; ++ sp23 = nextline [xx]; ++ sp33 = nextline [xx+1]; ++ nextdiff = sp23 - sp22; ++ lefttotal = sp11 + sp12 + sp13; ++ righttotal = sp31 + sp32 + sp33; ++ } ++ ++ sidesdiff = lefttotal - righttotal; ++ leftdiff = sp22 - sp12; ++ rightdiff = sp32 - sp22; ++ ++ if ( sidesdiff < 0 ) ++ sidesdiff *= -1; ++ ++ if ( prevdiff < 0 ) ++ prevdiff *= -1; ++ ++ if ( nextdiff < 0 ) ++ nextdiff *= -1; ++ ++ if ( leftdiff < 0 ) ++ leftdiff *= -1; ++ ++ if ( rightdiff < 0 ) ++ rightdiff *= -1; ++ ++ /* if the current subpixel is less than threshold, and varies only ++ slightly to left or right, lighten it */ ++ if ( sp22 <= threshold && sp22 > 0 && ++ ( leftdiff < 10 || rightdiff < 10 ) ) ++ { ++ /* A pixel is horizontally isolated if: */ ++ /* 1: All upper adjecent subpixels are >= threshold and all lower ++ adjacent ones are essentially white */ ++ if ( prevtotal >= nexttotal && ++ sp11 >= threshold && ++ sp21 >= threshold && ++ sp31 >= threshold && ++ sp13 < 2 && ++ sp23 < 2 && ++ sp33 < 2 ) ++ ++ { ++ new_line[xx] -= ( new_line[xx] * strength ) / 100; ++ ++ if ( leftdiff < 10 ) ++ /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */ ++ new_line[xx-1] -= ( new_line[xx-1] * strength ) / 200; ++ ++ if ( rightdiff < 10 ) ++ /* OPPORTUNITY FOR IMPROVEMENT */ ++ new_line[xx+1] -= ( new_line[xx+1] * strength ) / 200; ++ } ++ else if ( nexttotal > prevtotal && ++ /* 2: the inverse of above */ ++ sp13 >= threshold && ++ sp23 >= threshold && ++ sp33 >= threshold && ++ sp11 < 2 && ++ sp21 < 2 && ++ sp31 < 2 ) ++ { ++ new_line[xx] -= ( new_line[xx] * strength ) / 100; ++ ++ if ( leftdiff < 10 ) ++ /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */ ++ new_line[xx-1] -= ( new_line[xx-1] * strength ) / 200; ++ ++ if ( rightdiff < 10 ) ++ /* OPPORTUNITY FOR IMPROVEMENT */ ++ new_line[xx+1] -= ( new_line[xx+1] * strength ) / 200; ++ } ++ } ++ /* otherwise if the current subpixel is more than threshold, and varies ++ slightly to left or right, darken it */ ++ else if ( sp22 > threshold && ++ sp22 < 255 && ++ ( leftdiff < 10 || ++ rightdiff < 10 ) ) ++ { ++ if ( sp11 <= 2 && ++ sp21 <= 2 && ++ sp31 <= 2 && ++ sp13 >= threshold && ++ sp23 >= threshold && ++ sp33 >= threshold && ++ prevtotal < nexttotal ) ++ new_line[xx] += ( ( 255 - new_line[xx] ) * strength ) / 100; ++ ++ else if ( sp13 <= 2 && ++ sp23 <= 2 && ++ sp33 <= 2 && ++ nexttotal < prevtotal && ++ sp11 >= threshold && ++ sp21 >= threshold && ++ sp31 >= threshold ) ++ new_line[xx] += ( ( 255 - new_line[xx] ) * strength ) / 100; ++ ++ } ++ } ++ } ++ FT_Bitmap_Copy( library, &new_bitmap, bitmap ); ++ FT_Bitmap_Done( library, &new_bitmap ); ++ } ++ ++ ++ /* Grayscale filter */ ++ static void ++ _ft_lcd_grayscale_filter ( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_UInt strength, ++ FT_Library library ) ++ { ++ ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* 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 += 3 ) ++ { ++ FT_UInt total = line [xx] + line [xx + 1] + line [xx + 2]; ++ line[xx] = ( ( 100 - strength ) * line[xx] ++ + strength * ( total / 3 ) ) / 100; ++ line[xx+1] = ( ( 100 - strength ) * line[xx+1] ++ + strength * ( total / 3 ) ) / 100; ++ line[xx+2] = ( ( 100 - strength ) * line[xx+2] ++ + strength * ( total / 3 ) ) / 100; ++ } ++ } ++ } ++ ++ ++ ++ /*************************************************************************/ ++ /* */ ++ /* */ ++ /* */ ++ /* */ ++ /* */ ++ /* */ ++ ++ ++ typedef struct SA_Rule_ ++ { ++ const char family[32]; ++ const int ppem[5]; ++ ++ } SA_Rule; ++ ++#define STEM_WIDTH_2_PPEM 18 ++#define MAX_PPEM 100 ++ ++ ++ ++/* "Font name", {ppem where stem width becomes 1, ++ * ppem where stem width becomes 2... etc.} */ ++/* 100 means auto-calculate */ ++#define SNAPPING_STEM_WIDTHS_RULES_SIZE 21 ++ SA_Rule SNAPPING_STEM_WIDTHS_Rules ++ [SNAPPING_STEM_WIDTHS_RULES_SIZE] = ++ { ++ { "Andale Mono", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Arial Narrow", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Calibri", {10, 19, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Cantarell", {10, 22, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Century Gothic", {10, 22, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Comfortaa", {10, 19, 22, MAX_PPEM, MAX_PPEM} }, ++ { "Consolas", {10, 20, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Corbel", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Futura", {10, 14, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Gill Sans", {10, 17, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Helvetica CY", {10, 23, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Inconsolata", {10, 23, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Liberation Sans Narrow", {10, 22, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Liberation Sans", {10, 19, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Lucida Grande", {10, 16, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Lucida Sans Unicode", {10, 16, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Luxi Sans", {10, 17, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Open Sans", {10, 20, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Rokkitt", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Segoe UI", {10, 23, MAX_PPEM, MAX_PPEM, MAX_PPEM} }, ++ { "Trebuchet MS", {10, 17, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} }, ++ }; ++ ++ ++/* "Font name", {ppem, scale_up=1|scale_down=0} */ ++#define SNAPPING_STEM_SCALING_RULES_SIZE 31 ++ SA_Rule SNAPPING_STEM_SCALING_Rules ++ [SNAPPING_STEM_SCALING_RULES_SIZE] = ++ { ++ { "Andale Mono", {11, 1,} }, ++ { "Bitstream Vera Sans", {12, 1,} }, ++ { "Calibri", {15, 1,} }, ++ { "Calibri", {17, 1,} }, ++ { "Calibri", {18, 1,} }, ++ { "Candara", {14, 1,} }, ++ { "Candara", {17, 1,} }, ++ { "Canwell", {13, 0,} }, ++ { "Comfortaa", {11, 0,} }, ++ { "Consolas", {11, 1,} }, ++ { "DejaVu Sans", {12, 1,} }, ++ { "Freesans", {16, 0,} }, ++ { "Freeserif", {13, 1,} }, ++ { "Freeserif", {17, 1,} }, ++ { "Inconsolata", {12, 1,} }, ++ { "Inconsolata", {15, 1,} }, ++ { "Lucida Grande", {13, 1,} }, ++ { "Myriad Pro", {14, 1,} }, ++ { "Myriad Pro", {17, 1,} }, ++ { "Nina", {11, 0,} }, ++ { "Nina", {12, 0,} }, ++ { "Nina", {13, 0,} }, ++ { "Optima", {17, 1,} }, ++ { "Raleway", {15, 0,} }, ++ { "Samba", {11, 0,} }, ++ { "Times New Roman", {17, 1,} }, ++ { "Trebuchet MS", {17, 0,} }, ++ { "Trebuchet MS", {13, 0,} }, ++ { "Trebuchet MS", {20, 1,} }, ++ { "Verdana", {12, 1,} }, ++ { "Verdana", {15, 1,} }, ++ }; ++ ++ ++/* "Font name", {ppem, scale_up=1|scale_down=0} */ ++#define SNAPPING_M_RULES_SIZE 9 ++ SA_Rule SNAPPING_M_Rules ++ [SNAPPING_M_RULES_SIZE] = ++ { ++ { "Courier New", {13, 1,} }, ++ { "Courier New", {14, 1,} }, ++ { "Courier", {13, 1,} }, ++ { "Courier", {14, 1,} }, ++ { "Droid Sans Mono", {12, 0,} }, ++ { "Bitstream Vera Sans", {12, 0,} }, ++ { "DejaVu Sans", {12, 0,} }, ++ { "Essential PragmataPro", {13, 0,} }, ++ { "Essential PragmataPro", {14, 0,} }, ++ }; ++ ++ ++/* "Font name", {ppem, ppem} */ ++#define SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE 1 ++ SA_Rule SNAPPING_SYNTHESIZE_STEMS_Rules ++ [SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE] = ++ { ++ { "---", {13, 13,} }, ++ }; ++ ++ ++/* "Font name", {ppem, ppem} */ ++#define SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE 1 ++ SA_Rule SNAPPING_NO_BEARING_CORRECTION_Rules ++ [SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE] = ++ { ++ { "Times New Roman", {0, 100,} }, ++ }; ++ ++ ++/* "Font name", {ppem, ppem} */ ++#define SNAPPING_EDGE_DETECTION_RULES_SIZE 8 ++ SA_Rule SNAPPING_EDGE_DETECTION_Rules ++ [SNAPPING_EDGE_DETECTION_RULES_SIZE] = ++ { ++ { "Tahoma", {11, 11,} }, ++ { "Courier New", {10, 12,} }, ++ { "Arial", {11, 11,} }, ++ { "Arial", {13, 13,} }, ++ { "Liberation Sans", {11, 11,} }, ++ { "FreeSans", {11, 11,} }, ++ { "FreeSans", {13, 13,} }, ++ { "Palatino Linotype", {0, 100,} }, ++ }; ++ ++/* "Font name", {ppem, translate_value} */ ++#define SNAPPING_STEM_TRANSLATING_RULES_SIZE 6 ++ SA_Rule SNAPPING_STEM_TRANSLATING_Rules ++ [SNAPPING_STEM_TRANSLATING_RULES_SIZE] = ++ { ++ { "Arial", {11, 32,} }, ++ { "Arial Unicode MS", {11, 32,} }, ++ { "FreeSans", {11, 32,} }, ++ { "Arimo", {11, 32,} }, ++ { "Liberation Sans", {11, 32,} }, ++ { "Tahoma", {11, 32,} }, ++ }; ++ ++/* "Font name", {ppem, translate_value} */ ++#define SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE 74 ++ SA_Rule SNAPPING_STEM_TRANSLATING_ONLY_Rules ++ [SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE] = ++ { ++ { "Arial Unicode MS", {10, 16,} }, ++ { "Arial Unicode MS", {8, 32,} }, ++ { "Arial Unicode MS", {9, 32,} }, ++ { "Arial", {10, 16,} }, ++ { "Arial", {8, 32,} }, ++ { "Arial", {9, 32,} }, ++ { "Arial", {16, -24,} }, ++ { "Arimo", {10, 8,} }, ++ { "Arimo", {8, 32,} }, ++ { "Arimo", {9, 32,} }, ++ { "Bitstream Vera Sans", {8, 16,} }, ++ { "Calibri", {10, 16,} }, ++ { "Calibri", {15, 0,} }, ++ { "Candara", {10, 16,} }, ++ { "Cantarell", {11, 0} }, ++ { "Cantarell", {12, 0} }, ++ { "Consolas", {8, 32,} }, ++ { "Consolas", {9, 32,} }, ++ { "Corbel", {10, 16,} }, ++ { "Courier", {13, 16,} }, ++ { "Courier", {15, 0,} }, ++ { "Dejavu Sans Mono", {7, 16,} }, ++ { "Dejavu Sans Mono", {8, 32,} }, ++ { "Dejavu Sans Mono", {9, 16,} }, ++ { "Dejavu Sans", {8, 16,} }, ++ { "Dejavu Sans", {15, -20,} }, ++ { "Droid Sans", {8, 16,} }, ++ { "Droid Sans", {9, 16,} }, ++ { "Freesans", {10, 16,} }, ++ { "Freesans", {9, 8,} }, ++ { "Georgia", {13, 16,} }, ++ { "Georgia", {14, 16,} }, ++ { "Georgia", {15, 0,} }, ++ { "Inconsolata", {10, 24,} }, ++ { "Inconsolata", {9, 32,} }, ++ { "Liberation Sans", {10, 8,} }, ++ { "Liberation Sans", {8, 32,} }, ++ { "Liberation Sans", {9, 32,} }, ++ { "Lucida Grande", {13, 24,} }, ++ { "Lucida Grande", {14, 24,} }, ++ { "Lucida Grande", {8, 16,} }, ++ { "Lucida Grande", {9, 16,} }, ++ { "Lucida Sans Unicode", {13, 24,} }, ++ { "Lucida Sans Unicode", {14, 24,} }, ++ { "Lucida Sans Unicode", {8, 16,} }, ++ { "Lucida Sans Unicode", {9, 16,} }, ++ { "Microsoft Sans Serif", {10, 16,} }, ++ { "Microsoft Sans Serif", {8, 32,} }, ++ { "Microsoft Sans Serif", {9, 32,} }, ++ { "Myriad Pro", {10, 16,} }, ++ { "Myriad Pro", {11, 0,} }, ++ { "Myriad Pro", {9, 16,} }, ++ { "Open Sans", {10, 16,} }, ++ { "Open Sans", {9, 16,} }, ++ { "Optima", {10, 0} }, ++ { "Optima", {11, 0} }, ++ { "Optima", {12, 0} }, ++ { "Segoe UI", {10, 0,} }, ++ { "Segoe UI", {7, 32,} }, ++ { "Segoe UI", {8, 16,} }, ++ { "Segoe UI", {9, 24,} }, ++ { "Tahoma", {7, 32,} }, ++ { "Tahoma", {8, 32,} }, ++ { "Tahoma", {9, 32,} }, ++ { "Times New Roman", {17, 8,} }, ++ { "Trebuchet MS", {10, 16,} }, ++ { "Trebuchet MS", {11, 0,} }, ++ { "Trebuchet MS", {8, 32,} }, ++ { "Trebuchet MS", {9, 32,} }, ++ { "Verdana", {8, 16,} }, ++ { "Verdana", {15, 16,} }, ++ { "Verdana", {14, 32,} }, ++ { "Verdana", {18, 32,} }, ++ { "Verdana", {19, 24,} }, ++ }; ++ ++ ++/* "Font name", {start ppem, end ppem} */ ++#define ALWAYS_USE_100_RULES_SIZE 46 ++ SA_Rule ALWAYS_USE_100_Rules ++ [ALWAYS_USE_100_RULES_SIZE] = ++ { ++ { "Andale Mono", {0, MAX_PPEM,} }, ++ { "Arial Unicode MS", {0, MAX_PPEM,} }, ++ { "Arial", {0, MAX_PPEM,} }, ++ { "Arimo", {0, MAX_PPEM,} }, ++ { "Bitstream Vera Sans Mono", {0, MAX_PPEM,} }, ++ { "Bitstream Vera Sans", {10, 14,} }, ++ { "Bitstream Vera Sans", {16, 17,} }, ++ { "Calibri", {23, MAX_PPEM,} }, ++ { "Consolas", {0, MAX_PPEM,} }, ++ { "Courier New", {12, 12,} }, ++ { "Courier", {0, MAX_PPEM,} }, ++ { "Cousine", {0, MAX_PPEM,} }, ++ { "DejaVu Sans Mono", {0, MAX_PPEM,} }, ++ { "DejaVu Sans", {10, 14,} }, ++ { "DejaVu Sans", {16, 17,} }, ++ { "Droid Sans", {12, 12,} }, ++ { "Droid Sans", {15, 15,} }, ++ { "FreeMono", {0, MAX_PPEM,} }, ++ { "FreeSans", {0, MAX_PPEM,} }, ++ { "Liberation Mono", {0, MAX_PPEM,} }, ++ { "Lucida Console", {0, MAX_PPEM,} }, ++ { "Luxi Sans", {13, 13,} }, ++ { "Microsoft Sans Serif", {0, MAX_PPEM,} }, ++ { "Monaco", {0, MAX_PPEM,} }, ++ { "Segoe UI", {11, 12,} }, ++ { "Segoe UI", {14, 14,} }, ++ { "Tahoma", {11, 11,} }, ++ { "Tahoma", {14, MAX_PPEM,} }, ++ { "Times New Roman", {14, 14,} }, ++ { "Times New Roman", {16, 16,} }, ++ { "Trebuchet MS", {13, 13,} }, ++ { "Ubuntu", {12, 13,} }, ++ { "Ubuntu", {15, 15,} }, ++ { "Verdana", {0, 14,} }, ++ { "Verdana", {16, MAX_PPEM,} }, ++ { "Pragmata", {0, MAX_PPEM,} }, ++ { "Essential PragmataPro", {0, MAX_PPEM,} }, ++ }; ++ ++ ++ ++ ++#define AUTOHINT_BRIGHTNESS_RULES_SIZE 3 ++ SA_Rule BRIGHTNESS_Rules ++ [AUTOHINT_BRIGHTNESS_RULES_SIZE] = ++ { ++ { "Baskerville", {0, -20,} }, ++ { "Garamond", {0, -20,} }, ++ { "Optima", {0, -20,} }, ++ }; ++ ++#define AUTOHINT_CONTRAST_RULES_SIZE 3 ++ SA_Rule CONTRAST_Rules ++ [AUTOHINT_CONTRAST_RULES_SIZE] = ++ { ++ { "Baskerville", {0, 25,} }, ++ { "Garamond", {0, 25,} }, ++ { "Optima", {0, 25,} }, ++ }; ++ ++#if 0 ++#define STEM_SPACING_RULES_SIZE 3 ++ SA_Rule STEM_SPACING_Rules ++ [STEM_SPACING_RULES_SIZE] = ++ { ++ { "Tahoma", {10, 12, 18, 18, 30} }, ++ { "Arial", {10, 11, 23, 25, 30} }, ++ { "Freesans", {10, 12, 18, 18, 30} }, ++ }; ++ ++#define STEM_START_RULES_SIZE 3 ++ SA_Rule STEM_START_Rules ++ [STEM_START_RULES_SIZE] = ++ { ++ { "Tahoma", {14, 17, 30, 100, 100} }, ++ { "Arial", {11, 18, 23, 30, 30} }, ++ { "Freesans", {10, 18, 18, 25, 30} }, ++ }; ++#endif ++ ++ typedef struct Stem_Data_ ++ { ++ FT_Int stem_width; ++ FT_Int stem_spacing; ++ FT_Int stem_start; ++ FT_Int stem_scaling; ++ FT_Int stem_translating_only; ++ FT_Int stem_translating; ++ FT_Int brightness; ++ FT_Int contrast; ++ FT_Bool use_100; ++ FT_Bool synth_stems; ++ FT_Bool edge_detection; ++ FT_Bool bearing_correction; ++ FT_Int m; ++ } Stem_Data; ++ ++ ++ typedef struct Stem_Segment_ ++ { ++ FT_Long x1; ++ FT_Long x2; ++ FT_Int y; ++ } Stem_Segment; ++ ++ typedef struct Stem_Center_ ++ { ++ FT_Long x; ++ FT_Long y; ++ FT_Long w; ++ FT_Long x1; ++ FT_Long x2; ++ } Stem_Center; ++ ++ typedef struct Stem_ ++ { ++ FT_Long center; ++ FT_Long count; ++ FT_Long rcount; /* used to count within a range in possible stems */ ++ FT_Long width; ++ FT_Long height; ++ FT_Short zone; /* 1 2 or 3 */ ++ FT_Bool generated; ++ } Stem; ++ ++ ++ static void ++ swap_stem ( Stem* s1, Stem* s2 ) ++ { ++ Stem s; ++ s.center = s1->center; ++ s.count = s1->count; ++ s.rcount = s1->rcount; ++ s.width = s1->width; ++ s.zone = s1->zone; ++ s.generated = s1->generated; ++ ++ s1->center = s2->center; ++ s1->count = s2->count; ++ s1->rcount = s2->rcount; ++ s1->width = s2->width; ++ s1->zone = s2->zone; ++ s1->generated = s2->generated; ++ ++ s2->center = s.center; ++ s2->count = s.count; ++ s2->rcount = s.rcount; ++ s2->width = s.width; ++ s2->zone = s.zone; ++ s2->generated = s.generated; ++ } ++ ++ ++ FT_LOCAL_DEF( void ) ++ sa_fill_known_stem_values ( ++ FT_String* family, ++ int ppem, ++ FT_String* style, ++ FT_UInt num_stems, ++ Stem_Data* known_stem_values ) ++ { ++ FT_Int i, j; ++ if (verbose) printf("%s ", family); ++ ++ i = 0; ++ while ( i < SNAPPING_STEM_WIDTHS_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_STEM_WIDTHS_Rules[i].family, ++ family ) == 0 ) ) ++ { ++ j = 0; ++ known_stem_values->stem_width = 1; ++ ++ while (j < 4) ++ { ++ if ( SNAPPING_STEM_WIDTHS_Rules[i].ppem[j] == MAX_PPEM ) ++ { ++ known_stem_values->stem_width = -1; /* use default */ ++ j = 5; ++ i = SNAPPING_STEM_WIDTHS_RULES_SIZE; ++ } ++ else if ( ppem < SNAPPING_STEM_WIDTHS_Rules[i].ppem[j] ) ++ { ++ known_stem_values->stem_width = j; ++ j = 5; ++ i = SNAPPING_STEM_WIDTHS_RULES_SIZE; ++ } ++ j++; ++ } ++ } ++ i++; ++ } ++ ++ i = 0; ++ while ( i < SNAPPING_STEM_SCALING_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_STEM_SCALING_Rules[i].family, ++ family ) == 0 ) ) ++ { ++ known_stem_values->stem_scaling = -1; /* default */ ++ ++ if ( ppem == SNAPPING_STEM_SCALING_Rules[i].ppem[0] ) ++ { ++ known_stem_values->stem_scaling ++ = SNAPPING_STEM_SCALING_Rules[i].ppem[1]; ++ i = SNAPPING_STEM_SCALING_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ ++ i = 0; ++ while ( i < SNAPPING_M_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_M_Rules[i].family, family ) == 0 ) ) ++ { ++ known_stem_values->m = -1; /* default */ ++ ++ if ( ppem == SNAPPING_M_Rules[i].ppem[0] ) ++ { ++ known_stem_values->m = SNAPPING_M_Rules[i].ppem[1]; ++ i = SNAPPING_M_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ i = 0; ++ while ( i < SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].family, ++ family ) == 0 ) ) ++ { ++ known_stem_values->stem_translating_only = -1024; /* default */ ++ ++ if ( ppem == SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].ppem[0] || ++ SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].ppem[0] == 0 ) ++ { ++ known_stem_values->stem_translating_only ++ = SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].ppem[1]; ++ i = SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ i = 0; ++ while ( i < SNAPPING_STEM_TRANSLATING_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_STEM_TRANSLATING_Rules[i].family, ++ family ) == 0 ) ) ++ { ++ known_stem_values->stem_translating = 0; /* default */ ++ ++ if ( ppem == SNAPPING_STEM_TRANSLATING_Rules[i].ppem[0] || ++ SNAPPING_STEM_TRANSLATING_Rules[i].ppem[0] == 0 ) ++ { ++ known_stem_values->stem_translating ++ = SNAPPING_STEM_TRANSLATING_Rules[i].ppem[1]; ++ i = SNAPPING_STEM_TRANSLATING_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ ++ i = 0; ++ while ( i < ALWAYS_USE_100_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( ALWAYS_USE_100_Rules[i].family, family ) == 0 ) ) ++ { ++ known_stem_values->use_100 = FALSE; /* default */ ++ ++ if ( ppem >= ALWAYS_USE_100_Rules[i].ppem[0] && ++ ppem <= ALWAYS_USE_100_Rules[i].ppem[1] ) ++ { ++ known_stem_values->use_100 = TRUE; ++ i = ALWAYS_USE_100_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ ++ i = 0; ++ while ( i < SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_SYNTHESIZE_STEMS_Rules[i].family, ++ family ) == 0 ) ) ++ { ++ known_stem_values->synth_stems = FALSE; /* default */ ++ ++ if ( ppem >= SNAPPING_SYNTHESIZE_STEMS_Rules[i].ppem[0] && ++ ppem <= SNAPPING_SYNTHESIZE_STEMS_Rules[i].ppem[1] ) ++ { ++ known_stem_values->synth_stems = TRUE; ++ i = SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ ++ i = 0; ++ while ( i < SNAPPING_EDGE_DETECTION_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_EDGE_DETECTION_Rules[i].family, ++ family ) == 0 ) ) ++ { ++ known_stem_values->edge_detection = FALSE; /* default */ ++ ++ if ( ppem >= SNAPPING_EDGE_DETECTION_Rules[i].ppem[0] && ++ ppem <= SNAPPING_EDGE_DETECTION_Rules[i].ppem[1] ) ++ { ++ known_stem_values->edge_detection = TRUE; ++ i = SNAPPING_EDGE_DETECTION_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ ++ i = 0; ++ while ( i < SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( SNAPPING_NO_BEARING_CORRECTION_Rules[i].family, ++ family ) == 0 ) ) ++ { ++ known_stem_values->bearing_correction = TRUE; /* default */ ++ ++ if ( ppem >= SNAPPING_NO_BEARING_CORRECTION_Rules[i].ppem[0] && ++ ppem <= SNAPPING_NO_BEARING_CORRECTION_Rules[i].ppem[1] ) ++ { ++ known_stem_values->bearing_correction = FALSE; ++ i = SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ ++#if 0 ++ i = 0; ++ while ( i < AUTOHINT_BRIGHTNESS_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( BRIGHTNESS_Rules[i].family, family ) == 0 ) ) ++ { ++ known_stem_values->brightness = 0.0; ++ ++ if ( ppem == BRIGHTNESS_Rules[i].ppem[0] || ++ BRIGHTNESS_Rules[i].ppem[0] == 0 ) ++ { ++ known_stem_values->brightness = BRIGHTNESS_Rules[i].ppem[1]; ++ i = AUTOHINT_BRIGHTNESS_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ i = 0; ++ while ( i < AUTOHINT_CONTRAST_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( CONTRAST_Rules[i].family, family ) == 0 ) ) ++ { ++ known_stem_values->contrast = 0.0; ++ ++ if ( ppem == CONTRAST_Rules[i].ppem[0] || ++ CONTRAST_Rules[i].ppem[0] == 0 ) ++ { ++ known_stem_values->contrast = CONTRAST_Rules[i].ppem[1]; ++ i = AUTOHINT_CONTRAST_RULES_SIZE; ++ } ++ } ++ i++; ++ } ++ ++ for ( i = 0; i <= STEM_SPACING_RULES_SIZE; i++ ) ++ { ++ if ( family && ++ ( strcasecmp( STEM_SPACING_Rules[i].family, family ) == 0 ) ) ++ { ++ j = 0; ++ known_stem_values->stem_spacing = 2; /* default */ ++ ++ while (j < 4) ++ { ++ if ( ppem < STEM_SPACING_Rules[i].ppem[j] ) ++ { ++ known_stem_values->stem_spacing = j; ++ j = 5; ++ } ++ j++; ++ } ++ } ++ } ++ ++ ++ for ( i = 0; i <= STEM_START_RULES_SIZE; i++ ) ++ { ++ if ( family && ++ ( strcasecmp( STEM_START_Rules[i].family, family ) == 0 ) ) ++ { ++ j = 0; ++ known_stem_values->stem_start = 1; /* default */ ++ ++ while (j < 4) ++ { ++ if ( ppem < STEM_START_Rules[i].ppem[j] ) ++ { ++ known_stem_values->stem_start = j; ++ j = 5; ++ } ++ j++; ++ } ++ } ++ } ++#endif ++ } ++ ++ ++ FT_LOCAL_DEF( FT_Int ) ++ get_contrast ( FT_String* family, ++ int ppem ) ++ { ++ FT_Int i; ++ ++ ++ if ( verbose ) ++ printf( "%s ", family ); ++ ++ i = 0; ++ while ( i < AUTOHINT_CONTRAST_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( CONTRAST_Rules[i].family, family ) == 0 ) ) ++ { ++ if ( ppem == CONTRAST_Rules[i].ppem[0] || ++ CONTRAST_Rules[i].ppem[0] == 0 ) ++ return CONTRAST_Rules[i].ppem[1]; ++ } ++ i++; ++ } ++ return 0; ++ } ++ ++ ++ FT_LOCAL_DEF( FT_Int ) ++ get_brightness ( FT_String* family, ++ int ppem ) ++ { ++ FT_Int i; ++ ++ ++ if ( verbose ) ++ printf("%s ", family); ++ ++ i = 0; ++ while ( i < AUTOHINT_BRIGHTNESS_RULES_SIZE ) ++ { ++ if ( family && ++ ( strcasecmp( BRIGHTNESS_Rules[i].family, family ) == 0 ) ) ++ { ++ if ( ppem == BRIGHTNESS_Rules[i].ppem[0] || ++ BRIGHTNESS_Rules[i].ppem[0] == 0 ) ++ return BRIGHTNESS_Rules[i].ppem[1]; ++ } ++ i++; ++ } ++ return 0; ++ } ++ ++ ++ /* Stem alignment for bitmaps; A hack with very nice results */ ++ /* Ideally this could be implemented on the outline, prior to ++ * rasterization. Possible future enhancement is to use the ++ * warper code to achieve this */ ++ static void ++ _lcd_stem_align ( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_GlyphSlot slot, ++ FT_Long* translate_value, ++ float* scale_value, ++ FT_UInt alignment_strength, ++ FT_UInt fitting_strength, ++ float* embolden_value ++ ) ++ { ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ ++ Stem_Segment* segments; ++ Stem_Segment* leftmost_segment; ++ Stem_Segment* rightmost_segment; ++ Stem_Segment* leftmost_segment_not_extrema; ++ Stem_Segment* rightmost_segment_not_extrema; ++ Stem* stems; ++ Stem* possible_stems; ++ Stem* leftmost_stem; ++ Stem* rightmost_stem; ++ Stem_Data* known_stem_values; ++ Stem_Center* centers; ++ FT_Long leftmost_point = width * 256; ++ FT_Long rightmost_point = 0; ++ FT_Long leftmost_point_not_extrema = width * 256; ++ FT_Long rightmost_point_not_extrema = 0; ++ FT_Long num_segments = 0; ++ FT_Long num_centers = 0; ++ FT_Long stem_centers[width * 256]; ++ FT_UInt h; ++ FT_ULong valid_stems = 0, valid_possible_stems = 0; ++ FT_Long center, stem_matches, stem_matches_ledge; ++ FT_Long stem_matches_redge, next_center, last_matching_center; ++ FT_Long last_matching_ledge, last_matching_redge, this_center; ++ FT_Int max_strength; ++ FT_Byte* line = bitmap->buffer; ++ FT_UInt current_value = 0; ++ FT_UInt xx; ++ FT_Long linearHoriAdvance = slot->linearHoriAdvance >> 10; ++ ++ FT_Int m_horiBearingX = slot->metrics.horiBearingX; ++ FT_Int m_horiAdvance = slot->metrics.horiAdvance; ++ FT_Int m_width = slot->metrics.width; ++ FT_Pos one_pixel = 768; ++ FT_Pos one_third_pixel = 256; ++ FT_Int columns_per_pixel = 3; ++ /*FT_Int extra_columns = 6;*/ ++ ++ /* on / off flags for testing different features */ ++ FT_Bool strategy_translate_using_closest_stem = TRUE; ++ FT_Bool strategy_scale_to_closest_centers = FALSE; ++ FT_Bool strategy_scale_to_closest_centers_up_only = FALSE; ++ FT_Bool strategy_always_use_distance_ceiling = FALSE; ++ FT_Bool strategy_auto_change_center_offset = TRUE; ++ FT_Bool strategy_use_m_control = FALSE; ++ FT_Bool strategy_correct_out_of_bounds_outlines = FALSE; ++ FT_Bool strategy_also_use_edge_detection_for_stems = FALSE; ++ FT_Bool strategy_use_strengths = TRUE; ++ FT_Bool strategy_synthesize_stems = FALSE; ++ FT_Bool strategy_bearing_correction = TRUE; ++ FT_Bool strategy_use_d_correction = TRUE; ++ FT_Bool strategy_fit_to_width = FALSE; ++ /*FT_Bool strategy_center_glyph = FALSE;*/ ++ ++ FT_Bool has_serifs = FALSE; ++ FT_Bool autohinted = FALSE; ++ ++ const FT_Int MIN_PPEM = 7; ++ /*const FT_Int MAX_PPEM = 100;*/ ++ const FT_Int MAX_STEMS = 3; ++ FT_Int ppem = 0; ++ ++ FT_Bool checked_use_known_settings_on_selected_fonts_env = FALSE; ++ FT_Bool use_known_settings_on_selected_fonts = FALSE; ++ ++ FT_Pos cur_width = infinality_cur_width; ++ ++ ++ if ( cur_width ) ++ { ++ autohinted = TRUE; ++ } ++ ++ /* reset to default */ ++ *scale_value = 1.0; ++ ++ if ( !checked_use_known_settings_on_selected_fonts_env ) ++ { ++ char *use_known_settings_on_selected_fonts_env = ++ getenv( "INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS" ); ++ if ( use_known_settings_on_selected_fonts_env != NULL ) ++ { ++ if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "default" ) != 0 ) ++ { ++ if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "true") == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ else if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "1") == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ else if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "on") == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ else if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "yes") == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ } ++ } ++ checked_use_known_settings_on_selected_fonts_env = TRUE; ++ } ++ ++ ++ /* Simply return in odd cases where these don't seem to be set */ ++ /* Flash and some pdf viewers will crash otherwise */ ++ if ( !slot->face || ++ !slot->face->size || ++ !slot->face->size->metrics.x_ppem ) ++ return; ++ ++ if ( slot->face->size->metrics.x_ppem > MAX_PPEM ) ++ return; ++ ++ if ( slot->face->size->metrics.x_ppem < MIN_PPEM ) ++ return; ++ ++ if ( !FT_IS_SCALABLE( slot->face ) ) ++ return; ++ ++ ppem = slot->face->size->metrics.x_ppem; ++ ++ ++ /* only perform alignment on styles we know, that aren't bold or italic */ ++ /* perhaps detection could be added on those that are not set? */ ++ /* Require certain ppems for narrow and light fonts */ ++ if( slot->face->style_name ) ++ { ++ if ( strcasestr( slot->face->style_name, "Italic" ) || ++ strcasestr( slot->face->style_name, "Oblique" ) || ++ strcasestr( slot->face->style_name, "Script" ) || ++ strcasestr( slot->face->style_name, "Handwriting" ) || ++ strcasestr( slot->face->style_name, "Bold" ) || ++ strcasestr( slot->face->style_name, "Black" ) || ++ ( ( strcasestr( slot->face->style_name, "Extra Thin" ) || ++ strcasestr( slot->face->style_name, "Extra Light" ) ) && ++ ppem < 10 ) || ++ ( strcasestr( slot->face->style_name, "Thin" ) ++ && ppem < 10 ) || ++ ( strcasestr( slot->face->style_name, "Light" ) ++ && ppem < 10 ) || ++ ( strcasestr( slot->face->style_name, "Narrow" ) ++ && ppem < 15 ) || ++ ( strcasestr( slot->face->style_name, "Condensed" ) ++ && ppem < 20 ) ) ++ return; ++ } ++ ++ if( slot->face->family_name ) ++ { ++ if ( strcasestr( slot->face->family_name, "Italic" ) || ++ strcasestr( slot->face->family_name, "Oblique" ) || ++ strcasestr( slot->face->family_name, "Script" ) || ++ strcasestr( slot->face->family_name, "Handwriting" ) || ++ strcasestr( slot->face->family_name, "Bold" ) || ++ strcasestr( slot->face->family_name, "Black" ) || ++ ( ( strcasestr( slot->face->family_name, "Extra Thin" ) || ++ strcasestr( slot->face->family_name, "Extra Light" ) ) && ++ ppem < 10 ) || ++ ( strcasestr( slot->face->family_name, "Thin" ) ++ && ppem < 10 ) || ++ ( strcasestr( slot->face->family_name, "Light" ) ++ && ppem < 10 ) || ++ ( strcasestr( slot->face->family_name, "Narrow" ) ++ && ppem < 15 ) || ++ ( strcasestr( slot->face->family_name, "Condensed" ) ++ && ppem < 20 ) ) ++ return; ++ } ++ else if ( slot->face->style_flags ) ++ { ++ if ( slot->face->style_flags & FT_STYLE_FLAG_ITALIC || ++ slot->face->style_flags & FT_STYLE_FLAG_BOLD || ++ FT_IS_TRICKY( slot->face ) ) ++ return; ++ } ++ else return; ++ ++ if ( slot->face->family_name ) ++ { ++ if ( strcasestr(slot->face->family_name, "Courier" ) || ++ strcasestr(slot->face->family_name, "Serif" ) || ++ strcasestr(slot->face->family_name, "Times" ) ) ++ has_serifs = TRUE; ++ } ++ ++ if ( mode != FT_RENDER_MODE_LCD ) ++ { ++ columns_per_pixel = 1; ++ one_pixel = 256; ++ one_third_pixel = 85; ++ /*extra_columns = 0;*/ ++ /* until this can be figured out just return */ ++ /* There are issues with missing glyphs */ ++ return; ++ } ++ /* only look at top 3 for now */ ++ known_stem_values ++ = (Stem_Data*) malloc ( columns_per_pixel * sizeof ( Stem_Data ) ); ++ known_stem_values->stem_spacing = -1; ++ known_stem_values->stem_width = -1; ++ known_stem_values->stem_start = -1; ++ known_stem_values->stem_scaling = -1; ++ known_stem_values->stem_translating_only = -1024; ++ known_stem_values->stem_translating = 0; ++ known_stem_values->brightness = 0; ++ known_stem_values->contrast = 0; ++ known_stem_values->use_100 = FALSE; ++ known_stem_values->m = -1; ++ known_stem_values->synth_stems = FALSE; ++ known_stem_values->bearing_correction = TRUE; ++ ++ if ( use_known_settings_on_selected_fonts ) ++ { ++ sa_fill_known_stem_values ( slot->face->family_name, ++ ppem, slot->face->style_name, ++ valid_stems, known_stem_values ); ++ if ( verbose ) ++ printf ( "width:%d,spacing:%d,start:%d,scaling:%d,translate:%d ", ++ known_stem_values->stem_width, ++ known_stem_values->stem_spacing, ++ known_stem_values->stem_start, ++ known_stem_values->stem_scaling, ++ known_stem_values->stem_translating_only ); ++ } ++ ++ /* translate value may be set for < 10 */ ++ if ( use_known_settings_on_selected_fonts && ++ known_stem_values->stem_translating_only > -1024 ) ++ { ++ *translate_value = known_stem_values->stem_translating_only; ++ free ( known_stem_values ); ++ return; ++ } ++ ++ if ( use_known_settings_on_selected_fonts && ++ known_stem_values->bearing_correction == FALSE ) ++ strategy_bearing_correction = FALSE; ++ ++ ++ if ( known_stem_values->use_100 || ++ known_stem_values->m >= 0 ) ++ { ++ alignment_strength = fitting_strength = 100; ++ strategy_use_m_control = TRUE; ++ } ++ ++ if ( known_stem_values->edge_detection ) ++ strategy_also_use_edge_detection_for_stems = TRUE; ++ ++ if ( ppem < 9 ) ++ return; ++ if ( ppem > 20 ) ++ strategy_use_m_control = TRUE; ++ ++ /* Allocate */ ++ segments ++ = (Stem_Segment*) malloc( (1) * sizeof ( Stem_Segment ) ); ++ leftmost_segment ++ = (Stem_Segment*) malloc( sizeof ( Stem_Segment ) ); ++ leftmost_segment_not_extrema ++ = (Stem_Segment*) malloc( sizeof ( Stem_Segment ) ); ++ rightmost_segment ++ = (Stem_Segment*) malloc( sizeof ( Stem_Segment ) ); ++ rightmost_segment_not_extrema ++ = (Stem_Segment*) malloc( sizeof ( Stem_Segment ) ); ++ ++ stems = (Stem*) malloc ( MAX_STEMS * sizeof ( Stem ) ); ++ possible_stems = (Stem*) malloc ( MAX_STEMS * sizeof ( Stem ) ); ++ leftmost_stem = (Stem*) malloc ( sizeof (Stem)); ++ rightmost_stem = (Stem*) malloc ( sizeof(Stem)); ++ centers = (Stem_Center*) malloc ( (1) * sizeof ( Stem_Center ) ); ++ ++ if ( verbose ) ++ printf("\n"); ++ ++ /* Initialize */ ++ for ( xx = 0; xx < width * 256; xx += 1 ) ++ stem_centers[xx] = 0; ++ ++ for ( xx = 0; xx < num_segments; xx += 1 ) ++ { ++ segments[xx].x1 = 0; ++ segments[xx].x2 = 0; ++ segments[xx].y = 0; ++ } ++ ++ rightmost_segment->x1 = 0; ++ rightmost_segment->x2 = 0; ++ rightmost_segment->y = 0; ++ leftmost_segment->x1 = 99999999; ++ leftmost_segment->x2 = 0; ++ leftmost_segment->y = 0; ++ ++ rightmost_segment_not_extrema->x1 = 0; ++ rightmost_segment_not_extrema->x2 = 0; ++ rightmost_segment_not_extrema->y = 0; ++ leftmost_segment_not_extrema->x1 = 99999999; ++ leftmost_segment_not_extrema->x2 = 0; ++ leftmost_segment_not_extrema->y = 0; ++ ++ /* Locate stem centers for later processing */ ++ for ( h = (FT_UInt)bitmap->rows; h > 0; h--, line += bitmap->pitch ) ++ { ++ current_value = 0; ++ /* Calculate various sums and stem widths of glyph */ ++ for ( xx = 0; xx < width; xx += 1 ) ++ { ++ /* Reallocate */ ++ segments = (Stem_Segment*) realloc ++ ( segments, ( num_segments + 1 ) * sizeof ( Stem_Segment ) ); ++ ++ /* if line is white, and now has color, it's the start of a stem */ ++ if ( current_value == 0 && line[xx] > 0 ) ++ { ++ /* start of stem */ ++ segments[num_segments].x1 = 256 * xx + ( 255 - line[xx] ); ++ segments[num_segments].y = h; ++ } ++ ++ /* otherwise, if it's currently black and the new value is 0, ++ it's the end of a stem */ ++ else if ( ( current_value > 0 && line[xx] == 0 ) || ++ ( current_value > 0 && xx == width - 1 ) ) ++ { ++ FT_Long stem_center_x; ++ segments[num_segments].x2 = 256 * ( xx - 1 ) + line[xx-1]; ++ ++ if ( xx == width - 1 ) ++ segments[num_segments].x2 += line[xx]; ++ ++ /*stem center is average of start and end of stem */ ++ stem_center_x = ( segments[num_segments].x2 ++ + segments[num_segments].x1 ) / 2; ++ ++ /* Reallocate */ ++ centers = (Stem_Center*) realloc ++ ( centers, ( num_centers + 1 ) * sizeof ( Stem_Center ) ); ++ centers[num_centers].x = stem_center_x; ++ centers[num_centers].y = h; ++ centers[num_centers].x1 = segments[num_segments].x1; ++ centers[num_centers].x2 = segments[num_segments].x2; ++ ++ num_centers++; ++ ++ stem_centers[stem_center_x] += 1; ++ ++ /* Find left and rightmost points for later calculations */ ++ /* OR - Favor ones that aren't on the top or bottom if */ ++ /* possible to prevent v and w from getting caught later */ ++ if ( segments[num_segments].x1 < leftmost_segment->x1 || ++ ( segments[num_segments].y > 1 && ++ segments[num_segments].y < height && ++ segments[num_segments].x1 == leftmost_segment->x1 ) ) ++ { ++ leftmost_segment->x1 = segments[num_segments].x1; ++ leftmost_segment->x2 = segments[num_segments].x2; ++ leftmost_segment->y = h; ++ } ++ if ( segments[num_segments].x2 > rightmost_segment->x2 || ++ ( segments[num_segments].y > 1 && ++ segments[num_segments].y < height && ++ segments[num_segments].x1 == rightmost_segment->x1 ) ) ++ { ++ rightmost_segment->x1 = segments[num_segments].x1; ++ rightmost_segment->x2 = segments[num_segments].x2; ++ rightmost_segment->y = h; ++ } ++ ++ if ( segments[num_segments].x1 ++ < leftmost_segment_not_extrema->x1 || ++ ( segments[num_segments].y > 1 && ++ segments[num_segments].y < height && ++ segments[num_segments].x1 ++ == leftmost_segment_not_extrema->x1 && ++ h < (FT_UInt)bitmap->rows && h > 0 ) ) ++ { ++ leftmost_segment_not_extrema->x1 = segments[num_segments].x1; ++ leftmost_segment_not_extrema->x2 = segments[num_segments].x2; ++ leftmost_segment_not_extrema->y = h; ++ } ++ if ( segments[num_segments].x2 ++ > rightmost_segment_not_extrema->x2 || ++ ( segments[num_segments].y > 1 && ++ segments[num_segments].y < height && ++ segments[num_segments].x1 ++ == rightmost_segment_not_extrema->x1 && ++ h < (FT_UInt)bitmap->rows && h > 0 ) ) ++ { ++ rightmost_segment_not_extrema->x1 = segments[num_segments].x1; ++ rightmost_segment_not_extrema->x2 = segments[num_segments].x2; ++ rightmost_segment_not_extrema->y = h; ++ } ++ ++ if ( segments[num_segments].x1 < leftmost_point ) ++ leftmost_point = segments[num_segments].x1; ++ ++ if ( segments[num_segments].x2 > rightmost_point ) ++ rightmost_point = segments[num_segments].x2; ++ ++ if ( segments[num_segments].x1 < leftmost_point_not_extrema && ++ h < (FT_UInt)bitmap->rows && h > 0 ) ++ leftmost_point_not_extrema = segments[num_segments].x1; ++ ++ if ( segments[num_segments].x2 > rightmost_point_not_extrema && ++ h < (FT_UInt)bitmap->rows && h > 0 ) ++ rightmost_point_not_extrema = segments[num_segments].x2; ++ ++ num_segments++; ++ } ++ /* else - other conditions - need some error checking here */ ++ current_value = line[xx]; ++ } ++ } ++ ++ /* initialize */ ++ for ( xx = 0; xx < MAX_STEMS; xx +=1 ) ++ { ++ stems[xx].center = 0; ++ stems[xx].count = 0; ++ stems[xx].width = 0; ++ stems[xx].height = 0; ++ possible_stems[xx].center = 0; ++ possible_stems[xx].count = 0; ++ possible_stems[xx].width = 0; ++ possible_stems[xx].height = 0; ++ } ++ ++ valid_stems = 0; ++ valid_possible_stems = 0; ++ ++ /* Determine which centers belong to stems */ ++ center = 0; ++ ++ while ( center < num_centers ) ++ { ++ /* slope at within which to consider a point part of a stem */ ++ /*const FT_UInt slope = 1; ++ const FT_UInt topslope = (256 * 3) / 10; */ ++ ++ /* 10 to 20 with 4 matches seems good, */ ++ /* but 1 or 2 with 3 stems needs to somehow get included */ ++ FT_Int deviation1 = 5; ++ FT_Int deviation2=-1, requirement1 = 4, stem_match_requirement = 3; ++ FT_Int best_height = 0, center_difference_in_height; ++ FT_Int center_difference_in_width, valid_center_average; ++ FT_Int smallest_width_ledge, smallest_width_redge; ++ FT_Int x1_difference_in_width, x2_difference_in_width; ++ FT_Bool large_gap_found = FALSE, no_gap_found = FALSE; ++ FT_Bool large_gap_found_ledge = FALSE, no_gap_found_ledge = FALSE; ++ FT_Bool large_gap_found_redge = FALSE, no_gap_found_redge = FALSE; ++ FT_Bool stem_detected = FALSE; ++ FT_Int set_width_to, set_center_to; ++ ++ /* seems to not do damage */ ++ /* May not be effective */ ++ requirement1 = height / 4; ++ if ( requirement1 < 5 ) ++ requirement1 = 5; ++ deviation1 = 20; ++ deviation2 = 20; ++ ++ if ( columns_per_pixel == 1 ) ++ deviation1 = deviation2 = 10; ++ ++ if ( (FT_Int)bitmap->rows <= 6 ) ++ deviation1 = 25; ++ ++ if ( (FT_Int)bitmap->rows <= 6 ) ++ deviation2 = 25; ++ ++ if ( columns_per_pixel == 1 && ++ (FT_Int)bitmap->rows <= 6 ) ++ deviation1 = deviation2 = 12; ++ ++ valid_center_average = 0; ++ ++ large_gap_found = large_gap_found_ledge = large_gap_found_redge = FALSE; ++ no_gap_found = no_gap_found_ledge = no_gap_found_redge = FALSE; ++ stem_detected = FALSE; ++ ++ if ( ppem < 11 ) ++ requirement1 = 4; ++ ++ if ( ppem > 18 ) ++ { ++ stem_match_requirement = height / 4; ++ if ( stem_match_requirement < 3 ) ++ stem_match_requirement = 3; ++ } ++ ++ smallest_width_ledge = smallest_width_redge = width * 256; ++ stem_matches = 0; ++ stem_matches_ledge = 0; ++ stem_matches_redge = 0; ++ last_matching_center = -1; ++ last_matching_ledge = -1; ++ last_matching_redge = -1; ++ ++ /* set currently looked at center to center value */ ++ this_center = center; ++ next_center = 0; ++ ++ /* For each center, compare with all other centers to see if others */ ++ /* match the properties of this one */ ++ while ( next_center < num_centers ) ++ { ++ ++ /* calculate differences */ ++ center_difference_in_width = abs ( centers[this_center].x ++ - centers[next_center].x ); ++ center_difference_in_height = abs ( centers[this_center].y ++ - centers[next_center].y ); ++ x1_difference_in_width = abs ( centers[this_center].x1 ++ - centers[next_center].x1 ); ++ x2_difference_in_width = abs ( centers[this_center].x2 ++ - centers[next_center].x2 ); ++ ++ ++ /* property - stem center points that align */ ++ /* if the center is within range, the center is less than */ ++ /* 1/2 the height away, and at least one edge is also within range */ ++ if ( center_difference_in_width ++ < center_difference_in_height * deviation1 && ++ center_difference_in_height ++ <= (FT_Int)bitmap->rows / 2 && ++ /* prevents w from getting caught ---- but also kills m */ ++ ( x1_difference_in_width ++ < center_difference_in_height * deviation2 || ++ x2_difference_in_width ++ < center_difference_in_height * deviation2 ) ) ++ { ++ stem_matches += 1; ++ valid_center_average += centers[next_center].x; ++ ++ /* try to find where the matching centers are far apart */ ++ if ( last_matching_center >= 0 && ++ abs( centers[last_matching_center].y ++ - centers[next_center].y ) >= (FT_Int)bitmap->rows / 2 ) ++ large_gap_found = TRUE; ++ ++ /* try to find where matching centers are next to each other */ ++ if ( last_matching_center >= 0 && ++ abs( centers[last_matching_center].y ++ - centers[next_center].y ) == 1 ) ++ no_gap_found = TRUE; ++ ++ last_matching_center = next_center; ++ } ++ ++ if ( strategy_also_use_edge_detection_for_stems ) ++ { ++ /* property - stem left edge points that align */ ++ /* if the center is within range, */ ++ /* the center is less than 1/2 the height away */ ++ if ( x1_difference_in_width ++ < center_difference_in_height * deviation1 && ++ center_difference_in_height <= (FT_Int)bitmap->rows / 2 ) ++ { ++ stem_matches_ledge += 1; ++ /* may not need for edges */ ++ /*valid_center_average += centers[next_center].x; */ ++ ++ if ( centers[next_center].x2 - centers[next_center].x1 ++ < smallest_width_ledge ) ++ smallest_width_ledge = centers[next_center].x2 ++ - centers[next_center].x1; ++ ++ /* try to find where the matching centers are far apart */ ++ if ( last_matching_ledge >= 0 && ++ abs( centers[last_matching_ledge].y ++ - centers[next_center].y) ++ >= (FT_Int)bitmap->rows / 2 ) ++ large_gap_found_ledge = TRUE; ++ ++ /* try to find where matching centers are next to each other */ ++ if ( last_matching_ledge >= 0 && ++ abs( centers[last_matching_ledge].y ++ - centers[next_center].y ) == 1 ) ++ no_gap_found_ledge = TRUE; ++ last_matching_ledge = next_center; ++ } ++ } ++ ++ if ( strategy_also_use_edge_detection_for_stems ) ++ { ++ /* property - stem right edge points that align */ ++ /* if the center is within range, the center is less than 1/2 */ ++ /* the height away */ ++ if ( x2_difference_in_width ++ < center_difference_in_height * deviation1 && ++ center_difference_in_height ++ <= (FT_Int)bitmap->rows / 2 ) ++ { ++ stem_matches_redge += 1; ++ /* may not need for edges */ ++ /*valid_center_average += centers[next_center].x; */ ++ ++ if ( centers[next_center].x2 - centers[next_center].x1 ++ < smallest_width_redge ) ++ smallest_width_redge = centers[next_center].x2 ++ - centers[next_center].x1; ++ ++ /* try to find where the matching centers are far apart */ ++ if ( last_matching_redge >= 0 && ++ abs( centers[last_matching_redge].y ++ - centers[next_center].y ) >= (FT_Int)bitmap->rows / 2 ) ++ large_gap_found_redge = TRUE; ++ ++ /* try to find where matching centers are next to each other */ ++ if ( last_matching_redge >= 0 && ++ abs( centers[last_matching_redge].y ++ - centers[next_center].y ) == 1 ) ++ no_gap_found_redge = TRUE; ++ ++ last_matching_redge = next_center; ++ } ++ } ++ ++ next_center++; ++ } ++ ++ if ( stem_matches > 0 ) ++ valid_center_average /= stem_matches; ++ ++ best_height = stem_matches; ++ ++ ++ if ( ( stem_matches >= stem_match_requirement || ++ ( ( (FT_Int)bitmap->rows <= 6 || ppem < 11 ) && ++ stem_matches >= 2 && ++ abs ( valid_center_average ++ - centers[center].x) < deviation1 /2 ) || ++ /* try to catch tightly aligned stuff where the matching centers */ ++ /* are next to each other only */ ++ ( stem_matches == 2 && ++ abs( valid_center_average ++ - centers[center].x) <= deviation1 /2 && ++ no_gap_found && ++ ppem < 18 ) ) && ++ /* catches things like times 16 u but gets a lot of w's too */ ++ /* stem width is less than 1/3 of the bitmap width, */ ++ /* or bitmap_width is small */ ++ ( centers[center].x2 - centers[center].x1 ++ < (m_horiAdvance * 12) / 2 || ++ m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) ) ++ { ++ stem_detected = TRUE; ++ set_width_to = centers[center].x2 - centers[center].x1; ++ best_height = stem_matches; ++ set_center_to = centers[center].x; ++ } ++ ++ /* see if edges found anything */ ++ if ( strategy_also_use_edge_detection_for_stems && !stem_detected ) ++ { ++ /* Require no gap for edges */ ++ /* stem width less than 1/3 bitmap width, or bitmap_width is small */ ++ /* The stem occurs on the left side of glyph only */ ++ if ( ( stem_matches_ledge >= stem_match_requirement && ++ no_gap_found_ledge ) && ++ ( centers[center].x2 - centers[center].x1 ++ < ( m_horiAdvance * 12 ) / 2 || ++ m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) && ++ centers[center].x < ( m_horiAdvance * 12 ) / 2 ) ++ { ++ stem_detected = TRUE; ++ set_width_to = smallest_width_ledge; ++ best_height = stem_matches_ledge; ++ set_center_to = centers[center].x1 + set_width_to / 2; ++ stem_matches = stem_matches_ledge; ++ } ++ /* Require no gap for edges */ ++ /* stem width is less than 1/3 bitmap width, or bitmap_width is small */ ++ /* The stem occurs on the right side of glyph only */ ++ else if ( ( stem_matches_redge >= stem_match_requirement && ++ no_gap_found_redge ) && ++ ( centers[center].x2 - centers[center].x1 ++ < ( m_horiAdvance * 12 ) / 2 || ++ m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) && ++ centers[center].x > (m_horiAdvance * 12) / 2 ) ++ { ++ stem_detected = TRUE; ++ set_width_to = smallest_width_redge; ++ best_height = stem_matches_redge; ++ set_center_to = centers[center].x2 - set_width_to / 2; ++ stem_matches = stem_matches_redge; ++ } ++ } ++ ++ ++ /*store and/or replace highest occurrences with 3 or more centers */ ++ /* because this matched, it will become the top dog regardless */ ++ if ( stem_detected ) ++ if ( stem_matches > possible_stems[0].height ) ++ { ++ /* if this is the first stem just go ahead */ ++ if ( valid_possible_stems == 0 ) ++ { ++ valid_possible_stems = 1; ++ possible_stems[0].center = set_center_to; ++ possible_stems[0].count = stem_matches; ++ possible_stems[0].width = set_width_to; ++ possible_stems[0].height = stem_matches; ++ } ++ ++ /* otherwise, if there is already a stem */ ++ else if ( valid_possible_stems == 1 ) ++ { ++ /* if stem is within range of existing one, replace existing one */ ++ ++ /* if the stem isn't within the range of this one swap it with */ ++ /* next one first */ ++ if ( abs ( set_center_to - possible_stems[0].center ) ++ >= one_pixel * 2 ) ++ { ++ swap_stem ( &possible_stems[0], &possible_stems[1] ); ++ valid_possible_stems = 2; ++ } ++ possible_stems[0].center = set_center_to; ++ possible_stems[0].count = stem_matches; ++ possible_stems[0].width = set_width_to; ++ possible_stems[0].height = stem_matches; ++ } ++ ++ /* otherwise if there are already 2 stems */ ++ else if ( valid_possible_stems >= 2 ) ++ { ++ /* if the stem is within the range of existing one, replace */ ++ /* existing one */ ++ if ( abs ( set_center_to - possible_stems[0].center ) ++ <= one_pixel * 2 ) ++ { ++ possible_stems[0].center = set_center_to; ++ possible_stems[0].count = stem_matches; ++ possible_stems[0].width = set_width_to; ++ possible_stems[0].height = stem_matches; ++ } ++ /* if the stem isn't within the range of this one */ ++ else ++ { ++ /* see if within range of next one and swap if so and proceed */ ++ /* overwriting it */ ++ if ( abs ( set_center_to - possible_stems[1].center ) ++ <= one_pixel * 2 ) ++ swap_stem ( &possible_stems[0], &possible_stems[1] ); ++ ++ /* otherwise see if in range of third one */ ++ else if ( abs ( set_center_to - possible_stems[2].center ) ++ <= one_pixel * 2 ) ++ swap_stem ( &possible_stems[0], &possible_stems[2] ); ++ ++ /* otherwise this is the new top dog, so demote everything */ ++ else ++ { ++ swap_stem ( &possible_stems[1], &possible_stems[2] ); ++ swap_stem ( &possible_stems[0], &possible_stems[1] ); ++ valid_possible_stems += 1; ++ } ++ possible_stems[0].center = set_center_to; ++ possible_stems[0].count = stem_matches; ++ possible_stems[0].width = set_width_to; ++ possible_stems[0].height = stem_matches; ++ } ++ } ++ } ++ ++ else if ( stem_matches > possible_stems[1].height && ++ set_center_to != 0 ) ++ { ++ ++ /* make sure it doesn't match the first stem */ ++ if ( abs ( set_center_to - possible_stems[0].center ) >= one_pixel * 2 ) ++ { ++ ++ /* if this is the second stem */ ++ if ( valid_possible_stems == 1 ) ++ valid_possible_stems = 2; ++ ++ /* otherwise if there is already a stem here */ ++ else if ( valid_possible_stems >= 2 ) ++ { ++ /* if it doesn't match the second stem, proceed to swap out */ ++ /* with the third. if it does, replace it */ ++ if ( abs ( set_center_to - possible_stems[1].center ) ++ >= one_pixel * 2 ) ++ { ++ swap_stem ( &possible_stems[1], &possible_stems[2] ); ++ valid_possible_stems +=1; ++ } ++ } ++ possible_stems[1].center = set_center_to; ++ possible_stems[1].count = stem_matches; ++ possible_stems[1].width = set_width_to; ++ possible_stems[1].height = stem_matches; ++ } ++ } ++ ++ else if ( stem_matches > possible_stems[2].height && ++ set_center_to != 0 ) ++ { ++ /* if it doesn't match the first or second one */ ++ if ( abs( set_center_to - possible_stems[0].center) >= one_pixel * 2 && ++ abs( set_center_to - possible_stems[1].center) >= one_pixel * 2 ) ++ { ++ if ( valid_possible_stems == 2 ) ++ valid_possible_stems += 1; ++ ++ possible_stems[2].center = set_center_to; ++ possible_stems[2].count = stem_matches; ++ possible_stems[2].width = set_width_to; ++ possible_stems[1].height = stem_matches; ++ } ++ } ++ ++ if ( valid_possible_stems > 3 ) ++ valid_possible_stems = 3; ++ ++ center++; ++ } ++ ++ /* promote to stem */ ++ if ( valid_possible_stems > 0 ) ++ { ++ stems[0].center = possible_stems[0].center; ++ stems[0].count = possible_stems[0].count; ++ stems[0].width = possible_stems[0].width; ++ stems[0].height = possible_stems[0].height; ++ stems[0].generated = FALSE; ++ valid_stems++; ++ } ++ ++ if ( valid_stems == 1 && ++ valid_possible_stems > 1 ) ++ { ++ stems[1].center = possible_stems[1].center; ++ stems[1].count = possible_stems[1].count; ++ stems[1].width = possible_stems[1].width; ++ stems[1].height = possible_stems[1].height; ++ stems[1].generated = FALSE; ++ valid_stems++; ++ } ++ ++ if ( valid_stems == 2 && ++ valid_possible_stems > 2 && ++ possible_stems[2].center != 0 ) ++ { ++ stems[2].center = possible_stems[2].center; ++ stems[2].count = possible_stems[2].count; ++ stems[2].width = possible_stems[2].width; ++ stems[2].height = possible_stems[2].height; ++ stems[2].generated = FALSE; ++ valid_stems++; ++ } ++ ++ /* sort stems in x direction */ ++ if ( valid_stems == 3 ) ++ { ++ if ( stems[0].center > stems[1].center ) ++ swap_stem ( &stems[0], &stems[1] ); ++ ++ if ( stems[0].center > stems[2].center ) ++ swap_stem ( &stems[1], &stems[2] ); ++ ++ if ( stems[1].center > stems[2].center ) ++ swap_stem ( &stems[1], &stems[2] ); ++ ++ if ( stems[0].center > stems[1].center ) ++ swap_stem ( &stems[0], &stems[1] ); ++ ++ /* only look at first and last stem for now */ ++ swap_stem ( &stems[1], &stems[2] ); ++ } ++ ++ /* synthesize stems - Works, but needs work */ ++ if ( ( strategy_synthesize_stems || ++ known_stem_values->synth_stems ) && ++ valid_stems == 0 && ++ ppem > 10 ) ++ { ++ /* if the leftmost segment's leftmost point is the same as the glyph's */ ++ /* leftmost point, and it is of reasonable width, and is not on the */ ++ /* top or bottom of the bitmap */ ++ if ( leftmost_segment_not_extrema->x1 ++ == leftmost_point_not_extrema && ++ abs ( leftmost_segment_not_extrema->x2 ++ - leftmost_segment_not_extrema->x1 ) ++ < ( rightmost_point_not_extrema ++ - leftmost_point_not_extrema ) / 3 && ++ leftmost_segment_not_extrema->y < height && ++ leftmost_segment_not_extrema->y > 1 ) ++ { ++ stems[valid_stems].center = ( leftmost_segment_not_extrema->x2 ++ + leftmost_segment_not_extrema->x1 ) / 2; ++ stems[valid_stems].width = leftmost_segment_not_extrema->x2 ++ - leftmost_segment_not_extrema->x1; ++ stems[valid_stems].generated = TRUE; ++ valid_stems += 1; ++ } ++ ++ ++ if ( rightmost_segment_not_extrema->x2 ++ == rightmost_point_not_extrema && ++ abs ( rightmost_segment_not_extrema->x2 ++ - rightmost_segment_not_extrema->x1 ) ++ < ( rightmost_point_not_extrema ++ - leftmost_point_not_extrema ) / 3 && ++ rightmost_segment_not_extrema->y < height && ++ rightmost_segment_not_extrema->y > 1 ) ++ { ++ stems[valid_stems].center = ( rightmost_segment_not_extrema->x2 ++ + rightmost_segment_not_extrema->x1 ) / 2; ++ stems[valid_stems].width = rightmost_segment_not_extrema->x2 ++ - rightmost_segment_not_extrema->x1; ++ stems[valid_stems].generated = TRUE; ++ valid_stems += 1; ++ } ++ ++ } ++ ++ /* sort stems in x direction */ ++ if ( valid_stems > 1 && stems[0].center > stems[1].center ) ++ swap_stem ( &stems[0], &stems[1] ); ++ ++ if ( valid_stems == 0 && known_stem_values->stem_translating != 0 ) ++ { ++ *translate_value += known_stem_values->stem_translating; ++ ++ if ( strategy_use_strengths ) ++ { ++ /* consider 1/2 pixel the max when strength is at 100%, ++ unless translate is already greater than that */ ++ FT_Int strength_cutoff = 32; ++ ++ ++ if ( abs ( *translate_value ) > strength_cutoff) ++ strength_cutoff = *translate_value; ++ ++ max_strength = ( strength_cutoff * alignment_strength ) / 100; ++ ++ if ( *translate_value < -max_strength ) ++ *translate_value = -max_strength; ++ else if ( *translate_value > max_strength ) ++ *translate_value = max_strength; ++ } ++ } ++ else ++ /* Start snapping */ ++ { ++ FT_Int center_offset; ++ FT_Int modulus; ++ FT_Int delta, delta2; ++ FT_Long stem_distance = 1, new_distance = 1; ++ FT_Int distance_floor, distance_ceiling; ++ FT_Int translate_value2 = 0; ++ FT_Int main_stem = 0; ++ FT_Int lbearing = m_horiBearingX * 12; ++ FT_Int bitmap_stem_location = stems[0].center; ++ FT_Int advance_stem_location = bitmap_stem_location ++ + lbearing - one_pixel; ++ FT_Int advance_width = m_horiAdvance * 12; ++ FT_Int original_advance_width = 12 * ( slot->linearHoriAdvance >> 10 ); ++ FT_Int glyph_width = rightmost_point - leftmost_point; ++ FT_Int stem_width = stems[0].width; ++ FT_Int advance_leftmost_location = leftmost_point ++ + lbearing - one_pixel; ++ FT_Int advance_rightmost_location = rightmost_point ++ + lbearing - one_pixel; ++ ++#define proposed_transformed_point(point) \ ++ point * (float)(new_distance) / (float)(stem_distance) \ ++ + *translate_value * 12 - ( stems[main_stem].center * (float)(new_distance) \ ++ / (float)(stem_distance) - stems[main_stem].center) ++ ++#define proposed_translated_point(point) point + *translate_value * 12 ++ ++ center_offset = one_pixel / 2; /* half pixel */ ++ modulus = one_pixel; /* whole pixel */ ++ ++ /* Determine center_offset via known values */ ++ if ( known_stem_values->stem_width >= 0 ) ++ { ++ if ( known_stem_values->stem_width % 2 == 0 ) ++ center_offset = 0; ++ else ++ center_offset = one_pixel / 2; ++ } ++ /* otherwise do intelligent guessing, if set */ ++ else if ( strategy_auto_change_center_offset && ++ ppem >= STEM_WIDTH_2_PPEM && ++ stems[0].width < one_pixel * 1.45 ) ++ center_offset = one_pixel / 2; ++ else if ( strategy_auto_change_center_offset && ++ ppem >= STEM_WIDTH_2_PPEM && ++ stems[0].width >= one_pixel * 1.45 && ++ stems[0].width < one_pixel * 2.6 ) ++ center_offset = 0; ++ else if ( strategy_auto_change_center_offset && ++ ppem >= STEM_WIDTH_2_PPEM && ++ stems[0].width >= one_pixel * 2.6 && ++ stems[0].width < one_pixel * 3.6 ) ++ center_offset = one_pixel / 2; ++ else if ( strategy_auto_change_center_offset && ++ ppem >= STEM_WIDTH_2_PPEM ) ++ center_offset = ++ ( one_pixel ++ * ( ( ( (int)( stems[0].width + one_pixel / 2 ) ) ++ / one_pixel ) % 2 ) ) / 2; ++ ++ /* Snap to closest translate and scale values by default */ ++ if ( valid_stems >= 1 ) ++ { ++ /* closest snapping point for stem 0 */ ++ delta = ( stems[0].center + center_offset ) % modulus; ++ ++ if ( delta < modulus / 2 ) ++ /* snap left */ ++ *translate_value = -delta / ( columns_per_pixel * 4 ); ++ else ++ /* snap right */ ++ *translate_value = ( modulus - delta ) / ( columns_per_pixel * 4 ); ++ } ++ ++ if ( strategy_use_d_correction ) ++ { ++ /* if the only stem is in the last 1/3 of glyph width, the advance */ ++ /* is 6 pixels, the ppem 11, and doing so doesn't violate bitmap , */ ++ /* boundaries force it to snap right */ ++ if ( valid_stems == 1 && ++ advance_stem_location > (advance_width * 2) / 3 && ++ advance_width == 6 * one_pixel && ++ rightmost_point + modulus - delta ++ <= ( width - (columns_per_pixel * 2) / 3) * 256 && ++ ppem == 11 ) ++ *translate_value = ( modulus - delta ) / ( columns_per_pixel * 4 ); ++ } ++ ++ if ( strategy_use_strengths ) ++ { ++ /* consider 1/2 pixel the max when strength is at 100%, ++ unless translate is already greater than that */ ++ FT_Int strength_cutoff = 32; ++ if ( abs ( *translate_value ) > strength_cutoff ) ++ strength_cutoff = *translate_value; ++ ++ max_strength = ( strength_cutoff * alignment_strength ) / 100; ++ ++ if ( *translate_value < -max_strength ) ++ *translate_value = -max_strength; ++ else if ( *translate_value > max_strength ) ++ *translate_value = max_strength; ++ } ++ ++ /* If 2 stems is detected, scale distance ++ between in order to land on pixels */ ++ if ( valid_stems >= 2 ) ++ { ++ stem_distance = abs ( stems[1].center - stems[0].center ); ++ ++ delta = stem_distance % modulus; ++ new_distance = stem_distance - delta; ++ ++ distance_floor = stem_distance - delta; ++ distance_ceiling = stem_distance + ( modulus - delta ); ++ ++ if ( delta < modulus / 2 ) ++ new_distance = distance_floor; ++ else ++ new_distance = distance_ceiling; ++ ++ if ( columns_per_pixel == 3 && ++ valid_stems == 3 && ++ strategy_use_m_control && ++ ( width - 2 * columns_per_pixel ) > 6 * columns_per_pixel && ++ ppem > 8 && ++ ( advance_stem_location - advance_leftmost_location ) ++ < stems[main_stem].width * 2 ) ++ { ++ /* Possibly use 2 only when compatible widths is on? */ ++ FT_Int mod_factor = 2; ++ ++ if ( verbose ) ++ printf ( "USING M CONTROL "); ++ ++ distance_floor = stem_distance ++ - stem_distance % ( modulus * mod_factor ) ; ++ distance_ceiling = distance_floor + modulus * mod_factor; ++ ++ new_distance = distance_ceiling; ++ ++ /* force certain ideal situations */ ++ /* these 2 are mostly safe to do */ ++ if ( distance_ceiling ++ + one_pixel * columns_per_pixel == advance_width && ++ stem_width < one_pixel * 1.25 ) ++ new_distance = distance_ceiling; ++ /* NEED TO FIGURE OUT A WAY TO DETERMINE WHETHER ++ THAT NUDGE IS UP OR DOWN */ ++ else if ( stem_distance + one_pixel * 2.6 >= advance_width && ++ stem_width < one_pixel * 1.25 ) ++ new_distance = distance_ceiling; ++ ++ if ( proposed_transformed_point ( leftmost_point ) ++ < one_third_pixel * 2 || ++ proposed_transformed_point ( rightmost_point ) ++ > ( width -2 ) * one_third_pixel ) ++ new_distance = distance_floor; ++ ++ /* NEED TO IGNORE SERIF Ms HERE */ ++ /* perhaps check bitmap boundaries instead??? */ ++ if ( strategy_bearing_correction && new_distance == distance_ceiling ) ++ { ++ /* Correct if bearings are made substantially worse ++ (more than 1/3 a pixel beyond advance) */ ++ if ( proposed_transformed_point( advance_rightmost_location ) ++ > advance_width + one_third_pixel && ++ proposed_transformed_point( advance_rightmost_location ) ++ > advance_rightmost_location && ++ -proposed_transformed_point( advance_leftmost_location ) ++ < advance_rightmost_location - advance_width ) ++ new_distance = distance_floor; ++ } ++ ++ if ( known_stem_values->m >= 0 ) ++ { ++ if ( known_stem_values->m == 0 ) ++ new_distance = distance_floor; ++ else ++ new_distance = distance_ceiling; ++ } ++ ++ if ( ( rightmost_point - leftmost_point) - ++ ( ( rightmost_point * *scale_value) ++ - ( leftmost_point * *scale_value ) ) >= one_pixel * 1.5 ) ++ { ++ *scale_value = 1.0; ++ *translate_value = 0; ++ goto Exit; ++ } ++ ++ } ++ else if ( columns_per_pixel == 1 && ++ valid_stems == 3 && ++ strategy_use_m_control && valid_stems == 3 && ++ width >= 6 * columns_per_pixel && ++ ppem > 8 && ++ ( advance_stem_location - advance_leftmost_location ) ++ < stems[main_stem].width * 2 ) ++ { ++ /* Possibly use 2 only when compatible widths is on? */ ++ FT_Int mod_factor = 2; ++ ++ if ( verbose ) ++ printf ("USING M CONTROL "); ++ distance_floor = stem_distance - stem_distance ++ % ( modulus * mod_factor) ; ++ distance_ceiling = distance_floor + modulus * mod_factor; ++ ++ new_distance = distance_ceiling; ++ ++ /* force certain ideal situations */ ++ /* these 2 are mostly safe to do */ ++ if ( distance_ceiling ++ + one_pixel * columns_per_pixel == advance_width && ++ stem_width < one_pixel * 1.25 ) ++ new_distance = distance_ceiling; ++ /* NEED TO FIGURE OUT A WAY TO DETERMINE WHETHER ++ THAT NUDGE IS UP OR DOWN */ ++ else if ( stem_distance + one_pixel * 2.6 >= advance_width && ++ stem_width < one_pixel * 1.25 ) ++ new_distance = distance_ceiling; ++ ++ if ( proposed_transformed_point( leftmost_point ) < 0 || ++ proposed_transformed_point( rightmost_point ) ++ > width * one_pixel - 2 * one_third_pixel ) ++ new_distance = distance_floor; ++ ++ /* NEED TO IGNORE SERIF Ms HERE */ ++ /* perhaps check bitmap boundaries instead??? */ ++ if ( strategy_bearing_correction && new_distance == distance_ceiling ) ++ { ++ /* Correct if bearings are made substantially worse ++ (more than 1/3 a pixel beyond advance) */ ++ if ( proposed_transformed_point( advance_rightmost_location ) ++ > advance_width + one_third_pixel && ++ proposed_transformed_point( advance_rightmost_location ) ++ > advance_rightmost_location && ++ -proposed_transformed_point( advance_leftmost_location ) ++ < advance_rightmost_location - advance_width ) ++ new_distance = distance_floor; ++ } ++ ++ if ( known_stem_values->m >= 0 ) ++ { ++ if ( known_stem_values->m == 0 ) ++ new_distance = distance_floor; ++ else ++ new_distance = distance_ceiling; ++ } ++ ++ ++ if ( ( rightmost_point - leftmost_point ) ++ - ( ( rightmost_point * *scale_value ) ++ - ( leftmost_point * *scale_value ) ) >= one_pixel * 1.5 ) ++ { ++ *scale_value = 1.0; ++ *translate_value = 0; ++ goto Exit; ++ } ++ ++ } ++ else ++ { ++ if ( strategy_fit_to_width ) ++ new_distance = advance_width - 3 * one_pixel; ++ else if ( known_stem_values->stem_scaling >= 0 ) ++ { ++ if ( known_stem_values->stem_scaling > 0 ) ++ new_distance = distance_ceiling; ++ else ++ new_distance = distance_floor; ++ ++ /* enforce advance width boundaries */ ++ /* TOO RESTRICTIVE ON SERIF FONTS */ ++ if ( proposed_transformed_point( advance_rightmost_location ) ++ >= advance_width || ++ proposed_transformed_point( advance_leftmost_location ) ++ <= 0 ) ++ new_distance = distance_floor; ++ ++ /* enforce literal bitmap boundaries if no translate room */ ++ if ( ( proposed_transformed_point(rightmost_point) >= width * 256 ++ || proposed_transformed_point(leftmost_point ) <= one_pixel ) ++ && new_distance + one_pixel * 3 > advance_width ) ++ new_distance = distance_floor; ++ ++ } ++ else if ( strategy_translate_using_closest_stem ) ++ { ++ /* closest snapping point for stem 1 */ ++ delta2 = ( stems[1].center + center_offset ) % modulus; ++ ++ if ( delta2 < modulus / 2 ) ++ /* snap left */ ++ translate_value2 = -delta2 / ( columns_per_pixel * 4 ); ++ else ++ /* snap right */ ++ translate_value2 = ( modulus - delta2 ) ++ / ( columns_per_pixel * 4 ); ++ ++ if ( abs ( translate_value2 ) < abs ( *translate_value ) ) ++ { ++ *translate_value = translate_value2; ++ main_stem = 1; ++ } ++ ++ } ++ else if ( strategy_scale_to_closest_centers ) ++ { ++ /* closest snapping point for stem 0 */ ++ delta = ( stems[0].center + center_offset ) % modulus; ++ delta2 = ( stems[1].center + center_offset ) % modulus; ++ ++ if ( delta < modulus / 2 ) ++ /* stretch left */ ++ new_distance = delta + stem_distance; ++ else ++ /* stretch right */ ++ new_distance = delta - modulus + stem_distance; ++ ++ if ( delta2 < modulus / 2 ) ++ new_distance -= delta2; /* stretch left */ ++ else ++ new_distance += modulus - delta2; /* stretch right */ ++ ++ } ++ else if ( strategy_scale_to_closest_centers_up_only ) ++ { ++ FT_Int net_change = 0; ++ ++ /* closest snapping point for stem 0 */ ++ delta = ( stems[0].center + center_offset ) % modulus; ++ delta2 = ( stems[1].center + center_offset ) % modulus; ++ ++ if ( delta < modulus / 2 ) ++ net_change = delta; /* stretch left */ ++ else ++ net_change = -( modulus - delta ); /* stretch right */ ++ ++ if ( delta2 < modulus / 2 ) ++ net_change -= delta2; /* stretch left */ ++ else ++ net_change += modulus - delta2; /* stretch right */ ++ ++ if ( net_change > 0 && ++ proposed_transformed_point( advance_rightmost_location ) ++ < advance_width && ++ proposed_transformed_point( advance_leftmost_location ) > 0 ) ++ new_distance = distance_ceiling; ++ } ++ ++ else if ( strategy_always_use_distance_ceiling ) ++ { ++ if ( proposed_transformed_point( advance_rightmost_location ) ++ < advance_width && ++ proposed_transformed_point( advance_leftmost_location ) > 0 ) ++ new_distance = distance_ceiling; ++ } ++ } ++ ++ if ( strategy_use_strengths ) ++ { ++ FT_Int strength_cutoff = center_offset; ++ ++ ++ delta2 = new_distance - stem_distance; ++ ++ if ( abs ( delta2 ) > strength_cutoff ) ++ strength_cutoff = delta2; ++ ++ max_strength = ( strength_cutoff * fitting_strength ) / 100; ++ ++ if ( delta2 < -max_strength ) ++ new_distance = stem_distance - max_strength; ++ else if ( delta2 > max_strength ) ++ new_distance = stem_distance + max_strength; ++ } ++ ++ *scale_value = (float)( new_distance ) / (float)( stem_distance ); ++ *translate_value = *translate_value ++ - ( (float)( stems[main_stem].center * (float)new_distance ) ++ / (float)stem_distance - stems[main_stem].center ) / 12; ++ ++ if ( valid_stems == 2 ) ++ *embolden_value = ( 64.0 / *scale_value - 64.0 ); ++ ++ if ( valid_stems == 3 ) ++ *embolden_value = ( 64.0 / *scale_value - 64.0 ) / 1.5; ++ } ++ ++ if ( verbose ) ++ printf ( "%lu stems:", valid_stems ); ++ ++ if ( valid_stems == 1 && verbose ) ++ printf ( "1 stem: bitmapwidth:%d glyphwidth:%f glyph_width:%f center:%f bearing:%f advance:%f lhadvance:%f stemwidth:%f %d %d", ++ (width - 6) / columns_per_pixel, ++ (float)m_width / 64.0, ++ (float)glyph_width / (float)one_pixel, ++ (float)( (float)advance_stem_location ) / (float)one_pixel, ++ (float)m_horiBearingX / 64.0, ++ (float)m_horiAdvance / 64.0, ++ (float)linearHoriAdvance / 64.0, ++ (float)stems[0].width / (float)one_pixel, ++ advance_width, original_advance_width ); ++ else if ( valid_stems >= 2 && verbose ) ++ printf ( "%lu stems: bitmapwidth:%d center1:%f center2:%f difference:%f bearing:%f advance:%f advstemloc:%f ", ++ valid_stems, ++ (width - 6) / columns_per_pixel, ++ ( (float)advance_stem_location ) / (float)one_pixel, ++ ( (float)advance_stem_location ++ + (float)abs ( stems[1].center ++ - stems[0].center) ) / (float)one_pixel, ++ ( (float)abs ( stems[1].center ++ - stems[0].center ) ) / (float)one_pixel, ++ (float)m_horiBearingX / 64.0, ++ (float)m_horiAdvance / 64.0, ++ (float)advance_stem_location / (float)one_pixel ); ++ ++ if ( strategy_bearing_correction ) ++ { ++ /* Correct if negative bearings are made substantially worse */ ++ /* (more than 1/3 a pixel) */ ++ if ( proposed_transformed_point( advance_rightmost_location ) ++ > advance_width && ++ proposed_transformed_point( advance_rightmost_location ) ++ > advance_rightmost_location && ++ -proposed_transformed_point( advance_leftmost_location ) ++ < advance_rightmost_location - advance_width && ++ *translate_value ++ > one_third_pixel / ( columns_per_pixel * 4 ) ) ++ { ++ *translate_value -=64 ; ++ if ( verbose ) ++ printf ( "TRANSLATING -64 " ); ++ } ++ } ++ goto Exit; ++ } ++ ++ Exit: ++ ++#define transformed_point( point ) point * *scale_value + *translate_value * 12 ++ ++ if ( strategy_correct_out_of_bounds_outlines ) ++ { ++ /* Correct if outside bitmap */ ++ if ( transformed_point( rightmost_point ) ++ >= width * 256 - 2 * one_third_pixel && ++ transformed_point( leftmost_point ) ++ > one_pixel + 2 * one_third_pixel ) ++ *translate_value -=64 ; ++ else if ( transformed_point( leftmost_point ) ++ <= one_pixel / 2 && ++ transformed_point( rightmost_point ) ++ <= width * 256 - ( one_pixel + one_pixel / 2 ) ) ++ *translate_value += 64; ++ } ++ ++ STVALUES ++ ++ free ( segments ); ++ free ( leftmost_segment ); ++ free ( leftmost_segment_not_extrema ); ++ free ( rightmost_segment ); ++ free ( rightmost_segment_not_extrema ); ++ free ( known_stem_values ); ++ free ( stems ); ++ free ( possible_stems ); ++ free ( leftmost_stem ); ++ free ( rightmost_stem ); ++ free ( centers ); ++ } ++ ++ ++ /* Gamma correction */ ++ static void ++ _ft_lcd_gamma_correction_correction ( FT_Bitmap* bitmap, ++ FT_Render_Mode mode, ++ FT_GlyphSlot slot, ++ float gamma_correction_lt, ++ float gamma_correction_value ) ++ { ++ if ( gamma_correction_value != 1.0 ) ++ { ++ FT_UInt width = (FT_UInt)bitmap->width; ++ FT_UInt height = (FT_UInt)bitmap->rows; ++ FT_Byte* line = bitmap->buffer; ++ float ppem = (float)slot->face->size->metrics.x_ppem; ++ ++ ++ if ( !slot->face || !slot->face->size ) return; ++ ++ 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] = pseudo_gamma ( line[xx], gamma_correction_value );*/ ++ ++ /* sloped */ ++ /*line[xx] = pseudo_gamma ( line[xx], gamma_correction_value - 5 ++ * (1-gamma_correction_value)/(gamma_correction_lt -5) ++ + ((1-gamma_correction_value)/(gamma_correction_lt -5)) * ppem );*/ ++ ++ /* 1/3-sloped */ ++ line[xx] = pseudo_gamma ( line[xx], gamma_correction_value - 5 ++ * ( ( 1 - gamma_correction_value ) ++ / ( 3 * ( gamma_correction_lt -5 ) ) ) ++ + ( ( 1 - gamma_correction_value ) ++ / ( 3 * ( gamma_correction_lt -5) ) ) * ppem ); ++ } ++ } ++ } ++ } ++ ++#endif ++ ++ /* convert a slot's glyph image into a bitmap */ ++ static FT_Error ++ ft_smooth_render_generic( FT_Renderer render, ++ FT_GlyphSlot slot, ++ FT_Render_Mode mode, ++ const FT_Vector* origin, ++ FT_Render_Mode required_mode ) ++ { ++ FT_Error error; ++ FT_Outline* outline = NULL; ++ FT_Outline* outline_orig = NULL; ++ FT_BBox cbox; ++ FT_Pos width, height, pitch, ppem; ++#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING ++ FT_Pos height_org, width_org; ++#endif ++ FT_Bitmap* bitmap = &slot->bitmap; ++ FT_Memory memory = render->root.memory; ++ FT_Int hmul = mode == FT_RENDER_MODE_LCD; ++ FT_Int vmul = mode == FT_RENDER_MODE_LCD_V; ++ FT_Pos x_shift = 0; ++ FT_Pos y_shift = 0; ++ FT_Pos x_left, y_top; ++ ++ FT_Raster_Params params; ++ ++ FT_Bool have_translated_origin = FALSE; ++ FT_Bool have_outline_shifted = FALSE; ++ FT_Bool have_buffer = FALSE; ++ ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ FT_Matrix scaleMat; ++ FT_Long translate_value = 0; ++ float scale_value = 1.0; ++ FT_Int align_called = 0; ++ ++ ++ int chromeos_style_sharpening_strength = 0; ++ int checked_chromeos_style_sharpening_strength = 0; ++ int alignment_strength = 0; ++ int fitting_strength = 0; ++ FT_UInt checked_alignment_strength = 0; ++ FT_UInt checked_fitting_strength = 0; ++ FT_UInt checked_fringe_filter_strength = 0; ++ int fringe_filter_strength = 0; ++ FT_UInt checked_grayscale_filter_strength = 0; ++ int grayscale_filter_strength = 0; ++ ++ FT_UInt checked_autohint_horizontal_stem_darken_strength = 0; ++ int autohint_horizontal_stem_darken_strength = 0; ++ ++ FT_UInt checked_autohint_vertical_stem_darken_strength = 0; ++ int autohint_vertical_stem_darken_strength = 0; ++ ++ int windows_style_sharpening_strength = 0; ++ FT_UInt checked_windows_style_sharpening_strength = 0; ++ float gamma_correction_value = 1; ++ float gamma_correction_lt = 0; ++ FT_UInt checked_gamma_correction_value = 0; ++ ++ FT_Int brightness_value = 0.0; ++ FT_UInt checked_brightness_value = 0; ++ ++ FT_Int contrast_value = 0.0; ++ FT_UInt checked_contrast_value = 0; ++ ++ FT_Int snapping_sliding_scale_value = 0; ++ FT_UInt checked_snapping_sliding_scale_value = 0; ++ ++ FT_Int global_embolden_x_value = 0; ++ FT_UInt checked_global_embolden_x_value = 0; ++ ++ FT_Int global_embolden_y_value = 0; ++ FT_UInt checked_global_embolden_y_value = 0; ++ ++ FT_Int bold_embolden_x_value = 0; ++ FT_UInt checked_bold_embolden_x_value = 0; ++ ++ FT_Int bold_embolden_y_value = 0; ++ FT_UInt checked_bold_embolden_y_value = 0; ++ ++ FT_Byte chromeos_cutoff; ++ double chromeos_gamma_value; ++ ++ float embolden_value = 0.0; ++ FT_Bool autohinted = FALSE; ++ ++ FT_UInt autohint_minimum_stem_height = 0; ++ FT_UInt checked_autohint_minimum_stem_height = 0; ++ ++ int checked_use_various_tweaks_env = 0; ++ FT_Bool use_various_tweaks = FALSE; ++ ++ FT_Pos cur_width = infinality_cur_width; ++ ++ const FT_Int MIN_PPEM = 1; ++ /*const FT_Int MAX_PPEM = 100; */ ++ ++ int checked_use_known_settings_on_selected_fonts_env = 0; ++ FT_Bool use_known_settings_on_selected_fonts = FALSE; ++ ++ if ( slot->face && ++ slot->face->size && ++ slot->face->size->metrics.x_ppem ) ++ ppem = slot->face->size->metrics.x_ppem; ++ else ++ ppem = 0; ++ ++ if ( cur_width ) ++ { ++ autohinted = TRUE; ++ } ++ ++ if ( checked_use_known_settings_on_selected_fonts_env == 0 ) ++ { ++ char *use_known_settings_on_selected_fonts_env = ++ getenv( "INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS" ); ++ if ( use_known_settings_on_selected_fonts_env != NULL ) ++ { ++ if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "default" ) != 0 ) ++ { ++ if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "true" ) == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ else if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "1" ) == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ else if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "on" ) == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ else if ( strcasecmp( use_known_settings_on_selected_fonts_env, ++ "yes" ) == 0 ) ++ use_known_settings_on_selected_fonts = TRUE; ++ } ++ } ++ checked_use_known_settings_on_selected_fonts_env = 1; ++ } ++ ++ if ( checked_use_various_tweaks_env == 0 ) ++ { ++ char *use_various_tweaks_env ++ = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" ); ++ ++ if ( use_various_tweaks_env != NULL ) ++ { ++ if ( strcasecmp( use_various_tweaks_env, "default" ) != 0 ) ++ { ++ if ( strcasecmp( use_various_tweaks_env, "true") == 0) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp( use_various_tweaks_env, "1") == 0) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp( use_various_tweaks_env, "on") == 0) ++ use_various_tweaks = TRUE; ++ else if ( strcasecmp( use_various_tweaks_env, "yes") == 0) ++ use_various_tweaks = TRUE; ++ } ++ } ++ checked_use_various_tweaks_env = 1; ++ } ++ ++ if ( checked_autohint_minimum_stem_height == 0 ) ++ { ++ char *autohint_minimum_stem_height_env = ++ getenv( "INFINALITY_FT_AUTOHINT_MINIMUM_STEM_WIDTH" ); ++ ++ if ( autohint_minimum_stem_height_env != NULL ) ++ { ++ sscanf ( autohint_minimum_stem_height_env, "%u", ++ &autohint_minimum_stem_height ); ++ ++ if ( autohint_minimum_stem_height > 100 ) ++ autohint_minimum_stem_height = 100; ++ else if ( autohint_minimum_stem_height < 0 ) ++ autohint_minimum_stem_height = 0; ++ } ++ checked_autohint_minimum_stem_height = 1; ++ } ++ ++ if ( checked_snapping_sliding_scale_value == 0 ) ++ { ++ char *snapping_sliding_scale_env = ++ getenv ( "INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE" ); ++ ++ if ( snapping_sliding_scale_env != NULL ) ++ { ++ sscanf ( snapping_sliding_scale_env, "%d", ++ &snapping_sliding_scale_value ); ++ ++ if ( snapping_sliding_scale_value > MAX_PPEM ) ++ snapping_sliding_scale_value = 0; ++ else if ( snapping_sliding_scale_value < 0 ) ++ snapping_sliding_scale_value = 0; ++ ++ if (snapping_sliding_scale_value < 11 && ++ snapping_sliding_scale_value > 0 ) ++ snapping_sliding_scale_value = 11; ++ } ++ checked_snapping_sliding_scale_value = 1; ++ } ++ ++ if ( checked_alignment_strength == 0) ++ { ++ char *alignment_strength_env = ++ getenv ( "INFINALITY_FT_STEM_ALIGNMENT_STRENGTH" ); ++ ++ if ( alignment_strength_env != NULL ) ++ { ++ sscanf ( alignment_strength_env, "%d", &alignment_strength ); ++ ++ if ( alignment_strength > 100 ) ++ alignment_strength = 100; ++ else if ( alignment_strength < 0 ) ++ alignment_strength = 0; ++ } ++ ++ if ( alignment_strength > 100 ) ++ alignment_strength = 100; ++ checked_alignment_strength = 1; ++ ++ if ( snapping_sliding_scale_value != 0 ) ++ alignment_strength = sliding_scale ++ ( 10, snapping_sliding_scale_value, alignment_strength, 100, ppem ); ++ } ++ ++ if ( checked_fitting_strength == 0 ) ++ { ++ char *fitting_strength_env = ++ getenv( "INFINALITY_FT_STEM_FITTING_STRENGTH" ); ++ ++ if ( fitting_strength_env != NULL ) ++ { ++ sscanf ( fitting_strength_env, "%d", &fitting_strength ); ++ ++ if ( fitting_strength > 100 ) ++ fitting_strength = 100; ++ else if ( fitting_strength < 0 ) ++ fitting_strength = 0; ++ } ++ ++ if ( fitting_strength > 100 ) ++ fitting_strength = 100; ++ ++ checked_fitting_strength = 1; ++ ++ if ( snapping_sliding_scale_value != 0 ) ++ fitting_strength = sliding_scale ++ ( 10, snapping_sliding_scale_value, fitting_strength, 100, ppem ); ++ } ++ ++ if ( checked_chromeos_style_sharpening_strength == 0 ) ++ { ++ char *chromeos_style_sharpening_strength_env = ++ getenv( "INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH" ); ++ if ( chromeos_style_sharpening_strength_env != NULL ) ++ { ++ sscanf ( chromeos_style_sharpening_strength_env, "%d", ++ &chromeos_style_sharpening_strength ); ++ ++ if ( chromeos_style_sharpening_strength > 100 ) ++ chromeos_style_sharpening_strength = 100; ++ else if ( chromeos_style_sharpening_strength < 0 ) ++ chromeos_style_sharpening_strength = 0; ++ } ++ ++ if ( ppem > 10 ) ++ chromeos_style_sharpening_strength = ++ ( chromeos_style_sharpening_strength * ppem ) / 10; ++ ++ if ( chromeos_style_sharpening_strength > 100 ) ++ chromeos_style_sharpening_strength = 100; ++ checked_chromeos_style_sharpening_strength = 1; ++ } ++ ++ ++ if ( checked_brightness_value == 0) ++ { ++ char *brightness_env = getenv( "INFINALITY_FT_BRIGHTNESS" ); ++ if ( brightness_env != NULL ) ++ { ++ sscanf ( brightness_env, "%d", &brightness_value ); ++ if (brightness_value > 100 ) ++ brightness_value = 100; ++ else if (brightness_value < -100 ) ++ brightness_value = 0; ++ } ++ checked_brightness_value = 1; ++ } ++ ++ if ( checked_contrast_value == 0) ++ { ++ char *contrast_env = getenv( "INFINALITY_FT_CONTRAST" ); ++ if ( contrast_env != NULL ) ++ { ++ sscanf ( contrast_env, "%d", &contrast_value ); ++ if (contrast_value > 100 ) ++ contrast_value = 100; ++ else if (contrast_value < -100 ) ++ contrast_value = 100; ++ } ++ checked_contrast_value = 1; ++ } + +- /* initialize renderer -- init its raster */ +- static FT_Error +- ft_smooth_init( FT_Renderer render ) +- { +- FT_Library library = FT_MODULE_LIBRARY( render ); ++ if ( checked_windows_style_sharpening_strength == 0) ++ { ++ char *windows_style_sharpening_strength_env = ++ getenv( "INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH" ); + ++ if ( windows_style_sharpening_strength_env != NULL ) ++ { ++ sscanf ( windows_style_sharpening_strength_env, "%d", ++ &windows_style_sharpening_strength ); + +- render->clazz->raster_class->raster_reset( render->raster, +- library->raster_pool, +- library->raster_pool_size ); ++ if ( windows_style_sharpening_strength > 100 ) ++ windows_style_sharpening_strength = 100; ++ else if ( windows_style_sharpening_strength < 0 ) ++ windows_style_sharpening_strength = 0; ++ } ++ /* Decrease effect slightly to have a more linear increase in sharpness */ ++ windows_style_sharpening_strength = ++ ( ( windows_style_sharpening_strength ++ * windows_style_sharpening_strength ) / 100 ++ + windows_style_sharpening_strength ) / 2; ++ checked_windows_style_sharpening_strength = 1; ++ } + +- return 0; +- } ++ if ( checked_gamma_correction_value == 0 ) ++ { ++ char *gamma_correction_value_env = ++ getenv( "INFINALITY_FT_GAMMA_CORRECTION" ); + ++ if ( gamma_correction_value_env != NULL ) ++ { ++ float f1, f2; + +- /* sets render-specific mode */ +- static FT_Error +- ft_smooth_set_mode( FT_Renderer render, +- FT_ULong mode_tag, +- FT_Pointer data ) +- { +- /* we simply pass it to the raster */ +- return render->clazz->raster_class->raster_set_mode( render->raster, +- mode_tag, +- data ); +- } ++ if ( strcasecmp( gamma_correction_value_env, "default" ) != 0 ) ++ { ++ sscanf ( gamma_correction_value_env, "%f %f", &f1, &f2 ); ++ gamma_correction_lt = f1; ++ gamma_correction_value = f2 / 100.0; ++ } ++ if ( gamma_correction_value < .01 ) gamma_correction_value = 1.0; ++ } ++ checked_gamma_correction_value = 1; ++ } + +- /* transform a given glyph image */ +- static FT_Error +- ft_smooth_transform( FT_Renderer render, +- FT_GlyphSlot slot, +- const FT_Matrix* matrix, +- const FT_Vector* delta ) +- { +- FT_Error error = FT_Err_Ok; ++ /* set gamma value to 1 if out of range */ ++ if ( slot->face && ++ slot->face->size && ++ slot->face->size->metrics.x_ppem ) ++ { ++ if ( slot->face->size->metrics.x_ppem >= gamma_correction_lt ) ++ gamma_correction_value = 1; ++ } ++ else ++ gamma_correction_value = 1; + + +- if ( slot->format != render->glyph_format ) ++ if ( checked_fringe_filter_strength == 0 ) + { +- error = FT_THROW( Invalid_Argument ); +- goto Exit; ++ char *fringe_filter_strength_env = ++ getenv( "INFINALITY_FT_FRINGE_FILTER_STRENGTH" ); ++ if ( fringe_filter_strength_env != NULL ) ++ { ++ sscanf ( fringe_filter_strength_env, "%d", &fringe_filter_strength ); ++ ++ if ( fringe_filter_strength > 100 ) ++ fringe_filter_strength = 100; ++ else if ( fringe_filter_strength < 0 ) ++ fringe_filter_strength = 0; ++ } ++ checked_fringe_filter_strength = 1; + } + +- if ( matrix ) +- FT_Outline_Transform( &slot->outline, matrix ); + +- if ( delta ) +- FT_Outline_Translate( &slot->outline, delta->x, delta->y ); ++ if ( checked_grayscale_filter_strength == 0) ++ { ++ char *grayscale_filter_strength_env = ++ getenv( "INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH" ); ++ if ( grayscale_filter_strength_env != NULL ) ++ { ++ sscanf ( grayscale_filter_strength_env, "%d", ++ &grayscale_filter_strength ); ++ if ( grayscale_filter_strength > 100 ) grayscale_filter_strength = 100; ++ else if (grayscale_filter_strength < 0 ) grayscale_filter_strength = 0; ++ } ++ checked_grayscale_filter_strength = 1; ++ } + +- Exit: +- return error; +- } + ++ if ( checked_autohint_horizontal_stem_darken_strength == 0) ++ { ++ char *autohint_horizontal_stem_darken_strength_env = ++ getenv( "INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH" ); ++ if ( autohint_horizontal_stem_darken_strength_env != NULL ) ++ { ++ sscanf ( autohint_horizontal_stem_darken_strength_env, "%d", ++ &autohint_horizontal_stem_darken_strength ); + +- /* return the glyph's control box */ +- static void +- ft_smooth_get_cbox( FT_Renderer render, +- FT_GlyphSlot slot, +- FT_BBox* cbox ) +- { +- FT_MEM_ZERO( cbox, sizeof ( *cbox ) ); ++ if ( autohint_horizontal_stem_darken_strength > 100 ) ++ autohint_horizontal_stem_darken_strength = 100; ++ else if ( autohint_horizontal_stem_darken_strength < 0 ) ++ autohint_horizontal_stem_darken_strength = 0; ++ } ++ checked_autohint_horizontal_stem_darken_strength = 1; ++ } + +- if ( slot->format == render->glyph_format ) +- FT_Outline_Get_CBox( &slot->outline, cbox ); +- } ++ if ( checked_autohint_vertical_stem_darken_strength == 0) ++ { ++ char *autohint_vertical_stem_darken_strength_env = ++ getenv( "INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH" ); ++ if ( autohint_vertical_stem_darken_strength_env != NULL ) ++ { ++ sscanf ( autohint_vertical_stem_darken_strength_env, "%d", ++ &autohint_vertical_stem_darken_strength ); + ++ if ( autohint_vertical_stem_darken_strength > 100 ) ++ autohint_vertical_stem_darken_strength = 100; ++ else if ( autohint_horizontal_stem_darken_strength < 0 ) ++ autohint_vertical_stem_darken_strength = 0; ++ } ++ checked_autohint_vertical_stem_darken_strength = 1; ++ } + +- /* convert a slot's glyph image into a bitmap */ +- static FT_Error +- ft_smooth_render_generic( FT_Renderer render, +- FT_GlyphSlot slot, +- FT_Render_Mode mode, +- const FT_Vector* origin, +- FT_Render_Mode required_mode ) +- { +- FT_Error error; +- FT_Outline* outline = &slot->outline; +- FT_Bitmap* bitmap = &slot->bitmap; +- FT_Memory memory = render->root.memory; +- FT_BBox cbox; +- FT_Pos x_shift = 0; +- FT_Pos y_shift = 0; +- FT_Pos x_left, y_top; +- FT_Pos width, height, pitch; +-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING +- FT_Pos height_org, width_org; +-#endif +- FT_Int hmul = mode == FT_RENDER_MODE_LCD; +- FT_Int vmul = mode == FT_RENDER_MODE_LCD_V; ++ if ( checked_global_embolden_x_value == 0) ++ { ++ char *global_embolden_x_env = ++ getenv ( "INFINALITY_FT_GLOBAL_EMBOLDEN_X_VALUE" ); ++ if ( global_embolden_x_env != NULL ) ++ { ++ sscanf ( global_embolden_x_env, "%d", &global_embolden_x_value ); + +- FT_Raster_Params params; ++ if ( global_embolden_x_value > 128 ) ++ global_embolden_x_value = 128; ++ else if ( global_embolden_x_value < -128 ) ++ global_embolden_x_value = -128; ++ } ++ checked_global_embolden_x_value = 1; ++ } ++ ++ if ( checked_global_embolden_y_value == 0) ++ { ++ char *global_embolden_y_env = ++ getenv ( "INFINALITY_FT_GLOBAL_EMBOLDEN_Y_VALUE" ); ++ if ( global_embolden_y_env != NULL ) ++ { ++ sscanf ( global_embolden_y_env, "%d", &global_embolden_y_value ); ++ if ( global_embolden_y_value > 128 ) ++ global_embolden_y_value = 128; ++ else if ( global_embolden_y_value < -128 ) ++ global_embolden_y_value = -128; ++ } ++ checked_global_embolden_y_value = 1; ++ } ++ ++ ++ if ( checked_bold_embolden_x_value == 0) ++ { ++ char *bold_embolden_x_env = ++ getenv ( "INFINALITY_FT_BOLD_EMBOLDEN_X_VALUE" ); ++ ++ if ( bold_embolden_x_env != NULL ) ++ { ++ sscanf ( bold_embolden_x_env, "%d", &bold_embolden_x_value ); ++ if (bold_embolden_x_value > 128 ) ++ bold_embolden_x_value = 128; ++ else if (bold_embolden_x_value < -128 ) ++ bold_embolden_x_value = -128; ++ } ++ checked_bold_embolden_x_value = 1; ++ } ++ ++ if ( checked_bold_embolden_y_value == 0) ++ { ++ char *bold_embolden_y_env = getenv ( "INFINALITY_FT_BOLD_EMBOLDEN_Y_VALUE" ); ++ ++ if ( bold_embolden_y_env != NULL ) ++ { ++ sscanf ( bold_embolden_y_env, "%d", &bold_embolden_y_value ); ++ if (bold_embolden_y_value > 128 ) ++ bold_embolden_y_value = 128; ++ else if (bold_embolden_y_value < -128 ) ++ bold_embolden_y_value = -128; ++ } ++ checked_bold_embolden_y_value = 1; ++ } + +- FT_Bool have_outline_shifted = FALSE; +- FT_Bool have_buffer = FALSE; ++ if( use_various_tweaks && ++ slot->face && ++ slot->face->style_name ) ++ { ++ /* needs to also check for artifical italics */ ++ if ( strcasestr(slot->face->style_name, "Italic" ) || ++ strcasestr(slot->face->style_name, "Oblique" ) ) ++ { ++ windows_style_sharpening_strength = 0; ++ chromeos_style_sharpening_strength = 0; ++ } ++ } + ++ /*if (fitting_strength == 100) scale_value = 1.1;*/ ++ ++#endif + + /* check glyph image format */ + if ( slot->format != render->glyph_format ) +@@ -137,26 +3610,119 @@ + goto Exit; + } + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++RERENDER: ++ if ( align_called == 1 ) ++ { ++ scaleMat.xx = FT_FixedFromFloat(scale_value); ++ scaleMat.xy = 0; ++ scaleMat.yx = 0; ++ scaleMat.yy = ( 1 << 16 ); ++ ++ FT_Outline_Copy(outline_orig, outline); ++ ++ if ( scale_value != 1.0 ) ++ FT_Outline_Transform( outline, &scaleMat ); ++ ++ FT_Outline_Translate( outline, translate_value, 0 ); ++ ++ FT_Outline_EmboldenXY( outline, embolden_value, 0 ); ++ } ++ else ++ { ++#endif ++ outline = &slot->outline; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ /* Need to get this PRIOR to embolden, otherwise bad things happen */ ++ FT_Outline_Get_CBox( outline, &cbox ); ++ ++ /* Various hacks that need to be turned into a new rule set */ ++ /*if ( !autohinted ++ && use_known_settings_on_selected_fonts ++ && mode == FT_RENDER_MODE_LCD ++ && slot->face->family_name ++ && slot->face->style_name ++ && ( strcasestr(slot->face->family_name, "Courier New" ) ++ && ( strcasestr(slot->face->style_name, "Regular" ) ++ || strcasestr(slot->face->style_name, "Italic" ) ) ) ) ++ FT_Outline_Embolden( outline, 24 );*/ ++ ++ if ( slot->face ) ++ { ++ if ( !autohinted && ++ use_known_settings_on_selected_fonts && ++ mode == FT_RENDER_MODE_LCD && ++ slot->face->family_name && ++ slot->face->style_name && ++ strcasestr( slot->face->family_name, "Times New Roman" ) && ++ strcasestr( slot->face->style_name, "Italic" ) ) ++ FT_Outline_EmboldenXY( outline, 12, 0 ); ++ ++ if ( use_known_settings_on_selected_fonts && ++ autohinted && ++ mode == FT_RENDER_MODE_LCD && ++ slot->face->family_name && ++ slot->face->style_name && ++ strcasestr(slot->face->family_name, "FreeSerif" ) && ++ strcasestr(slot->face->style_name, "Italic" ) ) ++ FT_Outline_EmboldenXY( outline, 8, 0 ); ++ ++ if ( global_embolden_x_value != 0 || global_embolden_y_value != 0 ) ++ FT_Outline_EmboldenXY( outline, ++ global_embolden_x_value, ++ global_embolden_y_value ); ++ ++ if ( ( bold_embolden_x_value != 0 || bold_embolden_y_value != 0 ) && ++ ( slot->face->style_name && ++ ( strcasestr(slot->face->style_name, "Bold" ) || ++ strcasestr(slot->face->style_name, "Black" ) || ++ ( slot->face->style_flags && ++ slot->face->style_flags & FT_STYLE_FLAG_BOLD ) ) ) ) ++ FT_Outline_EmboldenXY( outline, ++ bold_embolden_x_value, ++ bold_embolden_y_value ); ++ } ++ ++ FT_Outline_Copy( outline, outline_orig ); ++ } ++ ++ /* translate the outline to the new origin if needed */ ++ if ( align_called == 0 ) ++ { ++ FT_Pos enlarge_cbox = 0; ++ ++ /* enlarge for grayscale rendering */ ++ if ( mode == FT_RENDER_MODE_NORMAL ) ++ enlarge_cbox = 64; ++ ++ if ( origin ) ++ { ++ FT_Outline_Translate( outline, origin->x, origin->y ); ++ have_translated_origin = TRUE; ++ } ++ ++ /* compute the control box, and grid fit it */ ++ /*FT_Outline_Get_CBox( outline, &cbox );*/ ++ ++ cbox.xMin = FT_PIX_FLOOR( cbox.xMin - enlarge_cbox ); ++ cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); ++ cbox.xMax = FT_PIX_CEIL( cbox.xMax + enlarge_cbox ); ++ cbox.yMax = FT_PIX_CEIL( cbox.yMax ); ++#else + if ( origin ) + { +- x_shift = origin->x; +- y_shift = origin->y; ++ FT_Outline_Translate( outline, origin->x, origin->y ); ++ have_translated_origin = TRUE; + } + + /* compute the control box, and grid fit it */ +- /* taking into account the origin shift */ + FT_Outline_Get_CBox( outline, &cbox ); + +- cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift ); +- cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift ); +- cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift ); +- cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift ); +- +- x_shift -= cbox.xMin; +- y_shift -= cbox.yMin; +- +- x_left = cbox.xMin >> 6; +- y_top = cbox.yMax >> 6; ++ cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); ++ cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); ++ cbox.xMax = FT_PIX_CEIL( cbox.xMax ); ++ cbox.yMax = FT_PIX_CEIL( cbox.yMax ); ++#endif + + width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6; + height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6; +@@ -166,16 +3732,29 @@ + height_org = height; + #endif + ++ /* release old bitmap buffer */ ++ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ++ { ++ FT_FREE( bitmap->buffer ); ++ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; ++ } ++ ++ /* allocate new one */ + pitch = width; + if ( hmul ) + { +- width *= 3; +- pitch = FT_PAD_CEIL( width, 4 ); ++ width = width * 3; ++ pitch = FT_PAD_CEIL( width, 4 ); + } + + if ( vmul ) + height *= 3; + ++ x_shift = cbox.xMin; ++ y_shift = cbox.yMin; ++ x_left = cbox.xMin >> 6; ++ y_top = cbox.yMax >> 6; ++ + #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + + if ( slot->library->lcd_filter_func ) +@@ -185,33 +3764,25 @@ + + if ( hmul ) + { +- x_shift += 64 * ( extra >> 1 ); +- x_left -= extra >> 1; ++ x_shift -= 64 * ( extra >> 1 ); + width += 3 * extra; + pitch = FT_PAD_CEIL( width, 4 ); ++ x_left -= extra >> 1; + } + + if ( vmul ) + { +- y_shift += 64 * ( extra >> 1 ); +- y_top += extra >> 1; ++ y_shift -= 64 * ( extra >> 1 ); + height += 3 * extra; ++ y_top += extra >> 1; + } + } +- + #endif +- +- /* +- * XXX: on 16bit system, we return an error for huge bitmap +- * to prevent an overflow. +- */ +- if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX || +- x_left < FT_INT_MIN || y_top < FT_INT_MIN ) +- { +- error = FT_THROW( Invalid_Pixel_Size ); +- goto Exit; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET + } + ++#endif ++ + /* Required check is (pitch * height < FT_ULONG_MAX), */ + /* but we care realistic cases only. Always pitch <= width. */ + if ( width > 0x7FFF || height > 0x7FFF ) +@@ -222,25 +3793,6 @@ + goto Exit; + } + +- /* release old bitmap buffer */ +- if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) +- { +- FT_FREE( bitmap->buffer ); +- slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; +- } +- +- /* allocate new one */ +- if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) ) +- goto Exit; +- else +- have_buffer = TRUE; +- +- slot->internal->flags |= FT_GLYPH_OWN_BITMAP; +- +- slot->format = FT_GLYPH_FORMAT_BITMAP; +- slot->bitmap_left = (FT_Int)x_left; +- slot->bitmap_top = (FT_Int)y_top; +- + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap->num_grays = 256; + bitmap->width = (unsigned int)width; +@@ -248,11 +3800,22 @@ + bitmap->pitch = pitch; + + /* translate outline to render it into the bitmap */ +- if ( x_shift || y_shift ) ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( align_called == 0 ) + { +- FT_Outline_Translate( outline, x_shift, y_shift ); +- have_outline_shifted = TRUE; ++#endif ++ FT_Outline_Translate( outline, -x_shift, -y_shift ); ++ have_outline_shifted = TRUE; ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET + } ++#endif ++ ++ if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) ) ++ goto Exit; ++ else ++ have_buffer = TRUE; ++ ++ slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + /* set up parameters */ + params.target = bitmap; +@@ -299,9 +3862,153 @@ + if ( error ) + goto Exit; + ++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET ++ if ( ppem <= MAX_PPEM && ppem >= MIN_PPEM ) ++ { ++ if ( align_called == 0 && cur_width / ppem < 10 && ++ ( alignment_strength > 0 || fitting_strength > 0 ) ) ++ _lcd_stem_align ( bitmap, ++ mode, ++ slot, ++ &translate_value, ++ &scale_value, ++ alignment_strength, ++ fitting_strength, ++ &embolden_value ); ++ ++ if ( align_called == 0 && ++ ( translate_value != 0 || scale_value != 1.0 ) ) ++ { ++ align_called = 1; ++ goto RERENDER; ++ } ++ ++ if ( mode == FT_RENDER_MODE_LCD ) ++ { ++ ++ if ( fringe_filter_strength > 0 /*&& autohinted*/ ) ++ _ft_lcd_fringe_filter( bitmap, ++ mode, ++ fringe_filter_strength, ++ slot->library ); ++ ++ /*if ( autohinted) ++ _ft_lcd_stem_end_filter( bitmap, mode, 100, slot->library );*/ ++ ++ if ( gamma_correction_lt > 0 && gamma_correction_value != 1.0 ) ++ _ft_lcd_gamma_correction_correction( bitmap, ++ mode, ++ slot, ++ gamma_correction_lt, ++ gamma_correction_value ); ++ ++ chromeos_cutoff = (FT_Byte)( 0.5 * 255.0 ) ++ * ( chromeos_style_sharpening_strength / 100.0 ); ++ chromeos_gamma_value = 1; ++ ++ if ( chromeos_style_sharpening_strength > 0 ) ++ _ft_lcd_chromeos_sharpen( bitmap, ++ mode, ++ chromeos_cutoff, ++ chromeos_gamma_value ); ++ ++ if ( ppem > 8 ) ++ if ( windows_style_sharpening_strength > 0 ) ++ _ft_lcd_windows_sharpen( bitmap, ++ mode, ++ windows_style_sharpening_strength, ++ slot->library ); ++ ++ if ( autohinted && ++ ( cur_width * 100 ) / 64 ++ > autohint_horizontal_stem_darken_strength && ++ autohint_horizontal_stem_darken_strength != 0 ) ++ autohint_horizontal_stem_darken_strength = ( cur_width * 100 ) / 64; ++ ++ if ( autohint_horizontal_stem_darken_strength > 100) ++ autohint_horizontal_stem_darken_strength = 100; ++ ++ /* only do on autohinted fonts */ ++ /* Necessary to do on some non-thin fonts, which is why it is outside */ ++ /* of the below conditional */ ++ if ( autohint_horizontal_stem_darken_strength > 0 && autohinted ) ++ _ft_lcd_darken_x ( bitmap, ++ mode, ++ autohint_horizontal_stem_darken_strength, ++ slot->library ); ++ ++ /* Enhance thin fonts */ ++ if ( autohinted ) ++ { ++ /* if forcibly set use that, otherwise make a good estimate */ ++ if ( slot->face && !_ft_bitmap_bc ( bitmap, ++ (float)get_brightness( slot->face->family_name, ppem ) / 300.0, ++ (float)get_contrast( slot->face->family_name, ppem ) / 300.0 ) ) ++ { ++ FT_Bool is_fixed_name = FALSE; ++ ++ if ( slot->face->family_name && ++ strcasestr(slot->face->family_name, "Mono" ) ) ++ is_fixed_name = TRUE; ++ ++ /* Darken vertical stems */ ++ _ft_lcd_darken_y ( bitmap, ++ mode, ++ autohint_vertical_stem_darken_strength, ++ slot->library ); ++ ++ /* Adjust brightness / contrast automatically based on stem width */ ++ if ( cur_width != 0 && cur_width < 30 ) ++ cur_width = 30; ++ ++ if ( cur_width >= 30 && cur_width <= 60 ) ++ { ++ float ppem_factor = sliding_scale ( 5, 11, 0.0, 1.0, ppem ); ++ float brightness_factor = sliding_scale ( 30, 52, -.3, 0.0, ++ cur_width ); ++ float contrast_factor = sliding_scale ( 30, 52, .45, 0.0, ++ cur_width ); ++ _ft_bitmap_bc ( bitmap, ++ ppem_factor * brightness_factor, ++ ppem_factor * contrast_factor ); ++ ++ /* Only cap variable width thin-stemmed fonts */ ++ if ( !FT_IS_FIXED_WIDTH( slot->face ) && !is_fixed_name ) ++ _ft_bitmap_cap ( bitmap, ++ ( cur_width * 150 ) / 64, ++ slot->library ); ++ } ++ } ++ } ++ ++ ++ if ( slot->library->lcd_filter_func ) ++ slot->library->lcd_filter_func( bitmap, mode, slot->library ); ++ ++ if ( grayscale_filter_strength > 0 ) ++ _ft_lcd_grayscale_filter( bitmap, ++ mode, ++ grayscale_filter_strength, ++ slot->library ); ++ ++ } ++ ++ /* Global values */ ++ if ( brightness_value != 0 || contrast_value != 0 ) ++ _ft_bitmap_bc ( bitmap, ++ (float)brightness_value / 300.0, ++ (float)contrast_value / 300.0); ++ ++ FT_Outline_Done( slot->library, outline_orig ); ++ } ++ else if ( mode == FT_RENDER_MODE_LCD && ++ slot->library->lcd_filter_func ) ++ slot->library->lcd_filter_func( bitmap, mode, slot->library ); ++#else + if ( slot->library->lcd_filter_func ) + slot->library->lcd_filter_func( bitmap, mode, slot->library ); + ++#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ + #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + + /* render outline into bitmap */ +@@ -359,6 +4066,20 @@ + + #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + ++ /* ++ * XXX: on 16bit system, we return an error for huge bitmap ++ * to prevent an overflow. ++ */ ++ if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ) ++ { ++ error = FT_THROW( Invalid_Pixel_Size ); ++ goto Exit; ++ } ++ ++ slot->format = FT_GLYPH_FORMAT_BITMAP; ++ slot->bitmap_left = (FT_Int)x_left; ++ slot->bitmap_top = (FT_Int)y_top; ++ + /* everything is fine; don't deallocate buffer */ + have_buffer = FALSE; + +@@ -366,7 +4087,9 @@ + + Exit: + if ( have_outline_shifted ) +- FT_Outline_Translate( outline, -x_shift, -y_shift ); ++ FT_Outline_Translate( outline, x_shift, y_shift ); ++ if ( have_translated_origin ) ++ FT_Outline_Translate( outline, -origin->x, -origin->y ); + if ( have_buffer ) + { + FT_FREE( bitmap->buffer ); +diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c +index d00a0f8..da05b5a 100644 +--- a/src/truetype/ttinterp.c ++++ b/src/truetype/ttinterp.c +@@ -5801,6 +5801,7 @@ + + if ( exc->ignore_x_mode && + exc->GS.freeVector.x != 0 && ++ exc->GS.freeVector.y == 0 && + !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) + control_value_cutin = 0; + } @@ -1,17 +1,16 @@ # Maintainer: hadrons123 <piruthviraj@gmail.com> # Maintainer: Shanto <shanto@hotmail.com> +# Maintainer: Maarten de Boer <maarten@ikfixjewebstek.nl> # Contributor: JIN Xiao-Yong <jinxiaoyong@gmail.com> # Contributor: Andre Fettouhi <A.Fettouhi@gmail.com> pkgname=freetype2-infinality -pkgver=2.4.12 -pkgrel=4 -_pkgdate=20150206 -_pkgrel=01 +pkgver=2.6 +pkgrel=1 pkgdesc="TrueType font rendering library with infinality patch" arch=(i686 x86_64) license=('GPL') -url="http://www.infinality.net/blog/infinality-freetype-patches/" +url="https://github.com/bohoomil/fontconfig-ultimate" depends=('zlib' 'bzip2' 'sh') optdepends=( 'fontconfig-infinality: Infinality package for fontconfig (required)' @@ -23,44 +22,29 @@ install='install.sh' backup=('etc/profile.d/infinality-settings.sh') source=( "http://downloads.sourceforge.net/sourceforge/freetype/freetype-${pkgver}.tar.bz2" - "http://www.infinality.net/fedora/linux/zips/freetype-infinality-2.4.12-20130514_01-x86_64.tar.bz2" - "freetype-2.2.1-enable-valid.patch::https://projects.archlinux.org/svntogit/packages.git/plain/trunk/freetype-2.2.1-enable-valid.patch?h=packages/freetype2" - "freetype-2.5.0-CVE-2014-2240.patch" - "freetype-2.5.0-CVE-2014-2241.patch" -"freetype-2.4.11-ft-strncmp.patch" -"freetype-2.4.11-CVE-2014-9657.patch" -"freetype-2.4.11-CVE-2014-9658.patch" -"freetype-2.4.11-CVE-2014-9660.patch" -"freetype-2.4.11-CVE-2014-9663.patch" -"freetype-2.4.11-CVE-2014-9667.patch" -"freetype-2.4.11-CVE-2014-9669.patch" -"freetype-2.4.11-CVE-2014-9670.patch" -"freetype-2.4.11-CVE-2014-9671.patch") + "infinality-settings.sh" + "01-freetype-2.6-enable-valid.patch" + "02-upstream-2015.08.24.patch.xz" + "03-infinality-2.6-2015.08.24.patch") +sha256sums=('8469fb8124764f85029cc8247c31e132a2c5e51084ddce2a44ea32ee4ae8347e' + '21192ce47be46ccd44e8aeea99754d4e5e38cb52717f752d67c319c74fea2716' + '086c9874ba5217dab419ac03dbc5ad6480aaa67b3c9d802f7181d8a3e007f8eb' + '62eaa124f09916e237be994890178fb041b3648223f08429566df3a962971d8a' + '241de84ca25d7ff106a3ebd5121d12a315abe5a72771957bd674e8b2e41c97d2') + build() { - rm -rf "${srcdir}/freetype-${pkgver}-build" - cp -a "${srcdir}/freetype-${pkgver}" "${srcdir}/freetype-${pkgver}-build" - cd "${srcdir}/freetype-${pkgver}-build" - cat "$srcdir/"{freetype-2.2.1-enable-valid.patch,freetype-entire-infinality-patchset-20130514-01.patch,freetype-2.4.11-CVE-2014-9657.patch,freetype-2.4.11-CVE-2014-9658.patch,freetype-2.4.11-ft-strncmp.patch,freetype-2.4.11-CVE-2014-9660.patch,freetype-2.4.11-CVE-2014-9663.patch,freetype-2.4.11-CVE-2014-9669.patch,freetype-2.4.11-CVE-2014-9670.patch,freetype-2.4.11-CVE-2014-9671.patch,freetype-2.5.0-CVE-2014-2240.patch,freetype-2.5.0-CVE-2014-2241.patch} | patch -Np1 + cd "${srcdir}/freetype-${pkgver}" + + patch -Np1 -i ../01-freetype-2.6-enable-valid.patch + patch -Np1 -i ../02-upstream-2015.08.24.patch + patch -Np1 -i ../03-infinality-2.6-2015.08.24.patch + ./configure --prefix=/usr make } package() { - cd "${srcdir}/freetype-${pkgver}-build" + cd "${srcdir}/freetype-${pkgver}" make DESTDIR="${pkgdir}" install install -D -T "${srcdir}/infinality-settings.sh" "${pkgdir}/etc/profile.d/infinality-settings.sh" } -md5sums=('3463102764315eb86c0d3c2e1f3ffb7d' - '4f5ff3fd3e3e56310953e25eade4a2d3' - '214119610444c9b02766ccee5e220680' - 'e29654122be7dbfbc828b1f890257f40' - '54d52c143c5e399972f2928d17b0f28e' - '451163e82887b59f0c0fad72a652f316' - 'd8c69d190a81133d40b92d1d2ab81c98' - '82055b1adb096766cf4269658ce5a68b' - '79e695ff3714fb66dcdadd2a4b82f418' - '817ff425988e4f91dbd08b1f4bfaf5b4' - 'a1560e1032cd0fb113aee6ce7b0c951e' - 'c5cbf68b7b2f3beeb766e8d97d9f723e' - '1bf2b83b8623ac4fed57dbe4e4f7714c' - 'f543132d39f801a230768dc133fd4870') diff --git a/freetype-2.4.11-CVE-2014-9657.patch b/freetype-2.4.11-CVE-2014-9657.patch deleted file mode 100644 index 89544067708a..000000000000 --- a/freetype-2.4.11-CVE-2014-9657.patch +++ /dev/null @@ -1,40 +0,0 @@ -From eca0f067068020870a429fe91f6329e499390d55 Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Mon, 24 Nov 2014 09:22:08 +0000 -Subject: [truetype] Fix Savannah bug #43679. - -* src/truetype/ttpload.c (tt_face_load_hdmx): Check minimum size of -`record_size'. ---- -diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c -index 9723a51..9991925 100644 ---- a/src/truetype/ttpload.c -+++ b/src/truetype/ttpload.c -@@ -508,9 +508,9 @@ - record_size = FT_NEXT_ULONG( p ); - - /* The maximum number of bytes in an hdmx device record is the */ -- /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */ -- /* the reason why `record_size' is a long (which we read as */ -- /* unsigned long for convenience). In practice, two bytes */ -+ /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus */ -+ /* explaining why `record_size' is a long (which we read as */ -+ /* unsigned long for convenience). In practice, two bytes are */ - /* sufficient to hold the size value. */ - /* */ - /* There are at least two fonts, HANNOM-A and HANNOM-B version */ -@@ -522,8 +522,10 @@ - record_size &= 0xFFFFU; - - /* The limit for `num_records' is a heuristic value. */ -- -- if ( version != 0 || num_records > 255 || record_size > 0x10001L ) -+ if ( version != 0 || -+ num_records > 255 || -+ record_size > 0x10001L || -+ record_size < 4 ) - { - error = TT_Err_Invalid_File_Format; - goto Fail; --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-CVE-2014-9658.patch b/freetype-2.4.11-CVE-2014-9658.patch deleted file mode 100644 index 7aec5c89ad3a..000000000000 --- a/freetype-2.4.11-CVE-2014-9658.patch +++ /dev/null @@ -1,23 +0,0 @@ -From f70d9342e65cd2cb44e9f26b6d7edeedf191fc6c Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Mon, 24 Nov 2014 08:31:32 +0000 -Subject: [sfnt] Fix Savannah bug #43672. - -* src/sfnt/ttkern.c (tt_face_load_kern): Use correct value for -minimum table length test. ---- -diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c -index 32c4008..455e7b5 100644 ---- a/src/sfnt/ttkern.c -+++ b/src/sfnt/ttkern.c -@@ -99,7 +99,7 @@ - length = FT_NEXT_USHORT( p ); - coverage = FT_NEXT_USHORT( p ); - -- if ( length <= 6 ) -+ if ( length <= 6 + 8 ) - break; - - p_next += length; --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-CVE-2014-9660.patch b/freetype-2.4.11-CVE-2014-9660.patch deleted file mode 100644 index fc310f7ccfc8..000000000000 --- a/freetype-2.4.11-CVE-2014-9660.patch +++ /dev/null @@ -1,29 +0,0 @@ -From af8346172a7b573715134f7a51e6c5c60fa7f2ab Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Sat, 22 Nov 2014 12:29:10 +0000 -Subject: [bdf] Fix Savannah bug #43660. - -* src/bdf/bdflib.c (_bdf_parse_glyphs) <"ENDFONT">: Check -`_BDF_GLYPH_BITS'. ---- -diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c -index c128526..369c111 100644 ---- a/src/bdf/bdflib.c -+++ b/src/bdf/bdflib.c -@@ -1549,6 +1549,14 @@ - /* Check for the ENDFONT field. */ - if ( _bdf_strncmp( line, "ENDFONT", 7 ) == 0 ) - { -+ if ( p->flags & _BDF_GLYPH_BITS ) -+ { -+ /* Missing ENDCHAR field. */ -+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENDCHAR" )); -+ error = BDF_Err_Corrupted_Font_Glyphs; -+ goto Exit; -+ } -+ - /* Sort the glyphs by encoding. */ - ft_qsort( (char *)font->glyphs, - font->glyphs_used, --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-CVE-2014-9663.patch b/freetype-2.4.11-CVE-2014-9663.patch deleted file mode 100644 index 9e2496a4a59c..000000000000 --- a/freetype-2.4.11-CVE-2014-9663.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 9bd20b7304aae61de5d50ac359cf27132bafd4c1 Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Sat, 22 Nov 2014 05:24:45 +0000 -Subject: [sfnt] Fix Savannah bug #43656. - -* src/sfnt/ttcmap.c (tt_cmap4_validate): Fix order of validity -tests. ---- -diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c -index 712bd4f..fb863c3 100644 ---- a/src/sfnt/ttcmap.c -+++ b/src/sfnt/ttcmap.c -@@ -823,9 +823,6 @@ - FT_Error error = SFNT_Err_Ok; - - -- if ( length < 16 ) -- FT_INVALID_TOO_SHORT; -- - /* in certain fonts, the `length' field is invalid and goes */ - /* out of bound. We try to correct this here... */ - if ( table + length > valid->limit ) -@@ -836,6 +833,9 @@ - length = (FT_UInt)( valid->limit - table ); - } - -+ if ( length < 16 ) -+ FT_INVALID_TOO_SHORT; -+ - p = table + 6; - num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ - --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-CVE-2014-9667.patch b/freetype-2.4.11-CVE-2014-9667.patch deleted file mode 100644 index 1e349405c408..000000000000 --- a/freetype-2.4.11-CVE-2014-9667.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 677ddf4f1dc1b36cef7c7ddd59a14c508f4b1891 Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Wed, 12 Nov 2014 20:26:44 +0000 -Subject: [sfnt] Fix Savannah bug #43590. - -* src/sfnt/ttload.c (check_table_dir, tt_face_load_font_dir): -Protect against addition overflow. ---- -diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c -index 0a3cd29..8338150 100644 ---- a/src/sfnt/ttload.c -+++ b/src/sfnt/ttload.c -@@ -5,7 +5,7 @@ - /* Load the basic TrueType tables, i.e., tables that can be either in */ - /* TTF or OTF fonts (body). */ - /* */ --/* Copyright 1996-2010, 2012 by */ -+/* Copyright 1996-2010, 2012-2014 by */ - /* David Turner, Robert Wilhelm, and Werner Lemberg. */ - /* */ - /* This file is part of the FreeType project, and may only be used, */ -@@ -207,7 +207,10 @@ - } - - /* we ignore invalid tables */ -- if ( table.Offset + table.Length > stream->size ) -+ -+ /* table.Offset + table.Length > stream->size ? */ -+ if ( table.Length > stream->size || -+ table.Offset > stream->size - table.Length ) - { - FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); - continue; -@@ -398,7 +398,10 @@ - entry->Length = FT_GET_LONG(); - - /* ignore invalid tables */ -- if ( entry->Offset + entry->Length > stream->size ) -+ -+ /* entry->Offset + entry->Length > stream->size ? */ -+ if ( entry->Length > stream->size || -+ entry->Offset > stream->size - entry->Length ) - continue; - else - { --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-CVE-2014-9669.patch b/freetype-2.4.11-CVE-2014-9669.patch deleted file mode 100644 index 59fe8c3b67cd..000000000000 --- a/freetype-2.4.11-CVE-2014-9669.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 602040b1112c9f94d68e200be59ea7ac3d104565 Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Wed, 12 Nov 2014 19:51:20 +0000 -Subject: [sfnt] Fix Savannah bug #43588. - -* src/sfnt/ttcmap.c (tt_cmap8_validate, tt_cmap10_validate, -tt_cmap12_validate, tt_cmap13_validate, tt_cmap14_validate): Protect -against overflow in additions and multiplications. ---- -diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c -index f9acf5d..712bd4f 100644 ---- a/src/sfnt/ttcmap.c -+++ b/src/sfnt/ttcmap.c -@@ -1647,7 +1647,8 @@ - p = is32 + 8192; /* skip `is32' array */ - num_groups = TT_NEXT_ULONG( p ); - -- if ( p + num_groups * 12 > valid->limit ) -+ /* p + num_groups * 12 > valid->limit ? */ -+ if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 ) - FT_INVALID_TOO_SHORT; - - /* check groups, they must be in increasing order */ -@@ -1672,7 +1673,12 @@ - - if ( valid->level >= FT_VALIDATE_TIGHT ) - { -- if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) -+ FT_UInt32 d = end - start; -+ -+ -+ /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */ -+ if ( d > TT_VALID_GLYPH_COUNT( valid ) || -+ start_id >= TT_VALID_GLYPH_COUNT( valid ) - d ) - FT_INVALID_GLYPH_ID; - - count = (FT_UInt32)( end - start + 1 ); -@@ -1870,7 +1876,9 @@ - count = TT_NEXT_ULONG( p ); - - if ( length > (FT_ULong)( valid->limit - table ) || -- length < 20 + count * 2 ) -+ /* length < 20 + count * 2 ? */ -+ length < 20 || -+ ( length - 20 ) / 2 < count ) - FT_INVALID_TOO_SHORT; - - /* check glyph indices */ -@@ -2057,7 +2065,9 @@ - num_groups = TT_NEXT_ULONG( p ); - - if ( length > (FT_ULong)( valid->limit - table ) || -- length < 16 + 12 * num_groups ) -+ /* length < 16 + 12 * num_groups ? */ -+ length < 16 || -+ ( length - 16 ) / 12 < num_groups ) - FT_INVALID_TOO_SHORT; - - /* check groups, they must be in increasing order */ -@@ -2079,7 +2089,12 @@ - - if ( valid->level >= FT_VALIDATE_TIGHT ) - { -- if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) -+ FT_UInt32 d = end - start; -+ -+ -+ /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */ -+ if ( d > TT_VALID_GLYPH_COUNT( valid ) || -+ start_id >= TT_VALID_GLYPH_COUNT( valid ) - d ) - FT_INVALID_GLYPH_ID; - } - -@@ -2381,7 +2396,9 @@ - num_groups = TT_NEXT_ULONG( p ); - - if ( length > (FT_ULong)( valid->limit - table ) || -- length < 16 + 12 * num_groups ) -+ /* length < 16 + 12 * num_groups ? */ -+ length < 16 || -+ ( length - 16 ) / 12 < num_groups ) - FT_INVALID_TOO_SHORT; - - /* check groups, they must be in increasing order */ -@@ -2762,7 +2779,9 @@ - - - if ( length > (FT_ULong)( valid->limit - table ) || -- length < 10 + 11 * num_selectors ) -+ /* length < 10 + 11 * num_selectors ? */ -+ length < 10 || -+ ( length - 10 ) / 11 < num_selectors ) - FT_INVALID_TOO_SHORT; - - /* check selectors, they must be in increasing order */ -@@ -2798,7 +2817,8 @@ - FT_ULong lastBase = 0; - - -- if ( defp + numRanges * 4 > valid->limit ) -+ /* defp + numRanges * 4 > valid->limit ? */ -+ if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 ) - FT_INVALID_TOO_SHORT; - - for ( i = 0; i < numRanges; ++i ) -@@ -2825,7 +2845,8 @@ - FT_ULong i, lastUni = 0; - - -- if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ) -+ /* numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ? */ -+ if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 4 ) - FT_INVALID_TOO_SHORT; - - for ( i = 0; i < numMappings; ++i ) --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-CVE-2014-9670.patch b/freetype-2.4.11-CVE-2014-9670.patch deleted file mode 100644 index 0a9b70a03e20..000000000000 --- a/freetype-2.4.11-CVE-2014-9670.patch +++ /dev/null @@ -1,30 +0,0 @@ -From ef1eba75187adfac750f326b563fe543dd5ff4e6 Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Thu, 06 Nov 2014 22:25:05 +0000 -Subject: Fix Savannah bug #43548. - -* src/pcf/pcfread (pcf_get_encodings): Add sanity checks for row and -column values. ---- -diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c -index 8db31bd..668c962 100644 ---- a/src/pcf/pcfread.c -+++ b/src/pcf/pcfread.c -@@ -812,6 +812,15 @@ THE SOFTWARE. - if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) - return PCF_Err_Invalid_File_Format; - -+ /* sanity checks */ -+ if ( firstCol < 0 || -+ firstCol > lastCol || -+ lastCol > 0xFF || -+ firstRow < 0 || -+ firstRow > lastRow || -+ lastRow > 0xFF ) -+ return PCF_Err_Invalid_Table; -+ - FT_TRACE4(( "pdf_get_encodings:\n" )); - - FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-CVE-2014-9671.patch b/freetype-2.4.11-CVE-2014-9671.patch deleted file mode 100644 index a29115095cd7..000000000000 --- a/freetype-2.4.11-CVE-2014-9671.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0e2f5d518c60e2978f26400d110eff178fa7e3c3 Mon Sep 17 00:00:00 2001 -From: Werner Lemberg <wl@gnu.org> -Date: Thu, 06 Nov 2014 21:32:46 +0000 -Subject: Fix Savannah bug #43547. - -* src/pcf/pcfread.c (pcf_read_TOC): Check `size' and `offset' -values. ---- -diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c -index f63377b..8db31bd 100644 ---- a/src/pcf/pcfread.c -+++ b/src/pcf/pcfread.c -@@ -151,6 +151,21 @@ THE SOFTWARE. - break; - } - -+ /* we now check whether the `size' and `offset' values are reasonable: */ -+ /* `offset' + `size' must not exceed the stream size */ -+ tables = face->toc.tables; -+ for ( n = 0; n < toc->count; n++ ) -+ { -+ /* we need two checks to avoid overflow */ -+ if ( ( tables->size > stream->size ) || -+ ( tables->offset > stream->size - tables->size ) ) -+ { -+ error = PCF_Err_Invalid_Table; -+ goto Exit; -+ } -+ tables++; -+ } -+ - #ifdef FT_DEBUG_LEVEL_TRACE - - { --- -cgit v0.9.0.2 diff --git a/freetype-2.4.11-ft-strncmp.patch b/freetype-2.4.11-ft-strncmp.patch deleted file mode 100644 index 6de33c58b304..000000000000 --- a/freetype-2.4.11-ft-strncmp.patch +++ /dev/null @@ -1,228 +0,0 @@ -commit 9a56764037dfc01a89fe61f5c67971bf50343d00 -Author: Werner Lemberg <wl@gnu.org> -Date: Wed Feb 26 13:08:07 2014 +0100 - - [bdf] Fix Savannah bug #41692. - - bdflib puts data from the input stream into a buffer in chunks of - 1024 bytes. The data itself gets then parsed line by line, simply - increasing the current pointer into the buffer; if the search for - the final newline character exceeds the buffer size, more data gets - read. - - However, in case the current line's end is very near to the buffer - end, and the keyword to compare with is longer than the current - line's length, an out-of-bounds read might happen since `memcmp' - doesn't stop properly at the string end. - - * src/bdf/bdflib.c: s/ft_memcmp/ft_strncmp/ to make comparisons - stop at string ends. - -diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c -index c9e231e..b0ec292 100644 ---- a/src/bdf/bdflib.c -+++ b/src/bdf/bdflib.c -@@ -1402,7 +1402,7 @@ - - /* If the property happens to be a comment, then it doesn't need */ - /* to be added to the internal hash table. */ -- if ( ft_memcmp( name, "COMMENT", 7 ) != 0 ) -+ if ( ft_strncmp( name, "COMMENT", 7 ) != 0 ) - { - /* Add the property to the font property table. */ - error = hash_insert( fp->name, -@@ -1420,13 +1420,13 @@ - /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */ - /* present, and the SPACING property should override the default */ - /* spacing. */ -- if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 ) -+ if ( ft_strncmp( name, "DEFAULT_CHAR", 12 ) == 0 ) - font->default_char = fp->value.l; -- else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 ) -+ else if ( ft_strncmp( name, "FONT_ASCENT", 11 ) == 0 ) - font->font_ascent = fp->value.l; -- else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 ) -+ else if ( ft_strncmp( name, "FONT_DESCENT", 12 ) == 0 ) - font->font_descent = fp->value.l; -- else if ( ft_memcmp( name, "SPACING", 7 ) == 0 ) -+ else if ( ft_strncmp( name, "SPACING", 7 ) == 0 ) - { - if ( !fp->value.atom ) - { -@@ -1484,7 +1484,7 @@ - memory = font->memory; - - /* Check for a comment. */ -- if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) -+ if ( ft_strncmp( line, "COMMENT", 7 ) == 0 ) - { - linelen -= 7; - -@@ -1501,7 +1501,7 @@ - /* The very first thing expected is the number of glyphs. */ - if ( !( p->flags & _BDF_GLYPHS ) ) - { -- if ( ft_memcmp( line, "CHARS", 5 ) != 0 ) -+ if ( ft_strncmp( line, "CHARS", 5 ) != 0 ) - { - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" )); - error = BDF_Err_Missing_Chars_Field; -@@ -1535,7 +1535,7 @@ - } - - /* Check for the ENDFONT field. */ -- if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 ) -+ if ( ft_strncmp( line, "ENDFONT", 7 ) == 0 ) - { - /* Sort the glyphs by encoding. */ - ft_qsort( (char *)font->glyphs, -@@ -1549,7 +1549,7 @@ - } - - /* Check for the ENDCHAR field. */ -- if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 ) -+ if ( ft_strncmp( line, "ENDCHAR", 7 ) == 0 ) - { - p->glyph_enc = 0; - p->flags &= ~_BDF_GLYPH_BITS; -@@ -1565,7 +1565,7 @@ - goto Exit; - - /* Check for the STARTCHAR field. */ -- if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 ) -+ if ( ft_strncmp( line, "STARTCHAR", 9 ) == 0 ) - { - /* Set the character name in the parse info first until the */ - /* encoding can be checked for an unencoded character. */ -@@ -1599,7 +1599,7 @@ - } - - /* Check for the ENCODING field. */ -- if ( ft_memcmp( line, "ENCODING", 8 ) == 0 ) -+ if ( ft_strncmp( line, "ENCODING", 8 ) == 0 ) - { - if ( !( p->flags & _BDF_GLYPH ) ) - { -@@ -1785,7 +1785,7 @@ - } - - /* Expect the SWIDTH (scalable width) field next. */ -- if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 ) -+ if ( ft_strncmp( line, "SWIDTH", 6 ) == 0 ) - { - if ( !( p->flags & _BDF_ENCODING ) ) - goto Missing_Encoding; -@@ -1801,7 +1801,7 @@ - } - - /* Expect the DWIDTH (scalable width) field next. */ -- if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 ) -+ if ( ft_strncmp( line, "DWIDTH", 6 ) == 0 ) - { - if ( !( p->flags & _BDF_ENCODING ) ) - goto Missing_Encoding; -@@ -1829,7 +1829,7 @@ - } - - /* Expect the BBX field next. */ -- if ( ft_memcmp( line, "BBX", 3 ) == 0 ) -+ if ( ft_strncmp( line, "BBX", 3 ) == 0 ) - { - if ( !( p->flags & _BDF_ENCODING ) ) - goto Missing_Encoding; -@@ -1897,7 +1897,7 @@ - } - - /* And finally, gather up the bitmap. */ -- if ( ft_memcmp( line, "BITMAP", 6 ) == 0 ) -+ if ( ft_strncmp( line, "BITMAP", 6 ) == 0 ) - { - unsigned long bitmap_size; - -@@ -1972,7 +1972,7 @@ - p = (_bdf_parse_t *) client_data; - - /* Check for the end of the properties. */ -- if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 ) -+ if ( ft_strncmp( line, "ENDPROPERTIES", 13 ) == 0 ) - { - /* If the FONT_ASCENT or FONT_DESCENT properties have not been */ - /* encountered yet, then make sure they are added as properties and */ -@@ -2013,12 +2013,12 @@ - } - - /* Ignore the _XFREE86_GLYPH_RANGES properties. */ -- if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 ) -+ if ( ft_strncmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 ) - goto Exit; - - /* Handle COMMENT fields and properties in a special way to preserve */ - /* the spacing. */ -- if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) -+ if ( ft_strncmp( line, "COMMENT", 7 ) == 0 ) - { - name = value = line; - value += 7; -@@ -2082,7 +2082,7 @@ - - /* Check for a comment. This is done to handle those fonts that have */ - /* comments before the STARTFONT line for some reason. */ -- if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) -+ if ( ft_strncmp( line, "COMMENT", 7 ) == 0 ) - { - if ( p->opts->keep_comments != 0 && p->font != 0 ) - { -@@ -2108,7 +2108,7 @@ - { - memory = p->memory; - -- if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 ) -+ if ( ft_strncmp( line, "STARTFONT", 9 ) != 0 ) - { - /* we don't emit an error message since this code gets */ - /* explicitly caught one level higher */ -@@ -2156,7 +2156,7 @@ - } - - /* Check for the start of the properties. */ -- if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 ) -+ if ( ft_strncmp( line, "STARTPROPERTIES", 15 ) == 0 ) - { - if ( !( p->flags & _BDF_FONT_BBX ) ) - { -@@ -2185,7 +2185,7 @@ - } - - /* Check for the FONTBOUNDINGBOX field. */ -- if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 ) -+ if ( ft_strncmp( line, "FONTBOUNDINGBOX", 15 ) == 0 ) - { - if ( !( p->flags & _BDF_SIZE ) ) - { -@@ -2216,7 +2216,7 @@ - } - - /* The next thing to check for is the FONT field. */ -- if ( ft_memcmp( line, "FONT", 4 ) == 0 ) -+ if ( ft_strncmp( line, "FONT", 4 ) == 0 ) - { - error = _bdf_list_split( &p->list, (char *)" +", line, linelen ); - if ( error ) -@@ -2251,7 +2251,7 @@ - } - - /* Check for the SIZE field. */ -- if ( ft_memcmp( line, "SIZE", 4 ) == 0 ) -+ if ( ft_strncmp( line, "SIZE", 4 ) == 0 ) - { - if ( !( p->flags & _BDF_FONT_NAME ) ) - { -@@ -2305,7 +2305,7 @@ - } - - /* Check for the CHARS field -- font properties are optional */ -- if ( ft_memcmp( line, "CHARS", 5 ) == 0 ) -+ if ( ft_strncmp( line, "CHARS", 5 ) == 0 ) - { - char nbuf[128]; - diff --git a/freetype-2.5.0-CVE-2014-2240.patch b/freetype-2.5.0-CVE-2014-2240.patch deleted file mode 100644 index d838de3a265e..000000000000 --- a/freetype-2.5.0-CVE-2014-2240.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0eae6eb0645264c98812f0095e0f5df4541830e6 Mon Sep 17 00:00:00 2001 -From: Dave Arnold <darnold@adobe.com> -Date: Fri, 28 Feb 2014 06:40:01 +0000 -Subject: Fix Savannah bug #41697, part 1. - -* src/cff/cf2hints.c (cf2_hintmap_build): Return when `hintMask' is -invalid. In this case, it is not safe to use the length of -`hStemHintArray'; the exception has already been recorded in -`hintMask'. ---- -diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c -index 5f44161..79f84fc 100644 ---- a/src/cff/cf2hints.c -+++ b/src/cff/cf2hints.c -@@ -781,6 +781,8 @@ - cf2_hintmask_setAll( hintMask, - cf2_arrstack_size( hStemHintArray ) + - cf2_arrstack_size( vStemHintArray ) ); -+ if ( !cf2_hintmask_isValid( hintMask ) ) -+ return; /* too many stem hints */ - } - - /* begin by clearing the map */ --- -cgit v0.9.0.2 diff --git a/freetype-2.5.0-CVE-2014-2241.patch b/freetype-2.5.0-CVE-2014-2241.patch deleted file mode 100644 index 3e6cd60c9bbc..000000000000 --- a/freetype-2.5.0-CVE-2014-2241.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 135c3faebb96f8f550bd4f318716f2e1e095a969 Mon Sep 17 00:00:00 2001 -From: Dave Arnold <darnold@adobe.com> -Date: Fri, 28 Feb 2014 06:42:42 +0000 -Subject: Fix Savannah bug #41697, part 2. - -* src/cff/cf2ft.c (cf2_initLocalRegionBuffer, -cf2_initGlobalRegionBuffer): It is possible for a charstring to call -a subroutine if no subroutines exist. This is an error but should -not trigger an assert. Split the assert to account for this. ---- -diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c -index df5f8fb..82bac75 100644 ---- a/src/cff/cf2ft.c -+++ b/src/cff/cf2ft.c -@@ -521,7 +521,7 @@ - CF2_UInt idx, - CF2_Buffer buf ) - { -- FT_ASSERT( decoder && decoder->globals ); -+ FT_ASSERT( decoder ); - - FT_ZERO( buf ); - -@@ -529,6 +529,8 @@ - if ( idx >= decoder->num_globals ) - return TRUE; /* error */ - -+ FT_ASSERT( decoder->globals ); -+ - buf->start = - buf->ptr = decoder->globals[idx]; - buf->end = decoder->globals[idx + 1]; -@@ -594,7 +596,7 @@ - CF2_UInt idx, - CF2_Buffer buf ) - { -- FT_ASSERT( decoder && decoder->locals ); -+ FT_ASSERT( decoder ); - - FT_ZERO( buf ); - -@@ -602,6 +604,8 @@ - if ( idx >= decoder->num_locals ) - return TRUE; /* error */ - -+ FT_ASSERT( decoder->locals ); -+ - buf->start = - buf->ptr = decoder->locals[idx]; - buf->end = decoder->locals[idx + 1]; --- -cgit v0.9.0.2 diff --git a/infinality-settings.sh b/infinality-settings.sh new file mode 100755 index 000000000000..f293c652ead0 --- /dev/null +++ b/infinality-settings.sh @@ -0,0 +1,48 @@ +### freetype2-infinality-ultimate settings ### +### rev. 0.4.8.3, for freetype2 v.2.5.x ### +### ### +### Copyright (c) 2014 bohoomil ### +### The MIT License (MIT) http://opensource.org/licenses/MIT ### +### part of infinality-bundle http://bohoomil.com ### + + +XFT_SETTINGS=" +Xft.antialias: 1 +Xft.autohint: 0 +Xft.dpi: 96 +Xft.hinting: 1 +Xft.hintstyle: hintfull +Xft.lcdfilter: lcddefault +Xft.rgba: rgb +" + +echo "$XFT_SETTINGS" | xrdb -merge > /dev/null 2>&1 + +### Available styles: +### 1 <> extra sharp +### 2 <> sharper & lighter ultimate +### 3 <> ultimate: well balanced (default) +### 4 <> darker & smoother +### 5 <> darkest & heaviest ("MacIsh") + +USE_STYLE="3" + +if [ "$USE_STYLE" = "1" ]; then + export INFINALITY_FT_FILTER_PARAMS="04 22 38 22 04" +elif [ "$USE_STYLE" = "2" ]; then + export INFINALITY_FT_FILTER_PARAMS="06 22 36 22 06" +elif [ "$USE_STYLE" = "3" ]; then + export INFINALITY_FT_FILTER_PARAMS="08 24 36 24 08" +elif [ "$USE_STYLE" = "4" ]; then + export INFINALITY_FT_FILTER_PARAMS="10 25 37 25 10" +elif [ "$USE_STYLE" = "5" ]; then + export INFINALITY_FT_FILTER_PARAMS="12 28 42 28 12" +fi + +export INFINALITY_FT_FRINGE_FILTER_STRENGTH="25" +export INFINALITY_FT_USE_VARIOUS_TWEAKS="true" +export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH="25" +export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH="15" +export INFINALITY_FT_STEM_FITTING_STRENGTH="15" + +# vim:ft=sh: |