summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaarten de Boer2015-08-31 17:31:56 +0200
committerMaarten de Boer2015-08-31 19:20:13 +0200
commitb5e7833b99c67854a9f8db663edd825dd87831e7 (patch)
treea32d718daf84ee480e2663dad11530fe4e80a8d6
parent619a79ad7ef869b81ee83ce63247db2300594337 (diff)
downloadaur-b5e7833b99c67854a9f8db663edd825dd87831e7.tar.gz
Updated to 2.6 with patches from github
-rw-r--r--.SRCINFO46
-rw-r--r--01-freetype-2.6-enable-valid.patch20
-rw-r--r--02-upstream-2015.08.24.patch.xzbin0 -> 231920 bytes
-rw-r--r--03-infinality-2.6-2015.08.24.patch4839
-rw-r--r--PKGBUILD58
-rw-r--r--freetype-2.4.11-CVE-2014-9657.patch40
-rw-r--r--freetype-2.4.11-CVE-2014-9658.patch23
-rw-r--r--freetype-2.4.11-CVE-2014-9660.patch29
-rw-r--r--freetype-2.4.11-CVE-2014-9663.patch34
-rw-r--r--freetype-2.4.11-CVE-2014-9667.patch47
-rw-r--r--freetype-2.4.11-CVE-2014-9669.patch117
-rw-r--r--freetype-2.4.11-CVE-2014-9670.patch30
-rw-r--r--freetype-2.4.11-CVE-2014-9671.patch36
-rw-r--r--freetype-2.4.11-ft-strncmp.patch228
-rw-r--r--freetype-2.5.0-CVE-2014-2240.patch25
-rw-r--r--freetype-2.5.0-CVE-2014-2241.patch52
-rwxr-xr-xinfinality-settings.sh48
17 files changed, 4942 insertions, 730 deletions
diff --git a/.SRCINFO b/.SRCINFO
index a75a2940b0f6..978b59bfe0ab 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -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
new file mode 100644
index 000000000000..4d2493b9eb05
--- /dev/null
+++ b/02-upstream-2015.08.24.patch.xz
Binary files differ
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;
+ }
diff --git a/PKGBUILD b/PKGBUILD
index a34b3b31abd3..f4a1e3878a79 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -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: