summaryrefslogtreecommitdiffstats
path: root/testing
diff options
context:
space:
mode:
authorCarlo Landmeter <clandmeter@gmail.com>2014-10-29 15:41:04 +0100
committerCarlo Landmeter <clandmeter@gmail.com>2014-10-29 15:41:04 +0100
commit49a5bbad77b43010542ced663cdb1faf15316cfa (patch)
tree741e746c2fe81497d779fe20ca699b9d367fe35c /testing
parent9c28cbe94caec3865f2032dc468364436829c929 (diff)
downloadaports-49a5bbad77b43010542ced663cdb1faf15316cfa.tar.bz2
aports-49a5bbad77b43010542ced663cdb1faf15316cfa.tar.xz
testing/freetype-infinality: upgrade to 2.5.3
Diffstat (limited to 'testing')
-rw-r--r--testing/freetype-infinality/APKBUILD36
-rw-r--r--testing/freetype-infinality/freetype-2.5.3-enable-valid.patch (renamed from testing/freetype-infinality/freetype-2.2.1-enable-valid.patch)8
-rw-r--r--testing/freetype-infinality/infinality-2.5.3-2014.10.08.patch (renamed from testing/freetype-infinality/freetype-entire-infinality-patchset-20130514-01.patch)1213
-rw-r--r--testing/freetype-infinality/infinality-settings.sh1147
-rw-r--r--testing/freetype-infinality/upstream-2014.10.08.patch6990
5 files changed, 7179 insertions, 2215 deletions
diff --git a/testing/freetype-infinality/APKBUILD b/testing/freetype-infinality/APKBUILD
index 0b031cfd5..8bfd971bc 100644
--- a/testing/freetype-infinality/APKBUILD
+++ b/testing/freetype-infinality/APKBUILD
@@ -1,7 +1,7 @@
# Contributor: Carlo Landmeter <clandmeter@gmail.com>
# Maintainer:
pkgname=freetype-infinality
-pkgver=2.4.12
+pkgver=2.5.3
pkgrel=0
pkgdesc="TrueType font rendering library with infinality patch"
url="ttp://www.infinality.net/blog/infinality-freetype-patches/"
@@ -14,9 +14,10 @@ install=""
replaces="freetype"
subpackages="$pkgname-dev"
source="http://downloads.sourceforge.net/sourceforge/freetype/freetype-${pkgver}.tar.bz2
- freetype-entire-infinality-patchset-20130514-01.patch
- infinality-settings.sh
- freetype-2.2.1-enable-valid.patch"
+ upstream-2014.10.08.patch
+ freetype-2.5.3-enable-valid.patch
+ infinality-2.5.3-2014.10.08.patch
+ infinality-settings.sh"
_builddir=$srcdir/freetype-$pkgver
@@ -52,15 +53,18 @@ package() {
rm -f "$pkgdir"/usr/lib/*.la
}
-md5sums="3463102764315eb86c0d3c2e1f3ffb7d freetype-2.4.12.tar.bz2
-62ed195ffdf79c4e9089b8979ad64b7f freetype-entire-infinality-patchset-20130514-01.patch
-a952b8aee85f2f4a5a9dc872b678b97f infinality-settings.sh
-214119610444c9b02766ccee5e220680 freetype-2.2.1-enable-valid.patch"
-sha256sums="a78a17486689ab6852a9e1a759b179827ac9dfd7e2f237ddf169c73398c85381 freetype-2.4.12.tar.bz2
-dd062da4217c366dc715562e4b2aa194ffef9cee8589509e1ef1a4ef832a99cb freetype-entire-infinality-patchset-20130514-01.patch
-51d456528e60824f53e9d270b775de21dfa78bdb257f7e69d28737d5ac0e62d5 infinality-settings.sh
-54c83a91b0b2ad7edad7df00a2c26a11ca18431a8e323db9471268a139c46f7e freetype-2.2.1-enable-valid.patch"
-sha512sums="e028d603133c15f02f891b53c634b4243c541efbe8d9fcaa7b86582175e7749bc9198eddbe2fedcfe49359367ab9e9e0e29373f3a82f67599edf997866a2f501 freetype-2.4.12.tar.bz2
-816fed28ccd6ff73f186c564983aeb3342c0350d6a74ad7ccc56f5d6353d4ab940949faced212d214447db857ba360364d15035661a2654ba8a348d848c42ff7 freetype-entire-infinality-patchset-20130514-01.patch
-62b619b1161c8345932b222cf2812c555a54bfdf27d82cbba4505d6a7635555e3e7316b7b82f35e176d9404d3d27a3411023501b601eeb1d569f4ebbe41f0447 infinality-settings.sh
-de2aaa19a1eed20b026263e8865bd0da9a162b82967f1ce95e07f0ee7bee87bd109616b61b46142a443abe80ae794b8d664c788d7c53d8d4a228ab8a838d4165 freetype-2.2.1-enable-valid.patch"
+md5sums="d6b60f06bfc046e43ab2a6cbfd171d65 freetype-2.5.3.tar.bz2
+bd394dec102e48b34689869765b912c9 upstream-2014.10.08.patch
+aa55f7eae584dec7463930ab71ad3dc2 freetype-2.5.3-enable-valid.patch
+20dcb30fe4669b7239188e091708dfc6 infinality-2.5.3-2014.10.08.patch
+1b79263b344e4ca1e412f33da8399dbc infinality-settings.sh"
+sha256sums="c0848b29d52ef3ca27ad92e08351f023c5e24ce8cea7d8fe69fc96358e65f75e freetype-2.5.3.tar.bz2
+e63212a4e032470ac46fa459480fadf0dbee190e5d7040f1181d9465127053dd upstream-2014.10.08.patch
+086c9874ba5217dab419ac03dbc5ad6480aaa67b3c9d802f7181d8a3e007f8eb freetype-2.5.3-enable-valid.patch
+27199bfe792992f9db67a2f9776bde12efc0e809af7f538ac897991705d8853b infinality-2.5.3-2014.10.08.patch
+ec0cd975d5f5a4dd3363c6b92a49673ffad1460e48ddcddf5afeb2a3a9d60d9b infinality-settings.sh"
+sha512sums="bdd779dc11e9fdb52dfa87839ccc40293df3ea417da0232feadf0e711caa3e62ff145e9afdfd9c3d158df0bc69a805cfbf05b18af8ae7ab5a65213e9c66d242e freetype-2.5.3.tar.bz2
+7c4613849436096bfdb620ac7fd52859c083868f01c43c9f59a3407bda4fce826f657a4432653c4339b7bffbb7616e6f86bb40e642f6a02166622247a31973bd upstream-2014.10.08.patch
+1cefdab6a2de6dbae84140007b47a644bd2de72c112f7b0e9c17810df8897c768b8ce584863e9643405df27ffb4476830dd9a295af02b5ac2379e1bb9b1bb21f freetype-2.5.3-enable-valid.patch
+d041f3cf0413be82802dac4d48c25db808c95e94fa63c63bef148afe9d77393011cc2fae77e7dd5c83d6259070131a77a693e30f949337e59e1cb42250ed3611 infinality-2.5.3-2014.10.08.patch
+0d19740d71e8d1f283db3db1e0d66a2d500ea644155b02ee7fe0ec0cdd20146b07cba497594590157df8afee9ffb729f13fc6867f10322fba87e9c31a34ec318 infinality-settings.sh"
diff --git a/testing/freetype-infinality/freetype-2.2.1-enable-valid.patch b/testing/freetype-infinality/freetype-2.5.3-enable-valid.patch
index c78b6b70f..df81058b1 100644
--- a/testing/freetype-infinality/freetype-2.2.1-enable-valid.patch
+++ b/testing/freetype-infinality/freetype-2.5.3-enable-valid.patch
@@ -1,6 +1,6 @@
---- freetype-2.2.1/modules.cfg.orig 2006-07-07 21:01:09.000000000 -0400
-+++ freetype-2.2.1/modules.cfg 2006-07-07 21:01:54.000000000 -0400
-@@ -110,7 +110,7 @@
+--- 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.
@@ -9,7 +9,7 @@
# Support for streams compressed with gzip (files with suffix .gz).
#
-@@ -124,7 +124,7 @@
+@@ -129,7 +129,7 @@ AUX_MODULES += bzip2
# OpenType table validation. Needs ftotval.c below.
#
diff --git a/testing/freetype-infinality/freetype-entire-infinality-patchset-20130514-01.patch b/testing/freetype-infinality/infinality-2.5.3-2014.10.08.patch
index 873561db4..9e117d9fa 100644
--- a/testing/freetype-infinality/freetype-entire-infinality-patchset-20130514-01.patch
+++ b/testing/freetype-infinality/infinality-2.5.3-2014.10.08.patch
@@ -1,242 +1,5 @@
-After 20130513:
-
-Fix crash issue with certain fonts
-
-Fix issue with Courier New rendering
-
-Disable trace debug messages
-
-
-
-After 20130104:
-
-(ftsmooth.c) Perform additional checks in conditionals to prevent crashing.
-
-(ttsubpix.c) Remove unnecessary rules.
-
-(ttinterp.c) Enhance various functions with better default detection.
-
-(ttsubpix.c) Fix Load performance.
-
-Compatibility with Freetype 2.4.12
-
-Merge the subpixel-enable patch into the main patch
-
-
-
-
-After 20120616:
-
-Code simplification: Restore original rounding functions, and instead skip them outside when necessary.
-
-Fix Verdana/dejavu/verasans 12px 'a' spacing issue. Also make italics appearance consistent with regular.
-
-Lucida Grande Bold 'y' fixed.
-
-Substantial code formatting cleanup across all patches.
-
-Remove floating point arithmetic in subpixel patch. (Autohint patch eventually)
-
-Standardize the data types used to FT data types in subpixel patch
-
-Additional fixes with Verdana from Windows 7 SP1.
-
-
-
-After 20120615:
-
-Fix issue with Chrome and Verdana from Windows 7 SP1.
-
-
-
-
-After 20120403:
-
-Infinality autohint patches
-===========================
-Fix the forced slight hinting logic
-
-Enhance artificial emboldening at larger ppems
-
-
-Infinality subpixel patches
-===========================
-Substantial simplification of the TT rules, which helps with all the rest of the following improvements.
-
-Preparation for submission into Freetype tree.
-
-Fix Ubuntu S M N
-
-Courier fixes
-
-Make all fonts use standard (non-subpixel) TT hinting for characters '>' and '<'.
-
-Marked improvement on many non-Latin fonts, including Meiryo.
-
-Fix Oxygen rendering if usint TT hinting, and other ttfautohinted fonts
-
-Code cleanup
-
-
-Infinality Fontconfig Package
-=============================
-
-Add more fonts to the TT hinted list
-
-Fixes for font alias (thanks Yegorius)
-
-
-
-
-After 20111223:
-
-Get rid of TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS and do this by default if TT_CONFIG_OPTION_SUBPIXEL_HINTING is enabled.
-
-Update to Freetype 2.4.9
-
-Fix sdl_ttf
-
-Code cleanup
-
-Prevent crashes in OSX mode (thanks Markser)
-
-
-
-
-After 20111125:
-
-Courier New Hack for '2'.
-
-Tweak Arial 16px a bit.
-
-Various tweaks on Courier New, Times NR, Arial, Verdana and others that create a general improvement in appearance at certain ppems.
-
-Fixes on some Cyrillic glyphs
-
-Pragmata Pro and Pragmata added to patches
-
-Be a little more conservative in the way "known settings" of fonts are done.
-
-Many small improvements to the subpixel hinting patch.
-
-Fix a crasher in the Windows sharpening algorithm.
-
-Noticible improvement on spacing in Tahoma 11px, Arial 11px, and other Arial clones. Me likey.
-
-Code fixes to prevent some warnings and possible crashes. (Thanks banta)
-
-Fix Opera and Firefox crashes. slot->face->style_name and slot->face->family_name need to be checked for not NULL before using.
-
-
-
-
-After 20111117:
-
-Fix issue that prevented stem alignment on thin autohinted stems
-
-Fix regression in Arial italics
-
-Fix problem with bitmap copies in filters. Remove unnecessary processing.
-
-Added an internal capping filter that helps even out the filtering of very light/thin stems.
-
-General consistent and smoother appearance on very light/thin stems
-
-Add TT rules to make Droid fonts render more nicely if using TT hinter for them.
-
-TT fixes for Bitstream Vera Sans.
-
-Made the default style less stem-aligned. I may have been a little too gregarious in setting it to 100%. :)
-
-Fix problems with various autohinted fonts that result in ridiculously small letters.
-
-Fixed mangled Courier New glyphs. This pointed to a larger bug that is now fixed.
-
-Fix artifacts on Courier New glyphs 0 Q O k.
-
-OSX style in infinality settings should actually be UBUNTU style. Fixed. Still need to get a better OSX style going.
-
-Option to use predefined value on known good fonts (Verdana, Arial, etc.). This gives you the benefit of snapping and other enhancements when its known to work well, without creating misshapen glyphs on other fonts.
-
-Only do heavy snapping on m in known cases.
-
-Added LINUX style to infinality-settings.sh
-
-
-
-
-
-After 20110604:
-
-Features:
-
-Added a post-render, pre-lcd-filter filter that attempts to duplicate windows sharpness / graininess. Controlled by INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH.
-
-Added a fringe filter, intended mostly for autohint (but still effective for certain cases of TT hinting). This attempts to remove gray fringes that sometimes occur on horizontal stems and angled serifs and doodads (Times, Segoe '1', etc.)
-
-Added a grayscale filter.
-
-Added brightness/contrast filter.
-
-Substantial improvements in the stem alignment algorithm! Wow!
-
-Stem alignment now also happens on grayscale antialiased fonts (rgba=none).
-
-
-
-
-Fixes / Tweaks:
-
-Changes inside of local.conf, which are documented there.
-
-Removed an artificial shift of 1/8 pixel to the right on stem aligned glyphs which should result in sharper looking alignment.
-
-Added XFT_SETTINGS into infinality-settings.sh. This means it will require less configuration on the end-user side.
-
-Fixed code to not touch bold, thin, narrow or italic faces for scale or alignment (until they can be properly accounted for).
-
-Added -lm dependency to the code again. (It seems to sneak off now and then)
-
-Changed autohinter horizontal stem stem snapping from on/off to use a value between 0 and 100.
-
-Functions getenv() and system() were crashing evince in _lcd_stem_align() at odd times. A workaround has been put in place.
-
-Moved _lcd_stem_align and all other filters into ftsmooth.c, which is a better place.
-
-Use malloc() in _lcd_stem_align for allocating structs and arrays of structs instead of what I learned in C++ class 10+ years ago. Should prevent abiword from crashing with large pt sizes like 3000. (A workaround has been put in place to automatically skip alignment on any ppem > 300. This will prevent the crashes until the real solution can be figured out.)
-
-Fix some compiler warnings. Some are still present.
-
-Added "m" control to alignment algorithm. This will cause all stems to m (or other 3-pronged glyphs) to get aligned to pixels. It still needs a bit of work, as it makes the best looking glyph size change. This is because the glyph now needs to snap stems to only even or odd pixels, not single ones.
-
-Added rules to allow "compatible widths" (i.e. widths if the font were being bitmap TT hinted) on a glyph by glyph basis and tweaked certain fonts like arial, verdana, times new roman, segoe ui, and trebuchet to use them.
-
-Don't stem align anything below 9 ppem because it is not consistently good.
-
-When doing stem alignment, automatically align stems to center of pixel or start of pixel when necessary. When horizontal stems start snapping to 2 px, so should the vertical ones in order for it to look nice.
-
-A Verdana 12 hack to make it render more like Windows. This notoriously poor looking ppem now looks as good as Verdana 13 without needing fontconfig replacement.
-
-Courier New now looks good, and possibly better than Windows rendering, with TT or autohint rendering. By the way, the hinters of Courier New should either be commended or executed.
-
-Improvements in overshoot artifact and fringe correction- Freesans at large ppem looks nice now. Overshoots on letters like 6, g, s, 3, etc. will now be rounded to integer pixels.
-
-Wrap all infinality code within a macro that is set in ftoption.h: #ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET. Makes it easier to identify in the code and allows for easy compliation with or without the patches set.
-
-Variable renaming for more clarity, in code and in environment variables.
-
-Move stretching code into Freetype instead of relying on programs to handle fontconfig matrix (they SUCK at it... *cough* Chrome *cough*).
-
-Additional modifications to the TT subpixel rendering rules for corrections to Georgia, DejaVu Sans, Times New Roman, Courier New and a couple others.
-
-A general improvement in the way autohinted fonts render, particularly on ones that normally look fragile or thin. Examples include Optima, Freemono, Freeserif, Raleway, MgOpen, etc. I'm doing what Windows does, which is brightness/contrast adjustment, except you don't see rainbows.
-
-
-
-diff --git a/configure b/configure
-index 4d8a945..40eaa1b 100755
---- a/configure
-+++ b/configure
+--- a/configure 2013-05-28 23:00:03.000000000 +0200
++++ b/configure 2014-03-07 19:21:57.063320787 +0100
@@ -13,6 +13,8 @@
# Call the `configure' script located in `builds/unix'.
#
@@ -246,11 +9,9 @@ index 4d8a945..40eaa1b 100755
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 2b370e5..cf18bf6 100644
---- a/devel/ftoption.h
-+++ b/devel/ftoption.h
-@@ -582,6 +582,17 @@ FT_BEGIN_HEADER
+--- a/devel/ftoption.h 2013-12-21 21:39:04.000000000 +0100
++++ b/devel/ftoption.h 2014-03-07 19:21:57.066654119 +0100
+@@ -609,6 +609,17 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
@@ -268,10 +29,9 @@ index 2b370e5..cf18bf6 100644
/* 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 84f1695..3c69018 100644
---- a/include/freetype/config/ftoption.h
-+++ b/include/freetype/config/ftoption.h
+
+--- a/include/config/ftoption.h 2014-03-01 12:27:34.000000000 +0100
++++ b/include/config/ftoption.h 2014-03-07 19:21:57.066654119 +0100
@@ -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. */
@@ -281,7 +41,7 @@ index 84f1695..3c69018 100644
/*************************************************************************/
-@@ -577,11 +577,22 @@ FT_BEGIN_HEADER
+@@ -604,11 +604,22 @@ FT_BEGIN_HEADER
/* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */
/* defined. */
/* */
@@ -305,19 +65,29 @@ index 84f1695..3c69018 100644
/* 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 ef0157a..c75247e 100644
---- a/src/autofit/aflatin.c
-+++ b/src/autofit/aflatin.c
-@@ -23,6 +23,7 @@
- #include "afglobal.h"
+
+--- a/src/autofit/aflatin.c 2014-09-14 11:35:20.946193837 -0500
++++ b/src/autofit/aflatin.c 2014-09-14 11:58:37.726708173 -0500
+@@ -24,6 +24,7 @@
+ #include "afpic.h"
#include "aflatin.h"
#include "aferrors.h"
+#include "strings.h"
#ifdef AF_CONFIG_OPTION_USE_WARPER
-@@ -577,8 +578,33 @@
+@@ -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
++
+
+ /*************************************************************************/
+ /*************************************************************************/
+@@ -892,8 +897,33 @@
FT_Pos delta;
AF_LatinAxis axis;
FT_UInt nn;
@@ -351,7 +121,7 @@ index ef0157a..c75247e 100644
if ( dim == AF_DIMENSION_HORZ )
{
scale = scaler->x_scale;
-@@ -605,7 +631,7 @@
+@@ -920,7 +950,7 @@
{
AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT];
AF_LatinBlue blue = NULL;
@@ -360,7 +130,7 @@ index ef0157a..c75247e 100644
for ( nn = 0; nn < Axis->blue_count; nn++ )
{
-@@ -615,7 +641,12 @@
+@@ -930,7 +960,12 @@
break;
}
}
@@ -374,7 +144,7 @@ index ef0157a..c75247e 100644
if ( blue )
{
FT_Pos scaled;
-@@ -701,7 +732,13 @@
+@@ -1049,7 +1084,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 );
@@ -388,7 +158,7 @@ index ef0157a..c75247e 100644
{
#if 0
FT_Pos delta1;
-@@ -752,7 +789,12 @@
+@@ -1100,7 +1141,12 @@
delta2 = -delta2;
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
@@ -401,7 +171,7 @@ index ef0157a..c75247e 100644
#endif
-@@ -1498,7 +1540,10 @@
+@@ -1916,7 +1962,10 @@
dist = edge->fpos - blue->shoot.org;
if ( dist < 0 )
dist = -dist;
@@ -413,7 +183,7 @@ index ef0157a..c75247e 100644
dist = FT_MulFix( dist, scale );
if ( dist < best_dist )
{
-@@ -1659,8 +1704,31 @@
+@@ -2082,8 +2131,31 @@
FT_Pos dist = width;
FT_Int sign = 0;
FT_Int vertical = ( dim == AF_DIMENSION_VERT );
@@ -421,8 +191,8 @@ index ef0157a..c75247e 100644
+ 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 =
@@ -431,7 +201,7 @@ index ef0157a..c75247e 100644
+ {
+ 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 )
@@ -439,13 +209,13 @@ index ef0157a..c75247e 100644
+ }
+ 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;
-@@ -1670,9 +1738,73 @@
+@@ -2093,9 +2165,73 @@
dist = -width;
sign = 1;
}
@@ -457,8 +227,7 @@ index ef0157a..c75247e 100644
+ {
+ 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 &&
@@ -513,14 +282,15 @@ index ef0157a..c75247e 100644
+ ( ( 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 ) ) ||
+ 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 */
-@@ -1732,6 +1864,9 @@
+@@ -2155,6 +2291,9 @@
}
}
else
@@ -530,7 +300,7 @@ index ef0157a..c75247e 100644
{
/* strong hinting process: snap the stem width to integer pixels */
-@@ -1739,7 +1874,10 @@
+@@ -2162,7 +2301,10 @@
dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
@@ -542,7 +312,7 @@ index ef0157a..c75247e 100644
if ( vertical )
{
/* in the case of vertical hinting, always round */
-@@ -1802,6 +1940,32 @@
+@@ -2225,6 +2367,32 @@
}
Done_Width:
@@ -575,7 +345,7 @@ index ef0157a..c75247e 100644
if ( sign )
dist = -dist;
-@@ -1824,6 +1988,8 @@
+@@ -2247,6 +2415,8 @@
(AF_Edge_Flags)base_edge->flags,
(AF_Edge_Flags)stem_edge->flags );
@@ -584,10 +354,10 @@ index ef0157a..c75247e 100644
stem_edge->pos = base_edge->pos + fitted_width;
-@@ -2357,8 +2523,32 @@
- {
- FT_Error error;
+@@ -2810,8 +2980,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;
@@ -618,28 +388,21 @@ index ef0157a..c75247e 100644
error = af_glyph_hints_reload( hints, outline );
if ( error )
goto Exit;
-@@ -2415,7 +2605,17 @@
- }
+@@ -2877,7 +3071,11 @@
}
+
af_glyph_hints_save( hints, outline );
+-
+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
+ {
-+ /* Save this width for use in ftsmooth.c. This is a shameful hack */
-+ const char* c1 = "CUR_WIDTH";
-+ char c2[8];
-+
-
-+ snprintf( c2, 8, "%ld", metrics->axis->widths[0].cur );
-+ setenv( c1, c2, 1 );
++ infinality_cur_width = metrics->axis->widths[0].cur;
+ }
+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
Exit:
return error;
}
-diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
-index 852fb32..4c2d548 100644
---- a/src/base/ftlcdfil.c
-+++ b/src/base/ftlcdfil.c
+--- a/src/base/ftlcdfil.c 2014-07-07 23:10:20.720076929 +0200
++++ b/src/base/ftlcdfil.c 2014-07-07 23:35:53.756803457 +0200
@@ -23,6 +23,9 @@
#include FT_IMAGE_H
#include FT_INTERNAL_OBJECTS_H
@@ -650,7 +413,7 @@ index 852fb32..4c2d548 100644
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-@@ -289,10 +292,53 @@
+@@ -290,10 +293,53 @@
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
/* the values here sum up to a value larger than 256, */
/* providing a cheap gamma correction */
@@ -705,22 +468,21 @@ index 852fb32..4c2d548 100644
if ( !library )
return FT_THROW( Invalid_Argument );
-diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
-index 26118ed..d87be53 100644
---- a/src/base/ftobjs.c
-+++ b/src/base/ftobjs.c
-@@ -53,6 +53,10 @@
+--- a/src/base/ftobjs.c 2014-09-14 12:35:03.207593493 -0500
++++ b/src/base/ftobjs.c 2014-09-14 15:15:51.604552925 -0500
+@@ -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,
-@@ -524,6 +528,25 @@
+@@ -538,6 +543,25 @@
ft_lookup_glyph_renderer( FT_GlyphSlot slot );
@@ -746,7 +508,7 @@ index 26118ed..d87be53 100644
#ifdef GRID_FIT_METRICS
static void
ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
-@@ -582,8 +605,40 @@
+@@ -596,8 +620,40 @@
FT_Bool autohint = FALSE;
FT_Module hinter;
TT_Face ttface = (TT_Face)face;
@@ -787,7 +549,7 @@ index 26118ed..d87be53 100644
if ( !face || !face->size || !face->glyph )
return FT_THROW( Invalid_Face_Handle );
-@@ -664,6 +719,18 @@
+@@ -685,6 +741,18 @@
{
FT_AutoHinter_Interface hinting;
@@ -806,23 +568,12 @@ index 26118ed..d87be53 100644
/* try to load embedded bitmaps first if available */
/* */
-@@ -702,6 +769,10 @@
- }
- else
- {
-+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
-+ char* c1 = "CUR_WIDTH";
-+ char* c2 = "0";
-+#endif
- error = driver->clazz->load_glyph( slot,
- face->size,
- glyph_index,
-@@ -709,6 +780,18 @@
+@@ -730,6 +798,18 @@
if ( error )
goto Exit;
+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
-+ setenv ( c1, c2, 1 );
++ infinality_cur_width = 0;
+
+ {
+ /* fix for sdl_ttf */
@@ -836,11 +587,9 @@ index 26118ed..d87be53 100644
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 54ca5cd..bf34c9f 100644
---- a/src/base/ftoutln.c
-+++ b/src/base/ftoutln.c
-@@ -905,7 +905,34 @@
+--- a/src/base/ftoutln.c 2014-02-08 13:29:55.000000000 +0100
++++ b/src/base/ftoutln.c 2014-03-07 19:21:57.073320788 +0100
+@@ -908,7 +908,34 @@
FT_Vector v_prev, v_first, v_next, v_cur;
FT_Int c, n, first;
FT_Int orientation;
@@ -875,10 +624,9 @@ index 54ca5cd..bf34c9f 100644
if ( !outline )
return FT_THROW( Invalid_Argument );
-diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
-index 241d37f..3d5a593 100644
---- a/src/base/ftsynth.c
-+++ b/src/base/ftsynth.c
+
+--- a/src/base/ftsynth.c 2013-09-20 07:20:13.000000000 +0200
++++ b/src/base/ftsynth.c 2014-03-07 19:21:57.073320788 +0100
@@ -88,7 +88,32 @@
FT_Face face = slot->face;
FT_Error error;
@@ -886,7 +634,7 @@ index 241d37f..3d5a593 100644
+#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
@@ -904,7 +652,7 @@ index 241d37f..3d5a593 100644
+ else if ( strcasecmp(use_various_tweaks_env, "yes" ) == 0 )
+ use_various_tweaks = TRUE;
+ }
-+
+
+ }
+ checked_use_various_tweaks_env = 1;
+ }
@@ -928,28 +676,27 @@ index 241d37f..3d5a593 100644
}
@@ -141,6 +173,9 @@
- slot->metrics.width += xstr;
- slot->metrics.height += ystr;
+ 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;
-
-diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
-index 2735eaf..382f1f3 100644
---- a/src/smooth/ftsmooth.c
-+++ b/src/smooth/ftsmooth.c
+ slot->metrics.horiAdvance += xstr;
+ slot->metrics.vertAdvance += ystr;
+ slot->metrics.horiBearingY += ystr;
+
+--- a/src/smooth/ftsmooth.c 2013-06-05 05:12:47.000000000 -0500
++++ b/src/smooth/ftsmooth.c 2014-09-14 11:55:39.848343363 -0500
@@ -26,6 +26,17 @@
#include "ftsmerrs.h"
+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
+#include <math.h>
-+#include "../../include/freetype/ftbitmap.h"
++#include "../../include/ftbitmap.h"
+#include <strings.h>
+#include "../autofit/aflatin.h"
-+#include "../../include/freetype/ftoutln.h"
++#include "../../include/ftoutln.h"
+
+#define verbose FALSE
+#define STVALUES if (verbose) \
@@ -958,35 +705,10 @@ index 2735eaf..382f1f3 100644
/* initialize renderer -- init its raster */
static FT_Error
-@@ -70,29 +81,3017 @@
- goto Exit;
- }
+@@ -93,6 +104,2993 @@
+ FT_Outline_Get_CBox( &slot->outline, cbox );
+ }
-- if ( matrix )
-- FT_Outline_Transform( &slot->outline, matrix );
-+ 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)
+ {
@@ -2568,15 +2290,11 @@ index 2735eaf..382f1f3 100644
+ FT_Bool checked_use_known_settings_on_selected_fonts_env = FALSE;
+ FT_Bool use_known_settings_on_selected_fonts = FALSE;
+
-+ int cur_width;
-+ char *cur_width_env = getenv( "CUR_WIDTH" );
++ FT_Pos cur_width = infinality_cur_width;
+
+
-+
-+ if ( cur_width_env != NULL )
++ if ( cur_width )
+ {
-+ sscanf ( cur_width_env, "%d", &cur_width );
-+ if ( cur_width != 0 )
+ autohinted = TRUE;
+ }
+
@@ -2737,6 +2455,7 @@ index 2735eaf..382f1f3 100644
+ known_stem_values->stem_translating_only > -1024 )
+ {
+ *translate_value = known_stem_values->stem_translating_only;
++ free ( known_stem_values );
+ return;
+ }
+
@@ -3912,47 +3631,38 @@ index 2735eaf..382f1f3 100644
+ <= width * 256 - ( one_pixel + one_pixel / 2 ) )
+ *translate_value += 64;
+ }
-
-- if ( delta )
-- FT_Outline_Translate( &slot->outline, delta->x, delta->y );
++
+ STVALUES
-
-- Exit:
-- return error;
++
+ 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 );
- }
-
-
-- /* return the glyph's control box */
++ }
++
++
+ /* Gamma correction */
- static void
-- ft_smooth_get_cbox( FT_Renderer render,
-- FT_GlyphSlot slot,
-- FT_BBox* cbox )
++ 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 )
- {
-- FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
++ {
+ 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->format == render->glyph_format )
-- FT_Outline_Get_CBox( &slot->outline, cbox );
++
+
+ if ( !slot->face || !slot->face->size ) return;
+
@@ -3983,13 +3693,13 @@ index 2735eaf..382f1f3 100644
+ }
+ }
+ }
- }
-
++ }
++
+#endif
/* convert a slot's glyph image into a bitmap */
static FT_Error
-@@ -104,8 +3103,9 @@
+@@ -104,8 +3102,9 @@
{
FT_Error error;
FT_Outline* outline = NULL;
@@ -4000,7 +3710,7 @@ index 2735eaf..382f1f3 100644
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_Pos height_org, width_org;
#endif
-@@ -121,6 +3121,483 @@
+@@ -123,6 +3122,479 @@
FT_Bool have_outline_shifted = FALSE;
FT_Bool have_buffer = FALSE;
@@ -4067,8 +3777,7 @@ index 2735eaf..382f1f3 100644
+ int checked_use_various_tweaks_env = 0;
+ FT_Bool use_various_tweaks = FALSE;
+
-+ int cur_width;
-+ char *cur_width_env = getenv( "CUR_WIDTH" );
++ FT_Pos cur_width = infinality_cur_width;
+
+ const FT_Int MIN_PPEM = 1;
+ /*const FT_Int MAX_PPEM = 100; */
@@ -4083,11 +3792,8 @@ index 2735eaf..382f1f3 100644
+ else
+ ppem = 0;
+
-+ if ( cur_width_env != NULL )
++ if ( cur_width )
+ {
-+ sscanf ( cur_width_env, "%d", &cur_width );
-+
-+ if ( cur_width != 0 )
+ autohinted = TRUE;
+ }
+
@@ -4484,7 +4190,7 @@ index 2735eaf..382f1f3 100644
/* check glyph image format */
if ( slot->format != render->glyph_format )
-@@ -136,9 +3613,105 @@
+@@ -138,9 +3610,105 @@
goto Exit;
}
@@ -4590,7 +4296,7 @@ index 2735eaf..382f1f3 100644
if ( origin )
{
FT_Outline_Translate( outline, origin->x, origin->y );
-@@ -152,6 +3725,7 @@
+@@ -154,6 +3722,7 @@
cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
cbox.xMax = FT_PIX_CEIL( cbox.xMax );
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
@@ -4598,7 +4304,7 @@ index 2735eaf..382f1f3 100644
if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
{
-@@ -228,6 +3802,9 @@
+@@ -227,6 +3796,9 @@
y_top += extra >> 1;
}
}
@@ -4608,17 +4314,23 @@ index 2735eaf..382f1f3 100644
#endif
-@@ -252,6 +3829,9 @@
+@@ -251,8 +3823,15 @@
bitmap->pitch = pitch;
/* translate outline to render it into the bitmap */
+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
+ if ( align_called == 0 )
++ {
+#endif
FT_Outline_Translate( outline, -x_shift, -y_shift );
have_outline_shifted = TRUE;
++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
++ }
++#endif
-@@ -307,9 +3887,153 @@
+ if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+ goto Exit;
+@@ -306,9 +3885,153 @@
if ( error )
goto Exit;
@@ -4772,77 +4484,11 @@ index 2735eaf..382f1f3 100644
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* render outline into bitmap */
-diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
-index 872894d..44e4274 100644
---- a/src/truetype/ttinterp.c
-+++ b/src/truetype/ttinterp.c
-@@ -1842,8 +1842,7 @@
- FT_UNUSED_EXEC;
-
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- if ( !CUR.ignore_x_mode ||
-- ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVEX ) )
-+ if ( !CUR.ignore_x_mode )
+--- a/src/truetype/ttinterp.c 2014-09-14 23:02:01.616685627 +0200
++++ b/src/truetype/ttinterp.c 2014-09-14 23:02:59.846685964 +0200
+@@ -4886,6 +4886,10 @@
+ CUR.sph_in_func_flags = 0x0000;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- zone->cur[point].x += distance;
- zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
-@@ -4464,7 +4463,7 @@
-
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- /* arguments to opcodes are skipped by `SKIP_Code' */
-- FT_Byte opcode_pattern[7][12] = {
-+ FT_Byte opcode_pattern[9][12] = {
- /* #0 inline delta function 1 */
- {
- 0x4B, /* PPEM */
-@@ -4542,10 +4541,23 @@
- 0x43, /* RS */
- 0x58 /* IF */
- },
-+ /* #7 TypeMan Talk DiagEndCtrl function */
-+ {
-+ 0x01, /* SVTCA_x */
-+ 0x20, /* DUP */
-+ 0xB0, /* PUSHB_1 */
-+ /* 3 */
-+ 0x25, /* CINDEX */
-+ },
-+ /* #8 TypeMan Talk Align */
-+ {
-+ 0x06, /* SPVTL */
-+ 0x7D, /* RDTG */
-+ },
- };
-- FT_UShort opcode_patterns = 7;
-- FT_UShort opcode_pointer[7] = { 0, 0, 0, 0, 0, 0, 0 };
-- FT_UShort opcode_size[7] = { 12, 8, 8, 6, 7, 4, 5 };
-+ FT_UShort opcode_patterns = 9;
-+ FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-+ FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
- FT_UShort i;
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-@@ -4684,6 +4696,17 @@
- CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
- }
- break;
-+
-+ case 7:
-+ rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
-+ CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
-+ break;
-+
-+ case 8:
-+ /*rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
-+ CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;*/
-+ break;
-+
- }
- opcode_pointer[i] = 0;
- }
-@@ -4729,6 +4752,10 @@
- FT_UNUSED_ARG;
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ CUR.sph_in_func_flags = 0x0000;
@@ -4851,92 +4497,9 @@ index 872894d..44e4274 100644
if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
{
CUR.error = FT_THROW( ENDF_In_Exec_Stream );
-@@ -4814,7 +4841,13 @@
- goto Fail;
-
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- CUR.sph_in_func_flags &= def->sph_fdef_flags;
-+ if ( CUR.ignore_x_mode &&
-+ ( ( CUR.iup_called &&
-+ ( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
-+ ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) )
-+ goto Fail;
-+ else
-+ CUR.sph_in_func_flags = def->sph_fdef_flags;
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
- /* check the call stack */
-@@ -4839,10 +4872,6 @@
-
- CUR.step_ins = FALSE;
-
--#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- CUR.sph_in_func_flags &= !def->sph_fdef_flags;
--#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
--
- return;
-
- Fail:
-@@ -4900,7 +4929,11 @@
- goto Fail;
-
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- CUR.sph_in_func_flags &= def->sph_fdef_flags;
-+ if ( CUR.ignore_x_mode &&
-+ ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
-+ goto Fail;
-+ else
-+ CUR.sph_in_func_flags = def->sph_fdef_flags;
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
- /* check stack */
-@@ -4927,10 +4960,6 @@
- CUR.step_ins = FALSE;
- }
-
--#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- CUR.sph_in_func_flags &= !def->sph_fdef_flags;
--#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
--
- return;
-
- Fail:
-@@ -5779,9 +5808,7 @@
- if ( CUR.GS.freeVector.x != 0 )
- {
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- if ( !CUR.ignore_x_mode ||
-- ( CUR.ignore_x_mode &&
-- ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_MOVE_ZP2 ) ) )
-+ if ( !CUR.ignore_x_mode )
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- CUR.zp2.cur[point].x += dx;
- if ( touch )
-@@ -6030,14 +6057,17 @@
- else
- B1 = CUR.zp2.cur[point].x;
-
-- if ( CUR.GS.freeVector.y != 0 &&
-- ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_INLINE_DELTAS ) )
-- goto Skip;
--
- if ( !CUR.face->sph_compatibility_mode &&
- CUR.GS.freeVector.y != 0 )
- MOVE_Zp2_Point( point, dx, dy, TRUE );
-
-+ else if ( CUR.sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
-+ {
-+ MOVE_Zp2_Point( point, dx, dy, TRUE );
-+ /* don't allow reversals */
-+ goto Skip;
-+ }
-+
- else if ( CUR.face->sph_compatibility_mode )
- {
- if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
-@@ -6046,6 +6076,12 @@
- dy = FT_PIX_ROUND( B1 + dy ) - B1;
- }
+@@ -6231,6 +6235,12 @@
+ ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
+ goto Skip;
+ /* skip post-iup deltas */
+ if ( CUR.iup_called &&
@@ -4947,112 +4510,17 @@ index 872894d..44e4274 100644
if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
( ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) ||
( CUR.zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ||
-@@ -6223,6 +6259,7 @@
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+@@ -6520,6 +6530,7 @@
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.x != 0 &&
+ CUR.GS.freeVector.y == 0 &&
!( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
- control_value_cutin = 0;
+ minimum_distance = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-@@ -6489,11 +6526,6 @@
- cvt_dist = 0;
- else
- cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
--#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- if ( CUR.ignore_x_mode &&
-- ( CUR.sph_tweak_flags & SPH_TWEAK_MIRP_CVT_ZERO ) )
-- cvt_dist = 0;
--#endif
+@@ -8382,6 +8393,34 @@
- /* single width test */
-
-@@ -6642,12 +6674,6 @@
- ( B2 & 63 ) != 0 &&
- ( B1 & 63 ) != 0 )
- reverse_move = TRUE;
--
-- if ( ( CUR.sph_tweak_flags &
-- SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES ) &&
-- !reverse_move &&
-- FT_ABS( B1 - B2 ) >= 64 )
-- reverse_move = TRUE;
- }
-
- if ( reverse_move )
-@@ -7214,7 +7240,7 @@
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode )
- {
-- CUR.iup_called = 1;
-+ CUR.iup_called = TRUE;
- if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
- return;
- }
-@@ -7291,7 +7317,13 @@
- FT_Long B;
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- FT_UShort B1, B2;
--#endif
-+
-+
-+ if ( CUR.ignore_x_mode &&
-+ CUR.iup_called &&
-+ ( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
-+ goto Fail;
-+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-
- #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-@@ -7388,7 +7420,7 @@
- #if 0
- /* Standard Subpixel Hinting: Allow y move. */
- /* This messes up dejavu and may not be needed... */
-- if ( !CUR.face->sph_compatibility_mode &&
-+ if ( !CUR.face->sph_compatibility_mode &&
- CUR.GS.freeVector.y != 0 )
- CUR_Func_move( &CUR.zp0, A, B );
- else
-@@ -7419,14 +7451,14 @@
- ( B1 & 63 ) == 0 &&
- ( B2 & 63 ) != 0 ) ||
- ( ( CUR.sph_tweak_flags &
-- SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
-+ SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
- ( B1 & 63 ) != 0 &&
- ( B2 & 63 ) != 0 ) ) )
- CUR_Func_move( &CUR.zp0, A, -B );
- }
- #else
- CUR_Func_move( &CUR.zp0, A, B );
--#endif /* *TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- }
- }
- else
-@@ -8031,6 +8063,19 @@
- TT_RunIns( TT_ExecContext exc )
- {
- FT_Long ins_counter = 0; /* executed instructions counter */
-+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-+ FT_Byte opcode_pattern[1][2] = {
-+ /* #8 TypeMan Talk Align */
-+ {
-+ 0x06, /* SPVTL */
-+ 0x7D, /* RDTG */
-+ },
-+ };
-+ FT_UShort opcode_patterns = 1;
-+ FT_UShort opcode_pointer[1] = { 0 };
-+ FT_UShort opcode_size[1] = { 1 };
-+ FT_UShort i;
-+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-
- #ifdef TT_CONFIG_OPTION_STATIC_RASTER
-@@ -8116,6 +8161,34 @@
- CUR.step_ins = TRUE;
- CUR.error = FT_Err_Ok;
+ #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ for ( i = 0; i < opcode_patterns; i++ )
@@ -5085,426 +4553,15 @@ index 872894d..44e4274 100644
#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
{
-@@ -8312,13 +8385,7 @@
- break;
-
- case 0x2B: /* CALL */
--#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- if ( !CUR.ignore_x_mode ||
-- !CUR.iup_called ||
-- ( CUR.iup_called &&
-- !( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) )
--#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-- Ins_CALL( EXEC_ARG_ args );
-+ Ins_CALL( EXEC_ARG_ args );
- break;
+--- a/src/autofit/aflatin.h 2014-09-14 11:18:00.268465365 -0500
++++ b/src/autofit/aflatin.h 2014-09-14 11:23:45.223942422 -0500
+@@ -62,6 +62,9 @@
- case 0x2C: /* FDEF */
-@@ -8336,11 +8403,7 @@
+ #define AF_LATIN_MAX_WIDTHS 16
- case 0x30: /* IUP */
- case 0x31: /* IUP */
--#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- if ( CUR.ignore_x_mode )
-- CUR.iup_called = TRUE;
--#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-- Ins_IUP( EXEC_ARG_ args );
-+ Ins_IUP( EXEC_ARG_ args );
- break;
-
- case 0x32: /* SHP */
-@@ -8499,13 +8562,7 @@
- break;
-
- case 0x5D: /* DELTAP1 */
--#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-- if ( !CUR.ignore_x_mode ||
-- !CUR.iup_called ||
-- ( CUR.iup_called &&
-- !( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) )
--#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-- Ins_DELTAP( EXEC_ARG_ args );
-+ Ins_DELTAP( EXEC_ARG_ args );
- break;
-
- case 0x5E: /* SDB */
-diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c
-index 27e9b15..5267233 100644
---- a/src/truetype/ttsubpix.c
-+++ b/src/truetype/ttsubpix.c
-@@ -286,25 +286,14 @@
-
-
- /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */
--#define PIXEL_HINTING_RULES_SIZE 1
-+#define PIXEL_HINTING_RULES_SIZE 2
-
- const SPH_TweakRule PIXEL_HINTING_Rules
- [PIXEL_HINTING_RULES_SIZE] =
- {
- /* these characters are almost always safe */
-- { "-", 0, "", 0 },
-- };
--
--
-- /* According to Greg Hitchcock and the MS whitepaper, this should work */
-- /* on all legacy MS fonts, but creates artifacts with some. Only using */
-- /* where absolutely necessary. */
--#define SKIP_INLINE_DELTAS_RULES_SIZE 1
--
-- const SPH_TweakRule SKIP_INLINE_DELTAS_Rules
-- [SKIP_INLINE_DELTAS_RULES_SIZE] =
-- {
-- { "-", 0, "", 0 },
-+ { "Courier New", 12, "Italic", 'z' },
-+ { "Courier New", 11, "Italic", 'z' },
- };
-
-
-@@ -320,42 +309,41 @@
-
- /* Skip Y moves that start with a point that is not on a Y pixel */
- /* boundary and don't move that point to a Y pixel boundary. */
--#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 9
-+#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 5
-
- const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules
- [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
- {
- /* fix vwxyz thinness*/
-- { "Consolas", 0, "Regular", 0 },
-- /* fix tiny gap at top of m */
-- { "Arial", 0, "Regular", 'm' },
-+ { "Consolas", 0, "", 0 }, { "-", 0, "N", 0 },
- /* Fix thin middle stems */
-- { "Core MS Legacy Fonts", 0, "Regular/Bold Class", 'N' },
-- { "Lucida Grande", 0, "", 'N' },
-- { "Lucida Grande", 0, "Bold", 'y' },
-+ { "-Core MS Legacy Fonts", 0, "Regular/Bold Class", 0 },
- /* Cyrillic small letter I */
-- { "Legacy Sans Fonts", 0, "", 0x438 },
-- { "Verdana Clones", 0, "",'N' },
-- /* Fix misshapen x */
-- { "Verdana", 0, "Bold", 'x' },
-- /* Fix misshapen s */
-- { "Tahoma", 0, "", 's' },
-+ { "Legacy Sans Fonts", 0, "", 0 },
-+ /* Fix artifacts with some Regular & Bold */
-+ { "Verdana Clones", 0, "", 0 },
- };
-
-
--#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 7
-+#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
-
- const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
- [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
- {
-- { "Tahoma", 0, "", 'N' },
-- { "Comic Sans MS", 0, "", 'N' },
-- { "Verdana", 0, "Regular/Bold Class", 'N' },
-- { "Verdana", 11, "Bold", 'x' },
-- /* Cyrillic small letter I */
-- { "Arial", 0, "", 0x438 },
-- { "Arial", 11, "Bold", 'N' },
-- { "Trebuchet MS", 0, "Bold", 0 },
-+ { "-", 0, "", 0 },
-+ };
-+
-+
-+ /* Skip Y moves that start with a point that is not on a Y pixel */
-+ /* boundary and don't move that point to a Y pixel boundary. */
-+#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE 2
-+
-+ const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules
-+ [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] =
-+ {
-+ /* Maintain thickness of diagonal in 'N' */
-+ { "Times New Roman", 0, "Regular/Bold Class", 'N' },
-+ { "Georgia", 0, "Regular/Bold Class", 'N' },
- };
-
-
-@@ -399,16 +387,6 @@
- };
-
-
-- /* Allow a Direct_Move_X along X freedom vector if matched. */
--#define ALLOW_X_DMOVEX_RULES_SIZE 1
--
-- const SPH_TweakRule ALLOW_X_DMOVEX_Rules
-- [ALLOW_X_DMOVEX_RULES_SIZE] =
-- {
-- { "-", 0, "Regular", 0 },
-- };
--
--
- /* Allow a Direct_Move along X freedom vector if matched. */
- #define ALLOW_X_DMOVE_RULES_SIZE 1
-
-@@ -420,17 +398,6 @@
- };
-
-
-- /* Allow a ZP2 move along freedom vector if matched; */
-- /* This is called from SHP, SHPIX, SHC, SHZ. */
--#define ALLOW_X_MOVE_ZP2_RULES_SIZE 1
--
-- const SPH_TweakRule ALLOW_X_MOVE_ZP2_Rules
-- [ALLOW_X_MOVE_ZP2_RULES_SIZE] =
-- {
-- { "-", 0, "", 0 },
-- };
--
--
- /* Return MS rasterizer version 35 if matched. */
- #define RASTERIZER_35_RULES_SIZE 8
-
-@@ -455,7 +422,8 @@
- const SPH_TweakRule NORMAL_ROUND_Rules
- [NORMAL_ROUND_RULES_SIZE] =
- {
-- /* Fix serif thickness */
-+ /* Fix serif thickness for certain ppems */
-+ /* Can probably be generalized somehow */
- { "Courier New", 0, "", 0 },
- };
-
-@@ -481,7 +449,7 @@
-
-
- /* Skip DELTAP instructions if matched. */
--#define ALWAYS_SKIP_DELTAP_RULES_SIZE 15
-+#define ALWAYS_SKIP_DELTAP_RULES_SIZE 18
-
- const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules
- [ALWAYS_SKIP_DELTAP_RULES_SIZE] =
-@@ -491,7 +459,11 @@
- { "Trebuchet MS", 14, "Regular", 'e' },
- { "Trebuchet MS", 13, "Regular", 'e' },
- { "Trebuchet MS", 15, "Regular", 'e' },
-+ { "Trebuchet MS", 0, "Italic", 'v' },
-+ { "Trebuchet MS", 0, "Italic", 'w' },
-+ { "Trebuchet MS", 0, "Regular", 'Y' },
- { "Arial", 11, "Regular", 's' },
-+ /* prevent problems with '3' and others */
- { "Verdana", 10, "Regular", 0 },
- { "Verdana", 9, "Regular", 0 },
- /* Cyrillic small letter short I */
-@@ -508,57 +480,23 @@
-
-
- /* Always do DELTAP instructions if matched. */
--#define ALWAYS_DO_DELTAP_RULES_SIZE 2
-+#define ALWAYS_DO_DELTAP_RULES_SIZE 1
-
- const SPH_TweakRule ALWAYS_DO_DELTAP_Rules
- [ALWAYS_DO_DELTAP_RULES_SIZE] =
- {
-- { "Verdana Clones", 17, "Regular Class", 'K' },
-- { "Verdana Clones", 17, "Regular Class", 'k' },
-- };
--
--
-- /* Do an extra RTG instruction in DELTAP if matched. */
--#define DELTAP_RTG_RULES_SIZE 1
--
-- static const SPH_TweakRule DELTAP_RTG_Rules
-- [DELTAP_RTG_RULES_SIZE] =
-- {
-- { "-", 0, "", 0 },
-- };
--
--
-- /* Force CVT distance to zero in MIRP. */
--#define MIRP_CVT_ZERO_RULES_SIZE 1
--
-- static const SPH_TweakRule MIRP_CVT_ZERO_Rules
-- [MIRP_CVT_ZERO_RULES_SIZE] =
-- {
-- { "-", 0, "", 0 },
-- };
--
--
-- /* Skip moves that meet or exceed 1 pixel. */
--#define DELTAP_SKIP_EXAGGERATED_VALUES_RULES_SIZE 1
--
-- static const SPH_TweakRule DELTAP_SKIP_EXAGGERATED_VALUES_Rules
-- [DELTAP_SKIP_EXAGGERATED_VALUES_RULES_SIZE] =
-- {
- { "-", 0, "", 0 },
- };
-
-
- /* Don't allow ALIGNRP after IUP. */
--#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 4
-+#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 1
-
- static const SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules
- [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] =
- {
- /* Prevent creation of dents in outline */
-- { "Courier New", 0, "Bold", 'C' },
-- { "Courier New", 0, "Bold", 'D' },
-- { "Courier New", 0, "Bold", 'Q' },
-- { "Courier New", 0, "Bold", '0' },
-+ { "-", 0, "", 0 },
- };
-
-
-@@ -573,16 +511,13 @@
-
-
- /* Don't allow CALL after IUP. */
--#define NO_CALL_AFTER_IUP_RULES_SIZE 4
-+#define NO_CALL_AFTER_IUP_RULES_SIZE 1
-
- static const SPH_TweakRule NO_CALL_AFTER_IUP_Rules
- [NO_CALL_AFTER_IUP_RULES_SIZE] =
- {
- /* Prevent creation of dents in outline */
-- { "Courier New", 0, "Bold", 'O' },
-- { "Courier New", 0, "Bold", 'Q' },
-- { "Courier New", 0, "Bold", 'k' },
-- { "Courier New", 0, "Bold Italic", 'M' },
-+ { "-", 0, "", 0 },
- };
-
-
-@@ -605,29 +540,16 @@
-
-
- /* Embolden these glyphs slightly. */
--#define EMBOLDEN_RULES_SIZE 5
-+#define EMBOLDEN_RULES_SIZE 2
++#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
++ extern FT_Pos infinality_cur_width;
++#endif
- static const SPH_TweakRule EMBOLDEN_Rules
- [EMBOLDEN_RULES_SIZE] =
+ enum
{
-- { "Courier New", 12, "Italic", 'z' },
-- { "Courier New", 11, "Italic", 'z' },
-- { "Courier New", 10, "Italic", 'z' },
- { "Courier New", 0, "Regular", 0 },
- { "Courier New", 0, "Italic", 0 },
- };
-
-
-- /* Do an extra RDTG instruction in DELTAP if matched. */
--#define DELTAP_RDTG_RULES_SIZE 1
--
-- static const SPH_TweakRule DELTAP_RDTG_Rules
-- [DELTAP_RDTG_RULES_SIZE] =
-- {
-- { "-", 0, "", 0 },
-- };
--
--
- /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */
- /* similar to Windows XP. */
- #define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12
-@@ -998,12 +920,9 @@
- }
-
- TWEAK_RULES( ALLOW_X_DMOVE );
-- TWEAK_RULES( ALLOW_X_DMOVEX );
-- TWEAK_RULES( ALLOW_X_MOVE_ZP2 );
- TWEAK_RULES( ALWAYS_DO_DELTAP );
- TWEAK_RULES( ALWAYS_SKIP_DELTAP );
- TWEAK_RULES( DEEMBOLDEN );
-- TWEAK_RULES( DELTAP_SKIP_EXAGGERATED_VALUES );
- TWEAK_RULES( DO_SHPIX );
- TWEAK_RULES( EMBOLDEN );
- TWEAK_RULES( MIAP_HACK );
-@@ -1012,13 +931,13 @@
- TWEAK_RULES( NO_CALL_AFTER_IUP );
- TWEAK_RULES( NO_DELTAP_AFTER_IUP );
- TWEAK_RULES( RASTERIZER_35 );
-- TWEAK_RULES( SKIP_INLINE_DELTAS );
- TWEAK_RULES( SKIP_IUP );
-- TWEAK_RULES( MIRP_CVT_ZERO );
-
- TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES );
- TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES );
-
-+ TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP );
-+
- TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES );
- TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES );
-
-diff --git a/src/truetype/ttsubpix.h b/src/truetype/ttsubpix.h
-index 5e5d8e6..8a54fc7 100644
---- a/src/truetype/ttsubpix.h
-+++ b/src/truetype/ttsubpix.h
-@@ -34,14 +34,15 @@ FT_BEGIN_HEADER
- /* ID flags to identify special functions at FDEF and runtime. */
- /* */
- /* */
--#define SPH_FDEF_INLINE_DELTA_1 0x0000001
--#define SPH_FDEF_INLINE_DELTA_2 0x0000002
--#define SPH_FDEF_DIAGONAL_STROKE 0x0000004
--#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008
--#define SPH_FDEF_TTFAUTOHINT_1 0x0000010
--#define SPH_FDEF_SPACING_1 0x0000020
--#define SPH_FDEF_SPACING_2 0x0000040
--#define SPH_FDEF_TYPEMAN_STROKES 0x0000080
-+#define SPH_FDEF_INLINE_DELTA_1 0x0000001
-+#define SPH_FDEF_INLINE_DELTA_2 0x0000002
-+#define SPH_FDEF_DIAGONAL_STROKE 0x0000004
-+#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008
-+#define SPH_FDEF_TTFAUTOHINT_1 0x0000010
-+#define SPH_FDEF_SPACING_1 0x0000020
-+#define SPH_FDEF_SPACING_2 0x0000040
-+#define SPH_FDEF_TYPEMAN_STROKES 0x0000080
-+#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100
-
-
- /*************************************************************************/
-@@ -50,29 +51,25 @@ FT_BEGIN_HEADER
- /* */
- /* */
- #define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001
--#define SPH_TWEAK_ALLOW_X_DMOVEX 0x0000002
--#define SPH_TWEAK_ALLOW_X_MOVE_ZP2 0x0000004
--#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000008
--#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000010
--#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000020
--#define SPH_TWEAK_DEEMBOLDEN 0x0000040
--#define SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES 0x0000080
--#define SPH_TWEAK_DO_SHPIX 0x0000100
--#define SPH_TWEAK_EMBOLDEN 0x0000200
--#define SPH_TWEAK_MIAP_HACK 0x0000400
--#define SPH_TWEAK_NORMAL_ROUND 0x0000800
--#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0001000
--#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0002000
--#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0004000
--#define SPH_TWEAK_PIXEL_HINTING 0x0008000
--#define SPH_TWEAK_RASTERIZER_35 0x0010000
--#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0020000
--#define SPH_TWEAK_SKIP_INLINE_DELTAS 0x0040000
--#define SPH_TWEAK_SKIP_IUP 0x0080000
--#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0100000
--#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0200000
--#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0400000
--#define SPH_TWEAK_MIRP_CVT_ZERO 0x0800000
-+#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002
-+#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004
-+#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008
-+#define SPH_TWEAK_DEEMBOLDEN 0x0000010
-+#define SPH_TWEAK_DO_SHPIX 0x0000020
-+#define SPH_TWEAK_EMBOLDEN 0x0000040
-+#define SPH_TWEAK_MIAP_HACK 0x0000080
-+#define SPH_TWEAK_NORMAL_ROUND 0x0000100
-+#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200
-+#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400
-+#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800
-+#define SPH_TWEAK_PIXEL_HINTING 0x0001000
-+#define SPH_TWEAK_RASTERIZER_35 0x0002000
-+#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000
-+#define SPH_TWEAK_SKIP_IUP 0x0008000
-+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000
-+#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000
-+#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000
-+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000
-
-
- FT_LOCAL( FT_Bool )
diff --git a/testing/freetype-infinality/infinality-settings.sh b/testing/freetype-infinality/infinality-settings.sh
index f428320e2..a23b99314 100644
--- a/testing/freetype-infinality/infinality-settings.sh
+++ b/testing/freetype-infinality/infinality-settings.sh
@@ -1,74 +1,13 @@
-##################################################################
-### INFINALITY ENVIRONMENT VARIABLES FOR EXTRA RUN-TIME OPTIONS ##
-##################################################################
-#
-# These environment variables require that their respective patches
-# from http://www.infinality.net have been applied to the Freetype
-# installation you are using. They will do abolutely
-# nothing otherwise!
-#
+#!/bin/sh
-# This file should be copied to /etc/profile.d/ for system-wide
-# effects and/or included in ~/.bashrc or ~/.bash_profile for per-user
-# effects:
-#
-# . ~/path/to/this/file/infinality-settings.sh
-#
-# Of course, the per-user settings will override the system-wide
-# settings. Default values indicated below will be used when the
-# environment variables below are not defined.
-#
-# When I say "Default:" below, I'm referring to the default if no
-# environment variables are set. Generally this ends up being
-# whatever Freetype's default is set to.
-#
+### freetype2-infinality-ultimate settings ###
+### rev. 0.4.8.1, 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 ###
-##################################################################
-# EXAMPLES
-#
-# Please see 3/4 down in this file for examples of different settings.
-#
-
-
-
-
-
-
-#################################################################
-################## EXPLANATION OF SETTINGS ######################
-#################################################################
-
-
-
-##################################################################
-# SET_XFT_SETTINGS
-#
-# Should the below Xft settings be set globally by this script? (true/false)
-
-SET_XFT_SETTINGS=true
-
-# XFT settings are like a red-headed stepchild that should be beaten severely.
-# These only affect legacy programs, and *parts* of some modern programs like
-# google-chrome. We only deal with these settings because we have to, otherwise
-# crap will slip by. I recommend using hintslight and autohint as the defaults
-# normally in /etc/fonts/. The reason hintfull and autohint:0 is needed here
-# because otherwise some programs will occassionally request slight hinting for
-# a truetype font. When a program does this, Freetype automatically uses the
-# autohinter, when you may actually want it to be rendered with the TT hinter,
-# (if specified in /etc/fonts/). So setting this to hintfull guarantees that the
-# TT font will be rendered with the TT hinter (assuming it is specified in
-# /etc/fonts/ to be rendered that way.) For TT fonts that you want
-# rendered with autohint, specifiying that in the /etc/fonts/
-# should be enough. But you might think that by setting this to hintfull
-# that it's going to use Freetype's full autohinting (which we *completely*
-# avoid) for fonts you want autohinted. This is where
-# INFINALITY_FT_AUTOFIT_FORCE_SLIGHT_HINTING comes in. It tells freetype to
-# use slight hinting on fonts set for autohinting, even if the program requests
-# full autohinting. Freetype's full hinting only looks OK under certain
-# circumstances. The goal of infinality is to make infinality hinting look
-# good all the time.
-
XFT_SETTINGS="
Xft.antialias: 1
Xft.autohint: 0
@@ -77,1059 +16,33 @@ Xft.hinting: 1
Xft.hintstyle: hintfull
Xft.lcdfilter: lcddefault
Xft.rgba: rgb
-"
-
-if [ "$SET_XFT_SETTINGS" = "true" ]; then
- echo "$XFT_SETTINGS" | xrdb -merge > /dev/null 2>&1
-fi
-
-
-
-##################################################################
-# INFINALITY_FT_FILTER_PARAMS
-#
-# This is a modified version of the patch here:
-# http://levelsofdetail.kendeeter.com/2008/12/dynamic_fir_filter_patch.html
-#
-# Allows you to adjust the FIR filter at runtime instead of at
-# compile time. The idea is to have values add up to 100, and be
-# symmetrical around the middle value. If the values add up to
-# more than 100, the glyphs will appear darker. If less than 100,
-# lighter. I recommend using this method to make glyphs darker
-# or lighter globally as opposed to using the gamma option (see note in
-# the gamma option).
-#
-# Here are some samples of various filter parameters:
-#
-# (this has been changed to use integers between 0 and 100 to
-# avoid problems with regional differences like comma for decimal point)
-#
-#
-# Strong Extra Smooth "15 20 30 20 15" (extra smooth, natural weight)
-# Extra Smooth "20 20 30 20 20" (extra smooth, extra weight)
-# Smooth "15 20 32 20 15" (smooth, natural weight)
-# Stronger Gibson "11 22 38 22 11" (smooth, extra weight)
-# Gibson "11 22 33 22 11" (smooth, natural weight)
-# Freetype Light "00 33 34 33 00" (sharp, natural weight) # freetype's "light" LCD filter
-# Freetype Default "06 25 44 25 06" (sharp, extra weight) # freetype's default
-# Extra Sharp "00 35 35 35 00" (extra sharp, extra weight) # freetype's "light" LCD filter on acid
-#
-#
-# Windows uses something more sharp, maybe along the lines of Freetype's default
-#
-# Default if no ENV_VARS present: [Freetype's default]
-# Recommended: "11 22 38 22 11" (too dark / smooth for some)
-#
-# Example 1: export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-#
-
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-
-
-
-##################################################################
-# INFINALITY_FT_STEM_ALIGNMENT_STRENGTH
-#
-# This performs analysis on each glyph and determines an amount
-# to shift the glyph, left or right, so that it aligns better to
-# pixel boundaries.
-#
-# This results in subtley cleaner looking stems, at the expense of
-# proper distances between glyphs. This is only active for sizes
-# 10 px or greater and does not apply to bold or italic fonts.
-#
-# There are also exceptions on a small number of fonts that I've
-# not been able to render nicely with alignment enabled. In those
-# cases, a forced translation is applied instead.
-#
-# Possible values:
-# 0 through 100 - think of as percentage of strength
-#
-# 0 corresponds to no shifting whatsoever. In other words, OFF.
-#
-# 100 corresponds to a full move to a snap zone defined by
-# the snapping algorithm, be it left or right. This
-# is the full amount any glyph could be moved in order to make it
-# align to the pixel.
-#
-# Values inbetween act as caps. If the algorithm determines that it
-# wants to move the glyph .33 of a pixel to the left, but the value
-# is set to 50 (i.e. 50%), then the maximum move that would be allowed
-# is 50% of half a pixel, in other words .25. So instead of .33 the
-# glyph is moved .25 of a pixel.
-#
-# For a subtle effect that doesn't dramatically affect the glyph, use
-# 25 for this and 25 for INFINALITY_FT_STEM_FITTING_STRENGTH
-#
-# Default if no ENV_VARS present: 0
-# Recommended if you want to use it: 100
-
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=25
-
-
-
-##################################################################
-# INFINALITY_FT_STEM_FITTING_STRENGTH
-#
-# This performs analysis on each glyph and determines an amount
-# to horizontally scale the glyph, so that stems align better to
-# pixel boundaries. An emboldening (or anti-emboldening) is
-# performed afterward to account for stem width exaggeration.
-#
-# This results in subtley cleaner looking fonts, at the expense of
-# proper distances between glyphs and slightly misshapen glyphs.
-# This is only active for sizes 10 px or greater and does not
-# apply to bold or italic fonts.
-#
-# There are also exceptions on a small number of fonts that I've
-# not been able to render nicely with fitting enabled. In those
-# cases, a forced translation is applied instead.
-#
-#
-# Possible values:
-# 0 through 100 - think of as percentage of strength
-#
-# 0 corresponds to no stretching whatsoever. In other words, OFF.
-#
-# 100 corresponds to a full pixel stretch, be outward or inward. This
-# is the full amount any glyph could be stretched in order to make it
-# align to a pixel boundary. Which direction is chosen is part
-# of the art of what I'm trying to do in the code. ;)
-#
-#
-# Values inbetween act as caps. If the algorithm determines that it
-# wants to stretch the glyph .75 of a pixel outward, but the value
-# is set to 50 (i.e. 50%), then the maximum move that would be allowed
-# is 50% of a pixel, in other words .50. So instead of .75 the
-# glyph is stretched .50 of a pixel.
-#
-# For a subtle effect that doesn't dramatically affect the glyph, use
-# 25 for this and 25 for INFINALITY_FT_STEM_FITTING_STRENGTH
-#
-# Default if no ENV_VARS present: 0
-# Recommended if you want to use it: 100
-
-export INFINALITY_FT_STEM_FITTING_STRENGTH=25
-
-
-
-##################################################################
-# INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE
-#
-# This allows you to set a ppem at which alignment and fitting
-# will reach 100%. As glyphs become larger, more dramatic
-# snapping will not affect the glyph shape as much, so it makes
-# sense to allow this.
-#
-# For fonts that are 10 ppem, the values set above for
-# INFINALITY_FT_STEM_ALIGNMENT_STRENGTH and
-# INFINALITY_FT_STEM_FITTING_STRENGTH will be used. As the ppem
-# gradually becomes larger, so will the strength settings, and
-# they will reach 100% at the ppem you specify here.
-#
-# This is a simple linear scale.
-#
-# Possible values:
-# 0 means to not use this feature
-#
-# 11 and up will set the 100% level to that ppem value
-#
-# Anything else is officially undefined, but I still bound it internally.
-#
-# Default if no ENV_VARS present: 0
-
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=40
-
-
-
-##################################################################
-# INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS
-#
-# This applies largely to certain MS fonts, but some others as well.
-# it will apply known good settings on a font-by-font basis, regardless
-# of the other settings above or below.
-#
-# - Use known values for selected fonts & ppems that are known to look
-# ok with 100:
-#
-# INFINALITY_FT_STEM_ALIGNMENT_STRENGTH
-# INFINALITY_FT_STEM_FITTING_STRENGTH
-#
-# - Use various internal tweaks like compatible widths and other
-# font-specific hacks.
-# - Use gamma, brightness or contrast adjustments automatically
-# on certain fonts. Global settings will still apply afterwards.
-# - Enable various forced settings on selective fonts during
-# rasterization and stem_alignment.
-#
-# If set to TRUE, this will use 100 regardless of the values you have
-# specified above. It will not affect fonts that are not in this
-# small list.
-#
-# Possible values:
-# FALSE means to not use this feature
-#
-# TRUE will enable this feature
-#
-# Default if no ENV_VARS present: FALSE
-# Recommended: TRUE
-#
-
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-
-
-##################################################################
-# INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH
-#
-# This enables an algorithm found in ChromeOS for sharpening the
-# appearance of glyphs. It is based off this patch:
-#
-# http://codereview.chromium.org/3298011/diff/9001/media-libs/freetype/files/freetype-2.3.11-lcd-sharpen.patches
-#
-# It gives glyphs a more "grainy" look through some gamma
-# correction. It does tend to thin out vertical stems, which
-# may be a feature or a bug depending on your taste ;)
-#
-#
-# Possible values:
-# 0 through 100 - think of as percentage of strength
-#
-# 0 corresponds to no sharpening whatsoever. In other words, OFF.
-#
-# 25 is good for a subtle effect.
-#
-# 50 corresponds to the default ChromeOS value.
-#
-# 100 corresponds to maximum sharpening. This usually results in
-# something undesirable looking.
-#
-#
-# As you increase this amount, it is good to decrease the gamma (2nd value)
-# of INFINALITY_FT_PSEUDO_GAMMA, and possibly increase
-# INFINALITY_FT_STEM_FITTING_STRENGTH and
-# INFINALITY_FT_STEM_ALIGNMENT_STRENGTH, as it seems like the algorithm
-# lightens stems that aren't fully on-pixel.
-#
-# Default if no ENV_VARS present: 0
-# Recommended: If you're going to use this filter - 50
-
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-
-
-
-##################################################################
-# INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH
-#
-# This enables an algorithm developed with the intention to sharpen
-# fonts to look similarly to Windows.
-#
-# It gives glyphs a more "grainy" look, like the ChromeOS filter
-# except it does so more selectively. This prevents the thinning
-# of vertical stems that is noticible when a blanket gamma filter
-# like the ChromeOS filter is applied.
-#
-# I also get a "cleaner" impression from the fonts with this Windows
-# style filter. This filter was done by 100% experimentation,
-# and there things that could probably be improved.
-#
-# Some may argue that I shouldn't be trying to take the shortcomings
-# of the MS approach and bring them here. I disagree, as part
-# of freedom is having the right to make your fonts look as
-# shitty as you'd like.
-#
-# Using this filter does somewhat lessen the need to use stem
-# fitting and stem alignment, as glyphs appear sharper.
-#
-# This setting can be used at the same time as the previous chromeOS
-# sharpening, and happens after it in the code.
-#
-#
-# Possible values:
-# 0 through 100 - think of as percentage of strength
-#
-# 0 corresponds to no sharpening whatsoever. In other words, OFF.
-#
-# 10-25 is good for a subtle effect while not completely decimating glyphs.
-#
-# 50-75 corresponds to probably something in the range that Windows uses.
-#
-# 100 corresponds to maximum sharpening.
-#
-#
-# Using a high value for this variable along with enabling the
-# fringe filter (below) almost eliminates the need
-# for INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT to be set to 100,
-# and can instead be set at 0. (Setting
-# INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT to 0 prevents missing
-# stems in the middle of s. The drawback is that many fonts just look
-# way too sharp and grainy at this setting. Your call.)
-#
-# Default if no ENV_VARS present: 0
-# Recommended if you want to use this filter: 65
-
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=10
-
-
-
-##################################################################
-# INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT
-#
-# When using autohinting, horizontal stems you'd find in E, f, T, -,
-# etc. are normally not snapped to full integer pixel heights, meaning
-# that you will get a semi-dark fringe on these stems, above or
-# below the black line of pixels:
-#
-# ##########
-# ##
-# ##-------
-# #########
-# ##
-# ##--------
-# ##########
-#
-# (- represents the semi-dark pixels)
-#
-# Setting this to 100 will force integer pixel heights. Setting it to
-# zero will do what Freetype does by default. Anything inbetween will
-# act as a weighted average of the two.
-#
-# This is disabled when the standard width is found (via voodoo) to be
-# less than 1 pixel, in order to prevent the vanishing stem issues on
-# letters with diagonal stems like a and s.
-#
-# Under most circumstances, this should be set at 100. If you choose to
-# not set it to 100, you may want to set INFINALITY_FT_FRINGE_FILTER_STRENGTH
-# to a non-zero value in order to reduce fringing.
-#
-#
-# Possible values:
-# 0 - default Freetype value
-# 100 - a full pixel
-#
-#
-# Default if no ENV_VARS present: 0
-# Recommended: 100
-
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-
-
-
-##################################################################
-# INFINALITY_FT_USE_VARIOUS_TWEAKS
-#
-# - Force autohint when no TT instructions present.
-# - Artificially embolden horizontally only.
-# - When artificially emboldening, maintain the glyph width.
-# - Embolden light and thin-stemmed glyphs automatically.
-# - Don't sharpen italics.
-#
-# Some fonts look bad when stem aligned at certain ppems, no matter
-# what. I've put exceptions in to deal with these, included in
-# these tweaks. Georgia and Lucida Grande are examples.
-#
-#
-# Possible values:
-# true - enable tweaks
-# false - do not enable tweaks (do Freetype default)
-#
-#
-# Default if no ENV_VARS present: false
-# Recommended: true
-
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-
-
-
-##################################################################
-# INFINALITY_FT_GAMMA_CORRECTION
-#
-# This does a weighted gamma correction at the LCD filter phase
-# PRIOR to the LCD filter. Unfortunately it does not however
-# take into account the color on which the glyph is being rendered
-# (or for that matter the color of the glyph),
-# which would need to happen in X rendering. It is actually
-# using the gamma function in calculations though.
-#
-# The first value indicates a px value, the second indicates a
-# "gamma" value. All sizes less than the px value will be corrected
-# on a weighted scale based on the second value.
-#
-# The gamma value is commonly between 0.0 and 3.0. Due to localization
-# issues, the gamma value should be specified as it's actual value
-# multiplied by 100. So a gamma of 1.3 would be 130. In practice,
-# I'd stay between 40 and 250.
-#
-#
-# Values 1 through 100 will darken the glyph
-# Values greater than 100 will lighten the glyph
-#
-#
-# Example 1: Darken glyphs that are less than 10 px. With some fonts
-# even 5 or 6px is readable!
-# export INFINALITY_FT_GAMMA_CORRECTION="10 60"
-#
-# Example 2: Lighten all glyphs (below 100px)
-# export INFINALITY_FT_GAMMA_CORRECTION="100 150"
-#
-# Example 3: Do nothing
-# export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-#
-# Default: [No gamma correction]
-
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-
-
-
-##################################################################
-# INFINALITY_FT_BRIGHTNESS
-#
-# This filter adjusts brightness, using the standard algorithm
-# for brightness. It is applied AFTER the LCD filtering.
-#
-# For a Windows XP look, set brightness to something and contrast to 50
-# This will also tend to increase its sharpness.
-# These values are relative and don't really mean anything
-# however they are satisfactory for a range of appearances.
-# Another tip is to use a gamma setting of "1000 110" or something
-# over 100 to lighten things before processing.
-#
-# Default if no ENV_VARS present: 0
-# Dark XP Experience: -25
-# Light XP Experience: 40
-#
-# Example: export INFINALITY_FT_BRIGHTNESS="-20"
-
-export INFINALITY_FT_BRIGHTNESS="0"
-
-
-
-##################################################################
-# INFINALITY_FT_CONTRAST
-#
-# This filter adjusts contrast, using the standard algorithm
-# for contrast. It is applied AFTER the LCD filtering.
-#
-# For a Windows XP look, set brightness to -25 and contrast to 50
-# This will also tend to increase its sharpness.
-# These values are relative and don't really mean anything
-# however they are satisfactory for a range of appearances.
-# Another tip is to use a gamma setting of "1000 110" or something
-# over 100 to lighten things before processing.
-#
-# Default if no ENV_VARS present: 0
-# Dark or Light XP Experience: 50
-#
-# Example: export INFINALITY_FT_CONTRAST="50"
-
-export INFINALITY_FT_CONTRAST="0"
-
-
-
-##################################################################
-# INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH
-#
-# This filter adjusts subpixel-rendered glyphs toward grayscale.
-# Sometimes this is useful in getting a rendering more like
-# OSX.
-#
-# Range: Integers 0 through 100
-# 0 represents no filtering
-# 50 represents halfway between subpixel and grayscale
-# 100 represents completely grayscale
-#
-# Default if no ENV_VARS present: 0
-# Recommended, if you want to use it: 30
-#
-# Example: export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH="33"
-
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH="0"
-
-
-
-##################################################################
-# INFINALITY_FT_FRINGE_FILTER_STRENGTH
-#
-# This filter tries to remove the horizontal fringing that is found on
-# default autohinted glyphs (similar to OSX-rendered glyphs).
-# For example, an E may be rendered so that the middle horizontal
-# stem is 100% black, but also has a horizonal row of pixels above
-# it that is at 50% intensity. This makes the glyph look dirty,
-# however it is technically accurate.
-#
-# This would be useful in cases where you have
-# INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT set to something less than 100
-# but also can affect glyphs at 100, to some degree.
-#
-# Unless fonts are showing fringes in a way that annoys you, I recommend
-# keeping it disabled, as it can slightly interfere with smooth appearance
-# sometimes.
-#
-#
-# Range: Integers 0 through 100
-# 0 represents no filtering
-# 50 represents a 50% reduction of detected fringes
-# 100 represents completely removing detected fringes
-#
-#
-# Default if no ENV_VARS present: 0
-# Recommended, if you want to use it: 100
-#
-# Example: export INFINALITY_FT_FRINGE_FILTER_STRENGTH="100"
-
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH="0"
-
-
-
-##################################################################
-# INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH
-#
-# This post-filter darkens horizontal stems that autohint renders as semi-dark.
-# Freetype will by default not force stems to render to pixel boundaries
-# because it results in "vanishing stems". This happens on things like
-# s S a and other glyphs with center diagonal stems.
-#
-# If you have INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT set to 100,
-# you're telling it to force pixel boundaries, which can result in the
-# vanishing stems. To get around this problem, I internally override the
-# INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT setting if the stem width
-# is less than a full pixel, regardless. This causes semi-dark stems, but
-# at least there are stems there.
-#
-# This filter is intended to darken those semi-dark stems. I highly
-# recommend using this, but setting to a low value like 10, because
-# it is particularly sensitive right now, and can make thin fonts
-# look weird otherwise.
-#
-#
-# Range: Integers 0 through 100
-# 0 represents no darkening
-# 50 represents a 50% increase toward 1 pixel in height
-# 100 represents a full pixel of height
-#
-#
-# Default if no ENV_VARS present: 0
-# Recommended, if you want to use it: 10
-#
-# Example: export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH="10"
-
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH="10"
-
-
-
-##################################################################
-# INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH
-#
-# This post-filter darkens vertical stems less than 1 pixel that autohint
-# renders as semi-dark. This applies mostly to thin fonts like
-# Courier New, Raleway, and fonts with the word "Light" in the title or
-# style. Although what autohint is doing is technically correct, it
-# results in a bad looking rendering because it's too light, at small
-# ppems. This filter tries to correct that.
-#
-# There is an aspect of this that is automatic, so it's safer to use
-# larger values for this than the above horizontal ENV_VAR. However
-# setting this higher has more impact on thinner fonts. So, I still
-# recommend lower values.
-#
-#
-# Range: Integers 0 through 100
-# 0 represents no darkening
-# 50 represents a 50% increase (from current strength) toward 1 pixel
-# 100 represents a full pixel of width
-#
-#
-# Default if no ENV_VARS present: 0
-# Recommended, if you want to use it: 25
-#
-# Example: export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH="25"
-
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH="25"
-
-
-
-##################################################################
-# INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS
-#
-# This will slightly stretch some glyphs vertically between 9px
-# and 14px (inclusive). Some people may find this more
-# aesthetically pleasing. This only applies to fonts that are
-# using autohint. I used to recommend this to be set true, but
-# it does mess with some (less popular) glyphs in a nasty way.
-#
-# The goal here is to increase the height of some fonts by 1 px
-# but leave the x-height where it is. Arial is a good example
-# of this working properly. Compare the heights of Arial, Times
-# and Freesans with this on, vs. TT hinted versions of Arial and
-# Times.
-#
-#
-# Possible values:
-# true - enable height adjustment
-# false - do not enable height adjustment
-#
-#
-# Default: false
-
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-
-
-# Experimental emboldening values for OSX mode
-export INFINALITY_FT_GLOBAL_EMBOLDEN_X_VALUE=0
-export INFINALITY_FT_GLOBAL_EMBOLDEN_Y_VALUE=0
-export INFINALITY_FT_BOLD_EMBOLDEN_X_VALUE=0 # This one seems to crash at anything other than 0
-export INFINALITY_FT_BOLD_EMBOLDEN_Y_VALUE=0
-
-#################################################################
-########################### EXAMPLES ############################
-#################################################################
-#
-# Set the USE_STYLE variable below to try each example.
-# Make sure to set your style in /etc/fonts/infinality.conf too.
-#
-# Possible options:
-#
-# DEFAULT - Use above settings. A compromise that should please most people.
-# OSX - Simulate OSX rendering
-# IPAD - Simulate iPad rendering
-# UBUNTU - Simulate Ubuntu rendering
-# LINUX - Generic "Linux" style - no snapping or certain other tweaks
-# WINDOWS - Simulate Windows rendering
-# WINDOWS7 - Simulate Windows rendering with normal glyphs
-# WINDOWS7LIGHT- Simulate Windows 7 rendering with lighter glyphs
-# WINDOWS - Simulate Windows rendering
-# VANILLA - Just subpixel hinting
-# CUSTOM - Your own choice. See below
-# ----- Infinality styles -----
-# CLASSIC - Infinality rendering circa 2010. No snapping.
-# NUDGE - CLASSIC with lightly stem snapping and tweaks
-# PUSH - CLASSIC with medium stem snapping and tweaks
-# SHOVE - Full stem snapping and tweaks without sharpening
-# SHARPENED - Full stem snapping, tweaks, and Windows-style sharpening
-# INFINALITY - Settings I use
-# DISABLED - Act as though running without the extra infinality enhancements (just subpixel hinting).
-
-USE_STYLE="DEFAULT"
-
-
-
-### WARNING - NEEDS WORK - ALSO LIABLE TO CRASH APPLICATIONS ###
-################# OSX STYLE #################
-if [ "$USE_STYLE" = "OSX" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="03 32 38 32 03"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=25
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="1000 80"
-export INFINALITY_FT_BRIGHTNESS="10"
-export INFINALITY_FT_CONTRAST="20"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=false
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=0
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-export INFINALITY_FT_GLOBAL_EMBOLDEN_X_VALUE=0
-export INFINALITY_FT_GLOBAL_EMBOLDEN_Y_VALUE=8
-export INFINALITY_FT_BOLD_EMBOLDEN_X_VALUE=0
-export INFINALITY_FT_BOLD_EMBOLDEN_Y_VALUE=0
-
-fi
-
-
-
-################# IPAD STYLE #################
-if [ "$USE_STYLE" = "IPAD" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="00 00 100 00 00"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=100
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=0
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="1000 80"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=false
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=0
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-export INFINALITY_FT_GLOBAL_EMBOLDEN_X_VALUE=0
-export INFINALITY_FT_GLOBAL_EMBOLDEN_Y_VALUE=0
-export INFINALITY_FT_BOLD_EMBOLDEN_X_VALUE=0
-export INFINALITY_FT_BOLD_EMBOLDEN_Y_VALUE=0
-
-fi
-
-
-
-################# UBUNTU STYLE #################
-if [ "$USE_STYLE" = "UBUNTU" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="1000 80"
-export INFINALITY_FT_BRIGHTNESS="-10"
-export INFINALITY_FT_CONTRAST="15"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=0
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-
-fi
-
-
-
-################# LINUX STYLE #################
-if [ "$USE_STYLE" = "LINUX" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="06 25 44 25 06"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-
-fi
-
-
-################# WINDOWS XP STYLE LIGHT #################
-if [ "$USE_STYLE" = "WINDOWSXPLIGHT" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="06 25 44 25 06"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=100
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=65
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=15
-export INFINALITY_FT_STEM_FITTING_STRENGTH=15
-export INFINALITY_FT_GAMMA_CORRECTION="1000 120"
-export INFINALITY_FT_BRIGHTNESS="20"
-export INFINALITY_FT_CONTRAST="30"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=30
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-################# WINDOWS 7 STYLE LIGHT #################
-if [ "$USE_STYLE" = "WINDOWS7LIGHT" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="20 25 38 25 05"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=100
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=100
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="1000 160"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="20"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=30
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-################# WINDOWS XP STYLE #################
-if [ "$USE_STYLE" = "WINDOWSXP" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="06 25 44 25 06"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=100
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=65
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=15
-export INFINALITY_FT_STEM_FITTING_STRENGTH=15
-export INFINALITY_FT_GAMMA_CORRECTION="1000 120"
-export INFINALITY_FT_BRIGHTNESS="10"
-export INFINALITY_FT_CONTRAST="20"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=30
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-################# WINDOWS 7 STYLE #################
-if [ "$USE_STYLE" = "WINDOWS7" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="20 25 42 25 06"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=100
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=65
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="1000 120"
-export INFINALITY_FT_BRIGHTNESS="10"
-export INFINALITY_FT_CONTRAST="20"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-############### VANILLA STYLE ##############
-if [ "$USE_STYLE" = "VANILLA" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="06 25 38 25 06"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=0
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=false
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=0
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-
-fi
-
-
-############### CLASSIC INFINALITY STYLE ##############
-if [ "$USE_STYLE" = "CLASSIC" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="06 25 38 25 06"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=0
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=0
-export INFINALITY_FT_STEM_FITTING_STRENGTH=0
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-
-fi
-
-
-################# NUDGE STYLE #################
-if [ "$USE_STYLE" = "NUDGE" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=25
-export INFINALITY_FT_STEM_FITTING_STRENGTH=15
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=30
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-
-fi
-
-
-################# PUSH STYLE #################
-if [ "$USE_STYLE" = "PUSH" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=75
-export INFINALITY_FT_STEM_FITTING_STRENGTH=50
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=30
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-################# INFINALITY STYLE #################
-if [ "$USE_STYLE" = "INFINALITY" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=5
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=25
-export INFINALITY_FT_STEM_FITTING_STRENGTH=25
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=40
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-################# SHOVE STYLE #################
-if [ "$USE_STYLE" = "SHOVE" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=100
-export INFINALITY_FT_STEM_FITTING_STRENGTH=100
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-################# SHARPENED INFINALITY STYLE #################
-if [ "$USE_STYLE" = "SHARPENED" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=65
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=25
-export INFINALITY_FT_STEM_FITTING_STRENGTH=25
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=40
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
-
-fi
-
-
-################# DISABLED STYLE #################
-if [ "$USE_STYLE" = "DISABLED" ]; then
-
-export INFINALITY_FT_FILTER_PARAMS=
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=
-export INFINALITY_FT_STEM_FITTING_STRENGTH=
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=false
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=false
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=false
-
-fi
+"
+echo "$XFT_SETTINGS" | xrdb -merge > /dev/null 2>&1
-################# CUSTOM STYLE #################
-if [ "$USE_STYLE" = "CUSTOM" ]; then
+### Available styles:
+### 1 <> extra sharp
+### 2 <> sharper & lighter ultimate
+### 3 <> ultimate: well balanced (default)
+### 4 <> darker & smoother
+### 5 <> darkest & heaviest ("MacIsh")
-export INFINALITY_FT_FILTER_PARAMS="11 22 38 22 11"
-export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH=0
-export INFINALITY_FT_FRINGE_FILTER_STRENGTH=0
-export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH=10
-export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH=25
-export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH=0
-export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH=100
-export INFINALITY_FT_STEM_FITTING_STRENGTH=100
-export INFINALITY_FT_GAMMA_CORRECTION="0 100"
-export INFINALITY_FT_BRIGHTNESS="0"
-export INFINALITY_FT_CONTRAST="0"
-export INFINALITY_FT_USE_VARIOUS_TWEAKS=true
-export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS=true
-export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT=100
-export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE=0
-export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS=true
+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="50"
+export INFINALITY_FT_USE_VARIOUS_TWEAKS="true"
+export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH="20"
+# vim:ft=sh:
diff --git a/testing/freetype-infinality/upstream-2014.10.08.patch b/testing/freetype-infinality/upstream-2014.10.08.patch
new file mode 100644
index 000000000..a51911886
--- /dev/null
+++ b/testing/freetype-infinality/upstream-2014.10.08.patch
@@ -0,0 +1,6990 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index a4e583d..df77d96 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -16,11 +16,16 @@
+ #
+ # cmake CMakeLists.txt
+ #
+-# to create a Makefile that builds a static version of the library. For a
+-# dynamic library, use
++# to create a Makefile that builds a static version of the library.
++#
++# For a dynamic library, use
+ #
+ # cmake CMakeLists.txt -DBUILD_SHARED_LIBS:BOOL=true
+ #
++# For a framework on OS X, use
++#
++# cmake CMakeLists.txt -DBUILD_FRAMEWORK:BOOL=true -G Xcode
++#
+ # instead. Please refer to the cmake manual for further options, in
+ # particular, how to modify compilation and linking parameters.
+ #
+@@ -39,6 +44,14 @@ cmake_minimum_required(VERSION 2.6)
+
+ project(freetype)
+
++if (BUILD_FRAMEWORK)
++ if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode")
++ message(FATAL_ERROR "You should use Xcode generator with BUILD_FRAMEWORK enabled")
++ endif ()
++ set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)")
++ set(BUILD_SHARED_LIBS ON)
++endif ()
++
+ set(VERSION_MAJOR "2")
+ set(VERSION_MINOR "5")
+ set(VERSION_PATCH "3")
+@@ -51,22 +64,27 @@ add_definitions(-DFT2_BUILD_LIBRARY)
+ include_directories("${PROJECT_SOURCE_DIR}/include")
+
+ # Create the configuration file
+-message(STATUS "Creating directory, ${PROJECT_BINARY_DIR}/include.")
+-file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include)
++message(STATUS "Creating directory, ${PROJECT_BINARY_DIR}/include/freetype2.")
++file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include/freetype2)
+
+ # For the auto-generated ftconfig.h file
+-include_directories("${PROJECT_BINARY_DIR}/include")
+-message(STATUS "Creating ${PROJECT_BINARY_DIR}/include/ftconfig.h.")
++include_directories(BEFORE "${PROJECT_BINARY_DIR}/include/freetype2")
++message(STATUS "Creating ${PROJECT_BINARY_DIR}/include/freetype2/ftconfig.h.")
+ execute_process(
+ COMMAND sed -e "s/FT_CONFIG_OPTIONS_H/<ftoption.h>/" -e "s/FT_CONFIG_STANDARD_LIBRARY_H/<ftstdlib.h>/" -e "s?/undef ?#undef ?"
+ INPUT_FILE ${PROJECT_SOURCE_DIR}/builds/unix/ftconfig.in
+- OUTPUT_FILE ${PROJECT_BINARY_DIR}/include/ftconfig.h
++ OUTPUT_FILE ${PROJECT_BINARY_DIR}/include/freetype2/ftconfig.h
+ )
+
++file(GLOB PUBLIC_HEADERS "include/*.h")
++file(GLOB PUBLIC_CONFIG_HEADERS "include/config/*.h")
++file(GLOB PRIVATE_HEADERS "include/internal/*.h")
++
+ set(BASE_SRCS
+ src/autofit/autofit.c
+ src/base/ftadvanc.c
+ src/base/ftbbox.c
++ src/base/ftbdf.c
+ src/base/ftbitmap.c
+ src/base/ftcalc.c
+ src/base/ftcid.c
+@@ -125,7 +143,31 @@ include_directories("src/raster")
+ include_directories("src/psaux")
+ include_directories("src/psnames")
+
+-add_library(freetype ${BASE_SRCS})
++if (BUILD_FRAMEWORK)
++ set(BASE_SRCS
++ ${BASE_SRCS}
++ builds/mac/freetype-Info.plist
++ )
++endif ()
++
++add_library(freetype
++ ${PUBLIC_HEADERS}
++ ${PUBLIC_CONFIG_HEADERS}
++ ${PRIVATE_HEADERS}
++ ${BASE_SRCS}
++)
++
++if (BUILD_FRAMEWORK)
++ set_property(SOURCE ${PUBLIC_CONFIG_HEADERS}
++ PROPERTY MACOSX_PACKAGE_LOCATION Headers/config
++ )
++ set_target_properties(freetype PROPERTIES
++ FRAMEWORK TRUE
++ MACOSX_FRAMEWORK_INFO_PLIST builds/mac/freetype-Info.plist
++ PUBLIC_HEADER "${PUBLIC_HEADERS}"
++ XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
++ )
++endif ()
+
+ # Installations
+ # Note the trailing slash in the argument to the `DIRECTORY' directive
+@@ -137,6 +179,7 @@ install(TARGETS freetype
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
++ FRAMEWORK DESTINATION Library/Frameworks
+ )
+
+ # Packaging
+diff --git a/ChangeLog b/ChangeLog
+index ea1eb4a..4e17454 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,703 @@
++2014-10-02 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Significant optimization of `ft_div64by32'
++
++ We shift as many bits as we can into the high register, perform
++ 32-bit division with modulo there, then work through the remaining
++ bits with long division. This optimization is especially noticeable
++ for smaller dividends that barely use the high register.
++
++ * src/base/ftcalc.c (ft_div64by32): Updated.
++
++2014-10-02 Dave Arnold <darnold@adobe.com>
++
++ [cff] Fix Savannah bug #43271.
++
++ * src/cff/cf2font.c (cf2_computeDarkening): Change overflow
++ detection to use logarithms and clamp `scaledStem'.
++
++2014-10-01 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ * src/base/ftcalc.c: Remove miscellaneous type casts.
++
++2014-10-01 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Use more common `FT_MSB' implementation with masks.
++
++ * src/base/ftcalc.c (FT_MSB): Updated.
++
++2014-09-30 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Clean up.
++
++ * src/base/ftcalc.c (FT_MOVE_SIGN): New macro for frequently used
++ code.
++
++2014-09-25 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Avoid unnecessary long division.
++
++ This applies to `FT_MulDiv' but not to `FT_DivFix', where overflows or
++ lack thereof are predicted accurately.
++
++ * src/base/ftcalc.c (ft_div64by32): Improve readability.
++ (FT_MulDiv, FT_MulDiv_No_Round) [!FT_LONG64]: Use straight division
++ when multiplication stayed within 32 bits.
++
++2014-09-24 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Minor clean-ups.
++
++ * src/autofit/afhints.c (AF_FLAGS): Remove obsolete values.
++
++ * src/autofit/afhints.c (af_glyph_hints_dump_points,
++ af_glyph_hints_align_strong_points): Updated.
++
++ * src/autofit/aflatin.c (af_latin_hints_link_segments,
++ af_latin_hints_compute_segments), src/autofit/afcjk.c
++ (af_cjk_hints_link_segments), src/autofit/aflatin2.c
++ (af_latin2_hints_link_segments, af_latin2_hints_compute_segments):
++ There are no longer fake segments since more than 10 years...
++
++2014-09-22 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Minor code streamlining.
++
++ * src/autofit/afhints.c (af_axis_hints_new_edge): Remove redundant
++ initialization.
++
++2014-09-19 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ * src/base/ftcalc.c: Harmonize code.
++
++2014-09-15 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Tighten the overflow check in `FT_MulDiv'.
++
++ * src/base/ftcalc.c (FT_MulDiv) [!FT_LONG64]: Updated.
++
++2014-09-08 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ Fix Savannah bug #43153.
++
++ * src/psaux/psconv.c (PS_Conv_ToFixed): Add protection against
++ overflow in `divider'.
++
++2014-09-03 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Tighten the overflow check in `FT_DivFix'.
++
++ This fixes a 13-year old bug. The original overflow check should have
++ been updated when rounding was introduced into this function
++ (c2cd00443b).
++
++ * src/base/ftcalc.c (FT_DivFix) [!FT_LONG64]: Updated.
++ * include/freetype.h (FT_DivFix): Updated documentation.
++
++2014-09-03 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Tighten the overflow check in `FT_MulFix'.
++
++ * src/base/ftcalc.c (FT_MulFix) [!FT_LONG64]: Updated.
++
++2014-09-02 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [truetype] Shortcut ppem calculations for square pixels.
++
++ * src/truetype/ttinterp.h (TT_ExecContextRec): New field
++ `cur_ppem_func' with a function pointer.
++ * src/truetype/ttinterp.c (TT_RunIns): Initialize `cur_ppem_func'
++ depending on the pixel geometry to either...
++ (Current_Ppem_Stretched): ... this for stretched pixels.
++ (Current_Ppem): ... or this for square pixels.
++ (DO_MPPEM, DO_MPS, Ins_DELTAP, Ins_DELTAC): Use `cur_ppem_func'.
++
++2014-08-31 Behdad Esfahbod <behdad@behdad.org>
++
++ Don't use `register' keyword. Fixes compiler warnings.
++
++ * src/base/ftcalc.c (FT_Add64) [!FT_LONG64]: Do it.
++ * src/gzip/inftrees.c (huft_build): Ditto.
++ * src/truetype/ttinterp.c (TT_MulFix14_arm): Ditto.
++
++2014-08-24 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [truetype] Optimize DELTAP and DELTAC.
++
++ * src/truetype/ttinterp.c (Ins_DELTAP, Ins_DELTAC): Move ppem
++ calculations outside of the loop.
++
++2014-08-21 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ Fix Savannah bug #43033.
++
++ * include/config/ftconfig.h, builds/unix/ftconfig.in,
++ builds/vms/ftconfig.h [FT_LONG64]: Do not disable the macro when
++ 64-bit type is `long'.
++
++2014-08-20 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Small optimization of `FT_MulFix'.
++
++ * src/base/ftcalc.c (FT_MulFix): Loosen up the condition for direct
++ 32-bit calculations.
++
++2014-08-19 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Use unsigned calculation in `FT_MulDiv'.
++
++ * src/base/ftcalc.c (FT_MulDiv): Updated to expand 32-bit range.
++
++2014-08-18 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Remove truncation in `FT_DivFix'.
++
++ * src/base/ftcalc.c (FT_DivFix): Updated.
++
++2014-08-14 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ Minor refactoring.
++
++ * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round): Updated.
++
++2014-08-14 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ Turn FT_MSB into a macro when using gcc builtins.
++
++ * src/base/ftcalc.c, include/internal/ftcalc.h: Updated.
++
++2014-08-12 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Avoid undefined FT_MSB in `BBox_Cubic_Check'.
++
++ * src/base/ftbbox.c (BBox_Cubic_Check): Update.
++ (update_cubic_max): Repalce with...
++ (cubic_peak): ... this, which now handles upscaling.
++
++2014-08-11 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Handle collapsed outlines to avoid undefined FT_MSB.
++
++ * src/base/ftoutln.c (FT_Outline_Get_Orientation): Update.
++
++2014-08-11 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Restore FT_MulFix inlining.
++
++ * include/freetype.h (FT_MulFix): Unconditionally defined.
++
++ * src/base/ftcalc.c [FT_MULFIX_ASSEMBLER]: Move code from here...
++
++ * include/internal/ftcalc.h [FT_MULFIX_ASSEMBLER]: ... to here,
++ which conditionally replaces the function with an inline version
++ through the macro.
++
++2014-08-08 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Refactor.
++
++2014-07-26 Werner Lemberg <wl@gnu.org>
++
++ [cff] Fix typo.
++
++ * src/cff/cf2hints.c (cf2_glyphpath_computeOffset): Use correct
++ offsets in third quadrant.
++
++ Reported by maks <maksqwe1@ukr.net>.
++
++2014-07-17 Werner Lemberg <wl@gnu.org>
++
++ Fix Savannah bug #42788.
++
++ * src/pfr/pfrobjs.c: Include `ftcalc.h'.
++
++2014-07-16 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ Replace `ft_highpow2' function.
++
++ * src/pfr/pfrobjs.c (pfr_face_get_kerning): Use `FT_MSB' instead of
++ `ft_highpow2'.
++
++ * src/base/ftutil.c, include/internal/ftobjs.h (ft_highpow2): Remove
++ it.
++
++2014-07-15 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ * src/base/ftcalc.c (FT_MSB): Utilize gcc builtins.
++
++2014-07-15 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Move assembler code back in the source file.
++
++ FT_MulFix assembler used to reside in ftcalc.c before f47d263f1b.
++
++ * include/config/ftconfig.h, builds/unix/ftconfig.in,
++ builds/vms/ftconfig.h [FT_MULFIX_ASSEMBLER]: Move code from here...
++
++ * src/base/ftcalc.c [FT_MULFIX_ASSEMBLER]: ... to here.
++
++2014-07-14 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Further clean up color bitmap conversion.
++
++ * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Stop
++ using FT_MulFix and FT_DivFix since all calculations fit into 32 bits.
++
++2014-07-13 Werner Lemberg <wl@gnu.org>
++
++ [truetype] Improve handling of buggy `prep' tables.
++
++ In case of an error in the `prep' table, no longer try to execute it
++ again and again. This makes FreeType handle endless loops in buggy
++ fonts much faster.
++
++ * src/truetype/ttobjs.h (TT_SizeRec): The fields `bytecode_ready'
++ and `cvt_ready' are now negative if not initialized yet, otherwise
++ they indicate the error code of the last run.
++
++ * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep,
++ tt_size_done_bytecode, tt_size_init_bytecode,
++ tt_size_ready_bytecode, tt_size_init, tt_size_done, tt_size_reset):
++ Updated.
++
++ * src/truetype/ttgload.c (tt_loader_init): Updated.
++ * src/truetype/ttinterp.c (TT_RunIns): Force reexecution of `fpgm'
++ and `prep' only if we are in the `glyf' table.
++
++2014-07-12 Werner Lemberg <wl@gnu.org>
++
++ * builds/vms/ftconfig.h: Synchronize.
++ Problem reported by Alexei.
++
++2014-07-11 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Clean up bitmap conversion.
++
++ * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Use
++ appropriate FT_DivFix and remove superfluous upscaling.
++
++2014-07-04 Alexei Podtelezhnikov <apodtele@gmail.com>
++
++ [base] Small optimization of the ancient code.
++
++ * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round): Loosen up the
++ condition for direct 32-bit calculations.
++
++2014-06-27 Werner Lemberg <wl@gnu.org>
++
++ Fix Apple standard glyph names.
++
++ * src/sfnt/ttpost.c (tt_post_default_names): Synchronize with
++ `tools/glnames.py'
++
++ Problem reported by Adam Twardoch <adam@fontlab.com>.
++
++2014-06-17 Werner Lemberg <wl@gnu.org>
++
++ Partially revert commit from 2014-06-13.
++
++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Move
++ declaration of `p_first' and `p_last' out of the loop.
++
++2014-06-17 Werner Lemberg <wl@gnu.org>
++
++ * builds/unix/freetype2.m4: s/AC_PATH_PROG/AC_PATH_TOOL/.
++
++ This simplifies cross-compiling.
++
++2014-06-13 Werner Lemberg <wl@gnu.org>
++
++ Fix more compiler warnings.
++ Reported by Wojciech Mamrak <wmamrak@gmail.com>.
++
++ * src/autofit/afglobal.c (af_face_globals_compute_style_coverage):
++ Make integer constant unsigned.
++
++ * src/sfnt/ttsbit.c (tt_face_load_strike_metrics)
++ <TT_SBIT_TABLE_TYPE_SBIX>: Fix types.
++ (tt_sbit_decoder_load_compound, tt_face_load_sbix_image): Add proper
++ casts.
++
++2014-06-13 Werner Lemberg <wl@gnu.org>
++
++ Fix compiler warnings.
++ Reported by Wojciech Mamrak <wmamrak@gmail.com>.
++
++ * src/autofit/afglobal.c (af_face_globals_compute_style_coverage),
++ src/autofit/afmodule.c (af_property_set): Fix `signed' vs.
++ `unsigned' issues.
++
++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Make compiler
++ happy.
++
++ * src/base/ftlcdfil.c (_ft_lcd_filter_fir): Use only four elements
++ for `fir'.
++ Fix `signed' vs. `unsigned' issues.
++
++ * src/sfnt/sfobjs.c (WRITE_BYTE): Removed, unused.
++ (WRITE_USHORT, WRITE_ULONG): Add proper casts.
++
++ * src/truetype/ttgload.c (TT_Get_VMetrics): Add proper casts.
++
++ * src/truetype/ttinterp.c (Ins_DELTAP): Add proper casts for `B1'
++ and `B2'.
++
++2014-05-16 Alexey Petruchik <alexey.petruchik@gmail.com>
++
++ [cmake] Add option to build OS X framework.
++
++ * CMakeLists.txt: Update accordingly.
++
++ * builds/mac/freetype-Info.plist: New file.
++
++2014-05-13 Pavel Koshevoy <pkoshevoy@gmail.com>
++
++ * CMakeLists.txt (BASE_SRCS): Add missing `ftbdf.c'.
++
++2014-05-11 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Fix variable initializations.
++
++ * src/autofit/afhints.c (af_glyph_hints_reload): Assign default
++ values to `in_dir' and `out_dir' for all points.
++
++2014-05-11 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Fix crash with font `CabinSketch-Bold.ttf'.
++
++ Problem reported by Ralf S. Engelschall <rse@engelschall.com>.
++
++ * src/autofit/afhints.c (af_glyph_hints_reload): Fix threshold for
++ finding first non-near point.
++ Properly initialize non-near point deltas.
++
++2014-05-01 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Add blue-zone support for Devanagari.
++
++ This essentially moves the Devanagari script from the `Indic' hinter
++ to the `Latin' hinter. Thanks to Girish Dalvi
++ <girish.dalvi@gmail.com> for guidance with blue zone characters!
++
++ * src/autofit/afblue.dat: Add blue zone data for Devanagari.
++
++ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
++
++ * src/autofit/afscript.h: Add Devanagari standard characters and
++ move data out of AF_CONFIG_OPTION_INDIC block.
++
++ * src/autofit/afranges.c: Move Devanagari data out of
++ AF_CONFIG_OPTION_INDIC block.
++ Move U+20B9, (new) Rupee sign, from Latin to Devanagari.
++
++ * src/autofit/afstyles.h: Update Devanagari data; in particular, use
++ AF_WRITING_SYSTEM_LATIN.
++
++2014-05-01 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Fix handling of neutral blue zones in stems.
++
++ * src/autofit/afhints.h (AF_Edge_Flags): New value
++ `AF_EDGE_NEUTRAL'.
++
++ * src/autofit/aflatin.c (af_latin_hints_compute_blue_edges): Trace
++ neutral blue zones with AF_EDGE_NEUTRAL.
++ (af_latin_hint_edges): Skip neutral blue zones if necessary.
++
++2014-04-28 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Introduce neutral blue zones to the latin module.
++
++ Such blue zones match either the top or the bottom of a contour. We
++ need them for scripts where accent-like elements directly touch the
++ base character (for example, some vowel signs in Devanagari, cf.
++ U+0913 or U+0914).
++
++ * src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_NEUTRAL): New
++ property.
++
++ * src/autofit/afblue.h: Regenerated.
++
++ * src/autofit/aflatin.h (AF_LATIN_IS_NEUTRAL_BLUE): New macro.
++ (AF_LATIN_BLUE_NEUTRAL): New enumeration value.
++
++ * src/autofit/aflatin.c (af_latin_metrics_init_blues,
++ af_latin_hints_compute_blue_edges): Handle neutral blue zones.
++
++2014-04-25 Werner Lemberg <wl@gnu.org>
++
++ * src/autofit/hbshim.c: Partially revert commit from 2014-04-17.
++
++ Using input glyph coverage data is simply wrong.
++
++ Problem reported by Nikolaus Waxweiler <madigens@gmail.com> and
++ Mantas Mikulėnas <grawity@gmail.com>.
++
++2014-04-23 Werner Lemberg <wl@gnu.org>
++
++ * src/raster/ftraster.c (Vertical_Sweep_Span): Use drop-out mode.
++
++ This spot has been missed while introducing support for various
++ drop-out modes years ago (including no drop-out mode, which this
++ commit fixes).
++
++ Problem reported by Patrick Thomas <pthomas505@gmail.com>.
++
++2014-04-22 Werner Lemberg <wl@gnu.org>
++
++ * src/sfnt/pngshim.c (error_callback): s/longjmp/ft_longjmp/.
++
++2014-04-20 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Fix Savannah bug #42148.
++
++ The adaptation of the cjk auto-hinter module to blue stringsets in
++ 2013-08-25 had three severe bugs. Mea culpa.
++
++ 1. Contrary to the latin auto-hinter, characters for reference and
++ overshoot values of a blue zone are specified separately. Due to
++ the screwed-up change it didn't work at all.
++
++ 2. A boolean comparison was erroneously replaced with a cast,
++ causing invalid results with the `^' operator later on. The
++ visual artifact caused by this problem is the topic of the bug
++ report.
++
++ 3. Two flag values were inverted, causing incorrect assignment of
++ reference and overshoot values.
++
++ * src/autofit/afblue.dat: Fix CJK bluestrings, introducing a new
++ syntax to have both reference and overshoot characters in a single
++ string. This is error #1.
++ Add extensive comments.
++
++ * src/autofit/afblue.hin (AF_BLUE_PROPERTY_CJK_FILL): Removed, no
++ longer used.
++ (AF_BLUE_PROPERTY_CJK_TOP, AF_BLUE_PROPERTY_CJK_HORIZ): Fix values.
++ This is error #3.
++
++ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
++
++ * src/autofit/afcjk.c (af_cjk_metrics_init_blues): Correct error #1.
++ Use character `|' to separate characters for reference and overshoot
++ values.
++ Improve tracing messages, synchronizing them with the latin
++ auto-hinter.
++ (af_cjk_hints_compute_blue_edges): Fix value of `is_top_right_blue'.
++ This is error #2.
++ (af_cjk_align_linked_edge): Add tracing message.
++
++ * src/autofit/afcjk.h (AF_CJK_IS_FILLED_BLUE): Removed, no longer
++ used.
++
++2014-04-17 Werner Lemberg <wl@gnu.org>
++
++ [autofit] More coverage fixes for complex scripts.
++
++ * src/autofit/hbshim.c (af_get_coverage): Merge input glyph coverage
++ of GSUB lookups into output coverage. Otherwise, ligatures are not
++ handled properly.
++ Don't check blue zone characters for default coverage.
++
++2014-04-17 Werner Lemberg <wl@gnu.org>
++
++ Make `FT_Get_SubGlyph_Info' actually work.
++
++ * src/base/ftobjs.c (FT_Get_SubGlyph_Info): Return FT_Err_Ok
++ if there is no error.
++
++2014-04-15 Werner Lemberg <wl@gnu.org>
++
++ [afblue.pl]: Minor improvements.
++
++ * src/tools/afblue.pl: Allow whitespace before comments.
++ Ignore whitespace in strings.
++
++2014-04-14 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Improve coverage handling.
++
++ * src/autofit/hbshim.c (af_get_coverage): Don't exclude glyphs
++ appearing in the GPOS table if we are processing the default
++ coverage.
++
++2014-04-13 David Weber <weber.aulendorf@googlemail.com>
++
++ [smooth] Fix stand-alone compilation.
++
++ * src/smooth/ftgrays.c (FT_BEGIN_STMNT, FT_END_STMNT): Define.
++
++2014-04-12 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Redesign the recognition algorithm of strong points.
++
++ In particular, local extrema without horizontal or vertical segments
++ are better recognized:
++
++ + A + D
++ \ /
++ \ /
++ \ /
++ \ /
++ \ + C
++ \ /
++ B +/
++
++ If the distances AB and CD are large, point B wasn't previously
++ detected as an extremum since the `ft_corner_is_flat' function
++ `swallowed' BC regardless of its direction, tagging point B as weak.
++ The next iteration started at B and made `ft_corner_is_flat' swallow
++ point C, tagging it as weak also, et voilà.
++
++ To improve that, another pass gets now performed before calling
++ `ft_corner_is_flat' to improve the `topology' of an outline: A
++ sequence of non-horizontal or non-vertical vectors that point into
++ the same quadrant are handled as a single, large vector.
++
++ Additionally, distances of near points are now accumulated, which
++ makes the auto-hinter handle them as if they were prepended to the
++ next non-near vector.
++
++ This generally improves the auto-hinter's rendering results.
++
++ * src/autofit/afhints.c (af_glyph_hints_reload): Implement it.
++
++ * src/autofit/afhints.h (AF_FLAGS): Remove no longer used flag
++ `AF_FLAG_NEAR'.
++
++2014-04-05 Werner Lemberg <wl@gnu.org>
++
++ [autofit] Improve scoring algorithm for identifying stems.
++
++ Problem reported by Karsten Lücke <karsten.luecke@kltf.de>.
++
++ The new algorithm takes care of the width of stems: If the distance
++ between two segments is larger than the largest stem width, the
++ demerits quickly increase for larger distances. This improves
++ hinting of slanted fonts (especially if the inner parts of serifs
++ have non-horizontal `shoulders'), avoiding false stem links.
++
++ * src/autofit/aflatin.c (af_latin_hints_link_segments): Use largest
++ stem width (if available) to compute better demerits for distances
++ between stems.
++ (af_latin_hints_detect_features): Pass stem width array and array
++ size.
++ (af_latin_metrics_init_widths): Updated to use original algorithm.
++ (af_latin_hints_apply): Updated to use new algorithm.
++
++ * src/autofit/aflatin.h: Updated.
++ * src/autofit/afcjk.c: Updated.
++
++2014-04-03 Werner Lemberg <wl@gnu.org>
++
++ Don't require `gzip' module for `sfnt'.
++
++ Reported by Preet <prismatic.project@gmail.com>.
++
++ * src/sfnt/sfobjs.c (woff_open_font): Guard use of
++ FT_Gzip_Uncompress with FT_CONFIG_OPTION_USE_ZLIB.
++
++2014-03-27 Werner Lemberg <wl@gnu.org>
++
++ Fix Savannah bug #38235.
++
++ Work around a bug in pkg-config version 0.28 and earlier: If a
++ variable value gets surrounded by doublequotes (in particular values
++ for the `prefix' variable), the prefix override mechanism fails.
++
++ * builds/unix/freetype2.in: Don't use doublequotes.
++ * builds/unix/unix-def.in (freetype.pc): Escape spaces in directory
++ names with backslashes.
++
++2014-03-24 Werner Lemberg <wl@gnu.org>
++
++ Fix Savannah bug #41946.
++
++ Based on a patch from Marek Kašík <mkasik@redhat.com>.
++
++ * builds/unix/configure.raw (LIBS_CONFIG): Remove.
++ * builds/unix/freetype-config.in (libs): Hard-code value.
++ * builds/unix/unix-def.in: Updated.
++
++2014-03-22 Werner Lemberg <wl@gnu.org>
++
++ Another revert for the change from 2014-03-18.
++
++ Problem reported by Nikolaus Waxweiler <madigens@gmail.com>.
++
++ * src/base/ftcalc.c (FT_MulFix): Ensure that an `FT_MulFix' symbol
++ gets always exported.
++
++2014-03-20 Werner Lemberg <wl@gnu.org>
++
++ CMakeLists.txt: Another fix for include directories.
++
++ Problem reported by Taylor Holberton <taylorcholberton@gmail.com>.
++
++2014-03-19 Werner Lemberg <wl@gnu.org>
++
++ CMakeLists.txt: Fix include directories.
++
++ Problem reported by Taylor Holberton <taylorcholberton@gmail.com>.
++
++2014-03-19 Werner Lemberg <wl@gnu.org>
++
++ Partially revert last commit.
++
++ Found by Alexei.
++
++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Initializing
++ those variables is plain wrong, since we are in a loop.
++
++2014-03-18 Sean McBride <sean@rogue-research.com>
++ Werner Lemberg <wl@gnu.org>
++
++ Fix clang warnings.
++
++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Initialize
++ some variables.
++
++ * src/base/ftcalc.c (FT_MulFix): Only use code if
++ `FT_MULFIX_INLINED' is not defined.
++
++ * src/bdf/bdfdrivr.c (bdf_cmap_class), src/cache/ftcbasic.c
++ (ftc_basic_image_family_class, ftc_basic_image_cache_class,
++ ftc_basic_sbit_family_class, ftc_basic_sbit_cache_class),
++ src/cache/ftccmap.c (ftc_cmap_cache_class), src/cache/ftcmanag.c
++ (ftc_size_list_class, ftc_face_list_class), src/pcf/pcfdrivr.c
++ (pcf_cmap_class), src/pfr/pfrdrivr.c (pfr_metrics_service_rec): Make
++ function static.
++
++ * src/type1/t1driver.c (t1_ps_get_font_value): Remove redundant
++ code.
++
++2014-03-17 Werner Lemberg <wl@gnu.org>
++
++ Fix Savannah bug #41869.
++
++ This works around a problem with HarfBuzz (<= 0.9.26), which doesn't
++ validate glyph indices returned by
++ `hb_ot_layout_lookup_collect_glyphs'.
++
++ * src/autofit/hbshim.c (af_get_coverage): Guard `idx'.
++
++ * docs/CHANGES: Updated.
++
++2014-03-14 Werner Lemberg <wl@gnu.org>
++
++ * builds/unix/configure.raw: Don't show error messages of `which'.
++
++2014-03-09 Alan Coopersmith <alan.coopersmith@oracle.com>
++
++ Fix cppcheck 1.64 warning.
++
++ * src/autofit/afglobal.c (af_face_globals_new): Catch NULL pointer
++ dereference in case of error.
++
++2014-03-09 Sean McBride <sean@rogue-research.com>
++
++ * src/sfnt/ttcmap.c (tt_face_build_cmaps): Remove clang warning.
++
+ 2014-03-06 Werner Lemberg <wl@gnu.org>
+
+ * Version 2.5.3 released.
+diff --git a/builds/mac/freetype-Info.plist b/builds/mac/freetype-Info.plist
+new file mode 100644
+index 0000000..b3d114d
+--- /dev/null
++++ b/builds/mac/freetype-Info.plist
+@@ -0,0 +1,36 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
++ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
++
++<plist version="1.0">
++
++<dict>
++ <key>CFBundleDevelopmentRegion</key>
++ <string>English</string>
++
++ <key>CFBundleExecutable</key>
++ <string>FreeType</string>
++
++ <key>CFBundleGetInfoString</key>
++ <string>FreeType ${PROJECT_VERSION}</string>
++
++ <key>CFBundleInfoDictionaryVersion</key>
++ <string>6.0</string>
++
++ <key>CFBundleName</key>
++ <string>FreeType</string>
++
++ <key>CFBundlePackageType</key>
++ <string>FMWK</string>
++
++ <key>CFBundleShortVersionString</key>
++ <string>${PROJECT_VERSION}</string>
++
++ <key>CFBundleSignature</key>
++ <string>????</string>
++
++ <key>CFBundleVersion</key>
++ <string>${PROJECT_VERSION}</string>
++</dict>
++
++</plist>
+diff --git a/builds/unix/configure.raw b/builds/unix/configure.raw
+index dd7e576..8a17ffe 100644
+--- a/builds/unix/configure.raw
++++ b/builds/unix/configure.raw
+@@ -437,7 +437,7 @@ if test x"$with_png" = xyes -o x"$with_png" = xauto; then
+ else
+ # fall back to config script.
+ AC_MSG_CHECKING([for libpng-config])
+- if which libpng-config > /dev/null; then
++ if which libpng-config > /dev/null 2>&1; then
+ LIBPNG_CFLAGS=`libpng-config --cflags`
+ LIBPNG_LIBS=`libpng-config --ldflags`
+ libpng_libpriv=`libpng-config --static --ldflags`
+@@ -656,7 +656,7 @@ else
+ fi
+
+
+-# Whether to use FileManager which is deprecated since Mac OS X 10.4.
++# Whether to use FileManager, which is deprecated since Mac OS X 10.4.
+
+ AC_ARG_WITH([fsspec],
+ AS_HELP_STRING([--with-fsspec],
+@@ -765,7 +765,7 @@ elif test x$with_old_mac_fonts = xyes -a x$with_fsref != x; then
+ fi
+
+
+-# Whether to use QuickDraw API in ToolBox which is deprecated since
++# Whether to use QuickDraw API in ToolBox, which is deprecated since
+ # Mac OS X 10.4.
+
+ AC_ARG_WITH([quickdraw-toolbox],
+@@ -807,7 +807,7 @@ elif test x$with_old_mac_fonts = xyes -a x$with_quickdraw_toolbox != x; then
+ fi
+
+
+-# Whether to use QuickDraw API in Carbon which is deprecated since
++# Whether to use QuickDraw API in Carbon, which is deprecated since
+ # Mac OS X 10.4.
+
+ AC_ARG_WITH([quickdraw-carbon],
+@@ -937,21 +937,6 @@ LIBS_PRIVATE=`echo "$LIBS_PRIVATE" \
+ -e 's/ *$//' \
+ -e 's/ */ /g'`
+
+-LIBS_CONFIG="-lfreetype \
+- $ZLIB_LIBS \
+- $BZIP2_LIBS \
+- $LIBPNG_LIBS \
+- $HARFBUZZ_LIBS \
+- $ft2_extra_libs"
+-# remove -L/usr/lib and -L/usr/lib64 since `freetype-config' adds them later
+-# on if necessary; also beautify
+-LIBS_CONFIG=`echo "$LIBS_CONFIG" \
+- | sed -e 's|-L */usr/lib64/* | |g' \
+- -e 's|-L */usr/lib/* | |g' \
+- -e 's/^ *//' \
+- -e 's/ *$//' \
+- -e 's/ */ /g'`
+-
+ LIBSSTATIC_CONFIG="-lfreetype \
+ $zlib_libstaticconf \
+ $bzip2_libstaticconf \
+@@ -971,7 +956,6 @@ LIBSSTATIC_CONFIG=`echo "$LIBSSTATIC_CONFIG" \
+ AC_SUBST([ftmac_c])
+ AC_SUBST([REQUIRES_PRIVATE])
+ AC_SUBST([LIBS_PRIVATE])
+-AC_SUBST([LIBS_CONFIG])
+ AC_SUBST([LIBSSTATIC_CONFIG])
+
+ AC_SUBST([hardcode_libdir_flag_spec])
+diff --git a/builds/unix/freetype-config.in b/builds/unix/freetype-config.in
+index 41c3a88..ebc311f 100644
+--- a/builds/unix/freetype-config.in
++++ b/builds/unix/freetype-config.in
+@@ -142,7 +142,7 @@ if test "$echo_cflags" = "yes" ; then
+ fi
+
+ if test "$echo_libs" = "yes" ; then
+- libs="%LIBS_CONFIG%"
++ libs="-lfreetype"
+ staticlibs="%LIBSSTATIC_CONFIG%"
+ if test "$show_static" = "yes" ; then
+ libs="$staticlibs"
+diff --git a/builds/unix/freetype2.in b/builds/unix/freetype2.in
+index 6e7fb10..a488d96 100644
+--- a/builds/unix/freetype2.in
++++ b/builds/unix/freetype2.in
+@@ -1,7 +1,7 @@
+-prefix="%prefix%"
+-exec_prefix="%exec_prefix%"
+-libdir="%libdir%"
+-includedir="%includedir%/freetype2"
++prefix=%prefix%
++exec_prefix=%exec_prefix%
++libdir=%libdir%
++includedir=%includedir%/freetype2
+
+ Name: FreeType 2
+ URL: http://freetype.org
+diff --git a/builds/unix/freetype2.m4 b/builds/unix/freetype2.m4
+index 3d0ecb3..3a806d9 100644
+--- a/builds/unix/freetype2.m4
++++ b/builds/unix/freetype2.m4
+@@ -1,7 +1,7 @@
+ # Configure paths for FreeType2
+ # Marcelo Magallon 2001-10-26, based on gtk.m4 by Owen Taylor
+ #
+-# Copyright 2001, 2003, 2007, 2009 by
++# Copyright 2001, 2003, 2007, 2009, 2014 by
+ # David Turner, Robert Wilhelm, and Werner Lemberg.
+ #
+ # This file is part of the FreeType project, and may only be used, modified,
+@@ -15,7 +15,7 @@
+ # generated by Autoconf, under the same distribution terms as the rest of
+ # that program.
+ #
+-# serial 3
++# serial 4
+
+ # AC_CHECK_FT2([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+ # Test for FreeType 2, and define FT2_CFLAGS and FT2_LIBS.
+@@ -61,7 +61,7 @@ AC_DEFUN([AC_CHECK_FT2],
+ fi
+
+ if test "x$FT2_CONFIG" = x ; then
+- AC_PATH_PROG([FT2_CONFIG], [freetype-config], [no])
++ AC_PATH_TOOL([FT2_CONFIG], [freetype-config], [no])
+ fi
+
+ min_ft_version=m4_if([$1], [], [7.0.1], [$1])
+diff --git a/builds/unix/ftconfig.in b/builds/unix/ftconfig.in
+index 2cf6708..e66f3ea 100644
+--- a/builds/unix/ftconfig.in
++++ b/builds/unix/ftconfig.in
+@@ -296,7 +296,16 @@ FT_BEGIN_HEADER
+ #define FT_INT64 long
+ #define FT_UINT64 unsigned long
+
+-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
++ /*************************************************************************/
++ /* */
++ /* A 64-bit data type may create compilation problems if you compile */
++ /* in strict ANSI mode. To avoid them, we disable other 64-bit data */
++ /* types if __STDC__ is defined. You can however ignore this rule */
++ /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
++ /* */
++#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
++
++#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+
+ /* this compiler provides the __int64 type */
+ #define FT_LONG64
+@@ -330,30 +339,9 @@ FT_BEGIN_HEADER
+ #define FT_INT64 long long int
+ #define FT_UINT64 unsigned long long int
+
+-#endif /* FT_SIZEOF_LONG == 8 */
+-
+-
+- /*************************************************************************/
+- /* */
+- /* A 64-bit data type will create compilation problems if you compile */
+- /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */
+- /* is defined. You can however ignore this rule by defining the */
+- /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
+- /* */
+-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )
+-
+-#ifdef __STDC__
+-
+- /* Undefine the 64-bit macros in strict ANSI compilation mode. */
+- /* Since `#undef' doesn't survive in configuration header files */
+- /* we use the postprocessing facility of AC_CONFIG_HEADERS to */
+- /* replace the leading `/' with `#'. */
+-/undef FT_LONG64
+-/undef FT_INT64
+-
+-#endif /* __STDC__ */
++#endif /* _MSC_VER */
+
+-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
++#endif /* FT_SIZEOF_LONG == 8 */
+
+ #ifdef FT_LONG64
+ typedef FT_INT64 FT_Int64;
+@@ -366,219 +354,6 @@ FT_BEGIN_HEADER
+ #define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
+
+
+-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+- /* Provide assembler fragments for performance-critical functions. */
+- /* These must be defined `static __inline__' with GCC. */
+-
+-#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+-
+- /* documentation is in freetype.h */
+-
+- static __inline FT_Int32
+- FT_MulFix_arm( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 t, t2;
+-
+-
+- __asm
+- {
+- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
+- mov a, t, asr #31 /* a = (hi >> 31) */
+- add a, a, #0x8000 /* a += 0x8000 */
+- adds t2, t2, a /* t2 += a */
+- adc t, t, #0 /* t += carry */
+- mov a, t2, lsr #16 /* a = t2 >> 16 */
+- orr a, a, t, lsl #16 /* a |= t << 16 */
+- }
+- return a;
+- }
+-
+-#endif /* __CC_ARM || __ARMCC__ */
+-
+-
+-#ifdef __GNUC__
+-
+-#if defined( __arm__ ) && \
+- ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
+- !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+-
+- /* documentation is in freetype.h */
+-
+- static __inline__ FT_Int32
+- FT_MulFix_arm( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 t, t2;
+-
+-
+- __asm__ __volatile__ (
+- "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
+- "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
+-#if defined( __clang__ ) && defined( __thumb2__ )
+- "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
+-#else
+- "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
+-#endif
+- "adds %1, %1, %0\n\t" /* %1 += %0 */
+- "adc %2, %2, #0\n\t" /* %2 += carry */
+- "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
+- "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
+- : "=r"(a), "=&r"(t2), "=&r"(t)
+- : "r"(a), "r"(b)
+- : "cc" );
+- return a;
+- }
+-
+-#endif /* __arm__ && */
+- /* ( __thumb2__ || !__thumb__ ) && */
+- /* !( __CC_ARM || __ARMCC__ ) */
+-
+-
+-#if defined( __i386__ )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+-
+- /* documentation is in freetype.h */
+-
+- static __inline__ FT_Int32
+- FT_MulFix_i386( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 result;
+-
+-
+- __asm__ __volatile__ (
+- "imul %%edx\n"
+- "movl %%edx, %%ecx\n"
+- "sarl $31, %%ecx\n"
+- "addl $0x8000, %%ecx\n"
+- "addl %%ecx, %%eax\n"
+- "adcl $0, %%edx\n"
+- "shrl $16, %%eax\n"
+- "shll $16, %%edx\n"
+- "addl %%edx, %%eax\n"
+- : "=a"(result), "=d"(b)
+- : "a"(a), "d"(b)
+- : "%ecx", "cc" );
+- return result;
+- }
+-
+-#endif /* i386 */
+-
+-#endif /* __GNUC__ */
+-
+-
+-#ifdef _MSC_VER /* Visual C++ */
+-
+-#ifdef _M_IX86
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+-
+- /* documentation is in freetype.h */
+-
+- static __inline FT_Int32
+- FT_MulFix_i386( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 result;
+-
+- __asm
+- {
+- mov eax, a
+- mov edx, b
+- imul edx
+- mov ecx, edx
+- sar ecx, 31
+- add ecx, 8000h
+- add eax, ecx
+- adc edx, 0
+- shr eax, 16
+- shl edx, 16
+- add eax, edx
+- mov result, eax
+- }
+- return result;
+- }
+-
+-#endif /* _M_IX86 */
+-
+-#endif /* _MSC_VER */
+-
+-
+-#if defined( __GNUC__ ) && defined( __x86_64__ )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64
+-
+- static __inline__ FT_Int32
+- FT_MulFix_x86_64( FT_Int32 a,
+- FT_Int32 b )
+- {
+- /* Temporarily disable the warning that C90 doesn't support */
+- /* `long long'. */
+-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+-#pragma GCC diagnostic push
+-#pragma GCC diagnostic ignored "-Wlong-long"
+-#endif
+-
+-#if 1
+- /* Technically not an assembly fragment, but GCC does a really good */
+- /* job at inlining it and generating good machine code for it. */
+- long long ret, tmp;
+-
+-
+- ret = (long long)a * b;
+- tmp = ret >> 63;
+- ret += 0x8000 + tmp;
+-
+- return (FT_Int32)( ret >> 16 );
+-#else
+-
+- /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */
+- /* code from the lines below. The main issue is that `wide_a' is not */
+- /* properly initialized by sign-extending `a'. Instead, the generated */
+- /* machine code assumes that the register that contains `a' on input */
+- /* can be used directly as a 64-bit value, which is wrong most of the */
+- /* time. */
+- long long wide_a = (long long)a;
+- long long wide_b = (long long)b;
+- long long result;
+-
+-
+- __asm__ __volatile__ (
+- "imul %2, %1\n"
+- "mov %1, %0\n"
+- "sar $63, %0\n"
+- "lea 0x8000(%1, %0), %0\n"
+- "sar $16, %0\n"
+- : "=&r"(result), "=&r"(wide_a)
+- : "r"(wide_b)
+- : "cc" );
+-
+- return (FT_Int32)result;
+-#endif
+-
+-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+-#pragma GCC diagnostic pop
+-#endif
+- }
+-
+-#endif /* __GNUC__ && __x86_64__ */
+-
+-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+-
+-
+-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
+-#ifdef FT_MULFIX_ASSEMBLER
+-#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER
+-#endif
+-#endif
+-
+-
+ #ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+
+ #define FT_LOCAL( x ) static x
+diff --git a/builds/unix/unix-def.in b/builds/unix/unix-def.in
+index 35ea9c8..4c06a05 100644
+--- a/builds/unix/unix-def.in
++++ b/builds/unix/unix-def.in
+@@ -64,7 +64,6 @@ version_info := @version_info@
+ #
+ REQUIRES_PRIVATE := @REQUIRES_PRIVATE@
+ LIBS_PRIVATE := @LIBS_PRIVATE@
+-LIBS_CONFIG := @LIBS_CONFIG@
+ LIBSSTATIC_CONFIG := @LIBSSTATIC_CONFIG@
+ build_libtool_libs := @build_libtool_libs@
+ ft_version := @ft_version@
+@@ -102,8 +101,7 @@ NO_OUTPUT := 2> /dev/null
+
+ $(OBJ_BUILD)/freetype-config: $(TOP_DIR)/builds/unix/freetype-config.in
+ rm -f $@ $@.tmp
+- sed -e 's|%LIBS_CONFIG%|$(LIBS_CONFIG)|' \
+- -e 's|%LIBSSTATIC_CONFIG%|$(LIBSSTATIC_CONFIG)|' \
++ sed -e 's|%LIBSSTATIC_CONFIG%|$(LIBSSTATIC_CONFIG)|' \
+ -e 's|%build_libtool_libs%|$(build_libtool_libs)|' \
+ -e 's|%exec_prefix%|$(exec_prefix)|' \
+ -e 's|%ft_version%|$(ft_version)|' \
+@@ -116,16 +114,29 @@ $(OBJ_BUILD)/freetype-config: $(TOP_DIR)/builds/unix/freetype-config.in
+ chmod a-w $@.tmp
+ mv $@.tmp $@
+
++# To support directory names with spaces (as might easily happen on Windows
++# platforms), the right solution would be to surround the pkg-variables in
++# `freetype2.pc' with double quotes. However, doing so ironically disables
++# the prefix override mechanism especially written for Windows. This is a
++# bug in pkg-config version 0.28 and earlier.
++#
++# For this reason, we escape spaces with backslashes.
++
++exec_prefix_x := $(subst $(space),\\$(space),$(exec_prefix))
++includedir_x := $(subst $(space),\\$(space),$(includedir))
++libdir_x := $(subst $(space),\\$(space),$(libdir))
++prefix_x := $(subst $(space),\\$(space),$(prefix))
++
+ $(OBJ_BUILD)/freetype2.pc: $(TOP_DIR)/builds/unix/freetype2.in
+ rm -f $@ $@.tmp
+ sed -e 's|%REQUIRES_PRIVATE%|$(REQUIRES_PRIVATE)|' \
+ -e 's|%LIBS_PRIVATE%|$(LIBS_PRIVATE)|' \
+ -e 's|%build_libtool_libs%|$(build_libtool_libs)|' \
+- -e 's|%exec_prefix%|$(exec_prefix)|' \
++ -e 's|%exec_prefix%|$(exec_prefix_x)|' \
+ -e 's|%ft_version%|$(ft_version)|' \
+- -e 's|%includedir%|$(includedir)|' \
+- -e 's|%libdir%|$(libdir)|' \
+- -e 's|%prefix%|$(prefix)|' \
++ -e 's|%includedir%|$(includedir_x)|' \
++ -e 's|%libdir%|$(libdir_x)|' \
++ -e 's|%prefix%|$(prefix_x)|' \
+ $< \
+ > $@.tmp
+ chmod a-w $@.tmp
+diff --git a/builds/vms/ftconfig.h b/builds/vms/ftconfig.h
+index 3fb8f84..b309651 100644
+--- a/builds/vms/ftconfig.h
++++ b/builds/vms/ftconfig.h
+@@ -4,7 +4,7 @@
+ /* */
+ /* VMS-specific configuration file (specification only). */
+ /* */
+-/* Copyright 1996-2004, 2006-2008, 2011, 2013 by */
++/* Copyright 1996-2004, 2006-2008, 2011, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -239,7 +239,16 @@ FT_BEGIN_HEADER
+ #define FT_INT64 long
+ #define FT_UINT64 unsigned long
+
+-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
++ /*************************************************************************/
++ /* */
++ /* A 64-bit data type may create compilation problems if you compile */
++ /* in strict ANSI mode. To avoid them, we disable other 64-bit data */
++ /* types if __STDC__ is defined. You can however ignore this rule */
++ /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
++ /* */
++#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
++
++#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+
+ /* this compiler provides the __int64 type */
+ #define FT_LONG64
+@@ -273,27 +282,9 @@ FT_BEGIN_HEADER
+ #define FT_INT64 long long int
+ #define FT_UINT64 unsigned long long int
+
+-#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
+-
+-
+- /*************************************************************************/
+- /* */
+- /* A 64-bit data type will create compilation problems if you compile */
+- /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */
+- /* is defined. You can however ignore this rule by defining the */
+- /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
+- /* */
+-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )
+-
+-#ifdef __STDC__
+-
+- /* undefine the 64-bit macros in strict ANSI compilation mode */
+-#undef FT_LONG64
+-#undef FT_INT64
+-
+-#endif /* __STDC__ */
++#endif /* _MSC_VER */
+
+-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
++#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
+
+ #ifdef FT_LONG64
+ typedef FT_INT64 FT_Int64;
+@@ -306,215 +297,6 @@ FT_BEGIN_HEADER
+ #define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
+
+
+-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+- /* Provide assembler fragments for performance-critical functions. */
+- /* These must be defined `static __inline__' with GCC. */
+-
+-#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+-
+- /* documentation is in freetype.h */
+-
+- static __inline FT_Int32
+- FT_MulFix_arm( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 t, t2;
+-
+-
+- __asm
+- {
+- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
+- mov a, t, asr #31 /* a = (hi >> 31) */
+- add a, a, #0x8000 /* a += 0x8000 */
+- adds t2, t2, a /* t2 += a */
+- adc t, t, #0 /* t += carry */
+- mov a, t2, lsr #16 /* a = t2 >> 16 */
+- orr a, a, t, lsl #16 /* a |= t << 16 */
+- }
+- return a;
+- }
+-
+-#endif /* __CC_ARM || __ARMCC__ */
+-
+-
+-#ifdef __GNUC__
+-
+-#if defined( __arm__ ) && \
+- ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
+- !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+-
+- /* documentation is in freetype.h */
+-
+- static __inline__ FT_Int32
+- FT_MulFix_arm( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 t, t2;
+-
+-
+- __asm__ __volatile__ (
+- "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
+- "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
+- "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
+- "adds %1, %1, %0\n\t" /* %1 += %0 */
+- "adc %2, %2, #0\n\t" /* %2 += carry */
+- "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
+- "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
+- : "=r"(a), "=&r"(t2), "=&r"(t)
+- : "r"(a), "r"(b)
+- : "cc" );
+- return a;
+- }
+-
+-#endif /* __arm__ && */
+- /* ( __thumb2__ || !__thumb__ ) && */
+- /* !( __CC_ARM || __ARMCC__ ) */
+-
+-
+-#if defined( __i386__ )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+-
+- /* documentation is in freetype.h */
+-
+- static __inline__ FT_Int32
+- FT_MulFix_i386( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 result;
+-
+-
+- __asm__ __volatile__ (
+- "imul %%edx\n"
+- "movl %%edx, %%ecx\n"
+- "sarl $31, %%ecx\n"
+- "addl $0x8000, %%ecx\n"
+- "addl %%ecx, %%eax\n"
+- "adcl $0, %%edx\n"
+- "shrl $16, %%eax\n"
+- "shll $16, %%edx\n"
+- "addl %%edx, %%eax\n"
+- : "=a"(result), "=d"(b)
+- : "a"(a), "d"(b)
+- : "%ecx", "cc" );
+- return result;
+- }
+-
+-#endif /* i386 */
+-
+-#endif /* __GNUC__ */
+-
+-
+-#ifdef _MSC_VER /* Visual C++ */
+-
+-#ifdef _M_IX86
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+-
+- /* documentation is in freetype.h */
+-
+- static __inline FT_Int32
+- FT_MulFix_i386( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 result;
+-
+- __asm
+- {
+- mov eax, a
+- mov edx, b
+- imul edx
+- mov ecx, edx
+- sar ecx, 31
+- add ecx, 8000h
+- add eax, ecx
+- adc edx, 0
+- shr eax, 16
+- shl edx, 16
+- add eax, edx
+- mov result, eax
+- }
+- return result;
+- }
+-
+-#endif /* _M_IX86 */
+-
+-#endif /* _MSC_VER */
+-
+-
+-#if defined( __GNUC__ ) && defined( __x86_64__ )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64
+-
+- static __inline__ FT_Int32
+- FT_MulFix_x86_64( FT_Int32 a,
+- FT_Int32 b )
+- {
+- /* Temporarily disable the warning that C90 doesn't support */
+- /* `long long'. */
+-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+-#pragma GCC diagnostic push
+-#pragma GCC diagnostic ignored "-Wlong-long"
+-#endif
+-
+-#if 1
+- /* Technically not an assembly fragment, but GCC does a really good */
+- /* job at inlining it and generating good machine code for it. */
+- long long ret, tmp;
+-
+-
+- ret = (long long)a * b;
+- tmp = ret >> 63;
+- ret += 0x8000 + tmp;
+-
+- return (FT_Int32)( ret >> 16 );
+-#else
+-
+- /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */
+- /* code from the lines below. The main issue is that `wide_a' is not */
+- /* properly initialized by sign-extending `a'. Instead, the generated */
+- /* machine code assumes that the register that contains `a' on input */
+- /* can be used directly as a 64-bit value, which is wrong most of the */
+- /* time. */
+- long long wide_a = (long long)a;
+- long long wide_b = (long long)b;
+- long long result;
+-
+-
+- __asm__ __volatile__ (
+- "imul %2, %1\n"
+- "mov %1, %0\n"
+- "sar $63, %0\n"
+- "lea 0x8000(%1, %0), %0\n"
+- "sar $16, %0\n"
+- : "=&r"(result), "=&r"(wide_a)
+- : "r"(wide_b)
+- : "cc" );
+-
+- return (FT_Int32)result;
+-#endif
+-
+-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+-#pragma GCC diagnostic pop
+-#endif
+- }
+-
+-#endif /* __GNUC__ && __x86_64__ */
+-
+-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+-
+-
+-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
+-#ifdef FT_MULFIX_ASSEMBLER
+-#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER
+-#endif
+-#endif
+-
+-
+ #ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+
+ #define FT_LOCAL( x ) static x
+diff --git a/docs/CHANGES b/docs/CHANGES
+index 803f02d..51b829c 100644
+--- a/docs/CHANGES
++++ b/docs/CHANGES
+@@ -1,11 +1,40 @@
+
++CHANGES BETWEEN 2.5.3 and 2.5.4
++
++ I. IMPORTANT BUG FIXES
++
++ - The new auto-hinter code using HarfBuzz crashed for some invalid
++ fonts.
++
++
++ II. IMPORTANT CHANGES
++
++ - Full auto-hinter support of the Devanagari script.
++
++
++ III. MISCELLANEOUS
++
++ - Improvements to the auto-hinter's algorithm to recognize stems
++ and local extrema.
++
++ - Function `FT_Get_SubGlyph_Info' always returned an error even in
++ case of success.
++
++ - Version 2.5.1 introduced major bugs in the cjk part of the
++ auto-hinter, which are now fixed.
++
++ - `cmake' now supports a build of FreeType as an OS X framework.
++
++
++======================================================================
++
+ CHANGES BETWEEN 2.5.2 and 2.5.3
+
+ I. IMPORTANT BUG FIXES
+
+- - A vulnerability was identified and fixed in the new CFF driver
+- (cf. http://savannah.nongnu.org/bugs/?41697; it doesn't have a
+- CVE number yet). All users should upgrade.
++ - A vulnerability (CVE-2014-2240) was identified and fixed in the
++ new CFF driver (cf. http://savannah.nongnu.org/bugs/?41697).
++ All users should upgrade.
+
+ - More bug fixes related to correct positioning of composite
+ glyphs.
+@@ -261,6 +290,9 @@ CHANGES BETWEEN 2.4.12 and 2.5
+ it accepts a new command line option `-H' to select the hinting
+ engine.
+
++ - `ftdump's verbose option has been renamed to `-V'. For all demo
++ programs, `-v' now shows version information.
++
+ - Another round of TrueType subpixel hinting fixes.
+
+ - The `apinames' tool can now create an import file for NetWare.
+diff --git a/include/config/ftconfig.h b/include/config/ftconfig.h
+index d98a311..22d70fd 100644
+--- a/include/config/ftconfig.h
++++ b/include/config/ftconfig.h
+@@ -266,7 +266,16 @@ FT_BEGIN_HEADER
+ #define FT_INT64 long
+ #define FT_UINT64 unsigned long
+
+-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
++ /*************************************************************************/
++ /* */
++ /* A 64-bit data type may create compilation problems if you compile */
++ /* in strict ANSI mode. To avoid them, we disable other 64-bit data */
++ /* types if __STDC__ is defined. You can however ignore this rule */
++ /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
++ /* */
++#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
++
++#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+
+ /* this compiler provides the __int64 type */
+ #define FT_LONG64
+@@ -300,27 +309,9 @@ FT_BEGIN_HEADER
+ #define FT_INT64 long long int
+ #define FT_UINT64 unsigned long long int
+
+-#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
+-
+-
+- /*************************************************************************/
+- /* */
+- /* A 64-bit data type will create compilation problems if you compile */
+- /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */
+- /* is defined. You can however ignore this rule by defining the */
+- /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
+- /* */
+-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )
+-
+-#ifdef __STDC__
+-
+- /* undefine the 64-bit macros in strict ANSI compilation mode */
+-#undef FT_LONG64
+-#undef FT_INT64
+-
+-#endif /* __STDC__ */
++#endif /* _MSC_VER */
+
+-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
++#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
+
+ #ifdef FT_LONG64
+ typedef FT_INT64 FT_Int64;
+@@ -333,219 +324,6 @@ FT_BEGIN_HEADER
+ #define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
+
+
+-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+- /* Provide assembler fragments for performance-critical functions. */
+- /* These must be defined `static __inline__' with GCC. */
+-
+-#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+-
+- /* documentation is in freetype.h */
+-
+- static __inline FT_Int32
+- FT_MulFix_arm( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 t, t2;
+-
+-
+- __asm
+- {
+- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
+- mov a, t, asr #31 /* a = (hi >> 31) */
+- add a, a, #0x8000 /* a += 0x8000 */
+- adds t2, t2, a /* t2 += a */
+- adc t, t, #0 /* t += carry */
+- mov a, t2, lsr #16 /* a = t2 >> 16 */
+- orr a, a, t, lsl #16 /* a |= t << 16 */
+- }
+- return a;
+- }
+-
+-#endif /* __CC_ARM || __ARMCC__ */
+-
+-
+-#ifdef __GNUC__
+-
+-#if defined( __arm__ ) && \
+- ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
+- !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+-
+- /* documentation is in freetype.h */
+-
+- static __inline__ FT_Int32
+- FT_MulFix_arm( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 t, t2;
+-
+-
+- __asm__ __volatile__ (
+- "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
+- "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
+-#if defined( __clang__ ) && defined( __thumb2__ )
+- "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
+-#else
+- "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
+-#endif
+- "adds %1, %1, %0\n\t" /* %1 += %0 */
+- "adc %2, %2, #0\n\t" /* %2 += carry */
+- "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
+- "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
+- : "=r"(a), "=&r"(t2), "=&r"(t)
+- : "r"(a), "r"(b)
+- : "cc" );
+- return a;
+- }
+-
+-#endif /* __arm__ && */
+- /* ( __thumb2__ || !__thumb__ ) && */
+- /* !( __CC_ARM || __ARMCC__ ) */
+-
+-
+-#if defined( __i386__ )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+-
+- /* documentation is in freetype.h */
+-
+- static __inline__ FT_Int32
+- FT_MulFix_i386( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 result;
+-
+-
+- __asm__ __volatile__ (
+- "imul %%edx\n"
+- "movl %%edx, %%ecx\n"
+- "sarl $31, %%ecx\n"
+- "addl $0x8000, %%ecx\n"
+- "addl %%ecx, %%eax\n"
+- "adcl $0, %%edx\n"
+- "shrl $16, %%eax\n"
+- "shll $16, %%edx\n"
+- "addl %%edx, %%eax\n"
+- : "=a"(result), "=d"(b)
+- : "a"(a), "d"(b)
+- : "%ecx", "cc" );
+- return result;
+- }
+-
+-#endif /* i386 */
+-
+-#endif /* __GNUC__ */
+-
+-
+-#ifdef _MSC_VER /* Visual C++ */
+-
+-#ifdef _M_IX86
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+-
+- /* documentation is in freetype.h */
+-
+- static __inline FT_Int32
+- FT_MulFix_i386( FT_Int32 a,
+- FT_Int32 b )
+- {
+- register FT_Int32 result;
+-
+- __asm
+- {
+- mov eax, a
+- mov edx, b
+- imul edx
+- mov ecx, edx
+- sar ecx, 31
+- add ecx, 8000h
+- add eax, ecx
+- adc edx, 0
+- shr eax, 16
+- shl edx, 16
+- add eax, edx
+- mov result, eax
+- }
+- return result;
+- }
+-
+-#endif /* _M_IX86 */
+-
+-#endif /* _MSC_VER */
+-
+-
+-#if defined( __GNUC__ ) && defined( __x86_64__ )
+-
+-#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64
+-
+- static __inline__ FT_Int32
+- FT_MulFix_x86_64( FT_Int32 a,
+- FT_Int32 b )
+- {
+- /* Temporarily disable the warning that C90 doesn't support */
+- /* `long long'. */
+-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+-#pragma GCC diagnostic push
+-#pragma GCC diagnostic ignored "-Wlong-long"
+-#endif
+-
+-#if 1
+- /* Technically not an assembly fragment, but GCC does a really good */
+- /* job at inlining it and generating good machine code for it. */
+- long long ret, tmp;
+-
+-
+- ret = (long long)a * b;
+- tmp = ret >> 63;
+- ret += 0x8000 + tmp;
+-
+- return (FT_Int32)( ret >> 16 );
+-#else
+-
+- /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */
+- /* code from the lines below. The main issue is that `wide_a' is not */
+- /* properly initialized by sign-extending `a'. Instead, the generated */
+- /* machine code assumes that the register that contains `a' on input */
+- /* can be used directly as a 64-bit value, which is wrong most of the */
+- /* time. */
+- long long wide_a = (long long)a;
+- long long wide_b = (long long)b;
+- long long result;
+-
+-
+- __asm__ __volatile__ (
+- "imul %2, %1\n"
+- "mov %1, %0\n"
+- "sar $63, %0\n"
+- "lea 0x8000(%1, %0), %0\n"
+- "sar $16, %0\n"
+- : "=&r"(result), "=&r"(wide_a)
+- : "r"(wide_b)
+- : "cc" );
+-
+- return (FT_Int32)result;
+-#endif
+-
+-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+-#pragma GCC diagnostic pop
+-#endif
+- }
+-
+-#endif /* __GNUC__ && __x86_64__ */
+-
+-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+-
+-
+-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
+-#ifdef FT_MULFIX_ASSEMBLER
+-#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER
+-#endif
+-#endif
+-
+-
+ #ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+
+ #define FT_LOCAL( x ) static x
+diff --git a/include/freetype.h b/include/freetype.h
+index fb62b62..6a31502 100644
+--- a/include/freetype.h
++++ b/include/freetype.h
+@@ -1592,7 +1592,6 @@ FT_BEGIN_HEADER
+ /* This field is only valid for the composite */
+ /* glyph format that should normally only be */
+ /* loaded with the @FT_LOAD_NO_RECURSE flag. */
+- /* For now this is internal to FreeType. */
+ /* */
+ /* subglyphs :: An array of subglyph descriptors for */
+ /* composite glyphs. There are `num_subglyphs' */
+@@ -2560,14 +2559,11 @@ FT_BEGIN_HEADER
+ * Ignored. Deprecated.
+ *
+ * FT_LOAD_NO_RECURSE ::
+- * This flag is only used internally. It merely indicates that the
+- * font driver should not load composite glyphs recursively. Instead,
+- * it should set the `num_subglyph' and `subglyphs' values of the
+- * glyph slot accordingly, and set `glyph->format' to
+- * @FT_GLYPH_FORMAT_COMPOSITE.
+- *
+- * The description of sub-glyphs is not available to client
+- * applications for now.
++ * Indicate that the font driver should not load composite glyphs
++ * recursively. Instead, it should set the `num_subglyph' and
++ * `subglyphs' values of the glyph slot accordingly, and set
++ * `glyph->format' to @FT_GLYPH_FORMAT_COMPOSITE. The description of
++ * subglyphs can then be accessed with @FT_Get_SubGlyph_Info.
+ *
+ * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM.
+ *
+@@ -3065,9 +3061,8 @@ FT_BEGIN_HEADER
+ /* glyph index~0 always corresponds to the `missing glyph' (called */
+ /* `.notdef'). */
+ /* */
+- /* This function is not compiled within the library if the config */
+- /* macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in */
+- /* `ftoptions.h'. */
++ /* This function always returns an error if the config macro */
++ /* `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoptions.h'. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Glyph_Name( FT_Face face,
+@@ -3767,12 +3762,6 @@ FT_BEGIN_HEADER
+ FT_Long c );
+
+
+- /* */
+-
+- /* The following #if 0 ... #endif is for the documentation formatter, */
+- /* hiding the internal `FT_MULFIX_INLINED' macro. */
+-
+-#if 0
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+@@ -3806,17 +3795,6 @@ FT_BEGIN_HEADER
+ FT_MulFix( FT_Long a,
+ FT_Long b );
+
+- /* */
+-#endif
+-
+-#ifdef FT_MULFIX_INLINED
+-#define FT_MulFix( a, b ) FT_MULFIX_INLINED( a, b )
+-#else
+- FT_EXPORT( FT_Long )
+- FT_MulFix( FT_Long a,
+- FT_Long b );
+-#endif
+-
+
+ /*************************************************************************/
+ /* */
+@@ -3829,18 +3807,12 @@ FT_BEGIN_HEADER
+ /* used to divide a given value by a 16.16 fixed-point factor. */
+ /* */
+ /* <Input> */
+- /* a :: The first multiplier. */
+- /* b :: The second multiplier. Use a 16.16 factor here whenever */
+- /* possible (see note below). */
++ /* a :: The numerator. */
++ /* b :: The denominator. Use a 16.16 factor here. */
+ /* */
+ /* <Return> */
+ /* The result of `(a*0x10000)/b'. */
+ /* */
+- /* <Note> */
+- /* The optimization for FT_DivFix() is simple: If (a~<<~16) fits in */
+- /* 32~bits, then the division is computed directly. Otherwise, we */
+- /* use a specialized version of @FT_MulDiv. */
+- /* */
+ FT_EXPORT( FT_Long )
+ FT_DivFix( FT_Long a,
+ FT_Long b );
+diff --git a/include/fterrdef.h b/include/fterrdef.h
+index 76c7b9e..99b2fad 100644
+--- a/include/fterrdef.h
++++ b/include/fterrdef.h
+@@ -31,218 +31,218 @@
+
+ /* generic errors */
+
+- FT_NOERRORDEF_( Ok, 0x00, \
++ FT_NOERRORDEF_( Ok, 0x00,
+ "no error" )
+
+- FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \
++ FT_ERRORDEF_( Cannot_Open_Resource, 0x01,
+ "cannot open resource" )
+- FT_ERRORDEF_( Unknown_File_Format, 0x02, \
++ FT_ERRORDEF_( Unknown_File_Format, 0x02,
+ "unknown file format" )
+- FT_ERRORDEF_( Invalid_File_Format, 0x03, \
++ FT_ERRORDEF_( Invalid_File_Format, 0x03,
+ "broken file" )
+- FT_ERRORDEF_( Invalid_Version, 0x04, \
++ FT_ERRORDEF_( Invalid_Version, 0x04,
+ "invalid FreeType version" )
+- FT_ERRORDEF_( Lower_Module_Version, 0x05, \
++ FT_ERRORDEF_( Lower_Module_Version, 0x05,
+ "module version is too low" )
+- FT_ERRORDEF_( Invalid_Argument, 0x06, \
++ FT_ERRORDEF_( Invalid_Argument, 0x06,
+ "invalid argument" )
+- FT_ERRORDEF_( Unimplemented_Feature, 0x07, \
++ FT_ERRORDEF_( Unimplemented_Feature, 0x07,
+ "unimplemented feature" )
+- FT_ERRORDEF_( Invalid_Table, 0x08, \
++ FT_ERRORDEF_( Invalid_Table, 0x08,
+ "broken table" )
+- FT_ERRORDEF_( Invalid_Offset, 0x09, \
++ FT_ERRORDEF_( Invalid_Offset, 0x09,
+ "broken offset within table" )
+- FT_ERRORDEF_( Array_Too_Large, 0x0A, \
++ FT_ERRORDEF_( Array_Too_Large, 0x0A,
+ "array allocation size too large" )
+- FT_ERRORDEF_( Missing_Module, 0x0B, \
++ FT_ERRORDEF_( Missing_Module, 0x0B,
+ "missing module" )
+- FT_ERRORDEF_( Missing_Property, 0x0C, \
++ FT_ERRORDEF_( Missing_Property, 0x0C,
+ "missing property" )
+
+ /* glyph/character errors */
+
+- FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \
++ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10,
+ "invalid glyph index" )
+- FT_ERRORDEF_( Invalid_Character_Code, 0x11, \
++ FT_ERRORDEF_( Invalid_Character_Code, 0x11,
+ "invalid character code" )
+- FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \
++ FT_ERRORDEF_( Invalid_Glyph_Format, 0x12,
+ "unsupported glyph image format" )
+- FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \
++ FT_ERRORDEF_( Cannot_Render_Glyph, 0x13,
+ "cannot render this glyph format" )
+- FT_ERRORDEF_( Invalid_Outline, 0x14, \
++ FT_ERRORDEF_( Invalid_Outline, 0x14,
+ "invalid outline" )
+- FT_ERRORDEF_( Invalid_Composite, 0x15, \
++ FT_ERRORDEF_( Invalid_Composite, 0x15,
+ "invalid composite glyph" )
+- FT_ERRORDEF_( Too_Many_Hints, 0x16, \
++ FT_ERRORDEF_( Too_Many_Hints, 0x16,
+ "too many hints" )
+- FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \
++ FT_ERRORDEF_( Invalid_Pixel_Size, 0x17,
+ "invalid pixel size" )
+
+ /* handle errors */
+
+- FT_ERRORDEF_( Invalid_Handle, 0x20, \
++ FT_ERRORDEF_( Invalid_Handle, 0x20,
+ "invalid object handle" )
+- FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \
++ FT_ERRORDEF_( Invalid_Library_Handle, 0x21,
+ "invalid library handle" )
+- FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \
++ FT_ERRORDEF_( Invalid_Driver_Handle, 0x22,
+ "invalid module handle" )
+- FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \
++ FT_ERRORDEF_( Invalid_Face_Handle, 0x23,
+ "invalid face handle" )
+- FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \
++ FT_ERRORDEF_( Invalid_Size_Handle, 0x24,
+ "invalid size handle" )
+- FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \
++ FT_ERRORDEF_( Invalid_Slot_Handle, 0x25,
+ "invalid glyph slot handle" )
+- FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \
++ FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26,
+ "invalid charmap handle" )
+- FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \
++ FT_ERRORDEF_( Invalid_Cache_Handle, 0x27,
+ "invalid cache manager handle" )
+- FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \
++ FT_ERRORDEF_( Invalid_Stream_Handle, 0x28,
+ "invalid stream handle" )
+
+ /* driver errors */
+
+- FT_ERRORDEF_( Too_Many_Drivers, 0x30, \
++ FT_ERRORDEF_( Too_Many_Drivers, 0x30,
+ "too many modules" )
+- FT_ERRORDEF_( Too_Many_Extensions, 0x31, \
++ FT_ERRORDEF_( Too_Many_Extensions, 0x31,
+ "too many extensions" )
+
+ /* memory errors */
+
+- FT_ERRORDEF_( Out_Of_Memory, 0x40, \
++ FT_ERRORDEF_( Out_Of_Memory, 0x40,
+ "out of memory" )
+- FT_ERRORDEF_( Unlisted_Object, 0x41, \
++ FT_ERRORDEF_( Unlisted_Object, 0x41,
+ "unlisted object" )
+
+ /* stream errors */
+
+- FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \
++ FT_ERRORDEF_( Cannot_Open_Stream, 0x51,
+ "cannot open stream" )
+- FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \
++ FT_ERRORDEF_( Invalid_Stream_Seek, 0x52,
+ "invalid stream seek" )
+- FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \
++ FT_ERRORDEF_( Invalid_Stream_Skip, 0x53,
+ "invalid stream skip" )
+- FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \
++ FT_ERRORDEF_( Invalid_Stream_Read, 0x54,
+ "invalid stream read" )
+- FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \
++ FT_ERRORDEF_( Invalid_Stream_Operation, 0x55,
+ "invalid stream operation" )
+- FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \
++ FT_ERRORDEF_( Invalid_Frame_Operation, 0x56,
+ "invalid frame operation" )
+- FT_ERRORDEF_( Nested_Frame_Access, 0x57, \
++ FT_ERRORDEF_( Nested_Frame_Access, 0x57,
+ "nested frame access" )
+- FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \
++ FT_ERRORDEF_( Invalid_Frame_Read, 0x58,
+ "invalid frame read" )
+
+ /* raster errors */
+
+- FT_ERRORDEF_( Raster_Uninitialized, 0x60, \
++ FT_ERRORDEF_( Raster_Uninitialized, 0x60,
+ "raster uninitialized" )
+- FT_ERRORDEF_( Raster_Corrupted, 0x61, \
++ FT_ERRORDEF_( Raster_Corrupted, 0x61,
+ "raster corrupted" )
+- FT_ERRORDEF_( Raster_Overflow, 0x62, \
++ FT_ERRORDEF_( Raster_Overflow, 0x62,
+ "raster overflow" )
+- FT_ERRORDEF_( Raster_Negative_Height, 0x63, \
++ FT_ERRORDEF_( Raster_Negative_Height, 0x63,
+ "negative height while rastering" )
+
+ /* cache errors */
+
+- FT_ERRORDEF_( Too_Many_Caches, 0x70, \
++ FT_ERRORDEF_( Too_Many_Caches, 0x70,
+ "too many registered caches" )
+
+ /* TrueType and SFNT errors */
+
+- FT_ERRORDEF_( Invalid_Opcode, 0x80, \
++ FT_ERRORDEF_( Invalid_Opcode, 0x80,
+ "invalid opcode" )
+- FT_ERRORDEF_( Too_Few_Arguments, 0x81, \
++ FT_ERRORDEF_( Too_Few_Arguments, 0x81,
+ "too few arguments" )
+- FT_ERRORDEF_( Stack_Overflow, 0x82, \
++ FT_ERRORDEF_( Stack_Overflow, 0x82,
+ "stack overflow" )
+- FT_ERRORDEF_( Code_Overflow, 0x83, \
++ FT_ERRORDEF_( Code_Overflow, 0x83,
+ "code overflow" )
+- FT_ERRORDEF_( Bad_Argument, 0x84, \
++ FT_ERRORDEF_( Bad_Argument, 0x84,
+ "bad argument" )
+- FT_ERRORDEF_( Divide_By_Zero, 0x85, \
++ FT_ERRORDEF_( Divide_By_Zero, 0x85,
+ "division by zero" )
+- FT_ERRORDEF_( Invalid_Reference, 0x86, \
++ FT_ERRORDEF_( Invalid_Reference, 0x86,
+ "invalid reference" )
+- FT_ERRORDEF_( Debug_OpCode, 0x87, \
++ FT_ERRORDEF_( Debug_OpCode, 0x87,
+ "found debug opcode" )
+- FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \
++ FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88,
+ "found ENDF opcode in execution stream" )
+- FT_ERRORDEF_( Nested_DEFS, 0x89, \
++ FT_ERRORDEF_( Nested_DEFS, 0x89,
+ "nested DEFS" )
+- FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \
++ FT_ERRORDEF_( Invalid_CodeRange, 0x8A,
+ "invalid code range" )
+- FT_ERRORDEF_( Execution_Too_Long, 0x8B, \
++ FT_ERRORDEF_( Execution_Too_Long, 0x8B,
+ "execution context too long" )
+- FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \
++ FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C,
+ "too many function definitions" )
+- FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \
++ FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D,
+ "too many instruction definitions" )
+- FT_ERRORDEF_( Table_Missing, 0x8E, \
++ FT_ERRORDEF_( Table_Missing, 0x8E,
+ "SFNT font table missing" )
+- FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \
++ FT_ERRORDEF_( Horiz_Header_Missing, 0x8F,
+ "horizontal header (hhea) table missing" )
+- FT_ERRORDEF_( Locations_Missing, 0x90, \
++ FT_ERRORDEF_( Locations_Missing, 0x90,
+ "locations (loca) table missing" )
+- FT_ERRORDEF_( Name_Table_Missing, 0x91, \
++ FT_ERRORDEF_( Name_Table_Missing, 0x91,
+ "name table missing" )
+- FT_ERRORDEF_( CMap_Table_Missing, 0x92, \
++ FT_ERRORDEF_( CMap_Table_Missing, 0x92,
+ "character map (cmap) table missing" )
+- FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \
++ FT_ERRORDEF_( Hmtx_Table_Missing, 0x93,
+ "horizontal metrics (hmtx) table missing" )
+- FT_ERRORDEF_( Post_Table_Missing, 0x94, \
++ FT_ERRORDEF_( Post_Table_Missing, 0x94,
+ "PostScript (post) table missing" )
+- FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \
++ FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95,
+ "invalid horizontal metrics" )
+- FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \
++ FT_ERRORDEF_( Invalid_CharMap_Format, 0x96,
+ "invalid character map (cmap) format" )
+- FT_ERRORDEF_( Invalid_PPem, 0x97, \
++ FT_ERRORDEF_( Invalid_PPem, 0x97,
+ "invalid ppem value" )
+- FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \
++ FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98,
+ "invalid vertical metrics" )
+- FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \
++ FT_ERRORDEF_( Could_Not_Find_Context, 0x99,
+ "could not find context" )
+- FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \
++ FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A,
+ "invalid PostScript (post) table format" )
+- FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \
++ FT_ERRORDEF_( Invalid_Post_Table, 0x9B,
+ "invalid PostScript (post) table" )
+
+ /* CFF, CID, and Type 1 errors */
+
+- FT_ERRORDEF_( Syntax_Error, 0xA0, \
++ FT_ERRORDEF_( Syntax_Error, 0xA0,
+ "opcode syntax error" )
+- FT_ERRORDEF_( Stack_Underflow, 0xA1, \
++ FT_ERRORDEF_( Stack_Underflow, 0xA1,
+ "argument stack underflow" )
+- FT_ERRORDEF_( Ignore, 0xA2, \
++ FT_ERRORDEF_( Ignore, 0xA2,
+ "ignore" )
+- FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \
++ FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3,
+ "no Unicode glyph name found" )
+- FT_ERRORDEF_( Glyph_Too_Big, 0xA4, \
++ FT_ERRORDEF_( Glyph_Too_Big, 0xA4,
+ "glyph to big for hinting" )
+
+ /* BDF errors */
+
+- FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \
++ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0,
+ "`STARTFONT' field missing" )
+- FT_ERRORDEF_( Missing_Font_Field, 0xB1, \
++ FT_ERRORDEF_( Missing_Font_Field, 0xB1,
+ "`FONT' field missing" )
+- FT_ERRORDEF_( Missing_Size_Field, 0xB2, \
++ FT_ERRORDEF_( Missing_Size_Field, 0xB2,
+ "`SIZE' field missing" )
+- FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \
++ FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3,
+ "`FONTBOUNDINGBOX' field missing" )
+- FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \
++ FT_ERRORDEF_( Missing_Chars_Field, 0xB4,
+ "`CHARS' field missing" )
+- FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \
++ FT_ERRORDEF_( Missing_Startchar_Field, 0xB5,
+ "`STARTCHAR' field missing" )
+- FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \
++ FT_ERRORDEF_( Missing_Encoding_Field, 0xB6,
+ "`ENCODING' field missing" )
+- FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \
++ FT_ERRORDEF_( Missing_Bbx_Field, 0xB7,
+ "`BBX' field missing" )
+- FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \
++ FT_ERRORDEF_( Bbx_Too_Big, 0xB8,
+ "`BBX' too big" )
+- FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \
++ FT_ERRORDEF_( Corrupted_Font_Header, 0xB9,
+ "Font header corrupted or missing fields" )
+- FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \
++ FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA,
+ "Font glyphs corrupted or missing fields" )
+
+
+diff --git a/include/fttrigon.h b/include/fttrigon.h
+index 65143cb..9c7b543 100644
+--- a/include/fttrigon.h
++++ b/include/fttrigon.h
+@@ -237,7 +237,7 @@ FT_BEGIN_HEADER
+ *
+ * @input:
+ * angle ::
+- * The address of angle.
++ * The input angle.
+ *
+ */
+ FT_EXPORT( void )
+@@ -259,7 +259,7 @@ FT_BEGIN_HEADER
+ *
+ * @input:
+ * angle ::
+- * The address of angle.
++ * The input angle.
+ *
+ */
+ FT_EXPORT( void )
+diff --git a/include/internal/ftcalc.h b/include/internal/ftcalc.h
+index 03bd68e..95165bf 100644
+--- a/include/internal/ftcalc.h
++++ b/include/internal/ftcalc.h
+@@ -4,7 +4,7 @@
+ /* */
+ /* Arithmetic computations (specification). */
+ /* */
+-/* Copyright 1996-2006, 2008, 2009, 2012-2013 by */
++/* Copyright 1996-2006, 2008, 2009, 2012-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -27,36 +27,223 @@
+ FT_BEGIN_HEADER
+
+
+-#if 0
+-
+ /*************************************************************************/
+ /* */
+- /* <Function> */
+- /* FT_SqrtFixed */
+- /* */
+- /* <Description> */
+- /* Computes the square root of a 16.16 fixed-point value. */
+- /* */
+- /* <Input> */
+- /* x :: The value to compute the root for. */
+- /* */
+- /* <Return> */
+- /* The result of `sqrt(x)'. */
+- /* */
+- /* <Note> */
+- /* This function is not very fast. */
++ /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */
+ /* */
+- FT_BASE( FT_Int32 )
+- FT_SqrtFixed( FT_Int32 x );
++ /*************************************************************************/
+
+-#endif /* 0 */
++#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
++ /* Provide assembler fragments for performance-critical functions. */
++ /* These must be defined `static __inline__' with GCC. */
+
++#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */
+
+- /*************************************************************************/
+- /* */
+- /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */
+- /* */
+- /*************************************************************************/
++#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
++
++ /* documentation is in freetype.h */
++
++ static __inline FT_Int32
++ FT_MulFix_arm( FT_Int32 a,
++ FT_Int32 b )
++ {
++ register FT_Int32 t, t2;
++
++
++ __asm
++ {
++ smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
++ mov a, t, asr #31 /* a = (hi >> 31) */
++ add a, a, #0x8000 /* a += 0x8000 */
++ adds t2, t2, a /* t2 += a */
++ adc t, t, #0 /* t += carry */
++ mov a, t2, lsr #16 /* a = t2 >> 16 */
++ orr a, a, t, lsl #16 /* a |= t << 16 */
++ }
++ return a;
++ }
++
++#endif /* __CC_ARM || __ARMCC__ */
++
++
++#ifdef __GNUC__
++
++#if defined( __arm__ ) && \
++ ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
++ !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
++
++#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
++
++ /* documentation is in freetype.h */
++
++ static __inline__ FT_Int32
++ FT_MulFix_arm( FT_Int32 a,
++ FT_Int32 b )
++ {
++ register FT_Int32 t, t2;
++
++
++ __asm__ __volatile__ (
++ "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
++ "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
++#if defined( __clang__ ) && defined( __thumb2__ )
++ "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
++#else
++ "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
++#endif
++ "adds %1, %1, %0\n\t" /* %1 += %0 */
++ "adc %2, %2, #0\n\t" /* %2 += carry */
++ "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
++ "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
++ : "=r"(a), "=&r"(t2), "=&r"(t)
++ : "r"(a), "r"(b)
++ : "cc" );
++ return a;
++ }
++
++#endif /* __arm__ && */
++ /* ( __thumb2__ || !__thumb__ ) && */
++ /* !( __CC_ARM || __ARMCC__ ) */
++
++
++#if defined( __i386__ )
++
++#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
++
++ /* documentation is in freetype.h */
++
++ static __inline__ FT_Int32
++ FT_MulFix_i386( FT_Int32 a,
++ FT_Int32 b )
++ {
++ register FT_Int32 result;
++
++
++ __asm__ __volatile__ (
++ "imul %%edx\n"
++ "movl %%edx, %%ecx\n"
++ "sarl $31, %%ecx\n"
++ "addl $0x8000, %%ecx\n"
++ "addl %%ecx, %%eax\n"
++ "adcl $0, %%edx\n"
++ "shrl $16, %%eax\n"
++ "shll $16, %%edx\n"
++ "addl %%edx, %%eax\n"
++ : "=a"(result), "=d"(b)
++ : "a"(a), "d"(b)
++ : "%ecx", "cc" );
++ return result;
++ }
++
++#endif /* i386 */
++
++#endif /* __GNUC__ */
++
++
++#ifdef _MSC_VER /* Visual C++ */
++
++#ifdef _M_IX86
++
++#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
++
++ /* documentation is in freetype.h */
++
++ static __inline FT_Int32
++ FT_MulFix_i386( FT_Int32 a,
++ FT_Int32 b )
++ {
++ register FT_Int32 result;
++
++ __asm
++ {
++ mov eax, a
++ mov edx, b
++ imul edx
++ mov ecx, edx
++ sar ecx, 31
++ add ecx, 8000h
++ add eax, ecx
++ adc edx, 0
++ shr eax, 16
++ shl edx, 16
++ add eax, edx
++ mov result, eax
++ }
++ return result;
++ }
++
++#endif /* _M_IX86 */
++
++#endif /* _MSC_VER */
++
++
++#if defined( __GNUC__ ) && defined( __x86_64__ )
++
++#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64
++
++ static __inline__ FT_Int32
++ FT_MulFix_x86_64( FT_Int32 a,
++ FT_Int32 b )
++ {
++ /* Temporarily disable the warning that C90 doesn't support */
++ /* `long long'. */
++#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wlong-long"
++#endif
++
++#if 1
++ /* Technically not an assembly fragment, but GCC does a really good */
++ /* job at inlining it and generating good machine code for it. */
++ long long ret, tmp;
++
++
++ ret = (long long)a * b;
++ tmp = ret >> 63;
++ ret += 0x8000 + tmp;
++
++ return (FT_Int32)( ret >> 16 );
++#else
++
++ /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */
++ /* code from the lines below. The main issue is that `wide_a' is not */
++ /* properly initialized by sign-extending `a'. Instead, the generated */
++ /* machine code assumes that the register that contains `a' on input */
++ /* can be used directly as a 64-bit value, which is wrong most of the */
++ /* time. */
++ long long wide_a = (long long)a;
++ long long wide_b = (long long)b;
++ long long result;
++
++
++ __asm__ __volatile__ (
++ "imul %2, %1\n"
++ "mov %1, %0\n"
++ "sar $63, %0\n"
++ "lea 0x8000(%1, %0), %0\n"
++ "sar $16, %0\n"
++ : "=&r"(result), "=&r"(wide_a)
++ : "r"(wide_b)
++ : "cc" );
++
++ return (FT_Int32)result;
++#endif
++
++#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
++#pragma GCC diagnostic pop
++#endif
++ }
++
++#endif /* __GNUC__ && __x86_64__ */
++
++#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
++
++
++#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
++#ifdef FT_MULFIX_ASSEMBLER
++#define FT_MulFix( a, b ) FT_MULFIX_ASSEMBLER( a, b )
++#endif
++#endif
+
+
+ /*************************************************************************/
+@@ -139,9 +326,32 @@ FT_BEGIN_HEADER
+ /*
+ * Return the most significant bit index.
+ */
++
++#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
++#if defined( __GNUC__ )
++#if ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 4 ) )
++
++#if FT_SIZEOF_INT == 4
++
++#define FT_MSB( x ) ( 31 - __builtin_clz( x ) )
++
++#elif FT_SIZEOF_LONG == 4
++
++#define FT_MSB( x ) ( 31 - __builtin_clzl( x ) )
++
++#endif
++
++#endif
++#endif /* __GNUC__ */
++#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
++
++#ifndef FT_MSB
++
+ FT_BASE( FT_Int )
+ FT_MSB( FT_UInt32 z );
+
++#endif
++
+
+ /*
+ * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
+@@ -152,6 +362,31 @@ FT_BEGIN_HEADER
+ FT_Fixed y );
+
+
++#if 0
++
++ /*************************************************************************/
++ /* */
++ /* <Function> */
++ /* FT_SqrtFixed */
++ /* */
++ /* <Description> */
++ /* Computes the square root of a 16.16 fixed-point value. */
++ /* */
++ /* <Input> */
++ /* x :: The value to compute the root for. */
++ /* */
++ /* <Return> */
++ /* The result of `sqrt(x)'. */
++ /* */
++ /* <Note> */
++ /* This function is not very fast. */
++ /* */
++ FT_BASE( FT_Int32 )
++ FT_SqrtFixed( FT_Int32 x );
++
++#endif /* 0 */
++
++
+ #define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 )
+ #define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 )
+ #define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 )
+diff --git a/include/internal/ftobjs.h b/include/internal/ftobjs.h
+index 701c850..faa37f8 100644
+--- a/include/internal/ftobjs.h
++++ b/include/internal/ftobjs.h
+@@ -83,14 +83,6 @@ FT_BEGIN_HEADER
+
+
+ /*
+- * Return the highest power of 2 that is <= value; this correspond to
+- * the highest bit in a given 32-bit value.
+- */
+- FT_BASE( FT_UInt32 )
+- ft_highpow2( FT_UInt32 value );
+-
+-
+- /*
+ * character classification functions -- since these are used to parse
+ * font files, we must not use those in <ctypes.h> which are
+ * locale-dependent
+diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c
+index 6e214c8..f3526bf 100644
+--- a/src/autofit/afblue.c
++++ b/src/autofit/afblue.c
+@@ -26,15 +26,21 @@
+ af_blue_strings[] =
+ {
+ /* */
+- 'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S', /* THEZOCQS */
++ '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕПЗОСЭ */
+ '\0',
+- 'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S', /* HEZLOCUS */
++ '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕШЗОСЭ */
+ '\0',
+- 'f', 'i', 'j', 'k', 'd', 'b', 'h', /* fijkdbh */
++ '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81', /* хпншезос */
+ '\0',
+- 'x', 'z', 'r', 'o', 'e', 's', 'c', /* xzroesc */
++ '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84', /* руф */
+ '\0',
+- 'p', 'q', 'g', 'j', 'y', /* pqgjy */
++ '\xE0', '\xA4', '\x95', '\xE0', '\xA4', '\xAE', '\xE0', '\xA4', '\x85', '\xE0', '\xA4', '\x86', '\xE0', '\xA4', '\xA5', '\xE0', '\xA4', '\xA7', '\xE0', '\xA4', '\xAD', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */
++ '\0',
++ '\xE0', '\xA4', '\x88', '\xE0', '\xA4', '\x90', '\xE0', '\xA4', '\x93', '\xE0', '\xA4', '\x94', '\xE0', '\xA4', '\xBF', '\xE0', '\xA5', '\x80', '\xE0', '\xA5', '\x8B', '\xE0', '\xA5', '\x8C', /* ई ऐ ओ औ ि ी ो ौ */
++ '\0',
++ '\xE0', '\xA4', '\x95', '\xE0', '\xA4', '\xAE', '\xE0', '\xA4', '\x85', '\xE0', '\xA4', '\x86', '\xE0', '\xA4', '\xA5', '\xE0', '\xA4', '\xA7', '\xE0', '\xA4', '\xAD', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */
++ '\0',
++ '\xE0', '\xA5', '\x81', '\xE0', '\xA5', '\x83', /* ु ृ */
+ '\0',
+ '\xCE', '\x93', '\xCE', '\x92', '\xCE', '\x95', '\xCE', '\x96', '\xCE', '\x98', '\xCE', '\x9F', '\xCE', '\xA9', /* ΓΒΕΖΘΟΩ */
+ '\0',
+@@ -46,26 +52,27 @@
+ '\0',
+ '\xCE', '\xB2', '\xCE', '\xB3', '\xCE', '\xB7', '\xCE', '\xBC', '\xCF', '\x81', '\xCF', '\x86', '\xCF', '\x87', '\xCF', '\x88', /* βγημρφχψ */
+ '\0',
+- '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕПЗОСЭ */
++ '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', /* בדהחךכםס */
+ '\0',
+- '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕШЗОСЭ */
++ '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6', /* בטכםסצ */
+ '\0',
+- '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81', /* хпншезос */
++ '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5', /* קךןףץ */
+ '\0',
+- '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84', /* руф */
++ 'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S', /* THEZOCQS */
+ '\0',
+- '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', /* בדהחךכםס */
++ 'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S', /* HEZLOCUS */
+ '\0',
+- '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6', /* בטכםסצ */
++ 'f', 'i', 'j', 'k', 'd', 'b', 'h', /* fijkdbh */
+ '\0',
+- '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5', /* קךןףץ */
++ 'x', 'z', 'r', 'o', 'e', 's', 'c', /* xzroesc */
++ '\0',
++ 'p', 'q', 'g', 'j', 'y', /* pqgjy */
+ #ifdef AF_CONFIG_OPTION_CJK
+ '\0',
+ '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0', /* 他们你來們到和地 */
+ '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1', '\xE5', '\xB8', '\xAD', '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x83', /* 对對就席我时時會 */
+ '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\x83', '\xBD', '\xE8', '\x88', '\xB0', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99', /* 来為能舰說说这這 */
+- '\xE9', '\xBD', '\x8A', /* 齊 */
+- '\0',
++ '\xE9', '\xBD', '\x8A', '|', /* 齊 | */
+ '\xE5', '\x86', '\x9B', '\xE5', '\x90', '\x8C', '\xE5', '\xB7', '\xB2', '\xE6', '\x84', '\xBF', '\xE6', '\x97', '\xA2', '\xE6', '\x98', '\x9F', '\xE6', '\x98', '\xAF', '\xE6', '\x99', '\xAF', /* 军同已愿既星是景 */
+ '\xE6', '\xB0', '\x91', '\xE7', '\x85', '\xA7', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\xA8', '\xE7', '\xBD', '\xAE', '\xE8', '\xA6', '\x81', /* 民照现現理用置要 */
+ '\xE8', '\xBB', '\x8D', '\xE9', '\x82', '\xA3', '\xE9', '\x85', '\x8D', '\xE9', '\x87', '\x8C', '\xE9', '\x96', '\x8B', '\xE9', '\x9B', '\xB7', '\xE9', '\x9C', '\xB2', '\xE9', '\x9D', '\xA2', /* 軍那配里開雷露面 */
+@@ -74,8 +81,7 @@
+ '\xE4', '\xB8', '\xAA', '\xE4', '\xB8', '\xBA', '\xE4', '\xBA', '\xBA', '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xA5', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', /* 个为人他以们你來 */
+ '\xE5', '\x80', '\x8B', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\xA4', '\xA7', '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1', /* 個們到和大对對就 */
+ '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x89', '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\xA6', '\x81', '\xE8', '\xAA', '\xAA', /* 我时時有来為要說 */
+- '\xE8', '\xAF', '\xB4', /* 说 */
+- '\0',
++ '\xE8', '\xAF', '\xB4', '|', /* 说 | */
+ '\xE4', '\xB8', '\xBB', '\xE4', '\xBA', '\x9B', '\xE5', '\x9B', '\xA0', '\xE5', '\xAE', '\x83', '\xE6', '\x83', '\xB3', '\xE6', '\x84', '\x8F', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\x9F', /* 主些因它想意理生 */
+ '\xE7', '\x95', '\xB6', '\xE7', '\x9C', '\x8B', '\xE7', '\x9D', '\x80', '\xE7', '\xBD', '\xAE', '\xE8', '\x80', '\x85', '\xE8', '\x87', '\xAA', '\xE8', '\x91', '\x97', '\xE8', '\xA3', '\xA1', /* 當看着置者自著裡 */
+ '\xE8', '\xBF', '\x87', '\xE8', '\xBF', '\x98', '\xE8', '\xBF', '\x9B', '\xE9', '\x80', '\xB2', '\xE9', '\x81', '\x8E', '\xE9', '\x81', '\x93', '\xE9', '\x82', '\x84', '\xE9', '\x87', '\x8C', /* 过还进進過道還里 */
+@@ -85,8 +91,7 @@
+ '\xE4', '\xBA', '\x9B', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0', /* 些们你來們到和地 */
+ '\xE5', '\xA5', '\xB9', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE5', '\xB0', '\xB1', '\xE5', '\xB9', '\xB4', '\xE5', '\xBE', '\x97', '\xE6', '\x83', '\x85', '\xE6', '\x9C', '\x80', /* 她将將就年得情最 */
+ '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE7', '\x90', '\x86', '\xE8', '\x83', '\xBD', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99', /* 样樣理能說说这這 */
+- '\xE9', '\x80', '\x9A', /* 通 */
+- '\0',
++ '\xE9', '\x80', '\x9A', '|', /* 通 | */
+ '\xE5', '\x8D', '\xB3', '\xE5', '\x90', '\x97', '\xE5', '\x90', '\xA7', '\xE5', '\x90', '\xAC', '\xE5', '\x91', '\xA2', '\xE5', '\x93', '\x81', '\xE5', '\x93', '\x8D', '\xE5', '\x97', '\x8E', /* 即吗吧听呢品响嗎 */
+ '\xE5', '\xB8', '\x88', '\xE5', '\xB8', '\xAB', '\xE6', '\x94', '\xB6', '\xE6', '\x96', '\xAD', '\xE6', '\x96', '\xB7', '\xE6', '\x98', '\x8E', '\xE7', '\x9C', '\xBC', '\xE9', '\x96', '\x93', /* 师師收断斷明眼間 */
+ '\xE9', '\x97', '\xB4', '\xE9', '\x99', '\x85', '\xE9', '\x99', '\x88', '\xE9', '\x99', '\x90', '\xE9', '\x99', '\xA4', '\xE9', '\x99', '\xB3', '\xE9', '\x9A', '\x8F', '\xE9', '\x9A', '\x9B', /* 间际陈限除陳随際 */
+@@ -95,8 +100,7 @@
+ '\xE4', '\xBA', '\x8B', '\xE5', '\x89', '\x8D', '\xE5', '\xAD', '\xB8', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE6', '\x83', '\x85', '\xE6', '\x83', '\xB3', '\xE6', '\x88', '\x96', /* 事前學将將情想或 */
+ '\xE6', '\x94', '\xBF', '\xE6', '\x96', '\xAF', '\xE6', '\x96', '\xB0', '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE6', '\xB0', '\x91', '\xE6', '\xB2', '\x92', '\xE6', '\xB2', '\xA1', /* 政斯新样樣民沒没 */
+ '\xE7', '\x84', '\xB6', '\xE7', '\x89', '\xB9', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x83', '\xE7', '\xAC', '\xAC', '\xE7', '\xB6', '\x93', '\xE8', '\xB0', '\x81', /* 然特现現球第經谁 */
+- '\xE8', '\xB5', '\xB7', /* 起 */
+- '\0',
++ '\xE8', '\xB5', '\xB7', '|', /* 起 | */
+ '\xE4', '\xBE', '\x8B', '\xE5', '\x88', '\xA5', '\xE5', '\x88', '\xAB', '\xE5', '\x88', '\xB6', '\xE5', '\x8A', '\xA8', '\xE5', '\x8B', '\x95', '\xE5', '\x90', '\x97', '\xE5', '\x97', '\x8E', /* 例別别制动動吗嗎 */
+ '\xE5', '\xA2', '\x9E', '\xE6', '\x8C', '\x87', '\xE6', '\x98', '\x8E', '\xE6', '\x9C', '\x9D', '\xE6', '\x9C', '\x9F', '\xE6', '\x9E', '\x84', '\xE7', '\x89', '\xA9', '\xE7', '\xA1', '\xAE', /* 增指明朝期构物确 */
+ '\xE7', '\xA7', '\x8D', '\xE8', '\xAA', '\xBF', '\xE8', '\xB0', '\x83', '\xE8', '\xB2', '\xBB', '\xE8', '\xB4', '\xB9', '\xE9', '\x82', '\xA3', '\xE9', '\x83', '\xBD', '\xE9', '\x96', '\x93', /* 种調调費费那都間 */
+@@ -113,14 +117,21 @@
+ af_blue_stringsets[] =
+ {
+ /* */
+- { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+- { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 },
+- { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+- { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+- AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+- { AF_BLUE_STRING_LATIN_SMALL, 0 },
+- { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 },
+- { AF_BLUE_STRING_MAX, 0 },
++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 },
++ { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
++ { AF_BLUE_STRING_CYRILLIC_SMALL, 0 },
++ { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 },
++ { AF_BLUE_STRING_MAX, 0 },
++ { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
++ { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP },
++ { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
++ AF_BLUE_PROPERTY_LATIN_NEUTRAL |
++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
++ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 },
++ { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 },
++ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+@@ -129,35 +140,28 @@
+ { AF_BLUE_STRING_GREEK_SMALL, 0 },
+ { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+- { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+- { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 },
+- { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+- AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+- { AF_BLUE_STRING_CYRILLIC_SMALL, 0 },
+- { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 },
+- { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_LONG },
+ { AF_BLUE_STRING_HEBREW_BOTTOM, 0 },
+ { AF_BLUE_STRING_HEBREW_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
++ { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
++ { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 },
++ { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
++ { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
++ { AF_BLUE_STRING_LATIN_SMALL, 0 },
++ { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 },
++ { AF_BLUE_STRING_MAX, 0 },
+ #ifdef AF_CONFIG_OPTION_CJK
+- { AF_BLUE_STRING_CJK_TOP_FILL, AF_BLUE_PROPERTY_CJK_TOP |
+- AF_BLUE_PROPERTY_CJK_FILL },
+- { AF_BLUE_STRING_CJK_TOP_UNFILL, AF_BLUE_PROPERTY_CJK_TOP },
+- { AF_BLUE_STRING_CJK_BOTTOM_FILL, AF_BLUE_PROPERTY_CJK_FILL },
+- { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0 },
++ { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP },
++ { AF_BLUE_STRING_CJK_BOTTOM, 0 },
+ #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+- { AF_BLUE_STRING_CJK_LEFT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ |
+- AF_BLUE_PROPERTY_CJK_FILL },
+- { AF_BLUE_STRING_CJK_LEFT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ },
+- { AF_BLUE_STRING_CJK_RIGHT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ |
+- AF_BLUE_PROPERTY_CJK_RIGHT |
+- AF_BLUE_PROPERTY_CJK_FILL },
+- { AF_BLUE_STRING_CJK_RIGHT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ |
+- AF_BLUE_PROPERTY_CJK_RIGHT },
++ { AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ },
++ { AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ |
++ AF_BLUE_PROPERTY_CJK_RIGHT },
+ #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+- { AF_BLUE_STRING_MAX, 0 },
++ { AF_BLUE_STRING_MAX, 0 },
+ #endif /* AF_CONFIG_OPTION_CJK */
+
+ };
+diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat
+index d488f3f..74a472d 100644
+--- a/src/autofit/afblue.dat
++++ b/src/autofit/afblue.dat
+@@ -2,7 +2,7 @@
+ //
+ // Auto-fitter data for blue strings.
+ //
+-// Copyright 2013 by
++// Copyright 2013, 2014 by
+ // David Turner, Robert Wilhelm, and Werner Lemberg.
+ //
+ // This file is part of the FreeType project, and may only be used,
+@@ -34,11 +34,11 @@
+ // using C syntax. There can be only one string per line, thus the
+ // starting and ending double quote must be the first and last character
+ // in the line, respectively, ignoring whitespace before and after the
+-// string. If there are multiple strings (in multiple lines), they are
+-// concatenated to a single string. In the output, a string gets
+-// represented as a series of singles bytes, followed by a zero byte. The
+-// enumeration values simply hold byte offsets to the start of the
+-// corresponding strings.
++// string. Space characters within the string are ignored too. If there
++// are multiple strings (in multiple lines), they are concatenated to a
++// single string. In the output, a string gets represented as a series of
++// singles bytes, followed by a zero byte. The enumeration values simply
++// hold byte offsets to the start of the corresponding strings.
+ //
+ // - Data blocks enclosed in balanced braces, which get copied verbatim and
+ // which can span multiple lines. The opening brace of a block must be
+@@ -63,18 +63,32 @@
+ // characters, not bytes.
+
+
++// The blue zone string data, to be used in the blue stringsets below.
++
+ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+
+- AF_BLUE_STRING_LATIN_CAPITAL_TOP
+- "THEZOCQS"
+- AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
+- "HEZLOCUS"
+- AF_BLUE_STRING_LATIN_SMALL_F_TOP
+- "fijkdbh"
+- AF_BLUE_STRING_LATIN_SMALL
+- "xzroesc"
+- AF_BLUE_STRING_LATIN_SMALL_DESCENDER
+- "pqgjy"
++ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
++ "БВЕПЗОСЭ"
++ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
++ "БВЕШЗОСЭ"
++ AF_BLUE_STRING_CYRILLIC_SMALL
++ "хпншезос"
++ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
++ "руф"
++
++ // we separate the letters with spaces to avoid ligatures;
++ // this is just for convenience to simplify reading
++ AF_BLUE_STRING_DEVANAGARI_BASE
++ "क म अ आ थ ध भ श"
++ AF_BLUE_STRING_DEVANAGARI_TOP
++ "ई ऐ ओ औ ि ी ो ौ"
++ // note that some fonts have extreme variation in the height of the
++ // round head elements; for this reason we also define the `base'
++ // blue zone, which must be always present
++ AF_BLUE_STRING_DEVANAGARI_HEAD
++ "क म अ आ थ ध भ श"
++ AF_BLUE_STRING_DEVANAGARI_BOTTOM
++ "ु ृ"
+
+ AF_BLUE_STRING_GREEK_CAPITAL_TOP
+ "ΓΒΕΖΘΟΩ"
+@@ -87,15 +101,6 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+ AF_BLUE_STRING_GREEK_SMALL_DESCENDER
+ "βγημρφχψ"
+
+- AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
+- "БВЕПЗОСЭ"
+- AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
+- "БВЕШЗОСЭ"
+- AF_BLUE_STRING_CYRILLIC_SMALL
+- "хпншезос"
+- AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
+- "руф"
+-
+ AF_BLUE_STRING_HEBREW_TOP
+ "בדהחךכםס"
+ AF_BLUE_STRING_HEBREW_BOTTOM
+@@ -103,24 +108,33 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+ AF_BLUE_STRING_HEBREW_DESCENDER
+ "קךןףץ"
+
++ AF_BLUE_STRING_LATIN_CAPITAL_TOP
++ "THEZOCQS"
++ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
++ "HEZLOCUS"
++ AF_BLUE_STRING_LATIN_SMALL_F_TOP
++ "fijkdbh"
++ AF_BLUE_STRING_LATIN_SMALL
++ "xzroesc"
++ AF_BLUE_STRING_LATIN_SMALL_DESCENDER
++ "pqgjy"
++
+ #ifdef AF_CONFIG_OPTION_CJK
+
+- AF_BLUE_STRING_CJK_TOP_FILL
++ AF_BLUE_STRING_CJK_TOP
+ "他们你來們到和地"
+ "对對就席我时時會"
+ "来為能舰說说这這"
+- "齊"
+- AF_BLUE_STRING_CJK_TOP_UNFILL
++ "齊 |"
+ "军同已愿既星是景"
+ "民照现現理用置要"
+ "軍那配里開雷露面"
+ "顾"
+- AF_BLUE_STRING_CJK_BOTTOM_FILL
++ AF_BLUE_STRING_CJK_BOTTOM
+ "个为人他以们你來"
+ "個們到和大对對就"
+ "我时時有来為要說"
+- "说"
+- AF_BLUE_STRING_CJK_BOTTOM_UNFILL
++ "说 |"
+ "主些因它想意理生"
+ "當看着置者自著裡"
+ "过还进進過道還里"
+@@ -128,22 +142,20 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+
+ #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+
+- AF_BLUE_STRING_CJK_LEFT_FILL
++ AF_BLUE_STRING_CJK_LEFT
+ "些们你來們到和地"
+ "她将將就年得情最"
+ "样樣理能說说这這"
+- "通"
+- AF_BLUE_STRING_CJK_LEFT_UNFILL
++ "通 |"
+ "即吗吧听呢品响嗎"
+ "师師收断斷明眼間"
+ "间际陈限除陳随際"
+ "隨"
+- AF_BLUE_STRING_CJK_RIGHT_FILL
++ AF_BLUE_STRING_CJK_RIGHT
+ "事前學将將情想或"
+ "政斯新样樣民沒没"
+ "然特现現球第經谁"
+- "起"
+- AF_BLUE_STRING_CJK_RIGHT_UNFILL
++ "起 |"
+ "例別别制动動吗嗎"
+ "增指明朝期构物确"
+ "种調调費费那都間"
+@@ -154,17 +166,118 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+ #endif /* AF_CONFIG_OPTION_CJK */
+
+
++// The blue zone stringsets, as used in the script styles, cf. `afstyles.h'.
++//
++// The AF_BLUE_PROPERTY_XXX flags are defined in `afblue.h'; here some
++// explanations.
++//
++// A blue zone in general is defined by a reference and an overshoot line.
++// During the hinting process, all coordinate values between those two lines
++// are set equal to the reference value, provided that the blue zone is not
++// wider than 0.75 pixels (otherwise the blue zone gets ignored). All
++// entries must have `AF_BLUE_STRING_MAX' as the final line.
++//
++// During the glyph analysis, edges are sorted from bottom to top, and then
++// sequentially checked, edge by edge, against the blue zones in the order
++// given below.
++//
++//
++// latin auto-hinter
++// -----------------
++//
++// Characters in a blue string are automatically classified as having a flat
++// (reference) or a round (overshoot) extremum. The blue zone is then set
++// up by the mean values of all flat extrema and all round extrema,
++// respectively. Only horizontal blue zones (i.e., adjusting vertical
++// coordinate values) are supported.
++//
++// For the latin auto-hinter, the overshoot should be larger than the
++// reference for top zones, and vice versa for bottom zones.
++//
++// LATIN_TOP
++// Take the maximum flat and round coordinate values of the blue string
++// characters for computing the blue zone's reference and overshoot
++// values.
++//
++// If not set, take the minimum values.
++//
++// LATIN_NEUTRAL
++// Ignore round extrema and define the blue zone with flat values only.
++// Both top and bottom of contours can match. This is useful for
++// scripts like Devanagari where vowel signs attach to the base
++// character and are implemented as components of composite glyphs.
++//
++// If not set, both round and flat extrema are taken into account.
++// Additionally, only the top or the bottom of a contour can match,
++// depending on the LATIN_TOP flag.
++//
++// Neutral blue zones should always follow non-neutral blue zones.
++//
++// LATIN_X_HEIGHT
++// Scale all glyphs vertically from the corresponding script to make the
++// reference line of this blue zone align on the grid. The scaling
++// takes place before all other blue zones get aligned to the grid.
++// Only one blue character string of a script style can have this flag.
++//
++// LATIN_LONG
++// Apply an additional constraint for blue zone values: Don't
++// necessarily use the extremum as-is but a segment of the topmost (or
++// bottommost) contour that is longer than a heuristic threshold, and
++// which is not too far away vertically from the real extremum. This
++// ensures that small bumps in the outline are ignored (for example, the
++// `vertical serifs' found in many Hebrew glyph designs).
++//
++// The segment must be at least EM/25 font units long, and the distance
++// to the extremum must be smaller than EM/4.
++//
++//
++// cjk auto-hinter
++// ---------------
++//
++// Characters in a blue string are *not* automatically classified. Instead,
++// first come the characters used for the overshoot value, then the
++// character `|', then the characters used for the reference value. The
++// blue zone is then set up by the mean values of all reference values and
++// all overshoot values, respectively. Both horizontal and vertical blue
++// zones (i.e., adjusting vertical and horizontal coordinate values,
++// respectively) are supported.
++//
++// For the cjk auto-hinter, the overshoot should be smaller than the
++// reference for top zones, and vice versa for bottom zones.
++//
++// CJK_TOP
++// Take the maximum flat and round coordinate values of the blue string
++// characters. If not set, take the minimum values.
++//
++// CJK_RIGHT
++// A synonym for CJK_TOP. If CJK_HORIZ is set, this flag indicates the
++// right blue zone, taking horizontal maximum values.
++//
++// CJK_HORIZ
++// Define a blue zone for horizontal hinting (i.e., vertical blue
++// zones). If not set, this is a blue zone for vertical hinting.
++
++
+ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
+
+- AF_BLUE_STRINGSET_LATN
+- { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+- { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }
+- { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+- { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+- { AF_BLUE_STRING_LATIN_SMALL, 0 }
+- { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }
+- { AF_BLUE_STRING_MAX, 0 }
++ AF_BLUE_STRINGSET_CYRL
++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }
++ { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
++ { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }
++ { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }
++ { AF_BLUE_STRING_MAX, 0 }
++
++ AF_BLUE_STRINGSET_DEVA
++ { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
++ { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }
++ { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
++ AF_BLUE_PROPERTY_LATIN_NEUTRAL |
++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
++ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 }
++ { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 }
++ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_GREK
+ { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+@@ -176,15 +289,6 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
+ { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+- AF_BLUE_STRINGSET_CYRL
+- { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+- { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }
+- { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+- { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }
+- { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }
+- { AF_BLUE_STRING_MAX, 0 }
+-
+ AF_BLUE_STRINGSET_HEBR
+ { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_LONG }
+@@ -192,25 +296,27 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
+ { AF_BLUE_STRING_HEBREW_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
++ AF_BLUE_STRINGSET_LATN
++ { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
++ { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }
++ { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
++ { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
++ { AF_BLUE_STRING_LATIN_SMALL, 0 }
++ { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }
++ { AF_BLUE_STRING_MAX, 0 }
++
+ #ifdef AF_CONFIG_OPTION_CJK
+
+ AF_BLUE_STRINGSET_HANI
+- { AF_BLUE_STRING_CJK_TOP_FILL, AF_BLUE_PROPERTY_CJK_TOP |
+- AF_BLUE_PROPERTY_CJK_FILL }
+- { AF_BLUE_STRING_CJK_TOP_UNFILL, AF_BLUE_PROPERTY_CJK_TOP }
+- { AF_BLUE_STRING_CJK_BOTTOM_FILL, AF_BLUE_PROPERTY_CJK_FILL }
+- { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0 }
++ { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP }
++ { AF_BLUE_STRING_CJK_BOTTOM, 0 }
+ #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+- { AF_BLUE_STRING_CJK_LEFT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ |
+- AF_BLUE_PROPERTY_CJK_FILL }
+- { AF_BLUE_STRING_CJK_LEFT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ }
+- { AF_BLUE_STRING_CJK_RIGHT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ |
+- AF_BLUE_PROPERTY_CJK_RIGHT |
+- AF_BLUE_PROPERTY_CJK_FILL }
+- { AF_BLUE_STRING_CJK_RIGHT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ |
+- AF_BLUE_PROPERTY_CJK_RIGHT }
++ { AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ }
++ { AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ |
++ AF_BLUE_PROPERTY_CJK_RIGHT }
+ #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+- { AF_BLUE_STRING_MAX, 0 }
++ { AF_BLUE_STRING_MAX, 0 }
+
+ #endif /* AF_CONFIG_OPTION_CJK */
+
+diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h
+index 6f336ab..d239e8e 100644
+--- a/src/autofit/afblue.h
++++ b/src/autofit/afblue.h
+@@ -7,7 +7,7 @@
+ /* */
+ /* Auto-fitter data for blue strings (specification). */
+ /* */
+-/* Copyright 2013 by */
++/* Copyright 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -67,42 +67,42 @@ FT_BEGIN_HEADER
+ /* At the bottommost level, we define strings for finding blue zones. */
+
+
+-#define AF_BLUE_STRING_MAX_LEN 25
++#define AF_BLUE_STRING_MAX_LEN 51
+
+ /* The AF_Blue_String enumeration values are offsets into the */
+ /* `af_blue_strings' array. */
+
+ typedef enum AF_Blue_String_
+ {
+- AF_BLUE_STRING_LATIN_CAPITAL_TOP = 0,
+- AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 9,
+- AF_BLUE_STRING_LATIN_SMALL_F_TOP = 18,
+- AF_BLUE_STRING_LATIN_SMALL = 26,
+- AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 34,
+- AF_BLUE_STRING_GREEK_CAPITAL_TOP = 40,
+- AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 55,
+- AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 68,
+- AF_BLUE_STRING_GREEK_SMALL = 81,
+- AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 98,
+- AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 115,
+- AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 132,
+- AF_BLUE_STRING_CYRILLIC_SMALL = 149,
+- AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 166,
+- AF_BLUE_STRING_HEBREW_TOP = 173,
+- AF_BLUE_STRING_HEBREW_BOTTOM = 190,
+- AF_BLUE_STRING_HEBREW_DESCENDER = 203,
+- af_blue_1_1 = 213,
++ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 0,
++ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 17,
++ AF_BLUE_STRING_CYRILLIC_SMALL = 34,
++ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 51,
++ AF_BLUE_STRING_DEVANAGARI_BASE = 58,
++ AF_BLUE_STRING_DEVANAGARI_TOP = 83,
++ AF_BLUE_STRING_DEVANAGARI_HEAD = 108,
++ AF_BLUE_STRING_DEVANAGARI_BOTTOM = 133,
++ AF_BLUE_STRING_GREEK_CAPITAL_TOP = 140,
++ AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 155,
++ AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 168,
++ AF_BLUE_STRING_GREEK_SMALL = 181,
++ AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 198,
++ AF_BLUE_STRING_HEBREW_TOP = 215,
++ AF_BLUE_STRING_HEBREW_BOTTOM = 232,
++ AF_BLUE_STRING_HEBREW_DESCENDER = 245,
++ AF_BLUE_STRING_LATIN_CAPITAL_TOP = 256,
++ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 265,
++ AF_BLUE_STRING_LATIN_SMALL_F_TOP = 274,
++ AF_BLUE_STRING_LATIN_SMALL = 282,
++ AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 290,
++ af_blue_1_1 = 295,
+ #ifdef AF_CONFIG_OPTION_CJK
+- AF_BLUE_STRING_CJK_TOP_FILL = af_blue_1_1 + 1,
+- AF_BLUE_STRING_CJK_TOP_UNFILL = af_blue_1_1 + 77,
+- AF_BLUE_STRING_CJK_BOTTOM_FILL = af_blue_1_1 + 153,
+- AF_BLUE_STRING_CJK_BOTTOM_UNFILL = af_blue_1_1 + 229,
++ AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
++ AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 153,
+ af_blue_1_1_1 = af_blue_1_1 + 304,
+ #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+- AF_BLUE_STRING_CJK_LEFT_FILL = af_blue_1_1_1 + 1,
+- AF_BLUE_STRING_CJK_LEFT_UNFILL = af_blue_1_1_1 + 77,
+- AF_BLUE_STRING_CJK_RIGHT_FILL = af_blue_1_1_1 + 153,
+- AF_BLUE_STRING_CJK_RIGHT_UNFILL = af_blue_1_1_1 + 229,
++ AF_BLUE_STRING_CJK_LEFT = af_blue_1_1_1 + 1,
++ AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 153,
+ af_blue_1_1_2 = af_blue_1_1_1 + 304,
+ #else
+ af_blue_1_1_2 = af_blue_1_1_1 + 0,
+@@ -136,33 +136,34 @@ FT_BEGIN_HEADER
+ /* Properties are specific to a writing system. We assume that a given */
+ /* blue string can't be used in more than a single writing system, which */
+ /* is a safe bet. */
+-#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 )
+-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 )
+-#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 )
++#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */
++#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 )
++#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 )
++#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 )
+
+-#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 0 )
+-#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 1 )
+-#define AF_BLUE_PROPERTY_CJK_FILL ( 1 << 2 )
++#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */
++#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */
+ #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP
+
+
+-#define AF_BLUE_STRINGSET_MAX_LEN 9
++#define AF_BLUE_STRINGSET_MAX_LEN 7
+
+ /* The AF_Blue_Stringset enumeration values are offsets into the */
+ /* `af_blue_stringsets' array. */
+
+ typedef enum AF_Blue_Stringset_
+ {
+- AF_BLUE_STRINGSET_LATN = 0,
+- AF_BLUE_STRINGSET_GREK = 7,
+- AF_BLUE_STRINGSET_CYRL = 14,
+- AF_BLUE_STRINGSET_HEBR = 20,
+- af_blue_2_1 = 24,
++ AF_BLUE_STRINGSET_CYRL = 0,
++ AF_BLUE_STRINGSET_DEVA = 6,
++ AF_BLUE_STRINGSET_GREK = 12,
++ AF_BLUE_STRINGSET_HEBR = 19,
++ AF_BLUE_STRINGSET_LATN = 23,
++ af_blue_2_1 = 30,
+ #ifdef AF_CONFIG_OPTION_CJK
+ AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
+- af_blue_2_1_1 = af_blue_2_1 + 4,
++ af_blue_2_1_1 = af_blue_2_1 + 2,
+ #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+- af_blue_2_1_2 = af_blue_2_1_1 + 4,
++ af_blue_2_1_2 = af_blue_2_1_1 + 2,
+ #else
+ af_blue_2_1_2 = af_blue_2_1_1 + 0,
+ #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin
+index 4fc9917..0b4b48d 100644
+--- a/src/autofit/afblue.hin
++++ b/src/autofit/afblue.hin
+@@ -4,7 +4,7 @@
+ /* */
+ /* Auto-fitter data for blue strings (specification). */
+ /* */
+-/* Copyright 2013 by */
++/* Copyright 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -96,13 +96,13 @@ FT_BEGIN_HEADER
+ /* Properties are specific to a writing system. We assume that a given */
+ /* blue string can't be used in more than a single writing system, which */
+ /* is a safe bet. */
+-#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 )
+-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 )
+-#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 )
++#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */
++#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 )
++#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 )
++#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 )
+
+-#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 0 )
+-#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 1 )
+-#define AF_BLUE_PROPERTY_CJK_FILL ( 1 << 2 )
++#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */
++#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */
+ #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP
+
+
+diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
+index 3a65fc5..048e0e7 100644
+--- a/src/autofit/afcjk.c
++++ b/src/autofit/afcjk.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* Auto-fitter hinting routines for CJK writing system (body). */
+ /* */
+-/* Copyright 2006-2013 by */
++/* Copyright 2006-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -178,6 +178,8 @@
+ goto Exit;
+
+ af_latin_hints_link_segments( hints,
++ 0,
++ NULL,
+ (AF_Dimension)dim );
+
+ seg = axhints->segments;
+@@ -261,6 +263,8 @@
+ FT_Int num_fills;
+ FT_Int num_flats;
+
++ FT_Bool fill;
++
+ AF_CJKBlue blue;
+ FT_Error error;
+ AF_CJKAxis axis;
+@@ -271,22 +275,6 @@
+ AF_Blue_Stringset bss = sc->blue_stringset;
+ const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+
+-#ifdef FT_DEBUG_LEVEL_TRACE
+- FT_String* cjk_blue_name[4] =
+- {
+- (FT_String*)"bottom", /* -- , -- */
+- (FT_String*)"top", /* -- , TOP */
+- (FT_String*)"left", /* HORIZ, -- */
+- (FT_String*)"right" /* HORIZ, TOP */
+- };
+-
+- FT_String* cjk_blue_type_name[2] =
+- {
+- (FT_String*)"unfilled", /* -- */
+- (FT_String*)"filled" /* FILL */
+- };
+-#endif
+-
+
+ /* we walk over the blue character strings as specified in the */
+ /* style's entry in the `af_blue_stringset' array, computing its */
+@@ -308,15 +296,29 @@
+ else
+ axis = &metrics->axis[AF_DIMENSION_VERT];
+
+- FT_TRACE5(( "blue zone %d:\n", axis->blue_count ));
++#ifdef FT_DEBUG_LEVEL_TRACE
++ {
++ FT_String* cjk_blue_name[4] =
++ {
++ (FT_String*)"bottom", /* -- , -- */
++ (FT_String*)"top", /* -- , TOP */
++ (FT_String*)"left", /* HORIZ, -- */
++ (FT_String*)"right" /* HORIZ, TOP */
++ };
++
++
++ FT_TRACE5(( "blue zone %d (%s):\n",
++ axis->blue_count,
++ cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) |
++ AF_CJK_IS_TOP_BLUE( bs ) ] ));
++ }
++#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ num_fills = 0;
+ num_flats = 0;
+
+- FT_TRACE5(( " cjk blue %s/%s\n",
+- cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) |
+- AF_CJK_IS_TOP_BLUE( bs ) ],
+- cjk_blue_type_name[!!AF_CJK_IS_FILLED_BLUE( bs )] ));
++ fill = 1; /* start with characters that define fill values */
++ FT_TRACE5(( " [overshoot values]\n" ));
+
+ while ( *p )
+ {
+@@ -330,6 +332,14 @@
+
+ GET_UTF8_CHAR( ch, p );
+
++ /* switch to characters that define flat values */
++ if ( ch == '|' )
++ {
++ fill = 0;
++ FT_TRACE5(( " [reference values]\n" ));
++ continue;
++ }
++
+ /* load the character in the face -- skip unknown or empty ones */
+ af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
+ if ( glyph_index == 0 )
+@@ -417,7 +427,7 @@
+ FT_TRACE5(( " U+%04lX: best_pos = %5ld\n", ch, best_pos ));
+ }
+
+- if ( AF_CJK_IS_FILLED_BLUE( bs ) )
++ if ( fill )
+ fills[num_fills++] = best_pos;
+ else
+ flats[num_flats++] = best_pos;
+@@ -429,15 +439,15 @@
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
+ */
+- FT_TRACE5(( " empty\n" ));
++ FT_TRACE5(( " empty\n" ));
+ continue;
+ }
+
+- /* we have computed the contents of the `fill' and `flats' tables, */
+- /* now determine the reference position of the blue zone -- */
+- /* we simply take the median value after a simple sort */
+- af_sort_pos( num_flats, flats );
++ /* we have computed the contents of the `fill' and `flats' tables, */
++ /* now determine the reference and overshoot position of the blue -- */
++ /* we simply take the median value after a simple sort */
+ af_sort_pos( num_fills, fills );
++ af_sort_pos( num_flats, flats );
+
+ blue = &axis->blues[axis->blue_count];
+ blue_ref = &blue->ref.org;
+@@ -476,7 +486,7 @@
+ *blue_ref =
+ *blue_shoot = ( shoot + ref ) / 2;
+
+- FT_TRACE5(( " [overshoot smaller than reference,"
++ FT_TRACE5(( " [reference smaller than overshoot,"
+ " taking mean value]\n" ));
+ }
+ }
+@@ -755,10 +765,6 @@
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+- /* the fake segments are for metrics hinting only */
+- if ( seg1->first == seg1->last )
+- continue;
+-
+ if ( seg1->dir != major_dir )
+ continue;
+
+@@ -1018,10 +1024,11 @@
+
+ edge->first = seg;
+ edge->last = seg;
++ edge->dir = seg->dir;
+ edge->fpos = seg->pos;
+- edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
++ edge->opos = FT_MulFix( seg->pos, scale );
++ edge->pos = edge->opos;
+ seg->edge_next = seg;
+- edge->dir = seg->dir;
+ }
+ else
+ {
+@@ -1230,8 +1237,10 @@
+ /* zone, check for left edges */
+ /* */
+ /* of course, that's for TrueType */
+- is_top_right_blue = FT_BOOL( blue->flags & AF_CJK_BLUE_TOP );
+- is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
++ is_top_right_blue =
++ (FT_Byte)( ( blue->flags & AF_CJK_BLUE_TOP ) != 0 );
++ is_major_dir =
++ FT_BOOL( edge->dir == axis->major_dir );
+
+ /* if it is a top zone, the edge must be against the major */
+ /* direction; if it is a bottom zone, it must be in the major */
+@@ -1528,6 +1537,12 @@
+
+
+ stem_edge->pos = base_edge->pos + fitted_width;
++
++ FT_TRACE5(( " CJKLINK: edge %d @%d (opos=%.2f) linked to %.2f,"
++ " dist was %.2f, now %.2f\n",
++ stem_edge - hints->axis[dim].edges, stem_edge->fpos,
++ stem_edge->opos / 64.0, stem_edge->pos / 64.0,
++ dist / 64.0, fitted_width / 64.0 ));
+ }
+
+
+diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
+index a260b09..4dd4f39 100644
+--- a/src/autofit/afcjk.h
++++ b/src/autofit/afcjk.h
+@@ -4,7 +4,7 @@
+ /* */
+ /* Auto-fitter hinting routines for CJK writing system (specification). */
+ /* */
+-/* Copyright 2006, 2007, 2011-2013 by */
++/* Copyright 2006, 2007, 2011-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -50,8 +50,6 @@ FT_BEGIN_HEADER
+ ( (b)->properties & AF_BLUE_PROPERTY_CJK_TOP )
+ #define AF_CJK_IS_HORIZ_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_CJK_HORIZ )
+-#define AF_CJK_IS_FILLED_BLUE( b ) \
+- ( (b)->properties & AF_BLUE_PROPERTY_CJK_FILL )
+ #define AF_CJK_IS_RIGHT_BLUE AF_CJK_IS_TOP_BLUE
+
+ #define AF_CJK_MAX_WIDTHS 16
+diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
+index 7aa2e11..a54c20c 100644
+--- a/src/autofit/afglobal.c
++++ b/src/autofit/afglobal.c
+@@ -138,7 +138,7 @@
+ FT_Byte* gstyles = globals->glyph_styles;
+ FT_UInt ss;
+ FT_UInt i;
+- FT_UInt dflt = -1;
++ FT_UInt dflt = ~0U; /* a non-valid value */
+
+
+ /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
+@@ -176,7 +176,8 @@
+ */
+ if ( style_class->coverage == AF_COVERAGE_DEFAULT )
+ {
+- if ( style_class->script == globals->module->default_script )
++ if ( (FT_UInt)style_class->script ==
++ globals->module->default_script )
+ dflt = ss;
+
+ for ( range = script_class->script_uni_ranges;
+@@ -332,8 +333,8 @@
+ af_face_globals_free( globals );
+ globals = NULL;
+ }
+-
+- globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
++ else
++ globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
+
+ Exit:
+ *aglobals = globals;
+diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
+index d2da40e..38d8d69 100644
+--- a/src/autofit/afglobal.h
++++ b/src/autofit/afglobal.h
+@@ -66,16 +66,16 @@ FT_BEGIN_HEADER
+
+ /* index of fallback style in `af_style_classes' */
+ #ifdef AF_CONFIG_OPTION_CJK
+-#define AF_STYLE_FALLBACK AF_STYLE_HANI_DFLT
++#define AF_STYLE_FALLBACK AF_STYLE_HANI_DFLT
+ #else
+-#define AF_STYLE_FALLBACK AF_STYLE_NONE_DFLT
++#define AF_STYLE_FALLBACK AF_STYLE_NONE_DFLT
+ #endif
+ /* default script for OpenType; ignored if HarfBuzz isn't used */
+-#define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN
++#define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN
+ /* a bit mask indicating an uncovered glyph */
+ #define AF_STYLE_UNASSIGNED 0x7F
+ /* if this flag is set, we have an ASCII digit */
+-#define AF_DIGIT 0x80
++#define AF_DIGIT 0x80
+
+ /* `increase-x-height' property */
+ #define AF_PROP_INCREASE_X_HEIGHT_MIN 6
+diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
+index 270a06b..9fbc541 100644
+--- a/src/autofit/afhints.c
++++ b/src/autofit/afhints.c
+@@ -74,7 +74,8 @@
+ }
+
+
+- /* Get new edge for given axis, direction, and position. */
++ /* Get new edge for given axis, direction, and position, */
++ /* without initializing the edge itself. */
+
+ FT_LOCAL( FT_Error )
+ af_axis_hints_new_edge( AF_AxisHints axis,
+@@ -130,10 +131,6 @@
+
+ axis->num_edges++;
+
+- FT_ZERO( edge );
+- edge->fpos = (FT_Short)fpos;
+- edge->dir = (FT_Char)dir;
+-
+ Exit:
+ *anedge = edge;
+ return error;
+@@ -204,7 +201,7 @@
+
+ for ( point = points; point < limit; point++ )
+ AF_DUMP(( " [ %5d | %5d | %5d | %6.2f | %6.2f"
+- " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
++ " | %5.2f | %5.2f | %c ]\n",
+ point - points,
+ point->fx,
+ point->fy,
+@@ -212,12 +209,7 @@
+ point->oy / 64.0,
+ point->x / 64.0,
+ point->y / 64.0,
+- ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
+- ( point->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ',
+- ( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ',
+- ( point->flags & AF_FLAG_EXTREMA_Y ) ? 'v' : ' ',
+- ( point->flags & AF_FLAG_ROUND_X ) ? '(' : ' ',
+- ( point->flags & AF_FLAG_ROUND_Y ) ? 'u' : ' '));
++ ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' '));
+ AF_DUMP(( "\n" ));
+ }
+ #ifdef __cplusplus
+@@ -651,6 +643,9 @@
+
+ for ( point = points; point < point_limit; point++, vec++, tag++ )
+ {
++ point->in_dir = (FT_Char)AF_DIR_NONE;
++ point->out_dir = (FT_Char)AF_DIR_NONE;
++
+ point->fx = (FT_Short)vec->x;
+ point->fy = (FT_Short)vec->y;
+ point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
+@@ -698,91 +693,186 @@
+ }
+ }
+
+- /* compute directions of in & out vectors */
+ {
+- AF_Point first = points;
+- AF_Point prev = NULL;
+- FT_Pos in_x = 0;
+- FT_Pos in_y = 0;
+- AF_Direction in_dir = AF_DIR_NONE;
+-
+- FT_Pos last_good_in_x = 0;
+- FT_Pos last_good_in_y = 0;
+-
++ /*
++ * Compute directions of `in' and `out' vectors.
++ *
++ * Note that distances between points that are very near to each
++ * other are accumulated. In other words, the auto-hinter
++ * prepends the small vectors between near points to the first
++ * non-near vector. All intermediate points are tagged as
++ * weak; the directions are adjusted also to be equal to the
++ * accumulated one.
++ */
++
++ /* value 20 in `near_limit' is heuristic */
+ FT_UInt units_per_em = hints->metrics->scaler.face->units_per_EM;
+ FT_Int near_limit = 20 * units_per_em / 2048;
++ FT_Int near_limit2 = 2 * near_limit - 1;
+
++ AF_Point* contour;
++ AF_Point* contour_limit = hints->contours + hints->num_contours;
+
+- for ( point = points; point < point_limit; point++ )
++
++ for ( contour = hints->contours; contour < contour_limit; contour++ )
+ {
+- AF_Point next;
+- FT_Pos out_x, out_y;
++ AF_Point first = *contour;
++ AF_Point next, prev, curr;
++
++ FT_Pos out_x, out_y;
+
++ FT_Bool is_first;
+
+- if ( point == first )
++
++ /* since the first point of a contour could be part of a */
++ /* series of near points, go backwards to find the first */
++ /* non-near point and adjust `first' */
++
++ point = first;
++ prev = first->prev;
++
++ while ( prev != first )
+ {
+- prev = first->prev;
++ out_x = point->fx - prev->fx;
++ out_y = point->fy - prev->fy;
++
++ /*
++ * We use Taxicab metrics to measure the vector length.
++ *
++ * Note that the accumulated distances so far could have the
++ * opposite direction of the distance measured here. For this
++ * reason we use `near_limit2' for the comparison to get a
++ * non-near point even in the worst case.
++ */
++ if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 )
++ break;
++
++ point = prev;
++ prev = prev->prev;
++ }
+
+- in_x = first->fx - prev->fx;
+- in_y = first->fy - prev->fy;
++ /* adjust first point */
++ first = point;
+
+- last_good_in_x = in_x;
+- last_good_in_y = in_y;
++ /* now loop over all points of the contour to get */
++ /* `in' and `out' vector directions */
+
+- if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit )
+- {
+- /* search first non-near point to get a good `in_dir' value */
++ curr = first;
+
+- AF_Point point_ = prev;
++ /*
++ * We abuse the `u' and `v' fields to store index deltas to the
++ * next and previous non-near point, respectively.
++ *
++ * To avoid problems with not having non-near points, we point to
++ * `first' by default as the next non-near point.
++ *
++ */
++ curr->u = (FT_Pos)( first - curr );
++ first->v = -curr->u;
+
++ out_x = 0;
++ out_y = 0;
+
+- while ( point_ != first )
+- {
+- AF_Point prev_ = point_->prev;
++ is_first = 1;
+
+- FT_Pos in_x_ = point_->fx - prev_->fx;
+- FT_Pos in_y_ = point_->fy - prev_->fy;
++ for ( point = first;
++ point != first || is_first;
++ point = point->next )
++ {
++ AF_Direction out_dir;
+
+
+- if ( FT_ABS( in_x_ ) + FT_ABS( in_y_ ) >= near_limit )
+- {
+- last_good_in_x = in_x_;
+- last_good_in_y = in_y_;
++ is_first = 0;
+
+- break;
+- }
++ next = point->next;
+
+- point_ = prev_;
+- }
++ out_x += next->fx - point->fx;
++ out_y += next->fy - point->fy;
++
++ if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
++ {
++ next->flags |= AF_FLAG_WEAK_INTERPOLATION;
++ continue;
++ }
++
++ curr->u = (FT_Pos)( next - curr );
++ next->v = -curr->u;
++
++ out_dir = af_direction_compute( out_x, out_y );
++
++ /* adjust directions for all points inbetween; */
++ /* the loop also updates position of `curr' */
++ curr->out_dir = (FT_Char)out_dir;
++ for ( curr = curr->next; curr != next; curr = curr->next )
++ {
++ curr->in_dir = (FT_Char)out_dir;
++ curr->out_dir = (FT_Char)out_dir;
+ }
++ next->in_dir = (FT_Char)out_dir;
+
+- in_dir = af_direction_compute( in_x, in_y );
+- first = prev + 1;
++ curr->u = (FT_Pos)( first - curr );
++ first->v = -curr->u;
++
++ out_x = 0;
++ out_y = 0;
+ }
++ }
+
+- point->in_dir = (FT_Char)in_dir;
++ /*
++ * The next step is to `simplify' an outline's topology so that we
++ * can identify local extrema more reliably: A series of
++ * non-horizontal or non-vertical vectors pointing into the same
++ * quadrant are handled as a single, long vector. From a
++ * topological point of the view, the intermediate points are of no
++ * interest and thus tagged as weak.
++ */
+
+- /* check whether the current point is near to the previous one */
+- /* (value 20 in `near_limit' is heuristic; we use Taxicab */
+- /* metrics for the test) */
++ for ( point = points; point < point_limit; point++ )
++ {
++ if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
++ continue;
+
+- if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit )
+- point->flags |= AF_FLAG_NEAR;
+- else
++ if ( point->in_dir == AF_DIR_NONE &&
++ point->out_dir == AF_DIR_NONE )
+ {
+- last_good_in_x = in_x;
+- last_good_in_y = in_y;
+- }
++ /* check whether both vectors point into the same quadrant */
++
++ FT_Pos in_x, in_y;
++ FT_Pos out_x, out_y;
++
++ AF_Point next_u = point + point->u;
++ AF_Point prev_v = point + point->v;
++
+
+- next = point->next;
+- out_x = next->fx - point->fx;
+- out_y = next->fy - point->fy;
++ in_x = point->fx - prev_v->fx;
++ in_y = point->fy - prev_v->fy;
++
++ out_x = next_u->fx - point->fx;
++ out_y = next_u->fy - point->fy;
++
++ if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 )
++ {
++ /* yes, so tag current point as weak */
++ /* and update index deltas */
++
++ point->flags |= AF_FLAG_WEAK_INTERPOLATION;
++
++ prev_v->u = (FT_Pos)( next_u - prev_v );
++ next_u->v = -prev_v->u;
++ }
++ }
++ }
+
+- in_dir = af_direction_compute( out_x, out_y );
+- point->out_dir = (FT_Char)in_dir;
++ /*
++ * Finally, check for remaining weak points. Everything else not
++ * collected in edges so far is then implicitly classified as strong
++ * points.
++ */
+
+- /* Check for weak points. The remaining points not collected */
+- /* in edges are then implicitly classified as strong points. */
++ for ( point = points; point < point_limit; point++ )
++ {
++ if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
++ continue;
+
+ if ( point->flags & AF_FLAG_CONTROL )
+ {
+@@ -799,18 +889,25 @@
+ goto Is_Weak_Point;
+ }
+
+- /* test whether `in' and `out' direction is approximately */
+- /* the same (and use the last good `in' vector in case */
+- /* the current point is near to the previous one) */
+- if ( ft_corner_is_flat(
+- point->flags & AF_FLAG_NEAR ? last_good_in_x : in_x,
+- point->flags & AF_FLAG_NEAR ? last_good_in_y : in_y,
+- out_x,
+- out_y ) )
+ {
+- /* current point lies on a straight, diagonal line */
+- /* (more or less) */
+- goto Is_Weak_Point;
++ AF_Point next_u = point + point->u;
++ AF_Point prev_v = point + point->v;
++
++
++ if ( ft_corner_is_flat( point->fx - prev_v->fx,
++ point->fy - prev_v->fy,
++ next_u->fx - point->fx,
++ next_u->fy - point->fy ) )
++ {
++ /* either the `in' or the `out' vector is much more */
++ /* dominant than the other one, so tag current point */
++ /* as weak and update index deltas */
++
++ prev_v->u = (FT_Pos)( next_u - prev_v );
++ next_u->v = -prev_v->u;
++
++ goto Is_Weak_Point;
++ }
+ }
+ }
+ else if ( point->in_dir == -point->out_dir )
+@@ -818,9 +915,6 @@
+ /* current point forms a spike */
+ goto Is_Weak_Point;
+ }
+-
+- in_x = out_x;
+- in_y = out_y;
+ }
+ }
+ }
+@@ -977,8 +1071,7 @@
+ /* if this point is candidate to weak interpolation, we */
+ /* interpolate it after all strong points have been processed */
+
+- if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
+- !( point->flags & AF_FLAG_INFLECTION ) )
++ if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) )
+ continue;
+
+ if ( dim == AF_DIMENSION_VERT )
+diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
+index 5f1507f..92101de 100644
+--- a/src/autofit/afhints.h
++++ b/src/autofit/afhints.h
+@@ -4,7 +4,7 @@
+ /* */
+ /* Auto-fitter hinting routines (specification). */
+ /* */
+-/* Copyright 2003-2008, 2010-2012 by */
++/* Copyright 2003-2008, 2010-2012, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -72,13 +72,9 @@ FT_BEGIN_HEADER
+ * `af_{cjk,latin,...}_hints_compute_segments' are the functions to
+ * find segments in an outline.
+ *
+- * A segment is a series of consecutive points that are approximately
+- * aligned along a coordinate axis. The analysis to do so is specific
+- * to a writing system.
+- *
+- * A segment must have at least two points, except in the case of
+- * `fake' segments that are generated to hint metrics appropriately,
+- * and which consist of a single point.
++ * A segment is a series of at least two consecutive points that are
++ * approximately aligned along a coordinate axis. The analysis to do
++ * so is specific to a writing system.
+ *
+ *
+ * Edges
+@@ -148,7 +144,7 @@ FT_BEGIN_HEADER
+ * Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
+ *
+ * In comparison to a stem, a serif (as handled by the auto-hinter
+- * module which takes care of the `latin' writing system) has
++ * module that takes care of the `latin' writing system) has
+ *
+ * best segment_1 = segment_2 && best segment_2 != segment_1
+ *
+@@ -178,19 +174,19 @@ FT_BEGIN_HEADER
+ *
+ * Strong Points
+ *
+- * Experience has shown that points which are not part of an edge need
+- * to be interpolated linearly between their two closest edges, even if
+- * these are not part of the contour of those particular points.
+- * Typical candidates for this are
++ * Experience has shown that points not part of an edge need to be
++ * interpolated linearly between their two closest edges, even if these
++ * are not part of the contour of those particular points. Typical
++ * candidates for this are
+ *
+ * - angle points (i.e., points where the `in' and `out' direction
+ * differ greatly)
+ *
+ * - inflection points (i.e., where the `in' and `out' angles are the
+ * same, but the curvature changes sign) [currently, such points
+- * aren't handled in the auto-hinter]
++ * aren't handled specially in the auto-hinter]
+ *
+- * `af_glyph_hints_align_strong_points' is the function which takes
++ * `af_glyph_hints_align_strong_points' is the function that takes
+ * care of such situations; it is equivalent to the TrueType `IP'
+ * hinting instruction.
+ *
+@@ -220,26 +216,12 @@ FT_BEGIN_HEADER
+ AF_FLAG_CUBIC = 1 << 1,
+ AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
+
+- /* point extremum flags */
+- AF_FLAG_EXTREMA_X = 1 << 2,
+- AF_FLAG_EXTREMA_Y = 1 << 3,
+-
+- /* point roundness flags */
+- AF_FLAG_ROUND_X = 1 << 4,
+- AF_FLAG_ROUND_Y = 1 << 5,
+-
+ /* point touch flags */
+- AF_FLAG_TOUCH_X = 1 << 6,
+- AF_FLAG_TOUCH_Y = 1 << 7,
++ AF_FLAG_TOUCH_X = 1 << 2,
++ AF_FLAG_TOUCH_Y = 1 << 3,
+
+ /* candidates for weak interpolation have this flag set */
+- AF_FLAG_WEAK_INTERPOLATION = 1 << 8,
+-
+- /* all inflection points in the outline have this flag set */
+- AF_FLAG_INFLECTION = 1 << 9,
+-
+- /* the current point is very near to another one */
+- AF_FLAG_NEAR = 1 << 10
++ AF_FLAG_WEAK_INTERPOLATION = 1 << 4
+
+ } AF_Flags;
+
+@@ -247,10 +229,11 @@ FT_BEGIN_HEADER
+ /* edge hint flags */
+ typedef enum AF_Edge_Flags_
+ {
+- AF_EDGE_NORMAL = 0,
+- AF_EDGE_ROUND = 1 << 0,
+- AF_EDGE_SERIF = 1 << 1,
+- AF_EDGE_DONE = 1 << 2
++ AF_EDGE_NORMAL = 0,
++ AF_EDGE_ROUND = 1 << 0,
++ AF_EDGE_SERIF = 1 << 1,
++ AF_EDGE_DONE = 1 << 2,
++ AF_EDGE_NEUTRAL = 1 << 3 /* set if edge aligns to a neutral blue zone */
+
+ } AF_Edge_Flags;
+
+diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
+index e3a7742..36a3689 100644
+--- a/src/autofit/aflatin.c
++++ b/src/autofit/aflatin.c
+@@ -171,7 +171,15 @@
+ if ( error )
+ goto Exit;
+
++ /*
++ * We assume that the glyphs selected for the stem width
++ * computation are `featureless' enough so that the linking
++ * algorithm works fine without adjustments of its scoring
++ * function.
++ */
+ af_latin_hints_link_segments( hints,
++ 0,
++ NULL,
+ (AF_Dimension)dim );
+
+ seg = axhints->segments;
+@@ -298,6 +306,14 @@
+ have_flag = 1;
+ }
+
++ if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
++ {
++ if ( have_flag )
++ FT_TRACE5(( ", " ));
++ FT_TRACE5(( "neutral" ));
++ have_flag = 1;
++ }
++
+ if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
+ {
+ if ( have_flag )
+@@ -520,6 +536,13 @@
+ FT_Int last;
+ FT_Bool hit;
+
++ /* we intentionally declare these two variables */
++ /* outside of the loop since various compilers emit */
++ /* incorrect warning messages otherwise, talking about */
++ /* `possibly uninitialized variables' */
++ FT_Int p_first = 0; /* make compiler happy */
++ FT_Int p_last = 0;
++
+ FT_Bool left2right;
+
+
+@@ -552,7 +575,6 @@
+ {
+ FT_Bool l2r;
+ FT_Pos d;
+- FT_Int p_first, p_last;
+
+
+ if ( !hit )
+@@ -688,6 +710,13 @@
+ FT_CURVE_TAG( outline.tags[best_segment_last] ) !=
+ FT_CURVE_TAG_ON );
+
++ if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
++ {
++ /* only use flat segments for a neutral blue zone */
++ FT_TRACE5(( " (round, skipped)\n" ));
++ continue;
++ }
++
+ FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
+ }
+
+@@ -758,6 +787,8 @@
+ blue->flags = 0;
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+ blue->flags |= AF_LATIN_BLUE_TOP;
++ if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
++ blue->flags |= AF_LATIN_BLUE_NEUTRAL;
+
+ /*
+ * The following flag is used later to adjust the y and x scales
+@@ -1262,17 +1293,19 @@
+ /* this is the start of a new segment! */
+ segment_dir = (AF_Direction)point->out_dir;
+
+- /* clear all segment fields */
+ error = af_axis_hints_new_segment( axis, memory, &segment );
+ if ( error )
+ goto Exit;
+
+- segment[0] = seg0;
++ /* clear all segment fields */
++ segment[0] = seg0;
++
+ segment->dir = (FT_Char)segment_dir;
+ min_pos = max_pos = point->u;
+ segment->first = point;
+ segment->last = point;
+- on_edge = 1;
++
++ on_edge = 1;
+ }
+
+ point = point->next;
+@@ -1296,9 +1329,6 @@
+ FT_Pos last_v = last->v;
+
+
+- if ( first == last )
+- continue;
+-
+ if ( first_v < last_v )
+ {
+ AF_Point p;
+@@ -1337,31 +1367,44 @@
+ }
+
+
+- /* Link segments to form stems and serifs. */
++ /* Link segments to form stems and serifs. If `width_count' and */
++ /* `widths' are non-zero, use them to fine-tune the scoring function. */
+
+ FT_LOCAL_DEF( void )
+ af_latin_hints_link_segments( AF_GlyphHints hints,
++ FT_UInt width_count,
++ AF_WidthRec* widths,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+- FT_Pos len_threshold, len_score;
++ FT_Pos len_threshold, len_score, dist_score, max_width;
+ AF_Segment seg1, seg2;
+
+
++ if ( width_count )
++ max_width = widths[width_count - 1].org;
++ else
++ max_width = 0;
++
++ /* a heuristic value to set up a minimum value for overlapping */
+ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
+ if ( len_threshold == 0 )
+ len_threshold = 1;
+
++ /* a heuristic value to weight lengths */
+ len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
+
++ /* a heuristic value to weight distances (no call to */
++ /* AF_LATIN_CONSTANT needed, since we work on multiples */
++ /* of the stem width) */
++ dist_score = 3000;
++
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+- /* the fake segments are introduced to hint the metrics -- */
+- /* we must never link them to anything */
+- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
++ if ( seg1->dir != axis->major_dir )
+ continue;
+
+ /* search for stems having opposite directions, */
+@@ -1375,10 +1418,9 @@
+ if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 )
+ {
+ /* compute distance between the two segments */
+- FT_Pos dist = pos2 - pos1;
+- FT_Pos min = seg1->min_coord;
+- FT_Pos max = seg1->max_coord;
+- FT_Pos len, score;
++ FT_Pos min = seg1->min_coord;
++ FT_Pos max = seg1->max_coord;
++ FT_Pos len;
+
+
+ if ( min < seg2->min_coord )
+@@ -1388,15 +1430,49 @@
+ max = seg2->max_coord;
+
+ /* compute maximum coordinate difference of the two segments */
++ /* (this is, how much they overlap) */
+ len = max - min;
+ if ( len >= len_threshold )
+ {
+- /* small coordinate differences cause a higher score, and */
+- /* segments with a greater distance cause a higher score also */
+- score = dist + len_score / len;
++ /*
++ * The score is the sum of two demerits indicating the
++ * `badness' of a fit, measured along the segments' main axis
++ * and orthogonal to it, respectively.
++ *
++ * o The less overlapping along the main axis, the worse it
++ * is, causing a larger demerit.
++ *
++ * o The nearer the orthogonal distance to a stem width, the
++ * better it is, causing a smaller demerit. For simplicity,
++ * however, we only increase the demerit for values that
++ * exceed the largest stem width.
++ */
++
++ FT_Pos dist = pos2 - pos1;
++
++ FT_Pos dist_demerit, score;
++
++
++ if ( max_width )
++ {
++ /* distance demerits are based on multiples of `max_width'; */
++ /* we scale by 1024 for getting more precision */
++ FT_Pos delta = ( dist << 10 ) / max_width - ( 1 << 10 );
++
++
++ if ( delta > 10000 )
++ dist_demerit = 32000;
++ else if ( delta > 0 )
++ dist_demerit = delta * delta / dist_score;
++ else
++ dist_demerit = 0;
++ }
++ else
++ dist_demerit = dist; /* default if no widths available */
++
++ score = dist_demerit + len_score / len;
+
+ /* and we search for the smallest score */
+- /* of the sum of the two values */
+ if ( score < seg1->score )
+ {
+ seg1->score = score;
+@@ -1728,6 +1804,8 @@
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin_hints_detect_features( AF_GlyphHints hints,
++ FT_UInt width_count,
++ AF_WidthRec* widths,
+ AF_Dimension dim )
+ {
+ FT_Error error;
+@@ -1736,7 +1814,7 @@
+ error = af_latin_hints_compute_segments( hints, dim );
+ if ( !error )
+ {
+- af_latin_hints_link_segments( hints, dim );
++ af_latin_hints_link_segments( hints, width_count, widths, dim );
+
+ error = af_latin_hints_compute_edges( hints, dim );
+ }
+@@ -1765,8 +1843,9 @@
+ for ( ; edge < edge_limit; edge++ )
+ {
+ FT_UInt bb;
+- AF_Width best_blue = NULL;
+- FT_Pos best_dist; /* initial threshold */
++ AF_Width best_blue = NULL;
++ FT_Bool best_blue_is_neutral = 0;
++ FT_Pos best_dist; /* initial threshold */
+
+
+ /* compute the initial threshold as a fraction of the EM size */
+@@ -1780,24 +1859,26 @@
+ for ( bb = 0; bb < latin->blue_count; bb++ )
+ {
+ AF_LatinBlue blue = latin->blues + bb;
+- FT_Bool is_top_blue, is_major_dir;
++ FT_Bool is_top_blue, is_neutral_blue, is_major_dir;
+
+
+ /* skip inactive blue zones (i.e., those that are too large) */
+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
+
+- /* if it is a top zone, check for right edges -- if it is a bottom */
+- /* zone, check for left edges */
+- /* */
+- /* of course, that's for TrueType */
+- is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
+- is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+-
+- /* if it is a top zone, the edge must be against the major */
+- /* direction; if it is a bottom zone, it must be in the major */
+- /* direction */
+- if ( is_top_blue ^ is_major_dir )
++ /* if it is a top zone, check for right edges (against the major */
++ /* direction); if it is a bottom zone, check for left edges (in */
++ /* the major direction) -- this assumes the TrueType convention */
++ /* for the orientation of contours */
++ is_top_blue =
++ (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
++ is_neutral_blue =
++ (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0);
++ is_major_dir =
++ FT_BOOL( edge->dir == axis->major_dir );
++
++ /* neutral blue zones are handled for both directions */
++ if ( is_top_blue ^ is_major_dir || is_neutral_blue )
+ {
+ FT_Pos dist;
+
+@@ -1810,15 +1891,19 @@
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+- best_dist = dist;
+- best_blue = &blue->ref;
++ best_dist = dist;
++ best_blue = &blue->ref;
++ best_blue_is_neutral = is_neutral_blue;
+ }
+
+ /* now compare it to the overshoot position and check whether */
+ /* the edge is rounded, and whether the edge is over the */
+ /* reference position of a top zone, or under the reference */
+- /* position of a bottom zone */
+- if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
++ /* position of a bottom zone (provided we don't have a */
++ /* neutral blue zone) */
++ if ( edge->flags & AF_EDGE_ROUND &&
++ dist != 0 &&
++ !is_neutral_blue )
+ {
+ FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
+
+@@ -1832,8 +1917,9 @@
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+- best_dist = dist;
+- best_blue = &blue->shoot;
++ best_dist = dist;
++ best_blue = &blue->shoot;
++ best_blue_is_neutral = is_neutral_blue;
+ }
+ }
+ }
+@@ -1841,7 +1927,11 @@
+ }
+
+ if ( best_blue )
++ {
+ edge->blue_edge = best_blue;
++ if ( best_blue_is_neutral )
++ edge->flags |= AF_EDGE_NEUTRAL;
++ }
+ }
+ }
+
+@@ -2159,7 +2249,7 @@
+
+ FT_TRACE5(( " LINK: edge %d (opos=%.2f) linked to %.2f,"
+ " dist was %.2f, now %.2f\n",
+- stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
++ stem_edge - hints->axis[dim].edges, stem_edge->opos / 64.0,
+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ }
+
+@@ -2226,14 +2316,41 @@
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+- blue = edge->blue_edge;
+ edge1 = NULL;
+ edge2 = edge->link;
+
++ /*
++ * If a stem contains both a neutral and a non-neutral blue zone,
++ * skip the neutral one. Otherwise, outlines with different
++ * directions might be incorrectly aligned at the same vertical
++ * position.
++ *
++ * If we have two neutral blue zones, skip one of them.
++ *
++ */
++ if ( edge->blue_edge && edge2 && edge2->blue_edge )
++ {
++ FT_Byte neutral = edge->flags & AF_EDGE_NEUTRAL;
++ FT_Byte neutral2 = edge2->flags & AF_EDGE_NEUTRAL;
++
++
++ if ( ( neutral && neutral2 ) || neutral2 )
++ {
++ edge2->blue_edge = NULL;
++ edge2->flags &= ~AF_EDGE_NEUTRAL;
++ }
++ else if ( neutral )
++ {
++ edge->blue_edge = NULL;
++ edge->flags &= ~AF_EDGE_NEUTRAL;
++ }
++ }
++
++ blue = edge->blue_edge;
+ if ( blue )
+ edge1 = edge;
+
+- /* flip edges if the other stem is aligned to a blue zone */
++ /* flip edges if the other edge is aligned to a blue zone */
+ else if ( edge2 && edge2->blue_edge )
+ {
+ blue = edge2->blue_edge;
+@@ -2300,7 +2417,7 @@
+ /* this should not happen, but it's better to be safe */
+ if ( edge2->blue_edge )
+ {
+- FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2-edges ));
++ FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2 - edges ));
+
+ af_latin_align_linked_edge( hints, dim, edge2, edge );
+ edge->flags |= AF_EDGE_DONE;
+@@ -2689,6 +2806,8 @@
+ FT_Error error;
+ int dim;
+
++ AF_LatinAxis axis;
++
+
+ error = af_glyph_hints_reload( hints, outline );
+ if ( error )
+@@ -2702,14 +2821,22 @@
+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )
+ #endif
+ {
+- error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
++ axis = &metrics->axis[AF_DIMENSION_HORZ];
++ error = af_latin_hints_detect_features( hints,
++ axis->width_count,
++ axis->widths,
++ AF_DIMENSION_HORZ );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( AF_HINTS_DO_VERTICAL( hints ) )
+ {
+- error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
++ axis = &metrics->axis[AF_DIMENSION_VERT];
++ error = af_latin_hints_detect_features( hints,
++ axis->width_count,
++ axis->widths,
++ AF_DIMENSION_VERT );
+ if ( error )
+ goto Exit;
+
+diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
+index a958af3..2c0bfca 100644
+--- a/src/autofit/aflatin.h
++++ b/src/autofit/aflatin.h
+@@ -5,7 +5,7 @@
+ /* Auto-fitter hinting routines for latin writing system */
+ /* (specification). */
+ /* */
+-/* Copyright 2003-2007, 2009, 2011-2013 by */
++/* Copyright 2003-2007, 2009, 2011-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -53,6 +53,8 @@ FT_BEGIN_HEADER
+
+ #define AF_LATIN_IS_TOP_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
++#define AF_LATIN_IS_NEUTRAL_BLUE( b ) \
++ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
+ #define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )
+ #define AF_LATIN_IS_LONG_BLUE( b ) \
+@@ -63,10 +65,11 @@ FT_BEGIN_HEADER
+
+ enum
+ {
+- AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */
+- AF_LATIN_BLUE_TOP = 1 << 1, /* result of AF_LATIN_IS_TOP_BLUE */
+- AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
+- /* optimization */
++ AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */
++ AF_LATIN_BLUE_TOP = 1 << 1, /* set if we have a top blue zone */
++ AF_LATIN_BLUE_NEUTRAL = 1 << 2, /* set if we have neutral blue zone */
++ AF_LATIN_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment */
++ /* optimization */
+ AF_LATIN_BLUE_FLAG_MAX
+ };
+
+@@ -169,6 +172,8 @@ FT_BEGIN_HEADER
+
+ FT_LOCAL( void )
+ af_latin_hints_link_segments( AF_GlyphHints hints,
++ FT_UInt width_count,
++ AF_WidthRec* widths,
+ AF_Dimension dim );
+
+ FT_LOCAL( FT_Error )
+@@ -177,6 +182,8 @@ FT_BEGIN_HEADER
+
+ FT_LOCAL( FT_Error )
+ af_latin_hints_detect_features( AF_GlyphHints hints,
++ FT_UInt width_count,
++ AF_WidthRec* widths,
+ AF_Dimension dim );
+
+ /* */
+diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
+index 930fa98..07590b3 100644
+--- a/src/autofit/aflatin2.c
++++ b/src/autofit/aflatin2.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* Auto-fitter hinting routines for latin writing system (body). */
+ /* */
+-/* Copyright 2003-2013 by */
++/* Copyright 2003-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -890,9 +890,6 @@
+ FT_Pos last_v = last->v;
+
+
+- if ( first == last )
+- continue;
+-
+ if ( first_v < last_v )
+ {
+ p = first->prev;
+@@ -984,7 +981,7 @@
+ #ifdef AF_SORT_SEGMENTS
+ for ( seg1 = segments; seg1 < segment_mid; seg1++ )
+ {
+- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
++ if ( seg1->dir != axis->major_dir )
+ continue;
+
+ for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
+@@ -992,9 +989,7 @@
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+- /* the fake segments are introduced to hint the metrics -- */
+- /* we must never link them to anything */
+- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
++ if ( seg1->dir != axis->major_dir )
+ continue;
+
+ for ( seg2 = segments; seg2 < segment_limit; seg2++ )
+@@ -1194,9 +1189,10 @@
+
+ edge->first = seg;
+ edge->last = seg;
+- edge->fpos = seg->pos;
+ edge->dir = seg->dir;
+- edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
++ edge->fpos = seg->pos;
++ edge->opos = FT_MulFix( seg->pos, scale );
++ edge->pos = edge->opos;
+ seg->edge_next = seg;
+ }
+ else
+diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
+index 73bf832..181cf55 100644
+--- a/src/autofit/afmodule.c
++++ b/src/autofit/afmodule.c
+@@ -103,8 +103,8 @@
+ AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss];
+
+
+- if ( style_class->script == *fallback_script &&
+- style_class->coverage == AF_COVERAGE_DEFAULT )
++ if ( (FT_UInt)style_class->script == *fallback_script &&
++ style_class->coverage == AF_COVERAGE_DEFAULT )
+ {
+ module->fallback_style = ss;
+ break;
+diff --git a/src/autofit/afranges.c b/src/autofit/afranges.c
+index 3d919b5..139a4c1 100644
+--- a/src/autofit/afranges.c
++++ b/src/autofit/afranges.c
+@@ -21,51 +21,59 @@
+
+ const AF_Script_UniRangeRec af_cyrl_uniranges[] =
+ {
+- AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */
++ AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */
+ AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */
+ AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */
+ AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
++ const AF_Script_UniRangeRec af_deva_uniranges[] =
++ {
++ AF_UNIRANGE_REC( 0x0900UL, 0x097FUL ), /* Devanagari */
++ AF_UNIRANGE_REC( 0x20B9UL, 0x20B9UL ), /* (new) Rupee sign */
++ AF_UNIRANGE_REC( 0UL, 0UL )
++ };
++
+ const AF_Script_UniRangeRec af_grek_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */
+- AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */
++ AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_hebr_uniranges[] =
+ {
+- AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */
++ AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */
+ AF_UNIRANGE_REC( 0xFB1DUL, 0xFB4FUL ), /* Alphab. Present. Forms (Hebrew) */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_latn_uniranges[] =
+ {
+- AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */
+- AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */
+- AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */
+- AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */
+- AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */
+- AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */
+- AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */
+- AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */
+- AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */
++ AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */
++ AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */
++ AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */
++ AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */
++ AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */
++ AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */
++ AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */
++ AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */
++ AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */
+ AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */
+- AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */
+- AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */
+- AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */
+- AF_UNIRANGE_REC( 0x20A0UL, 0x20CFUL ), /* Currency Symbols */
+- AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */
+- AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */
+- AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */
+- AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */
+- AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */
+- AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */
+- AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */
+- AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */
++ AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */
++ AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */
++ AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */
++ AF_UNIRANGE_REC( 0x20A0UL, 0x20B8UL ), /* Currency Symbols ... */
++ AF_UNIRANGE_REC( 0x20BAUL, 0x20CFUL ), /* ... except new Rupee sign */
++ AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */
++ AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */
++ AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */
++ AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */
++ AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */
++ AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */
++ AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */
++ AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+@@ -82,12 +90,6 @@
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+- const AF_Script_UniRangeRec af_deva_uniranges[] =
+- {
+- AF_UNIRANGE_REC( 0x0900UL, 0x097FUL ), /* Devanagari */
+- AF_UNIRANGE_REC( 0UL, 0UL )
+- };
+-
+ const AF_Script_UniRangeRec af_gujr_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0A80UL, 0x0AFFUL ), /* Gujarati */
+diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h
+index ae20932..a418b05 100644
+--- a/src/autofit/afscript.h
++++ b/src/autofit/afscript.h
+@@ -31,6 +31,11 @@
+ HB_SCRIPT_CYRILLIC,
+ 0x43E, 0x41E, 0x0 ) /* оО */
+
++ SCRIPT( deva, DEVA,
++ "Devanagari",
++ HB_SCRIPT_DEVANAGARI,
++ 0x920, 0x935, 0x91F ) /* ठ व ट */
++
+ SCRIPT( grek, GREK,
+ "Greek",
+ HB_SCRIPT_GREEK,
+@@ -58,11 +63,6 @@
+ HB_SCRIPT_BENGALI,
+ 'o', 0x0, 0x0 ) /* XXX */
+
+- SCRIPT( deva, DEVA,
+- "Devanagari",
+- HB_SCRIPT_DEVANAGARI,
+- 'o', 0x0, 0x0 ) /* XXX */
+-
+ SCRIPT( gujr, GUJR,
+ "Gujarati",
+ HB_SCRIPT_GUJARATI,
+diff --git a/src/autofit/afstyles.h b/src/autofit/afstyles.h
+index 429da76..27fdd2e 100644
+--- a/src/autofit/afstyles.h
++++ b/src/autofit/afstyles.h
+@@ -81,7 +81,9 @@
+ DEFAULT )
+
+ META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" )
++
+ META_STYLE_LATIN( grek, GREK, "Greek" )
++
+ STYLE( hebr_dflt, HEBR_DFLT,
+ "Hebrew default style",
+ AF_WRITING_SYSTEM_LATIN,
+@@ -90,6 +92,13 @@
+ AF_COVERAGE_DEFAULT )
+ META_STYLE_LATIN( latn, LATN, "Latin" )
+
++ STYLE( deva_dflt, DEVA_DFLT,
++ "Devanagari default style",
++ AF_WRITING_SYSTEM_LATIN,
++ AF_SCRIPT_DEVA,
++ AF_BLUE_STRINGSET_DEVA,
++ AF_COVERAGE_DEFAULT )
++
+ #ifdef FT_OPTION_AUTOFIT2
+ STYLE( ltn2_dflt, LTN2_DFLT,
+ "Latin 2 default style",
+@@ -119,7 +128,6 @@
+ AF_COVERAGE_DEFAULT )
+
+ STYLE_DEFAULT_INDIC( beng, BENG, "Bengali" )
+- STYLE_DEFAULT_INDIC( deva, DEVA, "Devanagari" )
+ STYLE_DEFAULT_INDIC( gujr, GUJR, "Gujarati" )
+ STYLE_DEFAULT_INDIC( guru, GURU, "Gurmukhi" )
+ STYLE_DEFAULT_INDIC( knda, KNDA, "Kannada" )
+diff --git a/src/autofit/hbshim.c b/src/autofit/hbshim.c
+index 11fb743..cc04815 100644
+--- a/src/autofit/hbshim.c
++++ b/src/autofit/hbshim.c
+@@ -247,6 +247,7 @@
+ * (this is, not a single character is covered), we skip this coverage.
+ *
+ */
++ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
+ {
+ AF_Blue_Stringset bss = style_class->blue_stringset;
+ const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+@@ -328,8 +329,15 @@
+ * out whether a glyph gets shifted vertically, but this is something I
+ * would like to avoid if not really necessary.
+ *
++ * Note that we don't follow this logic for the default coverage.
++ * Complex scripts like Devanagari have mandatory GPOS features to
++ * position many glyph elements, using mark-to-base or mark-to-ligature
++ * tables; the number of glyphs missed due to condition (b) would be far
++ * too large.
++ *
+ */
+- hb_set_subtract( gsub_glyphs, gpos_glyphs );
++ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
++ hb_set_subtract( gsub_glyphs, gpos_glyphs );
+
+ #ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " glyphs without GPOS data (`*' means already assigned)" ));
+@@ -347,6 +355,12 @@
+ count++;
+ #endif
+
++ /* glyph indices returned by `hb_ot_layout_lookup_collect_glyphs' */
++ /* can be arbitrary: some fonts use fake indices for processing */
++ /* internal to GSUB or GPOS, which is fully valid */
++ if ( idx >= (hb_codepoint_t)globals->glyph_count )
++ continue;
++
+ if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
+ gstyles[idx] = (FT_Byte)style_class->style;
+ #ifdef FT_DEBUG_LEVEL_TRACE
+diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c
+index 8d3f383..349cb95 100644
+--- a/src/base/ftbbox.c
++++ b/src/base/ftbbox.c
+@@ -203,15 +203,48 @@
+ /* max :: The address of the current maximum. */
+ /* */
+ static FT_Pos
+- update_cubic_max( FT_Pos q1,
+- FT_Pos q2,
+- FT_Pos q3,
+- FT_Pos q4,
+- FT_Pos max )
++ cubic_peak( FT_Pos q1,
++ FT_Pos q2,
++ FT_Pos q3,
++ FT_Pos q4 )
+ {
+- /* for a cubic segment to possibly reach new maximum, at least */
+- /* one of its off-points must stay above the current value */
+- while ( q2 > max || q3 > max )
++ FT_Pos peak = 0;
++ FT_Int shift;
++
++ /* This function finds a peak of a cubic segment if it is above 0 */
++ /* using iterative bisection of the segment, or returns 0. */
++ /* The fixed-point arithmetic of bisection is inherently stable */
++ /* but may loose accuracy in the two lowest bits. To compensate, */
++ /* we upscale the segment if there is room. Large values may need */
++ /* to be downscaled to avoid overflows during bisection. */
++ /* It is called with either q2 or q3 positive, which is necessary */
++ /* for the peak to exist and avoids undefined FT_MSB. */
++
++ shift = 27 -
++ FT_MSB( FT_ABS( q1 ) | FT_ABS( q2 ) | FT_ABS( q3 ) | FT_ABS( q4 ) );
++
++ if ( shift > 0 )
++ {
++ /* upscaling too much just wastes time */
++ if ( shift > 2 )
++ shift = 2;
++
++ q1 <<= shift;
++ q2 <<= shift;
++ q3 <<= shift;
++ q4 <<= shift;
++ }
++ else
++ {
++ q1 >>= -shift;
++ q2 >>= -shift;
++ q3 >>= -shift;
++ q4 >>= -shift;
++ }
++
++ /* for a peak to exist above 0, the cubic segment must have */
++ /* at least one of its control off-points above 0. */
++ while ( q2 > 0 || q3 > 0 )
+ {
+ /* determine which half contains the maximum and split */
+ if ( q1 + q2 > q3 + q4 ) /* first half */
+@@ -240,17 +273,22 @@
+ /* check whether either end reached the maximum */
+ if ( q1 == q2 && q1 >= q3 )
+ {
+- max = q1;
++ peak = q1;
+ break;
+ }
+ if ( q3 == q4 && q2 <= q4 )
+ {
+- max = q4;
++ peak = q4;
+ break;
+ }
+ }
+
+- return max;
++ if ( shift > 0 )
++ peak >>= shift;
++ else
++ peak <<= -shift;
++
++ return peak;
+ }
+
+
+@@ -262,65 +300,17 @@
+ FT_Pos* min,
+ FT_Pos* max )
+ {
+- FT_Pos nmin, nmax;
+- FT_Int shift;
+-
+-
+ /* This function is only called when a control off-point is outside */
+- /* the bbox that contains all on-points. It finds a local extremum */
+- /* within the segment using iterative bisection of the segment. */
+- /* The fixed-point arithmetic of bisection is inherently stable */
+- /* but may loose accuracy in the two lowest bits. To compensate, */
+- /* we upscale the segment if there is room. Large values may need */
+- /* to be downscaled to avoid overflows during bisection. */
+- /* The control off-point outside the bbox is likely to have the top */
+- /* absolute value among arguments. */
+-
+- shift = 27 - FT_MSB( FT_ABS( p2 ) | FT_ABS( p3 ) );
+-
+- if ( shift > 0 )
+- {
+- /* upscaling too much just wastes time */
+- if ( shift > 2 )
+- shift = 2;
+-
+- p1 <<= shift;
+- p2 <<= shift;
+- p3 <<= shift;
+- p4 <<= shift;
+- nmin = *min << shift;
+- nmax = *max << shift;
+- }
+- else
+- {
+- p1 >>= -shift;
+- p2 >>= -shift;
+- p3 >>= -shift;
+- p4 >>= -shift;
+- nmin = *min >> -shift;
+- nmax = *max >> -shift;
+- }
++ /* the bbox that contains all on-points. So at least one of the */
++ /* conditions below holds and cubic_peak is called with at least one */
++ /* non-zero argument. */
+
+- nmax = update_cubic_max( p1, p2, p3, p4, nmax );
++ if ( p2 > *max || p3 > *max )
++ *max += cubic_peak( p1 - *max, p2 - *max, p3 - *max, p4 - *max );
+
+ /* now flip the signs to update the minimum */
+- nmin = -update_cubic_max( -p1, -p2, -p3, -p4, -nmin );
+-
+- if ( shift > 0 )
+- {
+- nmin >>= shift;
+- nmax >>= shift;
+- }
+- else
+- {
+- nmin <<= -shift;
+- nmax <<= -shift;
+- }
+-
+- if ( nmin < *min )
+- *min = nmin;
+- if ( nmax > *max )
+- *max = nmax;
++ if ( p2 < *min || p3 < *min )
++ *min -= cubic_peak( *min - p1, *min - p2, *min - p3, *min - p4 );
+ }
+
+
+diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
+index 5606745..158a428 100644
+--- a/src/base/ftbitmap.c
++++ b/src/base/ftbitmap.c
+@@ -378,11 +378,8 @@
+ static FT_Byte
+ ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra )
+ {
+- FT_Long a = bgra[3];
+- FT_Long b = bgra[0];
+- FT_Long g = bgra[1];
+- FT_Long r = bgra[2];
+- FT_Long l;
++ FT_UInt a = bgra[3];
++ FT_UInt l;
+
+
+ /* Short-circuit transparent color to avoid div-by-zero. */
+@@ -397,38 +394,30 @@
+ *
+ * http://accessibility.kde.org/hsl-adjusted.php
+ *
+- * We do the computation with integers only.
++ * We do the computation with integers only, applying a gamma of 2.0.
++ * We guarantee 32-bit arithmetic to avoid overflow but the resulting
++ * luminosity fits into 16 bits.
++ *
+ */
+
+- /* Undo premultification, get the number in a 16.16 form. */
+- b = FT_MulDiv( b, 65536, a );
+- g = FT_MulDiv( g, 65536, a );
+- r = FT_MulDiv( r, 65536, a );
+- a = a * 256;
+-
+- /* Apply gamma of 2.0 instead of 2.2. */
+- b = FT_MulFix( b, b );
+- g = FT_MulFix( g, g );
+- r = FT_MulFix( r, r );
+-
+- /* Apply coefficients. */
+- b = FT_MulFix( b, 4731 /* 0.0722 * 65536 */ );
+- g = FT_MulFix( g, 46871 /* 0.7152 * 65536 */ );
+- r = FT_MulFix( r, 13933 /* 0.2126 * 65536 */ );
+-
+- l = r + g + b;
++ l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
++ 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
++ 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16;
+
+ /*
+- * Final transparency can be determined this way:
++ * Final transparency can be determined as follows.
+ *
+ * - If alpha is zero, we want 0.
+ * - If alpha is zero and luminosity is zero, we want 255.
+ * - If alpha is zero and luminosity is one, we want 0.
+ *
+- * So the formula is a * (1 - l).
++ * So the formula is a * (1 - l) = a - l * a.
++ *
++ * We still need to undo premultiplication by dividing l by a*a.
++ *
+ */
+
+- return (FT_Byte)( FT_MulFix( 65535 - l, a ) >> 8 );
++ return (FT_Byte)( a - l / a );
+ }
+
+
+diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
+index 6e65583..d0c43e0 100644
+--- a/src/base/ftcalc.c
++++ b/src/base/ftcalc.c
+@@ -39,7 +39,8 @@
+ #include FT_INTERNAL_DEBUG_H
+ #include FT_INTERNAL_OBJECTS_H
+
+-#ifdef FT_MULFIX_INLINED
++
++#ifdef FT_MULFIX_ASSEMBLER
+ #undef FT_MulFix
+ #endif
+
+@@ -67,6 +68,16 @@
+ #define FT_COMPONENT trace_calc
+
+
++ /* transfer sign leaving a positive number */
++#define FT_MOVE_SIGN( x, s ) \
++ FT_BEGIN_STMNT \
++ if ( x < 0 ) \
++ { \
++ x = -x; \
++ s = -s; \
++ } \
++ FT_END_STMNT
++
+ /* The following three functions are available regardless of whether */
+ /* FT_LONG64 is defined. */
+
+@@ -99,6 +110,7 @@
+ : -((-a) & ~0xFFFFL );
+ }
+
++#ifndef FT_MSB
+
+ FT_BASE_DEF ( FT_Int )
+ FT_MSB( FT_UInt32 z )
+@@ -106,27 +118,27 @@
+ FT_Int shift = 0;
+
+ /* determine msb bit index in `shift' */
+- if ( z >= ( 1L << 16 ) )
++ if ( z & 0xFFFF0000U )
+ {
+ z >>= 16;
+ shift += 16;
+ }
+- if ( z >= ( 1L << 8 ) )
++ if ( z & 0x0000FF00U )
+ {
+ z >>= 8;
+ shift += 8;
+ }
+- if ( z >= ( 1L << 4 ) )
++ if ( z & 0x000000F0U )
+ {
+ z >>= 4;
+ shift += 4;
+ }
+- if ( z >= ( 1L << 2 ) )
++ if ( z & 0x0000000CU )
+ {
+ z >>= 2;
+ shift += 2;
+ }
+- if ( z >= ( 1L << 1 ) )
++ if ( z & 0x00000002U )
+ {
+ /* z >>= 1; */
+ shift += 1;
+@@ -135,6 +147,8 @@
+ return shift;
+ }
+
++#endif /* !FT_MSB */
++
+
+ /* documentation is in ftcalc.h */
+
+@@ -162,14 +176,13 @@
+ FT_Long b,
+ FT_Long c )
+ {
+- FT_Int s;
++ FT_Int s = 1;
+ FT_Long d;
+
+
+- s = 1;
+- if ( a < 0 ) { a = -a; s = -1; }
+- if ( b < 0 ) { b = -b; s = -s; }
+- if ( c < 0 ) { c = -c; s = -s; }
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
++ FT_MOVE_SIGN( c, s );
+
+ d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
+ : 0x7FFFFFFFL );
+@@ -185,14 +198,13 @@
+ FT_Long b,
+ FT_Long c )
+ {
+- FT_Int s;
++ FT_Int s = 1;
+ FT_Long d;
+
+
+- s = 1;
+- if ( a < 0 ) { a = -a; s = -1; }
+- if ( b < 0 ) { b = -b; s = -s; }
+- if ( c < 0 ) { c = -c; s = -s; }
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
++ FT_MOVE_SIGN( c, s );
+
+ d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
+ : 0x7FFFFFFFL );
+@@ -217,17 +229,8 @@
+ FT_Long c;
+
+
+- if ( a < 0 )
+- {
+- a = -a;
+- s = -1;
+- }
+-
+- if ( b < 0 )
+- {
+- b = -b;
+- s = -s;
+- }
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
+
+ c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
+
+@@ -243,30 +246,17 @@
+ FT_DivFix( FT_Long a,
+ FT_Long b )
+ {
+- FT_Int32 s;
+- FT_UInt32 q;
++ FT_Int s = 1;
++ FT_Long q;
+
+
+- s = 1;
+- if ( a < 0 )
+- {
+- a = -a;
+- s = -1;
+- }
+- if ( b < 0 )
+- {
+- b = -b;
+- s = -s;
+- }
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
+
+- if ( b == 0 )
+- /* check for division by 0 */
+- q = 0x7FFFFFFFL;
+- else
+- /* compute result directly */
+- q = (FT_UInt32)( ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b );
++ q = (FT_Long)( b > 0 ? ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b
++ : 0x7FFFFFFFL );
+
+- return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
++ return ( s < 0 ? -q : q );
+ }
+
+
+@@ -314,25 +304,30 @@
+ FT_Int i;
+
+
+- q = 0;
+- r = hi;
+-
+- if ( r >= y )
++ if ( hi >= y )
+ return (FT_UInt32)0x7FFFFFFFL;
+
+- i = 32;
++ /* We shift as many bits as we can into the high register, perform */
++ /* 32-bit division with modulo there, then work through the remaining */
++ /* bits with long division. This optimization is especially noticeable */
++ /* for smaller dividends that barely use the high register. */
++
++ i = 31 - FT_MSB( hi );
++ r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i; /* left 64-bit shift */
++ q = r / y;
++ r -= q * y; /* remainder */
++
++ i = 32 - i; /* bits remaining in low register */
+ do
+ {
+- r <<= 1;
+ q <<= 1;
+- r |= lo >> 31;
++ r = ( r << 1 ) | ( lo >> 31 ); lo <<= 1;
+
+ if ( r >= y )
+ {
+ r -= y;
+ q |= 1;
+ }
+- lo <<= 1;
+ } while ( --i );
+
+ return q;
+@@ -344,7 +339,7 @@
+ FT_Int64* y,
+ FT_Int64 *z )
+ {
+- register FT_UInt32 lo, hi;
++ FT_UInt32 lo, hi;
+
+
+ lo = x->lo + y->lo;
+@@ -355,58 +350,93 @@
+ }
+
+
+- /* documentation is in freetype.h */
+-
+- /* The FT_MulDiv function has been optimized thanks to ideas from */
+- /* Graham Asher. The trick is to optimize computation when everything */
+- /* fits within 32-bits (a rather common case). */
++ /* The FT_MulDiv function has been optimized thanks to ideas from */
++ /* Graham Asher and Alexei Podtelezhnikov. The trick is to optimize */
++ /* a rather common case when everything fits within 32-bits. */
++ /* */
++ /* We compute 'a*b+c/2', then divide it by 'c' (all positive values). */
++ /* */
++ /* The product of two positive numbers never exceeds the square of */
++ /* its mean values. Therefore, we always avoid the overflow by */
++ /* imposing */
++ /* */
++ /* (a + b) / 2 <= sqrt(X - c/2) , */
+ /* */
+- /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */
++ /* where X = 2^32 - 1, the maximum unsigned 32-bit value, and using */
++ /* unsigned arithmetic. Now we replace `sqrt' with a linear function */
++ /* that is smaller or equal for all values of c in the interval */
++ /* [0;X/2]; it should be equal to sqrt(X) and sqrt(3X/4) at the */
++ /* endpoints. Substituting the linear solution and explicit numbers */
++ /* we get */
+ /* */
+- /* 46340 is FLOOR(SQRT(2^31-1)). */
++ /* a + b <= 131071.99 - c / 122291.84 . */
+ /* */
+- /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */
++ /* In practice, we should use a faster and even stronger inequality */
+ /* */
+- /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */
++ /* a + b <= 131071 - (c >> 16) */
+ /* */
+- /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */
++ /* or, alternatively, */
+ /* */
+- /* and 2*0x157F0 = 176096 */
++ /* a + b <= 129894 - (c >> 17) . */
+ /* */
++ /* FT_MulFix, on the other hand, is optimized for a small value of */
++ /* the first argument, when the second argument can be much larger. */
++ /* This can be achieved by scaling the second argument and the limit */
++ /* in the above inequalities. For example, */
++ /* */
++ /* a + (b >> 8) <= (131071 >> 4) */
++ /* */
++ /* covers the practical range of use. The actual test below is a bit */
++ /* tighter to avoid the border case overflows. */
++ /* */
++ /* In the case of FT_DivFix, the exact overflow check */
++ /* */
++ /* a << 16 <= X - c/2 */
++ /* */
++ /* is scaled down by 2^16 and we use */
++ /* */
++ /* a <= 65535 - (c >> 17) . */
++
++ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+- long s;
++ FT_Int s = 1;
+
+
+ /* XXX: this function does not allow 64-bit arguments */
+ if ( a == 0 || b == c )
+ return a;
+
+- s = a; a = FT_ABS( a );
+- s ^= b; b = FT_ABS( b );
+- s ^= c; c = FT_ABS( c );
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
++ FT_MOVE_SIGN( c, s );
+
+- if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
+- a = ( a * b + ( c >> 1 ) ) / c;
++ if ( c == 0 )
++ a = 0x7FFFFFFFL;
++
++ else if ( (FT_ULong)a + b <= 129894UL - ( c >> 17 ) )
++ a = ( (FT_ULong)a * b + ( c >> 1 ) ) / c;
+
+- else if ( (FT_Int32)c > 0 )
++ else
+ {
+ FT_Int64 temp, temp2;
+
+
+- ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
++ ft_multo64( a, b, &temp );
+
+ temp2.hi = 0;
+- temp2.lo = (FT_UInt32)(c >> 1);
++ temp2.lo = c >> 1;
++
+ FT_Add64( &temp, &temp2, &temp );
+- a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
++
++ /* last attempt to ditch long division */
++ a = temp.hi == 0 ? temp.lo / c
++ : ft_div64by32( temp.hi, temp.lo, c );
+ }
+- else
+- a = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -a : a );
+ }
+@@ -417,29 +447,33 @@
+ FT_Long b,
+ FT_Long c )
+ {
+- long s;
++ FT_Int s = 1;
+
+
+ if ( a == 0 || b == c )
+ return a;
+
+- s = a; a = FT_ABS( a );
+- s ^= b; b = FT_ABS( b );
+- s ^= c; c = FT_ABS( c );
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
++ FT_MOVE_SIGN( c, s );
+
+- if ( a <= 46340L && b <= 46340L && c > 0 )
+- a = a * b / c;
++ if ( c == 0 )
++ a = 0x7FFFFFFFL;
++
++ else if ( (FT_ULong)a + b <= 131071UL )
++ a = (FT_ULong)a * b / c;
+
+- else if ( (FT_Int32)c > 0 )
++ else
+ {
+ FT_Int64 temp;
+
+
+- ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
+- a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
++ ft_multo64( a, b, &temp );
++
++ /* last attempt to ditch long division */
++ a = temp.hi == 0 ? temp.lo / c
++ : ft_div64by32( temp.hi, temp.lo, c );
+ }
+- else
+- a = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -a : a );
+ }
+@@ -497,7 +531,7 @@
+ ua = (FT_ULong)a;
+ ub = (FT_ULong)b;
+
+- if ( ua <= 2048 && ub <= 1048576L )
++ if ( ua + ( ub >> 8 ) <= 8190UL )
+ ua = ( ua * ub + 0x8000U ) >> 16;
+ else
+ {
+@@ -515,20 +549,20 @@
+
+ #else /* 0 */
+
+- FT_Long s;
++ FT_Int s = 1;
+ FT_ULong ua, ub;
+
+
+ if ( a == 0 || b == 0x10000L )
+ return a;
+
+- s = a; a = FT_ABS( a );
+- s ^= b; b = FT_ABS( b );
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
+
+ ua = (FT_ULong)a;
+ ub = (FT_ULong)b;
+
+- if ( ua <= 2048 && ub <= 1048576L )
++ if ( ua + ( ub >> 8 ) <= 8190UL )
+ ua = ( ua * ub + 0x8000UL ) >> 16;
+ else
+ {
+@@ -552,23 +586,24 @@
+ FT_DivFix( FT_Long a,
+ FT_Long b )
+ {
+- FT_Int32 s;
+- FT_UInt32 q;
++ FT_Int s = 1;
++ FT_Long q;
+
+
+ /* XXX: this function does not allow 64-bit arguments */
+- s = (FT_Int32)a; a = FT_ABS( a );
+- s ^= (FT_Int32)b; b = FT_ABS( b );
+
+- if ( (FT_UInt32)b == 0 )
++ FT_MOVE_SIGN( a, s );
++ FT_MOVE_SIGN( b, s );
++
++ if ( b == 0 )
+ {
+ /* check for division by 0 */
+- q = (FT_UInt32)0x7FFFFFFFL;
++ q = 0x7FFFFFFFL;
+ }
+- else if ( ( a >> 16 ) == 0 )
++ else if ( a <= 65535L - ( b >> 17 ) )
+ {
+ /* compute result directly */
+- q = (FT_UInt32)( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / (FT_UInt32)b;
++ q = (FT_Long)( ( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / b );
+ }
+ else
+ {
+@@ -576,138 +611,18 @@
+ FT_Int64 temp, temp2;
+
+
+- temp.hi = (FT_Int32)( a >> 16 );
+- temp.lo = (FT_UInt32)a << 16;
++ temp.hi = a >> 16;
++ temp.lo = a << 16;
+ temp2.hi = 0;
+- temp2.lo = (FT_UInt32)( b >> 1 );
+- FT_Add64( &temp, &temp2, &temp );
+- q = ft_div64by32( temp.hi, temp.lo, (FT_Int32)b );
+- }
+-
+- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+- }
++ temp2.lo = b >> 1;
+
+-
+-#if 0
+-
+- /* documentation is in ftcalc.h */
+-
+- FT_EXPORT_DEF( void )
+- FT_MulTo64( FT_Int32 x,
+- FT_Int32 y,
+- FT_Int64 *z )
+- {
+- FT_Int32 s;
+-
+-
+- s = x; x = FT_ABS( x );
+- s ^= y; y = FT_ABS( y );
+-
+- ft_multo64( x, y, z );
+-
+- if ( s < 0 )
+- {
+- z->lo = (FT_UInt32)-(FT_Int32)z->lo;
+- z->hi = ~z->hi + !( z->lo );
+- }
+- }
+-
+-
+- /* apparently, the second version of this code is not compiled correctly */
+- /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */
+-
+-#if 1
+-
+- FT_EXPORT_DEF( FT_Int32 )
+- FT_Div64by32( FT_Int64* x,
+- FT_Int32 y )
+- {
+- FT_Int32 s;
+- FT_UInt32 q, r, i, lo;
+-
+-
+- s = x->hi;
+- if ( s < 0 )
+- {
+- x->lo = (FT_UInt32)-(FT_Int32)x->lo;
+- x->hi = ~x->hi + !x->lo;
+- }
+- s ^= y; y = FT_ABS( y );
+-
+- /* Shortcut */
+- if ( x->hi == 0 )
+- {
+- if ( y > 0 )
+- q = x->lo / y;
+- else
+- q = 0x7FFFFFFFL;
+-
+- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+- }
+-
+- r = x->hi;
+- lo = x->lo;
+-
+- if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
+- return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
+- /* Return Max/Min Int32 if division overflow. */
+- /* This includes division by zero! */
+- q = 0;
+- for ( i = 0; i < 32; i++ )
+- {
+- r <<= 1;
+- q <<= 1;
+- r |= lo >> 31;
+-
+- if ( r >= (FT_UInt32)y )
+- {
+- r -= y;
+- q |= 1;
+- }
+- lo <<= 1;
+- }
+-
+- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+- }
+-
+-#else /* 0 */
+-
+- FT_EXPORT_DEF( FT_Int32 )
+- FT_Div64by32( FT_Int64* x,
+- FT_Int32 y )
+- {
+- FT_Int32 s;
+- FT_UInt32 q;
+-
+-
+- s = x->hi;
+- if ( s < 0 )
+- {
+- x->lo = (FT_UInt32)-(FT_Int32)x->lo;
+- x->hi = ~x->hi + !x->lo;
+- }
+- s ^= y; y = FT_ABS( y );
+-
+- /* Shortcut */
+- if ( x->hi == 0 )
+- {
+- if ( y > 0 )
+- q = ( x->lo + ( y >> 1 ) ) / y;
+- else
+- q = 0x7FFFFFFFL;
+-
+- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
++ FT_Add64( &temp, &temp2, &temp );
++ q = (FT_Long)ft_div64by32( temp.hi, temp.lo, b );
+ }
+
+- q = ft_div64by32( x->hi, x->lo, y );
+-
+- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
++ return ( s < 0 ? -q : q );
+ }
+
+-#endif /* 0 */
+-
+-#endif /* 0 */
+-
+
+ #endif /* FT_LONG64 */
+
+diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
+index 852fb32..4aefb68 100644
+--- a/src/base/ftlcdfil.c
++++ b/src/base/ftlcdfil.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* FreeType API for color filtering of subpixel bitmap glyphs (body). */
+ /* */
+-/* Copyright 2006, 2008-2010, 2013 by */
++/* Copyright 2006, 2008-2010, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -46,9 +46,12 @@
+ FT_Byte* line = bitmap->buffer;
+
+
++ /* `fir' and `pix' must be at least 32 bit wide, since the sum of */
++ /* the values in `weights' can exceed 0xFF */
++
+ for ( ; height > 0; height--, line += bitmap->pitch )
+ {
+- FT_UInt fir[5];
++ FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
+ FT_UInt val1, xx;
+
+
+@@ -57,7 +60,6 @@
+ fir[1] = weights[3] * val1;
+ fir[2] = weights[4] * val1;
+ fir[3] = 0;
+- fir[4] = 0;
+
+ val1 = line[1];
+ fir[0] += weights[1] * val1;
+@@ -78,7 +80,7 @@
+ fir[3] = weights[4] * val;
+
+ pix >>= 8;
+- pix |= -( pix >> 8 );
++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
+ line[xx - 2] = (FT_Byte)pix;
+ }
+
+@@ -87,11 +89,11 @@
+
+
+ pix = fir[0] >> 8;
+- pix |= -( pix >> 8 );
++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
+ line[xx - 2] = (FT_Byte)pix;
+
+ pix = fir[1] >> 8;
+- pix |= -( pix >> 8 );
++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
+ line[xx - 1] = (FT_Byte)pix;
+ }
+ }
+@@ -107,7 +109,7 @@
+ for ( ; width > 0; width--, column++ )
+ {
+ FT_Byte* col = column;
+- FT_UInt fir[5];
++ FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
+ FT_UInt val1, yy;
+
+
+@@ -116,7 +118,6 @@
+ fir[1] = weights[3] * val1;
+ fir[2] = weights[4] * val1;
+ fir[3] = 0;
+- fir[4] = 0;
+ col += pitch;
+
+ val1 = col[0];
+@@ -139,7 +140,7 @@
+ fir[3] = weights[4] * val;
+
+ pix >>= 8;
+- pix |= -( pix >> 8 );
++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
+ col[-2 * pitch] = (FT_Byte)pix;
+ col += pitch;
+ }
+@@ -149,11 +150,11 @@
+
+
+ pix = fir[0] >> 8;
+- pix |= -( pix >> 8 );
++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
+ col[-2 * pitch] = (FT_Byte)pix;
+
+ pix = fir[1] >> 8;
+- pix |= -( pix >> 8 );
++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
+ col[-pitch] = (FT_Byte)pix;
+ }
+ }
+diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
+index 6f32336..cc56105 100644
+--- a/src/base/ftobjs.c
++++ b/src/base/ftobjs.c
+@@ -4881,6 +4881,8 @@
+ *p_arg1 = subg->arg1;
+ *p_arg2 = subg->arg2;
+ *p_transform = subg->transform;
++
++ error = FT_Err_Ok;
+ }
+
+ return error;
+diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
+index 4a39dcd..632b6d2 100644
+--- a/src/base/ftoutln.c
++++ b/src/base/ftoutln.c
+@@ -1045,6 +1045,10 @@
+
+ FT_Outline_Get_CBox( outline, &cbox );
+
++ /* Handle collapsed outlines to avoid undefined FT_MSB. */
++ if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax )
++ return FT_ORIENTATION_NONE;
++
+ xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14;
+ xshift = FT_MAX( xshift, 0 );
+
+diff --git a/src/base/fttrigon.c b/src/base/fttrigon.c
+index 4ffdcb7..e3ce8a6 100644
+--- a/src/base/fttrigon.c
++++ b/src/base/fttrigon.c
+@@ -111,6 +111,7 @@
+ #endif /* !FT_LONG64 */
+
+
++ /* undefined and never called for zero vector */
+ static FT_Int
+ ft_trig_prenorm( FT_Vector* vec )
+ {
+diff --git a/src/base/ftutil.c b/src/base/ftutil.c
+index 879d027..9f37189 100644
+--- a/src/base/ftutil.c
++++ b/src/base/ftutil.c
+@@ -411,26 +411,4 @@
+ }
+
+
+- FT_BASE_DEF( FT_UInt32 )
+- ft_highpow2( FT_UInt32 value )
+- {
+- FT_UInt32 value2;
+-
+-
+- /*
+- * We simply clear the lowest bit in each iteration. When
+- * we reach 0, we know that the previous value was our result.
+- */
+- for ( ;; )
+- {
+- value2 = value & (value - 1); /* clear lowest bit */
+- if ( value2 == 0 )
+- break;
+-
+- value = value2;
+- }
+- return value;
+- }
+-
+-
+ /* END */
+diff --git a/src/bdf/bdfdrivr.c b/src/bdf/bdfdrivr.c
+index 5a1c296..d7649ab 100644
+--- a/src/bdf/bdfdrivr.c
++++ b/src/bdf/bdfdrivr.c
+@@ -182,7 +182,7 @@ THE SOFTWARE.
+ }
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FT_CMap_ClassRec bdf_cmap_class =
+ {
+ sizeof ( BDF_CMapRec ),
+diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c
+index 84d336d..01be88c 100644
+--- a/src/cache/ftcbasic.c
++++ b/src/cache/ftcbasic.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* The FreeType basic cache interface (body). */
+ /* */
+-/* Copyright 2003-2007, 2009-2011, 2013 by */
++/* Copyright 2003-2007, 2009-2011, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -229,7 +229,7 @@
+ *
+ */
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FTC_IFamilyClassRec ftc_basic_image_family_class =
+ {
+ {
+@@ -243,7 +243,7 @@
+ };
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FTC_GCacheClassRec ftc_basic_image_cache_class =
+ {
+ {
+@@ -415,7 +415,7 @@
+ *
+ */
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
+ {
+ {
+@@ -430,7 +430,7 @@
+ };
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
+ {
+ {
+diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c
+index 848349b..b2e9609 100644
+--- a/src/cache/ftccmap.c
++++ b/src/cache/ftccmap.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* FreeType CharMap cache (body) */
+ /* */
+-/* Copyright 2000-2013 by */
++/* Copyright 2000-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -202,7 +202,7 @@
+ /*************************************************************************/
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FTC_CacheClassRec ftc_cmap_cache_class =
+ {
+ ftc_cmap_node_new,
+diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c
+index 4eb2c5b..a65f94d 100644
+--- a/src/cache/ftcmanag.c
++++ b/src/cache/ftcmanag.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* FreeType Cache Manager (body). */
+ /* */
+-/* Copyright 2000-2006, 2008-2010, 2013 by */
++/* Copyright 2000-2006, 2008-2010, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -151,7 +151,7 @@
+ }
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FTC_MruListClassRec ftc_size_list_class =
+ {
+ sizeof ( FTC_SizeNodeRec ),
+@@ -290,7 +290,7 @@
+ }
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FTC_MruListClassRec ftc_face_list_class =
+ {
+ sizeof ( FTC_FaceNodeRec),
+diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c
+index 6e99dc2..3d2c22a 100644
+--- a/src/cff/cf2font.c
++++ b/src/cff/cf2font.c
+@@ -105,6 +105,7 @@
+ /* adjusting for emRatio converts darkenAmount to character */
+ /* space (font units). */
+ CF2_Fixed stemWidthPer1000, scaledStem;
++ FT_Int logBase2;
+
+
+ *darkenAmount = 0;
+@@ -131,26 +132,33 @@
+ /* convert from true character space to 1000 unit character space; */
+ /* add synthetic emboldening effect */
+
+- /* we have to assure that the computation of `scaledStem' */
+- /* and `stemWidthPer1000' don't overflow */
++ /* `stemWidthPer1000' will not overflow for a legitimate font */
+
+ stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
+
+- if ( emRatio > CF2_FIXED_ONE &&
+- stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
+- {
+- stemWidthPer1000 = 0; /* to pacify compiler */
+- scaledStem = cf2_intToFixed( x4 );
+- }
++ /* `scaledStem' can easily overflow, so we must clamp its maximum */
++ /* value; the test doesn't need to be precise, but must be */
++ /* conservative. The clamp value (default 2333) where */
++ /* `darkenAmount' is zero is well below the overflow value of */
++ /* 32767. */
++ /* */
++ /* FT_MSB computes the integer part of the base 2 logarithm. The */
++ /* number of bits for the product is 1 or 2 more than the sum of */
++ /* logarithms; remembering that the 16 lowest bits of the fraction */
++ /* are dropped this is correct to within a factor of almost 4. */
++ /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and */
++ /* is flagged as possible overflow because 0xff.ffff * 0xff.ffff = */
++ /* 0xffff.fe00 is also 23+23. */
++
++ logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) +
++ FT_MSB( (FT_UInt32)ppem );
++
++ if ( logBase2 >= 46 )
++ /* possible overflow */
++ scaledStem = cf2_intToFixed( x4 );
+ else
+- {
+ scaledStem = FT_MulFix( stemWidthPer1000, ppem );
+
+- if ( ppem > CF2_FIXED_ONE &&
+- scaledStem <= stemWidthPer1000 )
+- scaledStem = cf2_intToFixed( x4 );
+- }
+-
+ /* now apply the darkening parameters */
+
+ if ( scaledStem < cf2_intToFixed( x1 ) )
+diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c
+index 5853d77..81049f4 100644
+--- a/src/cff/cf2hints.c
++++ b/src/cff/cf2hints.c
+@@ -1560,7 +1560,7 @@
+ {
+ /* -y */
+ *x = -glyphpath->xOffset;
+- *y = glyphpath->xOffset;
++ *y = glyphpath->yOffset;
+ }
+ else
+ {
+diff --git a/src/gzip/inftrees.c b/src/gzip/inftrees.c
+index ef53652..56f52b1 100644
+--- a/src/gzip/inftrees.c
++++ b/src/gzip/inftrees.c
+@@ -115,16 +115,16 @@ uIntf *v /* working area: values in order of bit length */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+- register uInt i; /* counter, current code */
+- register uInt j; /* counter */
+- register int k; /* number of bits in current code */
++ uInt i; /* counter, current code */
++ uInt j; /* counter */
++ int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
+- register uIntf *p; /* pointer into c[], b[], or v[] */
++ uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+- register int w; /* bits before this table == (l * h) */
++ int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c
+index 748cbca..5183f6f 100644
+--- a/src/pcf/pcfdrivr.c
++++ b/src/pcf/pcfdrivr.c
+@@ -2,7 +2,7 @@
+
+ FreeType font driver for pcf files
+
+- Copyright (C) 2000-2004, 2006-2011, 2013 by
++ Copyright (C) 2000-2004, 2006-2011, 2013, 2014 by
+ Francesco Zappa Nardelli
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -189,7 +189,7 @@ THE SOFTWARE.
+ }
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FT_CMap_ClassRec pcf_cmap_class =
+ {
+ sizeof ( PCF_CMapRec ),
+diff --git a/src/pfr/pfrdrivr.c b/src/pfr/pfrdrivr.c
+index 4c43947..188aa0d 100644
+--- a/src/pfr/pfrdrivr.c
++++ b/src/pfr/pfrdrivr.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* FreeType PFR driver interface (body). */
+ /* */
+-/* Copyright 2002-2004, 2006, 2008, 2010, 2011, 2013 by */
++/* Copyright 2002-2004, 2006, 2008, 2010, 2011, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -134,7 +134,7 @@
+ }
+
+
+- FT_CALLBACK_TABLE_DEF
++ static
+ const FT_Service_PfrMetricsRec pfr_metrics_service_rec =
+ {
+ pfr_get_metrics,
+diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c
+index 194d2df..0c89242 100644
+--- a/src/pfr/pfrobjs.c
++++ b/src/pfr/pfrobjs.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* FreeType PFR object methods (body). */
+ /* */
+-/* Copyright 2002-2008, 2010-2011, 2013 by */
++/* Copyright 2002-2008, 2010-2011, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -23,6 +23,7 @@
+ #include "pfrsbit.h"
+ #include FT_OUTLINE_H
+ #include FT_INTERNAL_DEBUG_H
++#include FT_INTERNAL_CALC_H
+ #include FT_TRUETYPE_IDS_H
+
+ #include "pfrerror.h"
+@@ -515,7 +516,7 @@
+ {
+ FT_UInt count = item->pair_count;
+ FT_UInt size = item->pair_size;
+- FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count );
++ FT_UInt power = 1 << FT_MSB( count );
+ FT_UInt probe = power * size;
+ FT_UInt extra = count - power;
+ FT_Byte* base = stream->cursor;
+diff --git a/src/psaux/psconv.c b/src/psaux/psconv.c
+index d0d8861..7792a62 100644
+--- a/src/psaux/psconv.c
++++ b/src/psaux/psconv.c
+@@ -250,7 +250,8 @@
+ if ( c < 0 || c >= 10 )
+ break;
+
+- if ( decimal < 0xCCCCCCCL )
++ /* only add digit if we don't overflow */
++ if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL )
+ {
+ decimal = decimal * 10 + c;
+
+diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
+index ddecc80..abbecb7 100644
+--- a/src/raster/ftraster.c
++++ b/src/raster/ftraster.c
+@@ -2284,6 +2284,8 @@
+ Long e1, e2;
+ Byte* target;
+
++ Int dropOutControl = left->flags & 7;
++
+ FT_UNUSED( y );
+ FT_UNUSED( left );
+ FT_UNUSED( right );
+@@ -2293,7 +2295,8 @@
+
+ e1 = TRUNC( CEILING( x1 ) );
+
+- if ( x2 - x1 - ras.precision <= ras.precision_jitter )
++ if ( dropOutControl != 2 &&
++ x2 - x1 - ras.precision <= ras.precision_jitter )
+ e2 = e1;
+ else
+ e2 = TRUNC( FLOOR( x2 ) );
+diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
+index 878de1f..9afbe5a 100644
+--- a/src/sfnt/pngshim.c
++++ b/src/sfnt/pngshim.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* PNG Bitmap glyph support. */
+ /* */
+-/* Copyright 2013 by Google, Inc. */
++/* Copyright 2013, 2014 by Google, Inc. */
+ /* Written by Stuart Gill and Behdad Esfahbod. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -129,7 +129,7 @@
+
+ *error = FT_THROW( Out_Of_Memory );
+ #ifdef PNG_SETJMP_SUPPORTED
+- longjmp( png_jmpbuf( png ), 1 );
++ ft_longjmp( png_jmpbuf( png ), 1 );
+ #endif
+ /* if we get here, then we have no choice but to abort ... */
+ }
+diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
+index a31c77c..44aa467 100644
+--- a/src/sfnt/sfobjs.c
++++ b/src/sfnt/sfobjs.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* SFNT object management (base). */
+ /* */
+-/* Copyright 1996-2008, 2010-2013 by */
++/* Copyright 1996-2008, 2010-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -348,29 +348,22 @@
+ }
+
+
+-#define WRITE_BYTE( p, v ) \
+- do \
+- { \
+- *(p)++ = (v) >> 0; \
+- \
++#define WRITE_USHORT( p, v ) \
++ do \
++ { \
++ *(p)++ = (FT_Byte)( (v) >> 8 ); \
++ *(p)++ = (FT_Byte)( (v) >> 0 ); \
++ \
+ } while ( 0 )
+
+-#define WRITE_USHORT( p, v ) \
+- do \
+- { \
+- *(p)++ = (v) >> 8; \
+- *(p)++ = (v) >> 0; \
+- \
+- } while ( 0 )
+-
+-#define WRITE_ULONG( p, v ) \
+- do \
+- { \
+- *(p)++ = (v) >> 24; \
+- *(p)++ = (v) >> 16; \
+- *(p)++ = (v) >> 8; \
+- *(p)++ = (v) >> 0; \
+- \
++#define WRITE_ULONG( p, v ) \
++ do \
++ { \
++ *(p)++ = (FT_Byte)( (v) >> 24 ); \
++ *(p)++ = (FT_Byte)( (v) >> 16 ); \
++ *(p)++ = (FT_Byte)( (v) >> 8 ); \
++ *(p)++ = (FT_Byte)( (v) >> 0 ); \
++ \
+ } while ( 0 )
+
+
+@@ -661,6 +654,8 @@
+ }
+ else
+ {
++#ifdef FT_CONFIG_OPTION_USE_ZLIB
++
+ /* Uncompress with zlib. */
+ FT_ULong output_len = table->OrigLength;
+
+@@ -675,6 +670,13 @@
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
++
++#else /* !FT_CONFIG_OPTION_USE_ZLIB */
++
++ error = FT_THROW( Unimplemented_Feature );
++ goto Exit;
++
++#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
+ }
+
+ FT_FRAME_EXIT();
+@@ -717,7 +719,6 @@
+ }
+
+
+-#undef WRITE_BYTE
+ #undef WRITE_USHORT
+ #undef WRITE_ULONG
+
+diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
+index c717f5f..f9acf5d 100644
+--- a/src/sfnt/ttcmap.c
++++ b/src/sfnt/ttcmap.c
+@@ -3473,10 +3473,9 @@
+ /* only recognize format 0 */
+ if ( TT_NEXT_USHORT( p ) != 0 )
+ {
+- p -= 2;
+ FT_ERROR(( "tt_face_build_cmaps:"
+ " unsupported `cmap' table format = %d\n",
+- TT_PEEK_USHORT( p ) ));
++ TT_PEEK_USHORT( p - 2) ));
+ return FT_THROW( Invalid_Table );
+ }
+
+diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
+index 47a85c0..99d8005 100644
+--- a/src/sfnt/ttpost.c
++++ b/src/sfnt/ttpost.c
+@@ -5,7 +5,7 @@
+ /* Postcript name table processing for TrueType and OpenType fonts */
+ /* (body). */
+ /* */
+-/* Copyright 1996-2003, 2006-2010, 2013 by */
++/* Copyright 1996-2003, 2006-2010, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -64,12 +64,12 @@
+
+ #define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] )
+
+- /* the 258 default Mac PS glyph names */
++ /* the 258 default Mac PS glyph names; see file `tools/glnames.py' */
+
+ static const FT_String* const tt_post_default_names[258] =
+ {
+ /* 0 */
+- ".notdef", ".null", "CR", "space", "exclam",
++ ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
+ "quotedbl", "numbersign", "dollar", "percent", "ampersand",
+ /* 10 */
+ "quotesingle", "parenleft", "parenright", "asterisk", "plus",
+@@ -120,7 +120,7 @@
+ "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
+ "radical", "florin", "approxequal", "Delta", "guillemotleft",
+ /* 170 */
+- "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
++ "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
+ "Otilde", "OE", "oe", "endash", "emdash",
+ /* 180 */
+ "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
+@@ -144,8 +144,8 @@
+ "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
+ "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
+ /* 250 */
+- "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
+- "Ccaron", "ccaron", "dmacron",
++ "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
++ "Ccaron", "ccaron", "dcroat",
+ };
+
+
+diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
+index 8ff7b9d..180d559 100644
+--- a/src/sfnt/ttsbit.c
++++ b/src/sfnt/ttsbit.c
+@@ -256,7 +256,8 @@
+ case TT_SBIT_TABLE_TYPE_SBIX:
+ {
+ FT_Stream stream = face->root.stream;
+- FT_UInt offset, ppem, resolution, upem;
++ FT_UInt offset, upem;
++ FT_UShort ppem, resolution;
+ TT_HoriHeader *hori;
+ FT_ULong table_size;
+
+@@ -800,12 +801,12 @@
+ FT_Error error = FT_Err_Ok;
+ FT_UInt num_components, nn;
+
+- FT_Char horiBearingX = decoder->metrics->horiBearingX;
+- FT_Char horiBearingY = decoder->metrics->horiBearingY;
+- FT_Byte horiAdvance = decoder->metrics->horiAdvance;
+- FT_Char vertBearingX = decoder->metrics->vertBearingX;
+- FT_Char vertBearingY = decoder->metrics->vertBearingY;
+- FT_Byte vertAdvance = decoder->metrics->vertAdvance;
++ FT_Char horiBearingX = (FT_Char)decoder->metrics->horiBearingX;
++ FT_Char horiBearingY = (FT_Char)decoder->metrics->horiBearingY;
++ FT_Byte horiAdvance = (FT_Byte)decoder->metrics->horiAdvance;
++ FT_Char vertBearingX = (FT_Char)decoder->metrics->vertBearingX;
++ FT_Char vertBearingY = (FT_Char)decoder->metrics->vertBearingY;
++ FT_Byte vertAdvance = (FT_Byte)decoder->metrics->vertAdvance;
+
+
+ if ( p + 2 > limit )
+@@ -1352,10 +1353,11 @@
+
+ tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance );
+
+- metrics->horiBearingX = originOffsetX;
+- metrics->horiBearingY = -originOffsetY + metrics->height;
+- metrics->horiAdvance = aadvance * face->root.size->metrics.x_ppem /
+- face->header.Units_Per_EM;
++ metrics->horiBearingX = (FT_Short)originOffsetX;
++ metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height );
++ metrics->horiAdvance = (FT_Short)( aadvance *
++ face->root.size->metrics.x_ppem /
++ face->header.Units_Per_EM );
+ }
+
+ return error;
+diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
+index 425911a..27be966 100644
+--- a/src/smooth/ftgrays.c
++++ b/src/smooth/ftgrays.c
+@@ -98,6 +98,9 @@
+ #define FT_ERR_XCAT( x, y ) x ## y
+ #define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
+
++#define FT_BEGIN_STMNT do {
++#define FT_END_STMNT } while ( 0 )
++
+
+ /* define this to dump debugging information */
+ /* #define FT_DEBUG_LEVEL_TRACE */
+diff --git a/src/tools/afblue.pl b/src/tools/afblue.pl
+index 58aa2a0..60fe696 100644
+--- a/src/tools/afblue.pl
++++ b/src/tools/afblue.pl
+@@ -63,8 +63,8 @@ my $enum_element_re = qr/ ^ \s* ( [A-Za-z0-9_]+ ) \s* $ /x;
+ # '#' <preprocessor directive> '\n'
+ my $preprocessor_re = qr/ ^ \# /x;
+
+-# '/' '/' <comment> '\n'
+-my $comment_re = qr| ^ // |x;
++# [<ws>] '/' '/' <comment> '\n'
++my $comment_re = qr| ^ \s* // |x;
+
+ # empty line
+ my $whitespace_only_re = qr/ ^ \s* $ /x;
+@@ -159,6 +159,9 @@ sub convert_ascii_chars
+ # A series of ASCII characters in the printable range.
+ my $s = shift;
+
++ # We ignore spaces.
++ $s =~ s/ //g;
++
+ my $count = $s =~ s/\G(.)/'$1', /g;
+ $curr_offset += $count;
+ $curr_elem_size += $count;
+diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
+index 5f676a2..ff2b339 100644
+--- a/src/truetype/ttgload.c
++++ b/src/truetype/ttgload.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* TrueType Glyph Loader (body). */
+ /* */
+-/* Copyright 1996-2013 */
++/* Copyright 1996-2014 */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -99,13 +99,13 @@
+
+ else if ( face->os2.version != 0xFFFFU )
+ {
+- *tsb = face->os2.sTypoAscender - yMax;
++ *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
+ *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
+ }
+
+ else
+ {
+- *tsb = face->horizontal.Ascender - yMax;
++ *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
+ *ah = face->horizontal.Ascender - face->horizontal.Descender;
+ }
+
+@@ -2120,7 +2120,7 @@
+ FT_Bool reexecute = FALSE;
+
+
+- if ( !size->cvt_ready )
++ if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
+ {
+ FT_Error error = tt_size_ready_bytecode( size, pedantic );
+
+@@ -2128,6 +2128,10 @@
+ if ( error )
+ return error;
+ }
++ else if ( size->bytecode_ready )
++ return size->bytecode_ready;
++ else if ( size->cvt_ready )
++ return size->cvt_ready;
+
+ /* query new execution context */
+ exec = size->debug ? size->context
+@@ -2238,12 +2242,15 @@
+
+ if ( reexecute )
+ {
+- FT_UInt i;
++ FT_UInt i;
++ FT_Error error;
+
+
+ for ( i = 0; i < size->cvt_size; i++ )
+ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
+- tt_size_run_prep( size, pedantic );
++ error = tt_size_run_prep( size, pedantic );
++ if ( error )
++ return error;
+ }
+
+ /* see whether the cvt program has disabled hinting */
+diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
+index 56e8fa7..7d0248b 100644
+--- a/src/truetype/ttinterp.c
++++ b/src/truetype/ttinterp.c
+@@ -172,6 +172,9 @@
+ #define CUR_Func_round( d, c ) \
+ CUR.func_round( EXEC_ARG_ d, c )
+
++#define CUR_Func_cur_ppem() \
++ CUR.func_cur_ppem( EXEC_ARG )
++
+ #define CUR_Func_read_cvt( index ) \
+ CUR.func_read_cvt( EXEC_ARG_ index )
+
+@@ -184,12 +187,6 @@
+ #define CURRENT_Ratio() \
+ Current_Ratio( EXEC_ARG )
+
+-#define CURRENT_Ppem() \
+- Current_Ppem( EXEC_ARG )
+-
+-#define CUR_Ppem() \
+- Cur_PPEM( EXEC_ARG )
+-
+ #define INS_SxVTL( a, b, c, d ) \
+ Ins_SxVTL( EXEC_ARG_ a, b, c, d )
+
+@@ -1446,7 +1443,7 @@
+ TT_MulFix14_arm( FT_Int32 a,
+ FT_Int b )
+ {
+- register FT_Int32 t, t2;
++ FT_Int32 t, t2;
+
+
+ #if defined( __CC_ARM ) || defined( __ARMCC__ )
+@@ -1706,9 +1703,16 @@
+ }
+
+
+- static FT_Long
++ FT_CALLBACK_DEF( FT_Long )
+ Current_Ppem( EXEC_OP )
+ {
++ return CUR.tt_metrics.ppem;
++ }
++
++
++ FT_CALLBACK_DEF( FT_Long )
++ Current_Ppem_Stretched( EXEC_OP )
++ {
+ return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+ }
+
+@@ -3089,7 +3093,7 @@
+
+
+ #define DO_MPPEM \
+- args[0] = CURRENT_Ppem();
++ args[0] = CUR_Func_cur_ppem();
+
+
+ /* Note: The pointSize should be irrelevant in a given font program; */
+@@ -3102,7 +3106,7 @@
+ #else
+
+ #define DO_MPS \
+- args[0] = CURRENT_Ppem();
++ args[0] = CUR_Func_cur_ppem();
+
+ #endif /* 0 */
+
+@@ -7487,9 +7491,9 @@
+ static void
+ Ins_DELTAP( INS_ARG )
+ {
+- FT_ULong k, nump;
++ FT_ULong nump, k;
+ FT_UShort A;
+- FT_ULong C;
++ FT_ULong C, P;
+ FT_Long B;
+ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ FT_UShort B1, B2;
+@@ -7523,6 +7527,7 @@
+ }
+ #endif
+
++ P = (FT_ULong)CUR_Func_cur_ppem();
+ nump = (FT_ULong)args[0]; /* some points theoretically may occur more
+ than once, thus UShort isn't enough */
+
+@@ -7567,7 +7572,7 @@
+
+ C += CUR.GS.delta_base;
+
+- if ( CURRENT_Ppem() == (FT_Long)C )
++ if ( P == C )
+ {
+ B = ( (FT_ULong)B & 0xF ) - 8;
+ if ( B >= 0 )
+@@ -7596,9 +7601,9 @@
+ else if ( CUR.ignore_x_mode )
+ {
+ if ( CUR.GS.freeVector.y != 0 )
+- B1 = CUR.zp0.cur[A].y;
++ B1 = (FT_UShort)CUR.zp0.cur[A].y;
+ else
+- B1 = CUR.zp0.cur[A].x;
++ B1 = (FT_UShort)CUR.zp0.cur[A].x;
+
+ #if 0
+ /* Standard Subpixel Hinting: Allow y move. */
+@@ -7615,7 +7620,7 @@
+ !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
+ {
+ /* save the y value of the point now; compare after move */
+- B1 = CUR.zp0.cur[A].y;
++ B1 = (FT_UShort)CUR.zp0.cur[A].y;
+
+ if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+ B = FT_PIX_ROUND( B1 + B ) - B1;
+@@ -7627,7 +7632,7 @@
+ CUR_Func_move( &CUR.zp0, A, B );
+ }
+
+- B2 = CUR.zp0.cur[A].y;
++ B2 = (FT_UShort)CUR.zp0.cur[A].y;
+
+ /* Reverse this move if it results in a disallowed move */
+ if ( CUR.GS.freeVector.y != 0 &&
+@@ -7667,7 +7672,7 @@
+ Ins_DELTAC( INS_ARG )
+ {
+ FT_ULong nump, k;
+- FT_ULong A, C;
++ FT_ULong A, C, P;
+ FT_Long B;
+
+
+@@ -7691,6 +7696,7 @@
+ }
+ #endif
+
++ P = (FT_ULong)CUR_Func_cur_ppem();
+ nump = (FT_ULong)args[0];
+
+ for ( k = 1; k <= nump; k++ )
+@@ -7736,7 +7742,7 @@
+
+ C += CUR.GS.delta_base;
+
+- if ( CURRENT_Ppem() == (FT_Long)C )
++ if ( P == C )
+ {
+ B = ( (FT_ULong)B & 0xF ) - 8;
+ if ( B >= 0 )
+@@ -8269,11 +8275,12 @@
+ CUR.iup_called = FALSE;
+ #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+- /* set CVT functions */
++ /* set PPEM and CVT functions */
+ CUR.tt_metrics.ratio = 0;
+ if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
+ {
+ /* non-square pixels, use the stretched routines */
++ CUR.func_cur_ppem = Current_Ppem_Stretched;
+ CUR.func_read_cvt = Read_CVT_Stretched;
+ CUR.func_write_cvt = Write_CVT_Stretched;
+ CUR.func_move_cvt = Move_CVT_Stretched;
+@@ -8281,6 +8288,7 @@
+ else
+ {
+ /* square pixels, use normal routines */
++ CUR.func_cur_ppem = Current_Ppem;
+ CUR.func_read_cvt = Read_CVT;
+ CUR.func_write_cvt = Write_CVT;
+ CUR.func_move_cvt = Move_CVT;
+@@ -9035,10 +9043,13 @@
+ /* If any errors have occurred, function tables may be broken. */
+ /* Force a re-execution of `prep' and `fpgm' tables if no */
+ /* bytecode debugger is run. */
+- if ( CUR.error && !CUR.instruction_trap )
++ if ( CUR.error
++ && !CUR.instruction_trap
++ && CUR.curRange == tt_coderange_glyph )
+ {
+ FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
+- exc->size->cvt_ready = FALSE;
++ exc->size->bytecode_ready = -1;
++ exc->size->cvt_ready = -1;
+ }
+
+ return CUR.error;
+diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
+index 1d8825d..3cfc859 100644
+--- a/src/truetype/ttinterp.h
++++ b/src/truetype/ttinterp.h
+@@ -4,7 +4,7 @@
+ /* */
+ /* TrueType bytecode interpreter (specification). */
+ /* */
+-/* Copyright 1996-2007, 2010, 2012-2013 by */
++/* Copyright 1996-2007, 2010, 2012-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -81,6 +81,10 @@ FT_BEGIN_HEADER
+ (*TT_Project_Func)( EXEC_OP_ FT_Pos dx,
+ FT_Pos dy );
+
++ /* getting current ppem. Take care of non-square pixels if necessary */
++ typedef FT_Long
++ (*TT_Cur_Ppem_Func)( EXEC_OP );
++
+ /* reading a cvt value. Take care of non-square pixels if necessary */
+ typedef FT_F26Dot6
+ (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong idx );
+@@ -228,11 +232,6 @@ FT_BEGIN_HEADER
+ FT_F26Dot6 phase; /* `SuperRounding' */
+ FT_F26Dot6 threshold;
+
+-#if 0
+- /* this seems to be unused */
+- FT_Int cur_ppem; /* ppem along the current proj vector */
+-#endif
+-
+ FT_Bool instruction_trap; /* If `True', the interpreter will */
+ /* exit after each instruction */
+
+@@ -254,6 +253,8 @@ FT_BEGIN_HEADER
+ TT_Move_Func func_move; /* current point move function */
+ TT_Move_Func func_move_orig; /* move original position function */
+
++ TT_Cur_Ppem_Func func_cur_ppem; /* get current proj. ppem value */
++
+ TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */
+ TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */
+ TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */
+diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
+index 4adba58..05a121c 100644
+--- a/src/truetype/ttobjs.c
++++ b/src/truetype/ttobjs.c
+@@ -813,6 +813,8 @@
+ else
+ error = FT_Err_Ok;
+
++ size->bytecode_ready = error;
++
+ if ( !error )
+ TT_Save_Context( exec, size );
+
+@@ -884,6 +886,8 @@
+ else
+ error = FT_Err_Ok;
+
++ size->cvt_ready = error;
++
+ /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */
+ /* graphics state variables to be modified by the CVT program. */
+
+@@ -912,10 +916,6 @@
+ return error;
+ }
+
+-#endif /* TT_USE_BYTECODE_INTERPRETER */
+-
+-
+-#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ static void
+ tt_size_done_bytecode( FT_Size ftsize )
+@@ -953,8 +953,8 @@
+ size->max_func = 0;
+ size->max_ins = 0;
+
+- size->bytecode_ready = 0;
+- size->cvt_ready = 0;
++ size->bytecode_ready = -1;
++ size->cvt_ready = -1;
+ }
+
+
+@@ -974,8 +974,8 @@
+ TT_MaxProfile* maxp = &face->max_profile;
+
+
+- size->bytecode_ready = 1;
+- size->cvt_ready = 0;
++ size->bytecode_ready = -1;
++ size->cvt_ready = -1;
+
+ size->max_function_defs = maxp->maxFunctionDefs;
+ size->max_instruction_defs = maxp->maxInstructionDefs;
+@@ -1052,15 +1052,14 @@
+ FT_Error error = FT_Err_Ok;
+
+
+- if ( !size->bytecode_ready )
+- {
++ if ( size->bytecode_ready < 0 )
+ error = tt_size_init_bytecode( (FT_Size)size, pedantic );
+- if ( error )
+- goto Exit;
+- }
++
++ if ( error || size->bytecode_ready )
++ goto Exit;
+
+ /* rescale CVT when needed */
+- if ( !size->cvt_ready )
++ if ( size->cvt_ready < 0 )
+ {
+ FT_UInt i;
+ TT_Face face = (TT_Face)size->root.face;
+@@ -1087,8 +1086,6 @@
+ size->GS = tt_default_graphics_state;
+
+ error = tt_size_run_prep( size, pedantic );
+- if ( !error )
+- size->cvt_ready = 1;
+ }
+
+ Exit:
+@@ -1119,8 +1116,8 @@
+ FT_Error error = FT_Err_Ok;
+
+ #ifdef TT_USE_BYTECODE_INTERPRETER
+- size->bytecode_ready = 0;
+- size->cvt_ready = 0;
++ size->bytecode_ready = -1;
++ size->cvt_ready = -1;
+ #endif
+
+ size->ttmetrics.valid = FALSE;
+@@ -1148,7 +1145,7 @@
+
+
+ #ifdef TT_USE_BYTECODE_INTERPRETER
+- if ( size->bytecode_ready )
++ if ( size->bytecode_ready >= 0 )
+ tt_size_done_bytecode( ttsize );
+ #endif
+
+@@ -1229,7 +1226,7 @@
+ }
+
+ #ifdef TT_USE_BYTECODE_INTERPRETER
+- size->cvt_ready = 0;
++ size->cvt_ready = -1;
+ #endif /* TT_USE_BYTECODE_INTERPRETER */
+
+ if ( !error )
+diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
+index a11dd37..47d50d9 100644
+--- a/src/truetype/ttobjs.h
++++ b/src/truetype/ttobjs.h
+@@ -4,7 +4,7 @@
+ /* */
+ /* Objects manager (specification). */
+ /* */
+-/* Copyright 1996-2009, 2011-2013 by */
++/* Copyright 1996-2009, 2011-2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -333,8 +333,10 @@ FT_BEGIN_HEADER
+ FT_Bool debug;
+ TT_ExecContext context;
+
+- FT_Bool bytecode_ready;
+- FT_Bool cvt_ready;
++ /* if negative, `fpgm' (resp. `prep'), wasn't executed yet; */
++ /* otherwise it is the returned error code */
++ FT_Error bytecode_ready;
++ FT_Error cvt_ready;
+
+ #endif /* TT_USE_BYTECODE_INTERPRETER */
+
+diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c
+index 28470ad..9871994 100644
+--- a/src/truetype/ttsubpix.c
++++ b/src/truetype/ttsubpix.c
+@@ -956,7 +956,7 @@
+ if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 )
+ {
+ loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
+- loader->exec->size->cvt_ready = FALSE;
++ loader->exec->size->cvt_ready = -1;
+
+ tt_size_ready_bytecode(
+ loader->exec->size,
+@@ -971,7 +971,7 @@
+ SPH_OPTION_SET_RASTERIZER_VERSION )
+ {
+ loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
+- loader->exec->size->cvt_ready = FALSE;
++ loader->exec->size->cvt_ready = -1;
+
+ tt_size_ready_bytecode(
+ loader->exec->size,
+diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c
+index 697288d..2602bdb 100644
+--- a/src/type1/t1driver.c
++++ b/src/type1/t1driver.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* Type 1 driver interface (body). */
+ /* */
+-/* Copyright 1996-2004, 2006, 2007, 2009, 2011, 2013 by */
++/* Copyright 1996-2004, 2006, 2007, 2009, 2011, 2013, 2014 by */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -557,9 +557,6 @@
+ if ( value && value_len >= retval )
+ *((FT_Long *)value) = type1->font_info.italic_angle;
+ break;
+-
+- default:
+- break;
+ }
+
+ return retval;