Update to FreeType 2.4.6+

This patch updates our copy of the FreeType sources to 2.4.6+.

More precisely, it contains source code corresponding to the
state of the upstream repository at the following hash
submitted on August 16 2001:

  c3fb981e2ac79acad09d5673352646696472f55e

This corresponds to 2.4.6 with 7 more patches applied on top
of it to fix bugs in the TrueType interpreter and the CFF parser.

Change-Id: I9f3ac736d616020c8d10fd1d4e4be466f35fb6e7
diff --git a/ThirdPartyProject.prop b/ThirdPartyProject.prop
index 7bf6d4d..3d91d63 100644
--- a/ThirdPartyProject.prop
+++ b/ThirdPartyProject.prop
@@ -1,7 +1,7 @@
-# Copyright 2010 Google Inc. All Rights Reserved.
-#Fri Jul 16 10:03:09 PDT 2010
-currentVersion=2.4.2
-version=2.4.2
+# Copyright 2011 Google Inc. All Rights Reserved.
+#Wed Aug 17 18:25:11 CEST 2011
+currentVersion=2.4.6
+version=2.4.6
 isNative=true
 feedurl=http\://freetype.sourceforge.net/index2.html
 name=freetype
diff --git a/include/freetype/config/ftconfig.h b/include/freetype/config/ftconfig.h
index cbe30f2..7af737f 100644
--- a/include/freetype/config/ftconfig.h
+++ b/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    ANSI-specific configuration file (specification only).               */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2010 by       */
+/*  Copyright 1996-2004, 2006-2008, 2010-2011 by                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -127,7 +127,12 @@
 #if ( defined( __APPLE__ ) && !defined( DARWIN_NO_CARBON ) ) || \
     ( defined( __MWERKS__ ) && defined( macintosh )        )
   /* no Carbon frameworks for 64bit 10.4.x */
+  /* AvailabilityMacros.h is available since Mac OS X 10.2,        */
+  /* so guess the system version by maximum errno before inclusion */
+#include <errno.h>
+#ifdef ECANCELED /* defined since 10.2 */
 #include "AvailabilityMacros.h"
+#endif
 #if defined( __LP64__ ) && \
     ( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 )
 #define DARWIN_NO_CARBON 1
@@ -348,14 +353,14 @@
     register FT_Int32  t, t2;
 
 
-    asm __volatile__ (
+    __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, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
+      "orr    %0, %0, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
       : "=r"(a), "=&r"(t2), "=&r"(t)
       : "r"(a), "r"(b) );
     return a;
@@ -395,6 +400,43 @@
 
 #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 */
+
 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
 
 
diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h
index b63945d..2a7b8c4 100644
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Build macros of the FreeType 2 library.                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by       */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -427,6 +427,19 @@
   /*************************************************************************
    *
    * @macro:
+   *   FT_BZIP2_H
+   *
+   * @description:
+   *   A macro used in #include statements to name the file containing the
+   *   definitions of an API which supports bzip2-compressed files.
+   *
+   */
+#define FT_BZIP2_H  <freetype/ftbzip2.h>
+
+
+  /*************************************************************************
+   *
+   * @macro:
    *   FT_WINFONTS_H
    *
    * @description:
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index c6d1974..c41f089 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    User-selectable configuration macros (specification only).           */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -190,6 +189,33 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /* Bzip2-compressed file support.                                        */
+  /*                                                                       */
+  /*   FreeType now handles font files that have been compressed with the  */
+  /*   `bzip2' program.  This is mostly used to parse many of the PCF      */
+  /*   files that come with XFree86.  The implementation uses `libbz2' to  */
+  /*   partially uncompress the file on the fly (see src/bzip2/ftbzip2.c). */
+  /*   Contrary to gzip, bzip2 currently is not included and need to use   */
+  /*   the system available bzip2 implementation.                          */
+  /*                                                                       */
+  /*   Define this macro if you want to enable this `feature'.             */
+  /*                                                                       */
+/* #define FT_CONFIG_OPTION_USE_BZIP2 */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define to disable the use of file stream functions and types, FILE,   */
+  /* fopen() etc.  Enables the use of smaller system libraries on embedded */
+  /* systems that have multiple system libraries, some with or without     */
+  /* file stream support, in the cases where file stream support is not    */
+  /* necessary such as memory loading of font files.                       */
+  /*                                                                       */
+/* #define FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* DLL export compilation                                                */
   /*                                                                       */
   /*   When compiling FreeType as a DLL, some systems/compilers need a     */
@@ -365,6 +391,39 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /* Autofitter debugging                                                  */
+  /*                                                                       */
+  /*   If FT_DEBUG_AUTOFIT is defined, FreeType provides some means to     */
+  /*   control the autofitter behaviour for debugging purposes with global */
+  /*   boolean variables (consequently, you should *never* enable this     */
+  /*   while compiling in `release' mode):                                 */
+  /*                                                                       */
+  /*     _af_debug_disable_horz_hints                                      */
+  /*     _af_debug_disable_vert_hints                                      */
+  /*     _af_debug_disable_blue_hints                                      */
+  /*                                                                       */
+  /*   Additionally, the following functions provide dumps of various      */
+  /*   internal autofit structures to stdout (using `printf'):             */
+  /*                                                                       */
+  /*     af_glyph_hints_dump_points                                        */
+  /*     af_glyph_hints_dump_segments                                      */
+  /*     af_glyph_hints_dump_edges                                         */
+  /*                                                                       */
+  /*   As an argument, they use another global variable:                   */
+  /*                                                                       */
+  /*     _af_debug_hints                                                   */
+  /*                                                                       */
+  /*   Please have a look at the `ftgrid' demo program to see how those    */
+  /*   variables and macros should be used.                                */
+  /*                                                                       */
+  /*   Do not #undef these macros here since the build system might define */
+  /*   them for certain configurations only.                               */
+  /*                                                                       */
+/* #define FT_DEBUG_AUTOFIT */
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* Memory Debugging                                                      */
   /*                                                                       */
   /*   FreeType now comes with an integrated memory debugger that is       */
@@ -503,10 +562,13 @@
   /*                                                                       */
   /* 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.  Note that the            */
-  /* TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* if you define  */
-  /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words, either define  */
-  /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER or                              */
+  /* any of the patented opcodes and algorithms.  The patents related to   */
+  /* TrueType hinting have expired worldwide since May 2010; this option   */
+  /* is now deprecated.                                                    */
+  /*                                                                       */
+  /* Note that the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored*  */
+  /* if you define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words,  */
+  /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or                */
   /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time.    */
   /*                                                                       */
   /* This macro is only useful for a small number of font files (mostly    */
@@ -572,7 +634,7 @@
   /* composite flags array which can be used to disambiguate, but old      */
   /* fonts will not have them.                                             */
   /*                                                                       */
-  /*   http://partners.adobe.com/asn/developer/opentype/glyf.html          */
+  /*   http://www.microsoft.com/typography/otspec/glyf.htm                 */
   /*   http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html                 */
   /*                                                                       */
 #undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
@@ -673,6 +735,19 @@
   /*                                                                       */
 #define AF_CONFIG_OPTION_INDIC
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* Compile autofit module with warp hinting.  The idea of the warping    */
+  /* code is to slightly scale and shift a glyph within a single dimension */
+  /* so that as much of its segments are aligned (more or less) on the     */
+  /* grid.  To find out the optimal scaling and shifting value, various    */
+  /* parameter combinations are tried and scored.                          */
+  /*                                                                       */
+  /* This experimental option is only active if the render mode is         */
+  /* FT_RENDER_MODE_LIGHT.                                                 */
+  /*                                                                       */
+/* #define AF_CONFIG_OPTION_USE_WARPER */
+
   /* */
 
 
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 7799b70..660b303 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    FreeType high-level API and common types (specification only).       */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -227,10 +226,12 @@
   /*      Left side bearing for vertical layout.                           */
   /*                                                                       */
   /*    vertBearingY ::                                                    */
-  /*      Top side bearing for vertical layout.                            */
+  /*      Top side bearing for vertical layout.  Larger positive values    */
+  /*      mean further below the vertical glyph origin.                    */
   /*                                                                       */
   /*    vertAdvance ::                                                     */
-  /*      Advance height for vertical layout.                              */
+  /*      Advance height for vertical layout.  Positive values mean the    */
+  /*      glyph has a positive advance downward.                           */
   /*                                                                       */
   /* <Note>                                                                */
   /*    If not disabled with @FT_LOAD_NO_HINTING, the values represent     */
@@ -1058,12 +1059,12 @@
   /*                                                                       */
   /*      It is not possible to autohint such fonts using                  */
   /*      @FT_LOAD_FORCE_AUTOHINT; it will also ignore                     */
-  /*      @FT_LOAD_NO_HINTING.  You have to set both FT_LOAD_NO_HINTING    */
+  /*      @FT_LOAD_NO_HINTING.  You have to set both @FT_LOAD_NO_HINTING   */
   /*      and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */
   /*      probably never want this except for demonstration purposes.      */
   /*                                                                       */
-  /*      Currently, there are six TrueType fonts in the list of tricky    */
-  /*      fonts; they are hard-coded in file `ttobjs.c'.                   */
+  /*      Currently, there are about a dozen TrueType fonts in the list of */
+  /*      tricky fonts; they are hard-coded in file `ttobjs.c'.            */
   /*                                                                       */
 #define FT_FACE_FLAG_SCALABLE          ( 1L <<  0 )
 #define FT_FACE_FLAG_FIXED_SIZES       ( 1L <<  1 )
@@ -2106,8 +2107,8 @@
   /*      used to determine both scaling values.                           */
   /*                                                                       */
   /*    FT_SIZE_REQUEST_TYPE_REAL_DIM ::                                   */
-  /*      The real dimension.  The sum of the the `Ascender' and (minus    */
-  /*      of) the `Descender' fields of @FT_FaceRec are used to determine  */
+  /*      The real dimension.  The sum of the the `ascender' and (minus    */
+  /*      of) the `descender' fields of @FT_FaceRec are used to determine  */
   /*      both scaling values.                                             */
   /*                                                                       */
   /*    FT_SIZE_REQUEST_TYPE_BBOX ::                                       */
@@ -2445,13 +2446,7 @@
    *     in fonts.  By default, FreeType tries to handle broken fonts also.
    *
    *   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
-   *     Indicates that the font driver should ignore the global advance
-   *     width defined in the font.  By default, that value is used as the
-   *     advance width for all glyphs when the face has
-   *     @FT_FACE_FLAG_FIXED_WIDTH set.
-   *
-   *     This flag exists for historical reasons (to support buggy CJK
-   *     fonts).
+   *     Ignored.  Deprecated.
    *
    *   FT_LOAD_NO_RECURSE ::
    *     This flag is only used internally.  It merely indicates that the
@@ -2921,6 +2916,10 @@
   /*    The glyph name is truncated to fit within the buffer if it is too  */
   /*    long.  The returned string is always zero-terminated.              */
   /*                                                                       */
+  /*    Be aware that FreeType reorders glyph indices internally so that   */
+  /*    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              */
   /*    `include/freetype/config/ftoptions.h'.                             */
@@ -3331,6 +3330,9 @@
   /*    in the @PS_FontInfoRec structure which is only guaranteed to       */
   /*    return the correct results for Type~1 fonts.                       */
   /*                                                                       */
+  /* <Since>                                                               */
+  /*    2.3.8                                                              */
+  /*                                                                       */
   FT_EXPORT( FT_UShort )
   FT_Get_FSType_Flags( FT_Face  face );
 
@@ -3808,7 +3810,7 @@
    */
 #define FREETYPE_MAJOR  2
 #define FREETYPE_MINOR  4
-#define FREETYPE_PATCH  2
+#define FREETYPE_PATCH  6
 
 
   /*************************************************************************/
diff --git a/include/freetype/ftbbox.h b/include/freetype/ftbbox.h
index 01fe3fb..9766919 100644
--- a/include/freetype/ftbbox.h
+++ b/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType exact bbox computation (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2007 by                                     */
+/*  Copyright 1996-2001, 2003, 2007, 2011 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -73,6 +73,14 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the font is tricky and the glyph has been loaded with           */
+  /*    @FT_LOAD_NO_SCALE, the resulting BBox is meaningless.  To get      */
+  /*    reasonable values for the BBox it is necessary to load the glyph   */
+  /*    at a large ppem value (so that the hinting instructions can        */
+  /*    properly shift and scale the subglyphs), then extracting the BBox  */
+  /*    which can be eventually converted back to font units.              */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Outline_Get_BBox( FT_Outline*  outline,
                        FT_BBox     *abbox );
diff --git a/include/freetype/ftcache.h b/include/freetype/ftcache.h
index a9e1237..6af5306 100644
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -56,9 +56,12 @@
    *   interpret them in any way.
    *
    *   Second, the cache calls, only when needed, a client-provided function
-   *   to convert a @FTC_FaceID into a new @FT_Face object.  The latter is
+   *   to convert an @FTC_FaceID into a new @FT_Face object.  The latter is
    *   then completely managed by the cache, including its termination
-   *   through @FT_Done_Face.
+   *   through @FT_Done_Face.  To monitor termination of face objects, the
+   *   finalizer callback in the `generic' field of the @FT_Face object can
+   *   be used, which might also be used to store the @FTC_FaceID of the
+   *   face.
    *
    *   Clients are free to map face IDs to anything else.  The most simple
    *   usage is to associate them to a (pathname,face_index) pair that is
@@ -211,12 +214,17 @@
 
  /* */
 
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+  /* these macros are incompatible with LLP64, should not be used */
+
 #define FT_POINTER_TO_ULONG( p )  ( (FT_ULong)(FT_Pointer)(p) )
 
 #define FTC_FACE_ID_HASH( i )                                \
           ((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^   \
                        ( FT_POINTER_TO_ULONG( i ) << 7 ) ) )
 
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
 
   /*************************************************************************/
   /*************************************************************************/
@@ -697,11 +705,17 @@
             (d1)->width   == (d2)->width   && \
             (d1)->flags   == (d2)->flags   )
 
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+  /* this macro is incompatible with LLP64, should not be used */
+
 #define FTC_IMAGE_TYPE_HASH( d )                          \
           (FT_UFast)( FTC_FACE_ID_HASH( (d)->face_id )  ^ \
                       ( (d)->width << 8 ) ^ (d)->height ^ \
                       ( (d)->flags << 4 )               )
 
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -1093,6 +1107,7 @@
             (f1)->pix_width  == (f2)->pix_width  && \
             (f1)->pix_height == (f2)->pix_height )
 
+  /* this macro is incompatible with LLP64, should not be used */
 #define FTC_FONT_HASH( f )                              \
           (FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \
                        ((f)->pix_width << 8)          ^ \
diff --git a/include/freetype/ftchapters.h b/include/freetype/ftchapters.h
index 7775a6b..6cdf54e 100644
--- a/include/freetype/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -98,6 +98,7 @@
 /*    module_management                                                    */
 /*    gzip                                                                 */
 /*    lzw                                                                  */
+/*    bzip2                                                                */
 /*    lcd_filtering                                                        */
 /*                                                                         */
 /***************************************************************************/
diff --git a/include/freetype/fterrdef.h b/include/freetype/fterrdef.h
index bf52220..d4e7287 100644
--- a/include/freetype/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -214,7 +214,6 @@
   FT_ERRORDEF_( No_Unicode_Glyph_Name,                       0xA3, \
                 "no Unicode glyph name found" )
 
-
   /* BDF errors */
 
   FT_ERRORDEF_( Missing_Startfont_Field,                     0xB0, \
diff --git a/include/freetype/ftgasp.h b/include/freetype/ftgasp.h
index 91a769e..5e978e5 100644
--- a/include/freetype/ftgasp.h
+++ b/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Access of TrueType's `gasp' table (specification).                   */
 /*                                                                         */
-/*  Copyright 2007, 2008 by                                                */
+/*  Copyright 2007, 2008, 2011 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -62,19 +62,27 @@
    *     It is up to the client to decide what to do.
    *
    *   FT_GASP_DO_GRIDFIT ::
-   *     Grid-fitting and hinting should be performed at the specified ppem.
-   *     This *really* means TrueType bytecode interpretation.
+   *     Grid-fitting and hinting should be performed at the specified ppem. 
+   *     This *really* means TrueType bytecode interpretation.  If this bit
+   *     is not set, no hinting gets applied.
    *
    *   FT_GASP_DO_GRAY ::
-   *     Anti-aliased rendering should be performed at the specified ppem.
+   *     Anti-aliased rendering should be performed at the specified ppem. 
+   *     If not set, do monochrome rendering.
    *
    *   FT_GASP_SYMMETRIC_SMOOTHING ::
-   *     Smoothing along multiple axes must be used with ClearType.
+   *     If set, smoothing along multiple axes must be used with ClearType.
    *
    *   FT_GASP_SYMMETRIC_GRIDFIT ::
    *     Grid-fitting must be used with ClearType's symmetric smoothing.
    *
    * @note:
+   *   The bit-flags `FT_GASP_DO_GRIDFIT' and `FT_GASP_DO_GRAY' are to be
+   *   used for standard font rasterization only.  Independently of that,
+   *   `FT_GASP_SYMMETRIC_SMOOTHING' and `FT_GASP_SYMMETRIC_GRIDFIT' are to
+   *   be used if ClearType is enabled (and `FT_GASP_DO_GRIDFIT' and
+   *   `FT_GASP_DO_GRAY' are consequently ignored).
+   *
    *   `ClearType' is Microsoft's implementation of LCD rendering, partly
    *   protected by patents.
    *
diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h
index 0b8f0c0..3de69f7 100644
--- a/include/freetype/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType convenience functions to handle glyphs (specification).     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009 by                   */
+/*  Copyright 1996-2003, 2006, 2008, 2009, 2011 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -384,6 +384,13 @@
   /*    units in 26.6 pixel format.  The value @FT_GLYPH_BBOX_SUBPIXELS    */
   /*    is another name for this constant.                                 */
   /*                                                                       */
+  /*    If the font is tricky and the glyph has been loaded with           */
+  /*    @FT_LOAD_NO_SCALE, the resulting CBox is meaningless.  To get      */
+  /*    reasonable values for the CBox it is necessary to load the glyph   */
+  /*    at a large ppem value (so that the hinting instructions can        */
+  /*    properly shift and scale the subglyphs), then extracting the CBox  */
+  /*    which can be eventually converted back to font units.              */
+  /*                                                                       */
   /*    Note that the maximum coordinates are exclusive, which means that  */
   /*    one can compute the width and height of the glyph image (be it in  */
   /*    integer or 26.6 pixels) as:                                        */
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index 0272e92..04b5e04 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -268,9 +268,21 @@
   /*                    flow.  In all cases, the pitch is an offset to add */
   /*                    to a bitmap pointer in order to go down one row.   */
   /*                                                                       */
+  /*                    Note that `padding' means the alignment of a       */
+  /*                    bitmap to a byte border, and FreeType functions    */
+  /*                    normally align to the smallest possible integer    */
+  /*                    value.                                             */
+  /*                                                                       */
   /*                    For the B/W rasterizer, `pitch' is always an even  */
   /*                    number.                                            */
   /*                                                                       */
+  /*                    To change the pitch of a bitmap (say, to make it a */
+  /*                    multiple of 4), use @FT_Bitmap_Convert.            */
+  /*                    Alternatively, you might use callback functions to */
+  /*                    directly render to the application's surface; see  */
+  /*                    the file `example2.cpp' in the tutorial for a      */
+  /*                    demonstration.                                     */
+  /*                                                                       */
   /*    buffer       :: A typeless pointer to the bitmap buffer.  This     */
   /*                    value should be aligned on 32-bit boundaries in    */
   /*                    most cases.                                        */
diff --git a/include/freetype/ftmoderr.h b/include/freetype/ftmoderr.h
index b0115dd..1bf3b38 100644
--- a/include/freetype/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType module error offsets (specification).                       */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2005 by                              */
+/*  Copyright 2001, 2002, 2003, 2004, 2005, 2010 by                        */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -105,24 +105,25 @@
   FT_MODERRDEF( Base,      0x000, "base module" )
   FT_MODERRDEF( Autofit,   0x100, "autofitter module" )
   FT_MODERRDEF( BDF,       0x200, "BDF module" )
-  FT_MODERRDEF( Cache,     0x300, "cache module" )
-  FT_MODERRDEF( CFF,       0x400, "CFF module" )
-  FT_MODERRDEF( CID,       0x500, "CID module" )
-  FT_MODERRDEF( Gzip,      0x600, "Gzip module" )
-  FT_MODERRDEF( LZW,       0x700, "LZW module" )
-  FT_MODERRDEF( OTvalid,   0x800, "OpenType validation module" )
-  FT_MODERRDEF( PCF,       0x900, "PCF module" )
-  FT_MODERRDEF( PFR,       0xA00, "PFR module" )
-  FT_MODERRDEF( PSaux,     0xB00, "PS auxiliary module" )
-  FT_MODERRDEF( PShinter,  0xC00, "PS hinter module" )
-  FT_MODERRDEF( PSnames,   0xD00, "PS names module" )
-  FT_MODERRDEF( Raster,    0xE00, "raster module" )
-  FT_MODERRDEF( SFNT,      0xF00, "SFNT module" )
-  FT_MODERRDEF( Smooth,   0x1000, "smooth raster module" )
-  FT_MODERRDEF( TrueType, 0x1100, "TrueType module" )
-  FT_MODERRDEF( Type1,    0x1200, "Type 1 module" )
-  FT_MODERRDEF( Type42,   0x1300, "Type 42 module" )
-  FT_MODERRDEF( Winfonts, 0x1400, "Windows FON/FNT module" )
+  FT_MODERRDEF( Bzip2,     0x300, "Bzip2 module" )
+  FT_MODERRDEF( Cache,     0x400, "cache module" )
+  FT_MODERRDEF( CFF,       0x500, "CFF module" )
+  FT_MODERRDEF( CID,       0x600, "CID module" )
+  FT_MODERRDEF( Gzip,      0x700, "Gzip module" )
+  FT_MODERRDEF( LZW,       0x800, "LZW module" )
+  FT_MODERRDEF( OTvalid,   0x900, "OpenType validation module" )
+  FT_MODERRDEF( PCF,       0xA00, "PCF module" )
+  FT_MODERRDEF( PFR,       0xB00, "PFR module" )
+  FT_MODERRDEF( PSaux,     0xC00, "PS auxiliary module" )
+  FT_MODERRDEF( PShinter,  0xD00, "PS hinter module" )
+  FT_MODERRDEF( PSnames,   0xE00, "PS names module" )
+  FT_MODERRDEF( Raster,    0xF00, "raster module" )
+  FT_MODERRDEF( SFNT,     0x1000, "SFNT module" )
+  FT_MODERRDEF( Smooth,   0x1100, "smooth raster module" )
+  FT_MODERRDEF( TrueType, 0x1200, "TrueType module" )
+  FT_MODERRDEF( Type1,    0x1300, "Type 1 module" )
+  FT_MODERRDEF( Type42,   0x1400, "Type 42 module" )
+  FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" )
 
 
 #ifdef FT_MODERR_END_LIST
diff --git a/include/freetype/ftoutln.h b/include/freetype/ftoutln.h
index 2829a05..1cf3c3f 100644
--- a/include/freetype/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
 /*    Support for the FT_Outline type used to store glyph shapes of        */
 /*    most scalable font formats (specification).                          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/*  Copyright 1996-2003, 2005-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -227,6 +227,9 @@
   /* <Output>                                                              */
   /*    acbox   :: The outline's control box.                              */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See @FT_Glyph_Get_CBox for a discussion of tricky fonts.           */
+  /*                                                                       */
   FT_EXPORT( void )
   FT_Outline_Get_CBox( const FT_Outline*  outline,
                        FT_BBox           *acbox );
@@ -332,7 +335,7 @@
   /*    handled incorrectly.                                               */
   /*                                                                       */
   /*    If you need `better' metrics values you should call                */
-  /*    @FT_Outline_Get_CBox ot @FT_Outline_Get_BBox.                      */
+  /*    @FT_Outline_Get_CBox or @FT_Outline_Get_BBox.                      */
   /*                                                                       */
   /*    Example call:                                                      */
   /*                                                                       */
diff --git a/include/freetype/ftrender.h b/include/freetype/ftrender.h
index e06a814..dd0229b 100644
--- a/include/freetype/ftrender.h
+++ b/include/freetype/ftrender.h
@@ -212,6 +212,14 @@
   /*                                                                       */
   /*    This doesn't change the current renderer for other formats.        */
   /*                                                                       */
+  /*    Currently, only the B/W renderer, if compiled with                 */
+  /*    FT_RASTER_OPTION_ANTI_ALIASING (providing a 5-levels               */
+  /*    anti-aliasing mode; this option must be set directly in            */
+  /*    `ftraster.c' and is undefined by default) accepts a single tag     */
+  /*    `pal5' to set its gray palette as a character string with          */
+  /*    5~elements.  Consequently, the third and fourth argument are zero  */
+  /*    normally.                                                          */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Set_Renderer( FT_Library     library,
                    FT_Renderer    renderer,
diff --git a/include/freetype/ftstroke.h b/include/freetype/ftstroke.h
index 3afb87d..dbda6d2 100644
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (specification).                               */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009 by                  */
+/*  Copyright 2002-2006, 2008, 2009, 2011 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -75,20 +75,44 @@
    *     to join two lines smoothly.
    *
    *   FT_STROKER_LINEJOIN_BEVEL ::
-   *     Used to render beveled line joins; i.e., the two joining lines
-   *     are extended until they intersect.
+   *     Used to render beveled line joins.  The outer corner of
+   *     the joined lines is filled by enclosing the triangular
+   *     region of the corner with a straight line between the
+   *     outer corners of each stroke.
    *
+   *   FT_STROKER_LINEJOIN_MITER_FIXED ::
+   *     Used to render mitered line joins, with fixed bevels if the
+   *     miter limit is exceeded.  The outer edges of the strokes
+   *     for the two segments are extended until they meet at an
+   *     angle.  If the segments meet at too sharp an angle (such
+   *     that the miter would extend from the intersection of the 
+   *     segments a distance greater than the product of the miter 
+   *     limit value and the border radius), then a bevel join (see 
+   *     above) is used instead.  This prevents long spikes being 
+   *     created.  FT_STROKER_LINEJOIN_MITER_FIXED generates a miter 
+   *     line join as used in PostScript and PDF.
+   *
+   *   FT_STROKER_LINEJOIN_MITER_VARIABLE ::
    *   FT_STROKER_LINEJOIN_MITER ::
-   *     Same as beveled rendering, except that an additional line
-   *     break is added if the angle between the two joining lines
-   *     is too closed (this is useful to avoid unpleasant spikes
-   *     in beveled rendering).
+   *     Used to render mitered line joins, with variable bevels if
+   *     the miter limit is exceeded.  The intersection of the 
+   *     strokes is clipped at a line perpendicular to the bisector 
+   *     of the angle between the strokes, at the distance from the 
+   *     intersection of the segments equal to the product of the 
+   *     miter limit value and the border radius.  This prevents 
+   *     long spikes being created.  
+   *     FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line 
+   *     join as used in XPS.  FT_STROKER_LINEJOIN_MITER is an alias 
+   *     for FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for 
+   *     backwards compatibility.
    */
   typedef enum  FT_Stroker_LineJoin_
   {
-    FT_STROKER_LINEJOIN_ROUND = 0,
-    FT_STROKER_LINEJOIN_BEVEL,
-    FT_STROKER_LINEJOIN_MITER
+    FT_STROKER_LINEJOIN_ROUND          = 0,
+    FT_STROKER_LINEJOIN_BEVEL          = 1,
+    FT_STROKER_LINEJOIN_MITER_VARIABLE = 2,
+    FT_STROKER_LINEJOIN_MITER          = FT_STROKER_LINEJOIN_MITER_VARIABLE,
+    FT_STROKER_LINEJOIN_MITER_FIXED    = 3
 
   } FT_Stroker_LineJoin;
 
@@ -245,7 +269,8 @@
    *     The line join style.
    *
    *   miter_limit ::
-   *     The miter limit for the FT_STROKER_LINEJOIN_MITER style,
+   *     The miter limit for the FT_STROKER_LINEJOIN_MITER_FIXED and
+   *     FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles,
    *     expressed as 16.16 fixed point value.
    *
    * @note:
diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h
index a91eb72..9c12186 100644
--- a/include/freetype/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Stream handling (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2005, 2006 by                         */
+/*  Copyright 1996-2002, 2004-2006, 2011 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -292,18 +292,18 @@
 
 #define FT_GET_CHAR()       FT_GET_MACRO( FT_Stream_GetChar, FT_Char )
 #define FT_GET_BYTE()       FT_GET_MACRO( FT_Stream_GetChar, FT_Byte )
-#define FT_GET_SHORT()      FT_GET_MACRO( FT_Stream_GetShort, FT_Short )
-#define FT_GET_USHORT()     FT_GET_MACRO( FT_Stream_GetShort, FT_UShort )
-#define FT_GET_OFF3()       FT_GET_MACRO( FT_Stream_GetOffset, FT_Long )
-#define FT_GET_UOFF3()      FT_GET_MACRO( FT_Stream_GetOffset, FT_ULong )
-#define FT_GET_LONG()       FT_GET_MACRO( FT_Stream_GetLong, FT_Long )
-#define FT_GET_ULONG()      FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )
-#define FT_GET_TAG4()       FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )
+#define FT_GET_SHORT()      FT_GET_MACRO( FT_Stream_GetUShort, FT_Short )
+#define FT_GET_USHORT()     FT_GET_MACRO( FT_Stream_GetUShort, FT_UShort )
+#define FT_GET_OFF3()       FT_GET_MACRO( FT_Stream_GetUOffset, FT_Long )
+#define FT_GET_UOFF3()      FT_GET_MACRO( FT_Stream_GetUOffset, FT_ULong )
+#define FT_GET_LONG()       FT_GET_MACRO( FT_Stream_GetULong, FT_Long )
+#define FT_GET_ULONG()      FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
+#define FT_GET_TAG4()       FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
 
-#define FT_GET_SHORT_LE()   FT_GET_MACRO( FT_Stream_GetShortLE, FT_Short )
-#define FT_GET_USHORT_LE()  FT_GET_MACRO( FT_Stream_GetShortLE, FT_UShort )
-#define FT_GET_LONG_LE()    FT_GET_MACRO( FT_Stream_GetLongLE, FT_Long )
-#define FT_GET_ULONG_LE()   FT_GET_MACRO( FT_Stream_GetLongLE, FT_ULong )
+#define FT_GET_SHORT_LE()   FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Short )
+#define FT_GET_USHORT_LE()  FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UShort )
+#define FT_GET_LONG_LE()    FT_GET_MACRO( FT_Stream_GetULongLE, FT_Long )
+#define FT_GET_ULONG_LE()   FT_GET_MACRO( FT_Stream_GetULongLE, FT_ULong )
 #endif
 
 #define FT_READ_MACRO( func, type, var )        \
@@ -312,17 +312,17 @@
 
 #define FT_READ_BYTE( var )       FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var )
 #define FT_READ_CHAR( var )       FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var )
-#define FT_READ_SHORT( var )      FT_READ_MACRO( FT_Stream_ReadShort, FT_Short, var )
-#define FT_READ_USHORT( var )     FT_READ_MACRO( FT_Stream_ReadShort, FT_UShort, var )
-#define FT_READ_OFF3( var )       FT_READ_MACRO( FT_Stream_ReadOffset, FT_Long, var )
-#define FT_READ_UOFF3( var )      FT_READ_MACRO( FT_Stream_ReadOffset, FT_ULong, var )
-#define FT_READ_LONG( var )       FT_READ_MACRO( FT_Stream_ReadLong, FT_Long, var )
-#define FT_READ_ULONG( var )      FT_READ_MACRO( FT_Stream_ReadLong, FT_ULong, var )
+#define FT_READ_SHORT( var )      FT_READ_MACRO( FT_Stream_ReadUShort, FT_Short, var )
+#define FT_READ_USHORT( var )     FT_READ_MACRO( FT_Stream_ReadUShort, FT_UShort, var )
+#define FT_READ_OFF3( var )       FT_READ_MACRO( FT_Stream_ReadUOffset, FT_Long, var )
+#define FT_READ_UOFF3( var )      FT_READ_MACRO( FT_Stream_ReadUOffset, FT_ULong, var )
+#define FT_READ_LONG( var )       FT_READ_MACRO( FT_Stream_ReadULong, FT_Long, var )
+#define FT_READ_ULONG( var )      FT_READ_MACRO( FT_Stream_ReadULong, FT_ULong, var )
 
-#define FT_READ_SHORT_LE( var )   FT_READ_MACRO( FT_Stream_ReadShortLE, FT_Short, var )
-#define FT_READ_USHORT_LE( var )  FT_READ_MACRO( FT_Stream_ReadShortLE, FT_UShort, var )
-#define FT_READ_LONG_LE( var )    FT_READ_MACRO( FT_Stream_ReadLongLE, FT_Long, var )
-#define FT_READ_ULONG_LE( var )   FT_READ_MACRO( FT_Stream_ReadLongLE, FT_ULong, var )
+#define FT_READ_SHORT_LE( var )   FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_Short, var )
+#define FT_READ_USHORT_LE( var )  FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_UShort, var )
+#define FT_READ_LONG_LE( var )    FT_READ_MACRO( FT_Stream_ReadULongLE, FT_Long, var )
+#define FT_READ_ULONG_LE( var )   FT_READ_MACRO( FT_Stream_ReadULongLE, FT_ULong, var )
 
 
 #ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
@@ -431,25 +431,25 @@
   FT_BASE( FT_Char )
   FT_Stream_GetChar( FT_Stream  stream );
 
-  /* read a 16-bit big-endian integer from an entered frame */
-  FT_BASE( FT_Short )
-  FT_Stream_GetShort( FT_Stream  stream );
+  /* read a 16-bit big-endian unsigned integer from an entered frame */
+  FT_BASE( FT_UShort )
+  FT_Stream_GetUShort( FT_Stream  stream );
 
-  /* read a 24-bit big-endian integer from an entered frame */
-  FT_BASE( FT_Long )
-  FT_Stream_GetOffset( FT_Stream  stream );
+  /* read a 24-bit big-endian unsigned integer from an entered frame */
+  FT_BASE( FT_ULong )
+  FT_Stream_GetUOffset( FT_Stream  stream );
 
-  /* read a 32-bit big-endian integer from an entered frame */
-  FT_BASE( FT_Long )
-  FT_Stream_GetLong( FT_Stream  stream );
+  /* read a 32-bit big-endian unsigned integer from an entered frame */
+  FT_BASE( FT_ULong )
+  FT_Stream_GetULong( FT_Stream  stream );
 
-  /* read a 16-bit little-endian integer from an entered frame */
-  FT_BASE( FT_Short )
-  FT_Stream_GetShortLE( FT_Stream  stream );
+  /* read a 16-bit little-endian unsigned integer from an entered frame */
+  FT_BASE( FT_UShort )
+  FT_Stream_GetUShortLE( FT_Stream  stream );
 
-  /* read a 32-bit little-endian integer from an entered frame */
-  FT_BASE( FT_Long )
-  FT_Stream_GetLongLE( FT_Stream  stream );
+  /* read a 32-bit little-endian unsigned integer from an entered frame */
+  FT_BASE( FT_ULong )
+  FT_Stream_GetULongLE( FT_Stream  stream );
 
 
   /* read a byte from a stream */
@@ -457,29 +457,29 @@
   FT_Stream_ReadChar( FT_Stream  stream,
                       FT_Error*  error );
 
-  /* read a 16-bit big-endian integer from a stream */
-  FT_BASE( FT_Short )
-  FT_Stream_ReadShort( FT_Stream  stream,
+  /* read a 16-bit big-endian unsigned integer from a stream */
+  FT_BASE( FT_UShort )
+  FT_Stream_ReadUShort( FT_Stream  stream,
                        FT_Error*  error );
 
-  /* read a 24-bit big-endian integer from a stream */
-  FT_BASE( FT_Long )
-  FT_Stream_ReadOffset( FT_Stream  stream,
+  /* read a 24-bit big-endian unsigned integer from a stream */
+  FT_BASE( FT_ULong )
+  FT_Stream_ReadUOffset( FT_Stream  stream,
                         FT_Error*  error );
 
   /* read a 32-bit big-endian integer from a stream */
-  FT_BASE( FT_Long )
-  FT_Stream_ReadLong( FT_Stream  stream,
+  FT_BASE( FT_ULong )
+  FT_Stream_ReadULong( FT_Stream  stream,
                       FT_Error*  error );
 
-  /* read a 16-bit little-endian integer from a stream */
-  FT_BASE( FT_Short )
-  FT_Stream_ReadShortLE( FT_Stream  stream,
+  /* read a 16-bit little-endian unsigned integer from a stream */
+  FT_BASE( FT_UShort )
+  FT_Stream_ReadUShortLE( FT_Stream  stream,
                          FT_Error*  error );
 
-  /* read a 32-bit little-endian integer from a stream */
-  FT_BASE( FT_Long )
-  FT_Stream_ReadLongLE( FT_Stream  stream,
+  /* read a 32-bit little-endian unsigned integer from a stream */
+  FT_BASE( FT_ULong )
+  FT_Stream_ReadULongLE( FT_Stream  stream,
                         FT_Error*  error );
 
   /* Read a structure from a stream.  The structure must be described */
diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h
index e9b383a..fbefdbd 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tracing handling (specification only).                               */
 /*                                                                         */
-/*  Copyright 2002, 2004, 2005, 2006, 2007 by                              */
+/*  Copyright 2002, 2004-2007, 2009, 2011 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -135,5 +135,10 @@
 FT_TRACE_DEF( gxvprop )
 FT_TRACE_DEF( gxvlcar )
 
+  /* autofit components */
+FT_TRACE_DEF( afcjk )
+FT_TRACE_DEF( aflatin )
+FT_TRACE_DEF( aflatin2 )
+FT_TRACE_DEF( afwarp )
 
 /* END */
diff --git a/include/freetype/tttables.h b/include/freetype/tttables.h
index 4610e50..02236c2 100644
--- a/include/freetype/tttables.h
+++ b/include/freetype/tttables.h
@@ -5,7 +5,7 @@
 /*    Basic SFNT/TrueType tables definitions and interface                 */
 /*    (specification only).                                                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 by       */
+/*  Copyright 1996-2005, 2008-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -687,12 +687,16 @@
   *     The index of an SFNT table.  The function returns
   *     FT_Err_Table_Missing for an invalid value.
   *
-  * @output:
+  * @inout:
   *   tag ::
-  *     The name tag of the SFNT table.
+  *     The name tag of the SFNT table.  If the value is NULL, `table_index'
+  *     is ignored, and `length' returns the number of SFNT tables in the
+  *     font.
   *
+  * @output:
   *   length ::
-  *     The length of the SFNT table.
+  *     The length of the SFNT table (or the number of SFNT tables, depending
+  *     on `tag').
   *
   * @return:
   *   FreeType error code.  0~means success.
diff --git a/src/autofit/afangles.c b/src/autofit/afangles.c
index e2360d1..790af17 100644
--- a/src/autofit/afangles.c
+++ b/src/autofit/afangles.c
@@ -5,7 +5,7 @@
 /*    Routines used to compute vector angles with limited accuracy         */
 /*    and very high speed.  It also contains sorting routines (body).      */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006 by                                    */
+/*  Copyright 2003-2006, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -77,7 +77,7 @@
       return 1 - 2 * ( delta < 0 );
   }
 
-#endif
+#endif /* 0 */
 
 
   /*
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index f3b1067..0acef9c 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for CJK script (body).                  */
 /*                                                                         */
-/*  Copyright 2006, 2007, 2008, 2009, 2010 by                              */
+/*  Copyright 2006-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,22 +22,38 @@
    *
    */
 
+#include <ft2build.h>
+#include FT_ADVANCES_H
+#include FT_INTERNAL_DEBUG_H
+
 #include "aftypes.h"
 #include "aflatin.h"
 
 
 #ifdef AF_CONFIG_OPTION_CJK
 
+#undef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+
 #include "afcjk.h"
 #include "aferrors.h"
 
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
 #include "afwarp.h"
 #endif
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_afcjk
+
+
+  /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
   /*****              C J K   G L O B A L   M E T R I C S              *****/
@@ -45,24 +61,504 @@
   /*************************************************************************/
   /*************************************************************************/
 
+
+  /* Basically the Latin version with AF_CJKMetrics */
+  /* to replace AF_LatinMetrics.                    */
+
+  FT_LOCAL_DEF( void )
+  af_cjk_metrics_init_widths( AF_CJKMetrics  metrics,
+                              FT_Face        face,
+                              FT_ULong       charcode )
+  {
+    /* scan the array of segments in each direction */
+    AF_GlyphHintsRec  hints[1];
+
+
+    af_glyph_hints_init( hints, face->memory );
+
+    metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
+    metrics->axis[AF_DIMENSION_VERT].width_count = 0;
+
+    {
+      FT_Error          error;
+      FT_UInt           glyph_index;
+      int               dim;
+      AF_CJKMetricsRec  dummy[1];
+      AF_Scaler         scaler = &dummy->root.scaler;
+
+
+      glyph_index = FT_Get_Char_Index( face, charcode );
+      if ( glyph_index == 0 )
+        goto Exit;
+
+      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+      if ( error || face->glyph->outline.n_points <= 0 )
+        goto Exit;
+
+      FT_ZERO( dummy );
+
+      dummy->units_per_em = metrics->units_per_em;
+
+      scaler->x_scale = 0x10000L;
+      scaler->y_scale = 0x10000L;
+      scaler->x_delta = 0;
+      scaler->y_delta = 0;
+
+      scaler->face        = face;
+      scaler->render_mode = FT_RENDER_MODE_NORMAL;
+      scaler->flags       = 0;
+
+      af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+
+      error = af_glyph_hints_reload( hints, &face->glyph->outline );
+      if ( error )
+        goto Exit;
+
+      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+      {
+        AF_CJKAxis    axis    = &metrics->axis[dim];
+        AF_AxisHints  axhints = &hints->axis[dim];
+        AF_Segment    seg, limit, link;
+        FT_UInt       num_widths = 0;
+
+
+        error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim );
+        if ( error )
+          goto Exit;
+
+        af_latin_hints_link_segments( hints, (AF_Dimension)dim );
+
+        seg   = axhints->segments;
+        limit = seg + axhints->num_segments;
+
+        for ( ; seg < limit; seg++ )
+        {
+          link = seg->link;
+
+          /* we only consider stem segments there! */
+          if ( link && link->link == seg && link > seg )
+          {
+            FT_Pos  dist;
+
+
+            dist = seg->pos - link->pos;
+            if ( dist < 0 )
+              dist = -dist;
+
+            if ( num_widths < AF_CJK_MAX_WIDTHS )
+              axis->widths[num_widths++].org = dist;
+          }
+        }
+
+        af_sort_widths( num_widths, axis->widths );
+        axis->width_count = num_widths;
+      }
+
+    Exit:
+      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+      {
+        AF_CJKAxis  axis = &metrics->axis[dim];
+        FT_Pos      stdw;
+
+
+        stdw = ( axis->width_count > 0 ) ? axis->widths[0].org
+                                         : AF_LATIN_CONSTANT( metrics, 50 );
+
+        /* let's try 20% of the smallest width */
+        axis->edge_distance_threshold = stdw / 5;
+        axis->standard_width          = stdw;
+        axis->extra_light             = 0;
+      }
+    }
+
+    af_glyph_hints_done( hints );
+  }
+
+
+#define AF_CJK_MAX_TEST_CHARACTERS  32
+
+
+  /* Each blue zone has two types of fill and unfill, this is, */
+  /* filling the entire glyph square or not.                   */
+
+  enum
+  {
+    AF_CJK_BLUE_TYPE_FILL,
+    AF_CJK_BLUE_TYPE_UNFILL,
+    AF_CJK_BLUE_TYPE_MAX
+  };
+
+
+  /* Put some common and representative Han Ideographs characters here. */
+  static const FT_ULong af_cjk_hani_blue_chars[AF_CJK_BLUE_MAX]
+                                              [AF_CJK_BLUE_TYPE_MAX]
+                                              [AF_CJK_MAX_TEST_CHARACTERS] =
+  {
+    {
+      {
+        0x4ED6, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
+        0x5BF9, 0x5C0D, 0x5C31, 0x5E2D, 0x6211, 0x65F6, 0x6642, 0x6703,
+        0x6765, 0x70BA, 0x80FD, 0x8230, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
+        0x9F4A /* top fill */
+      },
+      {
+        0x519B, 0x540C, 0x5DF2, 0x613F, 0x65E2, 0x661F, 0x662F, 0x666F,
+        0x6C11, 0x7167, 0x73B0, 0x73FE, 0x7406, 0x7528, 0x7F6E, 0x8981,
+        0x8ECD, 0x90A3, 0x914D, 0x91CC, 0x958B, 0x96F7, 0x9732, 0x9762,
+        0x987E /* top unfill */
+      }
+    },
+    {
+      {
+        0x4E2A, 0x4E3A, 0x4EBA, 0x4ED6, 0x4EE5, 0x4EEC, 0x4F60, 0x4F86,
+        0x500B, 0x5011, 0x5230, 0x548C, 0x5927, 0x5BF9, 0x5C0D, 0x5C31,
+        0x6211, 0x65F6, 0x6642, 0x6709, 0x6765, 0x70BA, 0x8981, 0x8AAA,
+        0x8BF4 /* bottom fill */
+      },
+      {
+        0x4E3B, 0x4E9B, 0x56E0, 0x5B83, 0x60F3, 0x610F, 0x7406, 0x751F,
+        0x7576, 0x770B, 0x7740, 0x7F6E, 0x8005, 0x81EA, 0x8457, 0x88E1,
+        0x8FC7, 0x8FD8, 0x8FDB, 0x9032, 0x904E, 0x9053, 0x9084, 0x91CC,
+        0x9762 /* bottom unfill */
+      }
+    },
+#ifndef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+      { {0x0000}, {0x0000} },
+      { {0x0000}, {0x0000} }
+#else
+    {
+      {
+        0x4E9B, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
+        0x5979, 0x5C06, 0x5C07, 0x5C31, 0x5E74, 0x5F97, 0x60C5, 0x6700,
+        0x6837, 0x6A23, 0x7406, 0x80FD, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
+        0x901A /* left fill */
+      },
+      {
+        0x5373, 0x5417, 0x5427, 0x542C, 0x5462, 0x54C1, 0x54CD, 0x55CE,
+        0x5E08, 0x5E2B, 0x6536, 0x65AD, 0x65B7, 0x660E, 0x773C, 0x9593,
+        0x95F4, 0x9645, 0x9648, 0x9650, 0x9664, 0x9673, 0x968F, 0x969B,
+        0x96A8 /* left unfill */
+      }
+    },
+    {
+      {
+        0x4E8B, 0x524D, 0x5B78, 0x5C06, 0x5C07, 0x60C5, 0x60F3, 0x6216,
+        0x653F, 0x65AF, 0x65B0, 0x6837, 0x6A23, 0x6C11, 0x6C92, 0x6CA1,
+        0x7136, 0x7279, 0x73B0, 0x73FE, 0x7403, 0x7B2C, 0x7D93, 0x8C01,
+        0x8D77 /* right fill */
+      },
+      {
+        0x4F8B, 0x5225, 0x522B, 0x5236, 0x52A8, 0x52D5, 0x5417, 0x55CE,
+        0x589E, 0x6307, 0x660E, 0x671D, 0x671F, 0x6784, 0x7269, 0x786E,
+        0x79CD, 0x8ABF, 0x8C03, 0x8CBB, 0x8D39, 0x90A3, 0x90FD, 0x9593,
+        0x95F4 /* right unfill */
+      }
+    }
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+  };
+
+
+  /* Calculate blue zones for all the CJK_BLUE_XXX's. */
+
+  static void
+  af_cjk_metrics_init_blues( AF_CJKMetrics   metrics,
+                             FT_Face         face,
+                             const FT_ULong  blue_chars
+                                               [AF_CJK_BLUE_MAX]
+                                               [AF_CJK_BLUE_TYPE_MAX]
+                                               [AF_CJK_MAX_TEST_CHARACTERS] )
+  {
+    FT_Pos        fills[AF_CJK_MAX_TEST_CHARACTERS];
+    FT_Pos        flats[AF_CJK_MAX_TEST_CHARACTERS];
+
+    FT_Int        num_fills;
+    FT_Int        num_flats;
+
+    FT_Int        bb;
+    AF_CJKBlue    blue;
+    FT_Error      error;
+    AF_CJKAxis    axis;
+    FT_GlyphSlot  glyph = face->glyph;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    FT_String*  cjk_blue_name[AF_CJK_BLUE_MAX] = {
+      (FT_String*)"top",
+      (FT_String*)"bottom",
+      (FT_String*)"left",
+      (FT_String*)"right"
+    };
+    FT_String*  cjk_blue_type_name[AF_CJK_BLUE_TYPE_MAX] = {
+      (FT_String*)"filled",
+      (FT_String*)"unfilled"
+    };
+#endif
+
+
+    /* We compute the blues simply by loading each character from the */
+    /* `blue_chars[blues]' string, then computing its extreme points  */
+    /* (depending blue zone type etc.).                               */
+
+    FT_TRACE5(( "cjk blue zones computation\n" ));
+    FT_TRACE5(( "------------------------------------------------\n" ));
+
+    for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ )
+    {
+      FT_Int   fill_type;
+      FT_Pos*  blue_ref;
+      FT_Pos*  blue_shoot;
+
+
+      num_fills = 0;
+      num_flats = 0;
+
+      for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ )
+      {
+        const FT_ULong*  p     = blue_chars[bb][fill_type];
+        const FT_ULong*  limit = p + AF_CJK_MAX_TEST_CHARACTERS;
+        FT_Bool          fill  = FT_BOOL(
+                                   fill_type == AF_CJK_BLUE_TYPE_FILL );
+
+
+        FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
+                                        cjk_blue_type_name[fill_type] ));
+
+
+        for ( ; p < limit && *p; p++ )
+        {
+          FT_UInt     glyph_index;
+          FT_Pos      best_pos; /* same as points.y */
+          FT_Int      best_point;
+          FT_Vector*  points;
+
+
+          FT_TRACE5(( "  U+%lX...", *p ));
+
+          /* load the character in the face -- skip unknown or empty ones */
+          glyph_index = FT_Get_Char_Index( face, *p );
+          if ( glyph_index == 0 )
+          {
+            FT_TRACE5(( "unavailable\n" ));
+            continue;
+          }
+
+          error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+          if ( error || glyph->outline.n_points <= 0 )
+          {
+            FT_TRACE5(( "no outline\n" ));
+            continue;
+          }
+
+          /* now compute min or max point indices and coordinates */
+          points     = glyph->outline.points;
+          best_point = -1;
+          best_pos   = 0;  /* make compiler happy */
+
+          {
+            FT_Int  nn;
+            FT_Int  first = 0;
+            FT_Int  last  = -1;
+
+
+            for ( nn = 0;
+                  nn < glyph->outline.n_contours;
+                  first = last + 1, nn++ )
+            {
+              FT_Int  pp;
+
+
+              last = glyph->outline.contours[nn];
+
+              /* Avoid single-point contours since they are never       */
+              /* rasterized.  In some fonts, they correspond to mark    */
+              /* attachment points which are way outside of the glyph's */
+              /* real outline.                                          */
+              if ( last <= first )
+                continue;
+
+              switch ( bb )
+              {
+              case AF_CJK_BLUE_TOP:
+                for ( pp = first; pp <= last; pp++ )
+                  if ( best_point < 0 || points[pp].y > best_pos )
+                  {
+                    best_point = pp;
+                    best_pos   = points[pp].y;
+                  }
+                break;
+
+              case AF_CJK_BLUE_BOTTOM:
+                for ( pp = first; pp <= last; pp++ )
+                  if ( best_point < 0 || points[pp].y < best_pos )
+                  {
+                    best_point = pp;
+                    best_pos   = points[pp].y;
+                  }
+                break;
+
+              case AF_CJK_BLUE_LEFT:
+                for ( pp = first; pp <= last; pp++ )
+                  if ( best_point < 0 || points[pp].x < best_pos )
+                  {
+                    best_point = pp;
+                    best_pos   = points[pp].x;
+                  }
+                break;
+
+              case AF_CJK_BLUE_RIGHT:
+                for ( pp = first; pp <= last; pp++ )
+                  if ( best_point < 0 || points[pp].x > best_pos )
+                  {
+                    best_point = pp;
+                    best_pos   = points[pp].x;
+                  }
+                break;
+
+              default:
+                ;
+              }
+            }
+            FT_TRACE5(( "best_pos=%5ld\n", best_pos ));
+          }
+
+          if ( fill )
+            fills[num_fills++] = best_pos;
+          else
+            flats[num_flats++] = best_pos;
+        }
+      }
+
+      if ( num_flats == 0 && num_fills == 0 )
+      {
+        /*
+         *  we couldn't find a single glyph to compute this blue zone,
+         *  we will simply ignore it then
+         */
+        FT_TRACE5(( "empty\n" ));
+        continue;
+      }
+
+      /* we have computed the contents of the `fill' and `flats' tables, */
+      /* now determine the reference position of the blue --             */
+      /* we simply take the median value after a simple sort             */
+      af_sort_pos( num_flats, flats );
+      af_sort_pos( num_fills, fills );
+
+      if ( AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_BOTTOM == bb )
+        axis = &metrics->axis[AF_DIMENSION_VERT];
+      else
+        axis = &metrics->axis[AF_DIMENSION_HORZ];
+
+      blue       = & axis->blues[axis->blue_count];
+      blue_ref   = & blue->ref.org;
+      blue_shoot = & blue->shoot.org;
+
+      axis->blue_count++;
+      if ( num_flats == 0 )
+      {
+        *blue_ref   = fills[num_fills / 2];
+        *blue_shoot = fills[num_fills / 2];
+      }
+      else if ( num_fills == 0 )
+      {
+        *blue_ref   = flats[num_flats / 2];
+        *blue_shoot = flats[num_flats / 2];
+      }
+      else
+      {
+        *blue_ref   = fills[num_fills / 2];
+        *blue_shoot = flats[num_flats / 2];
+      }
+
+      /* make sure blue_ref >= blue_shoot for top/right or */
+      /* vice versa for bottom/left                        */
+      if ( *blue_shoot != *blue_ref )
+      {
+        FT_Pos   ref       = *blue_ref;
+        FT_Pos   shoot     = *blue_shoot;
+        FT_Bool  under_ref = FT_BOOL( shoot < ref );
+
+
+        if ( (AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_RIGHT == bb) ^ under_ref )
+          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+      }
+
+      blue->flags = 0;
+      if ( AF_CJK_BLUE_TOP == bb )
+        blue->flags |= AF_CJK_BLUE_IS_TOP;
+      else if ( AF_CJK_BLUE_RIGHT == bb )
+        blue->flags |= AF_CJK_BLUE_IS_RIGHT;
+
+      FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n",
+                  cjk_blue_name[bb], *blue_ref, *blue_shoot ));
+    }
+
+    return;
+  }
+
+
+  /* Basically the Latin version with type AF_CJKMetrics for metrics. */
+  FT_LOCAL_DEF( void )
+  af_cjk_metrics_check_digits( AF_CJKMetrics  metrics,
+                               FT_Face        face )
+  {
+    FT_UInt   i;
+    FT_Bool   started = 0, same_width = 1;
+    FT_Fixed  advance, old_advance = 0;
+
+
+    /* check whether all ASCII digits have the same advance width; */
+    /* digit `0' is 0x30 in all supported charmaps                 */
+    for ( i = 0x30; i <= 0x39; i++ )
+    {
+      FT_UInt  glyph_index;
+
+
+      glyph_index = FT_Get_Char_Index( face, i );
+      if ( glyph_index == 0 )
+        continue;
+
+      if ( FT_Get_Advance( face, glyph_index,
+                           FT_LOAD_NO_SCALE         |
+                           FT_LOAD_NO_HINTING       |
+                           FT_LOAD_IGNORE_TRANSFORM,
+                           &advance ) )
+        continue;
+
+      if ( started )
+      {
+        if ( advance != old_advance )
+        {
+          same_width = 0;
+          break;
+        }
+      }
+      else
+      {
+        old_advance = advance;
+        started     = 1;
+      }
+    }
+
+    metrics->root.digits_have_same_width = same_width;
+  }
+
+
   FT_LOCAL_DEF( FT_Error )
-  af_cjk_metrics_init( AF_LatinMetrics  metrics,
-                       FT_Face          face )
+  af_cjk_metrics_init( AF_CJKMetrics  metrics,
+                       FT_Face        face )
   {
     FT_CharMap  oldmap = face->charmap;
 
 
     metrics->units_per_em = face->units_per_EM;
 
-    /* TODO are there blues? */
-
     if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
       face->charmap = NULL;
     else
     {
-      /* latin's version would suffice */
-      af_latin_metrics_init_widths( metrics, face, 0x7530 );
-      af_latin_metrics_check_digits( metrics, face );
+      af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+      af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars );
+      af_cjk_metrics_check_digits( metrics, face );
     }
 
     FT_Set_Charmap( face, oldmap );
@@ -72,31 +568,100 @@
 
 
   static void
-  af_cjk_metrics_scale_dim( AF_LatinMetrics  metrics,
-                            AF_Scaler        scaler,
-                            AF_Dimension     dim )
+  af_cjk_metrics_scale_dim( AF_CJKMetrics  metrics,
+                            AF_Scaler      scaler,
+                            AF_Dimension   dim )
   {
-    AF_LatinAxis  axis;
+    FT_Fixed    scale;
+    FT_Pos      delta;
+    AF_CJKAxis  axis;
+    FT_UInt     nn;
 
 
     axis = &metrics->axis[dim];
 
     if ( dim == AF_DIMENSION_HORZ )
     {
-      axis->scale = scaler->x_scale;
-      axis->delta = scaler->x_delta;
+      scale = scaler->x_scale;
+      delta = scaler->x_delta;
     }
     else
     {
-      axis->scale = scaler->y_scale;
-      axis->delta = scaler->y_delta;
+      scale = scaler->y_scale;
+      delta = scaler->y_delta;
+    }
+
+    if ( axis->org_scale == scale && axis->org_delta == delta )
+      return;
+
+    axis->org_scale = scale;
+    axis->org_delta = delta;
+
+    axis->scale = scale;
+    axis->delta = delta;
+
+    /* scale the blue zones */
+    for ( nn = 0; nn < axis->blue_count; nn++ )
+    {
+      AF_CJKBlue  blue = &axis->blues[nn];
+      FT_Pos      dist;
+
+
+      blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
+      blue->ref.fit   = blue->ref.cur;
+      blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
+      blue->shoot.fit = blue->shoot.cur;
+      blue->flags    &= ~AF_CJK_BLUE_ACTIVE;
+
+      /* 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 );
+      if ( dist <= 48 && dist >= -48 )
+      {
+        FT_Pos  delta1, delta2;
+
+
+        blue->ref.fit  = FT_PIX_ROUND( blue->ref.cur );
+
+        /* shoot is under shoot for cjk */
+        delta1 = FT_DivFix( blue->ref.fit, scale ) - blue->shoot.org;
+        delta2 = delta1;
+        if ( delta1 < 0 )
+          delta2 = -delta2;
+
+        delta2 = FT_MulFix( delta2, scale );
+
+        FT_TRACE5(( "delta: %d", delta1 ));
+        if ( delta2 < 32 )
+          delta2 = 0;
+#if 0
+        else if ( delta2 < 64 )
+          delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
+#endif
+        else
+          delta2 = FT_PIX_ROUND( delta2 );
+        FT_TRACE5(( "/%d\n", delta2 ));
+
+        if ( delta1 < 0 )
+          delta2 = -delta2;
+
+        blue->shoot.fit = blue->ref.fit - delta2;
+
+        FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]: "
+                     "ref: cur=%.2f fit=%.2f shoot: cur=%.2f fit=%.2f\n",
+                       ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
+                       nn, blue->ref.org, blue->shoot.org,
+                       blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+                       blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
+
+        blue->flags |= AF_CJK_BLUE_ACTIVE;
+      }
     }
   }
 
 
   FT_LOCAL_DEF( void )
-  af_cjk_metrics_scale( AF_LatinMetrics  metrics,
-                        AF_Scaler        scaler )
+  af_cjk_metrics_scale( AF_CJKMetrics  metrics,
+                        AF_Scaler      scaler )
   {
     metrics->root.scaler = *scaler;
 
@@ -329,7 +894,7 @@
     AF_AxisHints  axis   = &hints->axis[dim];
     FT_Error      error  = AF_Err_Ok;
     FT_Memory     memory = hints->memory;
-    AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
+    AF_CJKAxis    laxis  = &((AF_CJKMetrics)hints->metrics)->axis[dim];
 
     AF_Segment    segments      = axis->segments;
     AF_Segment    segment_limit = segments + axis->num_segments;
@@ -601,9 +1166,96 @@
   }
 
 
+  FT_LOCAL_DEF( void )
+  af_cjk_hints_compute_blue_edges( AF_GlyphHints  hints,
+                                   AF_CJKMetrics  metrics,
+                                   AF_Dimension   dim )
+  {
+    AF_AxisHints  axis       = &hints->axis[dim];
+    AF_Edge       edge       = axis->edges;
+    AF_Edge       edge_limit = edge + axis->num_edges;
+    AF_CJKAxis    cjk        = &metrics->axis[dim];
+    FT_Fixed      scale      = cjk->scale;
+    FT_Pos        best_dist0;  /* initial threshold */
+
+
+    /* compute the initial threshold as a fraction of the EM size */
+    best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
+
+    if ( best_dist0 > 64 / 2 ) /* maximum 1/2 pixel */
+      best_dist0 = 64 / 2;
+
+    /* compute which blue zones are active, i.e. have their scaled */
+    /* size < 3/4 pixels                                           */
+
+    /* If the distant between an edge and a blue zone is shorter than */
+    /* best_dist0, set the blue zone for the edge.  Then search for   */
+    /* the blue zone with the smallest best_dist to the edge.         */
+
+    for ( ; edge < edge_limit; edge++ )
+    {
+      FT_UInt   bb;
+      AF_Width  best_blue = NULL;
+      FT_Pos    best_dist = best_dist0;
+
+
+      for ( bb = 0; bb < cjk->blue_count; bb++ )
+      {
+        AF_CJKBlue  blue = cjk->blues + bb;
+        FT_Bool     is_top_right_blue, is_major_dir;
+
+
+        /* skip inactive blue zones (i.e., those that are too small) */
+        if ( !( blue->flags & AF_CJK_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_right_blue  =
+          FT_BOOL( ( ( blue->flags & AF_CJK_BLUE_IS_TOP )   != 0 ) ||
+                   ( ( blue->flags & AF_CJK_BLUE_IS_RIGHT ) != 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_right_blue ^ is_major_dir )
+        {
+          FT_Pos    dist;
+          AF_Width  compare;
+
+
+          /* Compare the edge to the closest blue zone type */
+          if ( FT_ABS( edge->fpos - blue->ref.org ) >
+               FT_ABS( edge->fpos - blue->shoot.org ) )
+            compare = &blue->shoot;
+          else
+            compare = &blue->ref;
+
+          dist = edge->fpos - compare->org;
+          if ( dist < 0 )
+            dist = -dist;
+
+          dist = FT_MulFix( dist, scale );
+          if ( dist < best_dist )
+          {
+            best_dist = dist;
+            best_blue = compare;
+          }
+        }
+      }
+
+      if ( best_blue )
+        edge->blue_edge = best_blue;
+    }
+  }
+
+
   FT_LOCAL_DEF( FT_Error )
-  af_cjk_hints_init( AF_GlyphHints    hints,
-                     AF_LatinMetrics  metrics )
+  af_cjk_hints_init( AF_GlyphHints  hints,
+                     AF_CJKMetrics  metrics )
   {
     FT_Render_Mode  mode;
     FT_UInt32       scaler_flags, other_flags;
@@ -623,7 +1275,7 @@
     /* compute flags depending on render mode, etc. */
     mode = metrics->root.scaler.render_mode;
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
     if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
       metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
 #endif
@@ -728,11 +1380,11 @@
                              AF_Edge_Flags  base_flags,
                              AF_Edge_Flags  stem_flags )
   {
-    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
-    AF_LatinAxis     axis     = & metrics->axis[dim];
-    FT_Pos           dist     = width;
-    FT_Int           sign     = 0;
-    FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
+    AF_CJKMetrics  metrics  = (AF_CJKMetrics) hints->metrics;
+    AF_CJKAxis     axis     = & metrics->axis[dim];
+    FT_Pos         dist     = width;
+    FT_Int         sign     = 0;
+    FT_Bool        vertical = FT_BOOL( dim == AF_DIMENSION_VERT );
 
     FT_UNUSED( base_flags );
     FT_UNUSED( stem_flags );
@@ -1025,8 +1677,62 @@
     AF_Edge       anchor   = 0;
     FT_Pos        delta    = 0;
     FT_Int        skipped  = 0;
+    FT_Bool       has_last_stem = FALSE;
+    FT_Pos        last_stem_pos = 0;
 
 
+    /* we begin by aligning all stems relative to the blue zone */
+    FT_TRACE5(( "==== cjk hinting %s edges =====\n",
+          dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
+
+    if ( AF_HINTS_DO_BLUES( hints ) )
+    {
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        AF_Width  blue;
+        AF_Edge   edge1, edge2;
+
+
+        if ( edge->flags & AF_EDGE_DONE )
+          continue;
+
+        blue  = edge->blue_edge;
+        edge1 = NULL;
+        edge2 = edge->link;
+
+        if ( blue )
+        {
+          edge1 = edge;
+        }
+        else if ( edge2 && edge2->blue_edge )
+        {
+          blue  = edge2->blue_edge;
+          edge1 = edge2;
+          edge2 = edge;
+        }
+
+        if ( !edge1 )
+          continue;
+
+        FT_TRACE5(( "CJKBLUE: edge %d @%d (opos=%.2f) snapped to (%.2f), "
+                 "was (%.2f)\n",
+                 edge1-edges, edge1->fpos, edge1->opos / 64.0, blue->fit / 64.0,
+                 edge1->pos / 64.0 ));
+
+        edge1->pos    = blue->fit;
+        edge1->flags |= AF_EDGE_DONE;
+
+        if ( edge2 && !edge2->blue_edge )
+        {
+          af_cjk_align_linked_edge( hints, dim, edge1, edge2 );
+          edge2->flags |= AF_EDGE_DONE;
+        }
+
+        if ( !anchor )
+          anchor = edge;
+      }
+    }
+
     /* now we align all stem edges. */
     for ( edge = edges; edge < edge_limit; edge++ )
     {
@@ -1044,12 +1750,43 @@
         continue;
       }
 
+      /* Some CJK characters have so many stems that
+       * the hinter is likely to merge two adjacent ones.
+       * To solve this problem, if either edge of a stem
+       * is too close to the previous one, we avoid
+       * aligning the two edges, but rather interpolate
+       * their locations at the end of this function in
+       * order to preserve the space between the stems.
+       */
+      if ( has_last_stem                       &&
+           ( edge->pos  < last_stem_pos + 64 ||
+             edge2->pos < last_stem_pos + 64 ) )
+      {
+        skipped++;
+        continue;
+      }
+
       /* now align the stem */
+      /* 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 ));
+
+        af_cjk_align_linked_edge( hints, dim, edge2, edge );
+        edge->flags |= AF_EDGE_DONE;
+        continue;
+      }
 
       if ( edge2 < edge )
       {
         af_cjk_align_linked_edge( hints, dim, edge2, edge );
         edge->flags |= AF_EDGE_DONE;
+        /* We rarely reaches here it seems;
+         * usually the two edges belonging
+         * to one stem are marked as DONE together
+         */
+        has_last_stem = TRUE;
+        last_stem_pos = edge->pos;
         continue;
       }
 
@@ -1142,6 +1879,8 @@
       anchor = edge;
       edge->flags  |= AF_EDGE_DONE;
       edge2->flags |= AF_EDGE_DONE;
+      has_last_stem = TRUE;
+      last_stem_pos = edge2->pos;
     }
 
     /* make sure that lowercase m's maintain their symmetry */
@@ -1361,9 +2100,9 @@
 
 
   FT_LOCAL_DEF( FT_Error )
-  af_cjk_hints_apply( AF_GlyphHints    hints,
-                      FT_Outline*      outline,
-                      AF_LatinMetrics  metrics )
+  af_cjk_hints_apply( AF_GlyphHints  hints,
+                      FT_Outline*    outline,
+                      AF_CJKMetrics  metrics )
   {
     FT_Error  error;
     int       dim;
@@ -1381,6 +2120,8 @@
       error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );
       if ( error )
         goto Exit;
+
+      af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_HORZ );
     }
 
     if ( AF_HINTS_DO_VERTICAL( hints ) )
@@ -1388,6 +2129,8 @@
       error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT );
       if ( error )
         goto Exit;
+
+      af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_VERT );
     }
 
     /* grid-fit the outline */
@@ -1397,7 +2140,7 @@
            ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
       {
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
         if ( dim == AF_DIMENSION_HORZ                                  &&
              metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )
         {
@@ -1406,11 +2149,13 @@
           FT_Pos        delta;
 
 
-          af_warper_compute( &warper, hints, dim, &scale, &delta );
-          af_glyph_hints_scale_dim( hints, dim, scale, delta );
+          af_warper_compute( &warper, hints, (AF_Dimension)dim,
+                             &scale, &delta );
+          af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+                                    scale, delta );
           continue;
         }
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
 
         af_cjk_hint_edges( hints, (AF_Dimension)dim );
         af_cjk_align_edge_points( hints, (AF_Dimension)dim );
@@ -1441,18 +2186,19 @@
   /*************************************************************************/
 
 
+  /* this corresponds to Unicode 6.0 */
+
   static const AF_Script_UniRangeRec  af_cjk_uniranges[] =
   {
-#if 0
-    AF_UNIRANGE_REC(  0x0100UL,  0xFFFFUL ),  /* why this? */
-#endif
     AF_UNIRANGE_REC(  0x2E80UL,  0x2EFFUL ),  /* CJK Radicals Supplement                 */
     AF_UNIRANGE_REC(  0x2F00UL,  0x2FDFUL ),  /* Kangxi Radicals                         */
+    AF_UNIRANGE_REC(  0x2FF0UL,  0x2FFFUL ),  /* Ideographic Description Characters      */
     AF_UNIRANGE_REC(  0x3000UL,  0x303FUL ),  /* CJK Symbols and Punctuation             */
     AF_UNIRANGE_REC(  0x3040UL,  0x309FUL ),  /* Hiragana                                */
     AF_UNIRANGE_REC(  0x30A0UL,  0x30FFUL ),  /* Katakana                                */
     AF_UNIRANGE_REC(  0x3100UL,  0x312FUL ),  /* Bopomofo                                */
     AF_UNIRANGE_REC(  0x3130UL,  0x318FUL ),  /* Hangul Compatibility Jamo               */
+    AF_UNIRANGE_REC(  0x3190UL,  0x319FUL ),  /* Kanbun                                  */
     AF_UNIRANGE_REC(  0x31A0UL,  0x31BFUL ),  /* Bopomofo Extended                       */
     AF_UNIRANGE_REC(  0x31C0UL,  0x31EFUL ),  /* CJK Strokes                             */
     AF_UNIRANGE_REC(  0x31F0UL,  0x31FFUL ),  /* Katakana Phonetic Extensions            */
@@ -1461,10 +2207,19 @@
     AF_UNIRANGE_REC(  0x3400UL,  0x4DBFUL ),  /* CJK Unified Ideographs Extension A      */
     AF_UNIRANGE_REC(  0x4DC0UL,  0x4DFFUL ),  /* Yijing Hexagram Symbols                 */
     AF_UNIRANGE_REC(  0x4E00UL,  0x9FFFUL ),  /* CJK Unified Ideographs                  */
+    AF_UNIRANGE_REC(  0xA960UL,  0xA97FUL ),  /* Hangul Jamo Extended-A                  */
+    AF_UNIRANGE_REC(  0xAC00UL,  0xD7AFUL ),  /* Hangul Syllables                        */
+    AF_UNIRANGE_REC(  0xD7B0UL,  0xD7FFUL ),  /* Hangul Jamo Extended-B                  */
     AF_UNIRANGE_REC(  0xF900UL,  0xFAFFUL ),  /* CJK Compatibility Ideographs            */
+    AF_UNIRANGE_REC(  0xFE10UL,  0xFE1FUL ),  /* Vertical forms                          */
     AF_UNIRANGE_REC(  0xFE30UL,  0xFE4FUL ),  /* CJK Compatibility Forms                 */
     AF_UNIRANGE_REC(  0xFF00UL,  0xFFEFUL ),  /* Halfwidth and Fullwidth Forms           */
+    AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ),  /* Kana Supplement                         */
+    AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ),  /* Tai Xuan Hing Symbols                   */
+    AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ),  /* Enclosed Ideographic Supplement         */
     AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ),  /* CJK Unified Ideographs Extension B      */
+    AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ),  /* CJK Unified Ideographs Extension C      */
+    AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ),  /* CJK Unified Ideographs Extension D      */
     AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ),  /* CJK Compatibility Ideographs Supplement */
     AF_UNIRANGE_REC(       0UL,       0UL )
   };
@@ -1474,7 +2229,7 @@
     AF_SCRIPT_CJK,
     af_cjk_uniranges,
 
-    sizeof( AF_LatinMetricsRec ),
+    sizeof( AF_CJKMetricsRec ),
 
     (AF_Script_InitMetricsFunc) af_cjk_metrics_init,
     (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,
@@ -1496,7 +2251,7 @@
     AF_SCRIPT_CJK,
     af_cjk_uniranges,
 
-    sizeof( AF_LatinMetricsRec ),
+    sizeof( AF_CJKMetricsRec ),
 
     (AF_Script_InitMetricsFunc) NULL,
     (AF_Script_ScaleMetricsFunc)NULL,
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index 0b20d4a..8416c0d 100644
--- a/src/autofit/afcjk.h
+++ b/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for CJK script (specification).         */
 /*                                                                         */
-/*  Copyright 2006, 2007 by                                                */
+/*  Copyright 2006, 2007, 2011 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,6 +20,7 @@
 #define __AFCJK_H__
 
 #include "afhints.h"
+#include "aflatin.h"
 
 
 FT_BEGIN_HEADER
@@ -29,23 +30,106 @@
 
   AF_DECLARE_SCRIPT_CLASS(af_cjk_script_class)
 
+  /* CJK (global) metrics management */
+
+  /*
+   *  CJK glyphs tend to fill the square.  So we have both vertical and
+   *  horizontal blue zones.  But some glyphs have flat bounding strokes that
+   *  leave some space between neighbour glyphs.
+   */
+  enum
+  {
+    AF_CJK_BLUE_TOP,
+    AF_CJK_BLUE_BOTTOM,
+    AF_CJK_BLUE_LEFT,
+    AF_CJK_BLUE_RIGHT,
+
+    AF_CJK_BLUE_MAX
+  };
+
+
+#define AF_CJK_MAX_WIDTHS  16
+#define AF_CJK_MAX_BLUES   AF_CJK_BLUE_MAX
+
+
+  enum
+  {
+    AF_CJK_BLUE_ACTIVE     = 1 << 0,
+    AF_CJK_BLUE_IS_TOP     = 1 << 1,
+    AF_CJK_BLUE_IS_RIGHT   = 1 << 2,
+    AF_CJK_BLUE_ADJUSTMENT = 1 << 3,  /* used for scale adjustment */
+                                      /* optimization              */
+    AF_CJK_BLUE_FLAG_MAX
+  };
+
+
+  typedef struct  AF_CJKBlueRec_
+  {
+    AF_WidthRec  ref;
+    AF_WidthRec  shoot; /* undershoot */
+    FT_UInt      flags;
+
+  } AF_CJKBlueRec, *AF_CJKBlue;
+
+
+  typedef struct  AF_CJKAxisRec_
+  {
+    FT_Fixed       scale;
+    FT_Pos         delta;
+
+    FT_UInt        width_count;
+    AF_WidthRec    widths[AF_CJK_MAX_WIDTHS];
+    FT_Pos         edge_distance_threshold;
+    FT_Pos         standard_width;
+    FT_Bool        extra_light;
+
+    /* used for horizontal metrics too for CJK */
+    FT_Bool        control_overshoot;
+    FT_UInt        blue_count;
+    AF_CJKBlueRec  blues[AF_CJK_BLUE_MAX];
+
+    FT_Fixed       org_scale;
+    FT_Pos         org_delta;
+
+  } AF_CJKAxisRec, *AF_CJKAxis;
+
+
+  typedef struct  AF_CJKMetricsRec_
+  {
+    AF_ScriptMetricsRec  root;
+    FT_UInt              units_per_em;
+    AF_CJKAxisRec        axis[AF_DIMENSION_MAX];
+
+  } AF_CJKMetricsRec, *AF_CJKMetrics;
+
 
   FT_LOCAL( FT_Error )
-  af_cjk_metrics_init( AF_LatinMetrics  metrics,
-                       FT_Face          face );
+  af_cjk_metrics_init( AF_CJKMetrics  metrics,
+                       FT_Face        face );
 
   FT_LOCAL( void )
-  af_cjk_metrics_scale( AF_LatinMetrics  metrics,
-                        AF_Scaler        scaler );
+  af_cjk_metrics_scale( AF_CJKMetrics  metrics,
+                        AF_Scaler      scaler );
 
   FT_LOCAL( FT_Error )
-  af_cjk_hints_init( AF_GlyphHints    hints,
-                     AF_LatinMetrics  metrics );
+  af_cjk_hints_init( AF_GlyphHints  hints,
+                     AF_CJKMetrics  metrics );
 
   FT_LOCAL( FT_Error )
-  af_cjk_hints_apply( AF_GlyphHints    hints,
-                      FT_Outline*      outline,
-                      AF_LatinMetrics  metrics );
+  af_cjk_hints_apply( AF_GlyphHints  hints,
+                      FT_Outline*    outline,
+                      AF_CJKMetrics  metrics );
+
+  /* Shared. called from afindic.c */
+  FT_LOCAL( void )
+  af_cjk_metrics_check_digits( AF_CJKMetrics  metrics,
+                               FT_Face        face );
+
+  FT_LOCAL( void )
+  af_cjk_metrics_init_widths( AF_CJKMetrics  metrics,
+                              FT_Face        face,
+                              FT_ULong       charcode );
+
 
 /* */
 
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index 42b2fcb..c712651 100644
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
 /*    Auto-fitter dummy routines to be used if no hinting should be        */
 /*    performed (body).                                                    */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005 by                                          */
+/*  Copyright 2003-2005, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -19,6 +19,7 @@
 
 #include "afdummy.h"
 #include "afhints.h"
+#include "aferrors.h"
 
 
   static FT_Error
@@ -27,7 +28,7 @@
   {
     af_glyph_hints_rescale( hints,
                             metrics );
-    return 0;
+    return AF_Err_Ok;
   }
 
 
@@ -38,11 +39,11 @@
     FT_UNUSED( hints );
     FT_UNUSED( outline );
 
-    return 0;
+    return AF_Err_Ok;
   }
 
 
-  AF_DEFINE_SCRIPT_CLASS(af_dummy_script_class,
+  AF_DEFINE_SCRIPT_CLASS( af_dummy_script_class,
     AF_SCRIPT_NONE,
     NULL,
 
diff --git a/src/autofit/afdummy.h b/src/autofit/afdummy.h
index b69ef43..95d8f8c 100644
--- a/src/autofit/afdummy.h
+++ b/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
 /*    Auto-fitter dummy routines to be used if no hinting should be        */
 /*    performed (specification).                                           */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005 by                                          */
+/*  Copyright 2003-2005, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -29,7 +29,7 @@
   *  be performed.  This is the default for non-latin glyphs!
   */
 
-  AF_DECLARE_SCRIPT_CLASS(af_dummy_script_class)
+  AF_DECLARE_SCRIPT_CLASS( af_dummy_script_class )
 
 /* */
 
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index 178c884..3c5f02e 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter routines to compute global hinting values (body).        */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by            */
+/*  Copyright 2003-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -31,8 +31,8 @@
 
 #ifndef FT_CONFIG_OPTION_PIC
 
-/* when updating this table, don't forget to update 
-  AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
+  /* when updating this table, don't forget to update          */
+  /* AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
 
   /* populate this list when you add new scripts */
   static AF_ScriptClass const  af_script_classes[] =
@@ -47,7 +47,7 @@
     NULL  /* do not remove */
   };
 
-#endif /* FT_CONFIG_OPTION_PIC */
+#endif /* !FT_CONFIG_OPTION_PIC */
 
   /* index of default script in `af_script_classes' */
 #define AF_SCRIPT_LIST_DEFAULT  2
@@ -85,7 +85,7 @@
     FT_UInt     ss, i;
 
 
-    /* the value 255 means `uncovered glyph' */
+    /* the value AF_SCRIPT_LIST_NONE means `uncovered glyph' */
     FT_MEM_SET( globals->glyph_scripts,
                 AF_SCRIPT_LIST_NONE,
                 globals->glyph_count );
@@ -126,9 +126,7 @@
         if ( gindex != 0                             &&
              gindex < (FT_ULong)globals->glyph_count &&
              gscripts[gindex] == AF_SCRIPT_LIST_NONE )
-        {
           gscripts[gindex] = (FT_Byte)ss;
-        }
 
         for (;;)
         {
@@ -139,9 +137,7 @@
 
           if ( gindex < (FT_ULong)globals->glyph_count &&
                gscripts[gindex] == AF_SCRIPT_LIST_NONE )
-          {
             gscripts[gindex] = (FT_Byte)ss;
-          }
         }
       }
     }
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index 2a68e19..cc6860b 100644
--- a/src/autofit/afglobal.h
+++ b/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
 /*    Auto-fitter routines to compute global hinting values                */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2007, 2009 by                              */
+/*  Copyright 2003-2005, 2007, 2009, 2011 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __AF_GLOBAL_H__
-#define __AF_GLOBAL_H__
+#ifndef __AFGLOBAL_H__
+#define __AFGLOBAL_H__
 
 
 #include "aftypes.h"
@@ -65,7 +65,7 @@
 
 FT_END_HEADER
 
-#endif /* __AF_GLOBALS_H__ */
+#endif /* __AFGLOBAL_H__ */
 
 
 /* END */
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index c349709..f51066f 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (body).                                 */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 by                  */
+/*  Copyright 2003-2007, 2009-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,6 +21,8 @@
 #include FT_INTERNAL_CALC_H
 
 
+  /* Get new segment for given axis. */
+
   FT_LOCAL_DEF( FT_Error )
   af_axis_hints_new_segment( AF_AxisHints  axis,
                              FT_Memory     memory,
@@ -61,6 +63,8 @@
   }
 
 
+  /* Get new edge for given axis, direction, and position. */
+
   FT_LOCAL( FT_Error )
   af_axis_hints_new_edge( AF_AxisHints  axis,
                           FT_Int        fpos,
@@ -125,7 +129,7 @@
   }
 
 
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
 
 #include FT_CONFIG_STANDARD_LIBRARY_H
 
@@ -160,6 +164,9 @@
 #define AF_INDEX_NUM( ptr, base )  ( (ptr) ? ( (ptr) - (base) ) : -1 )
 
 
+#ifdef __cplusplus
+  extern "C" {
+#endif
   void
   af_glyph_hints_dump_points( AF_GlyphHints  hints )
   {
@@ -169,20 +176,20 @@
 
 
     printf( "Table of points:\n" );
-    printf(   "  [ index |  xorg |  yorg |  xscale |  yscale "
-              "|  xfit  |  yfit  |  flags ]\n" );
+    printf(   "  [ index |  xorg |  yorg | xscale | yscale"
+              " |  xfit |  yfit |  flags ]\n" );
 
     for ( point = points; point < limit; point++ )
     {
-      printf( "  [ %5d | %5d | %5d | %-5.2f | %-5.2f "
-              "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
+      printf( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
+              " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
               point - points,
               point->fx,
               point->fy,
-              point->ox/64.0,
-              point->oy/64.0,
-              point->x/64.0,
-              point->y/64.0,
+              point->ox / 64.0,
+              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 )          ? '<' : ' ',
@@ -192,6 +199,9 @@
     }
     printf( "\n" );
   }
+#ifdef __cplusplus
+  }
+#endif
 
 
   static const char*
@@ -222,7 +232,11 @@
   }
 
 
-  /* A function to dump the array of linked segments. */
+  /* Dump the array of linked segments. */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
   void
   af_glyph_hints_dump_segments( AF_GlyphHints  hints )
   {
@@ -240,11 +254,11 @@
       printf ( "Table of %s segments:\n",
                dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
       printf ( "  [ index |  pos  |  dir  | link | serif |"
-               " height  | extra | flags    ]\n" );
+               " height | extra |    flags    ]\n" );
 
       for ( seg = segments; seg < limit; seg++ )
       {
-        printf ( "  [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
+        printf ( "  [ %5d | %5.2g | %5s | %4d | %5d | %6d | %5d | %11s ]\n",
                  seg - segments,
                  dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
                                                 : (int)seg->first->oy / 64.0,
@@ -253,13 +267,84 @@
                  AF_INDEX_NUM( seg->serif, segments ),
                  seg->height,
                  seg->height - ( seg->max_coord - seg->min_coord ),
-                 af_edge_flags_to_string( seg->flags ) );
+                 af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) );
       }
       printf( "\n" );
     }
   }
+#ifdef __cplusplus
+  }
+#endif
 
 
+  /* Fetch number of segments. */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+  FT_Error
+  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
+                                   FT_Int         dimension,
+                                   FT_Int*        num_segments )
+  {
+    AF_Dimension  dim;
+    AF_AxisHints  axis;
+
+
+    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+    axis          = &hints->axis[dim];
+    *num_segments = axis->num_segments;
+
+    return AF_Err_Ok;
+  }
+#ifdef __cplusplus
+  }
+#endif
+
+
+  /* Fetch offset of segments into user supplied offset array. */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+  FT_Error
+  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
+                                     FT_Int         dimension,
+                                     FT_Int         idx,
+                                     FT_Pos*        offset )
+  {
+    AF_Dimension  dim;
+    AF_AxisHints  axis;
+    AF_Segment    seg;
+
+
+    if ( !offset )
+      return AF_Err_Invalid_Argument;
+
+    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+    axis = &hints->axis[dim];
+
+    if ( idx < 0 || idx >= axis->num_segments )
+      return AF_Err_Invalid_Argument;
+
+    seg     = &axis->segments[idx];
+    *offset = (dim == AF_DIMENSION_HORZ) ? seg->first->ox
+                                         : seg->first->oy;
+
+    return AF_Err_Ok;
+  }
+#ifdef __cplusplus
+  }
+#endif
+
+
+  /* Dump the array of linked edges. */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
   void
   af_glyph_hints_dump_edges( AF_GlyphHints  hints )
   {
@@ -276,17 +361,17 @@
 
       /*
        *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
-       *        since they have constant a X coordinate.
+       *        since they have a constant X coordinate.
        */
       printf ( "Table of %s edges:\n",
                dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
       printf ( "  [ index |  pos  |  dir  | link |"
-               " serif | blue | opos  |  pos  | flags   ]\n" );
+               " serif | blue | opos  |  pos  |    flags    ]\n" );
 
       for ( edge = edges; edge < limit; edge++ )
       {
         printf ( "  [ %5d | %5.2g | %5s | %4d |"
-                 " %5d |   %c  | %5.2f | %5.2f | %s ]\n",
+                 " %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
                  edge - edges,
                  (int)edge->opos / 64.0,
                  af_dir_str( (AF_Direction)edge->dir ),
@@ -295,16 +380,23 @@
                  edge->blue_edge ? 'y' : 'n',
                  edge->opos / 64.0,
                  edge->pos / 64.0,
-                 af_edge_flags_to_string( edge->flags ) );
+                 af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) );
       }
       printf( "\n" );
     }
   }
+#ifdef __cplusplus
+  }
+#endif
 
-#else /* !AF_DEBUG */
+#else /* !FT_DEBUG_AUTOFIT */
 
   /* these empty stubs are only used to link the `ftgrid' test program */
-  /* when debugging is disabled                                        */
+  /* if debugging is disabled                                          */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
 
   void
   af_glyph_hints_dump_points( AF_GlyphHints  hints )
@@ -320,16 +412,49 @@
   }
 
 
+  FT_Error
+  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
+                                   FT_Int         dimension,
+                                   FT_Int*        num_segments )
+  {
+    FT_UNUSED( hints );
+    FT_UNUSED( dimension );
+    FT_UNUSED( num_segments );
+
+    return 0;
+  }
+
+
+  FT_Error
+  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
+                                     FT_Int         dimension,
+                                     FT_Int         idx,
+                                     FT_Pos*        offset )
+  {
+    FT_UNUSED( hints );
+    FT_UNUSED( dimension );
+    FT_UNUSED( idx );
+    FT_UNUSED( offset );
+
+    return 0;
+  }
+
+
   void
   af_glyph_hints_dump_edges( AF_GlyphHints  hints )
   {
     FT_UNUSED( hints );
   }
 
-#endif /* !AF_DEBUG */
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* !FT_DEBUG_AUTOFIT */
 
 
-  /* compute the direction value of a given vector */
+  /* Compute the direction value of a given vector. */
+
   FT_LOCAL_DEF( AF_Direction )
   af_direction_compute( FT_Pos  dx,
                         FT_Pos  dy )
@@ -369,6 +494,8 @@
       }
     }
 
+    /* return no direction if arm lengths differ too much */
+    /* (value 14 is heuristic)                            */
     ss *= 14;
     if ( FT_ABS( ll ) <= FT_ABS( ss ) )
       dir = AF_DIR_NONE;
@@ -397,7 +524,7 @@
 
       /*
        *  note that we don't need to free the segment and edge
-       *  buffers, since they are really within the hints->points array
+       *  buffers since they are really within the hints->points array
        */
       for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
       {
@@ -408,8 +535,8 @@
         axis->max_segments = 0;
         FT_FREE( axis->segments );
 
-        axis->num_edges    = 0;
-        axis->max_edges    = 0;
+        axis->num_edges = 0;
+        axis->max_edges = 0;
         FT_FREE( axis->edges );
       }
 
@@ -426,6 +553,8 @@
   }
 
 
+  /* Reset metrics. */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_rescale( AF_GlyphHints     hints,
                           AF_ScriptMetrics  metrics )
@@ -435,6 +564,9 @@
   }
 
 
+  /* Recompute all AF_Point in AF_GlyphHints from the definitions */
+  /* in a source outline.                                         */
+
   FT_LOCAL_DEF( FT_Error )
   af_glyph_hints_reload( AF_GlyphHints  hints,
                          FT_Outline*    outline )
@@ -457,12 +589,12 @@
     hints->axis[1].num_segments = 0;
     hints->axis[1].num_edges    = 0;
 
-    /* first of all, reallocate the contours array when necessary */
+    /* first of all, reallocate the contours array if necessary */
     new_max = (FT_UInt)outline->n_contours;
     old_max = hints->max_contours;
     if ( new_max > old_max )
     {
-      new_max = ( new_max + 3 ) & ~3;
+      new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
 
       if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
         goto Exit;
@@ -479,7 +611,7 @@
     old_max = hints->max_points;
     if ( new_max > old_max )
     {
-      new_max = ( new_max + 2 + 7 ) & ~7;
+      new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
 
       if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
         goto Exit;
@@ -545,7 +677,7 @@
             point->flags = AF_FLAG_CUBIC;
             break;
           default:
-            point->flags = 0;
+            point->flags = AF_FLAG_NONE;
           }
 
           point->prev = prev;
@@ -563,7 +695,7 @@
         }
       }
 
-      /* set-up the contours array */
+      /* set up the contours array */
       {
         AF_Point*  contour       = hints->contours;
         AF_Point*  contour_limit = contour + hints->num_contours;
@@ -611,6 +743,8 @@
           in_dir         = af_direction_compute( out_x, out_y );
           point->out_dir = (FT_Char)in_dir;
 
+          /* check for weak points */
+
           if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
           {
           Is_Weak_Point:
@@ -639,6 +773,8 @@
   }
 
 
+  /* Store the hinted outline in an FT_Outline structure. */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_save( AF_GlyphHints  hints,
                        FT_Outline*    outline )
@@ -671,6 +807,9 @@
    ****************************************************************/
 
 
+  /* Align all points of an edge to the same coordinate value, */
+  /* either horizontally or vertically.                        */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
                                     AF_Dimension   dim )
@@ -704,7 +843,6 @@
             break;
 
           point = point->next;
-
         }
       }
     }
@@ -744,8 +882,8 @@
    ****************************************************************/
 
 
-  /* hint the strong points -- this is equivalent to the TrueType `IP' */
-  /* hinting instruction                                               */
+  /* Hint the strong points -- this is equivalent to the TrueType `IP' */
+  /* hinting instruction.                                              */
 
   FT_LOCAL_DEF( void )
   af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
@@ -827,11 +965,12 @@
           max = edge_limit - edges;
 
 #if 1
-          /* for small edge counts, a linear search is better */
+          /* for a small number of edges, a linear search is better */
           if ( max <= 8 )
           {
             FT_PtrDist  nn;
 
+
             for ( nn = 0; nn < max; nn++ )
               if ( edges[nn].fpos >= u )
                 break;
@@ -863,6 +1002,7 @@
             }
           }
 
+          /* point is not on an edge */
           {
             AF_Edge  before = edges + min - 1;
             AF_Edge  after  = edges + min + 0;
@@ -898,6 +1038,10 @@
    ****************************************************************/
 
 
+  /* Shift the original coordinates of all points between `p1' and */
+  /* `p2' to get hinted coordinates, using the same difference as  */
+  /* given by `ref'.                                               */
+
   static void
   af_iup_shift( AF_Point  p1,
                 AF_Point  p2,
@@ -906,6 +1050,7 @@
     AF_Point  p;
     FT_Pos    delta = ref->u - ref->v;
 
+
     if ( delta == 0 )
       return;
 
@@ -917,6 +1062,13 @@
   }
 
 
+  /* Interpolate the original coordinates of all points between `p1' and  */
+  /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the       */
+  /* reference points.  The `u' and `v' members are the current and       */
+  /* original coordinate values, respectively.                            */
+  /*                                                                      */
+  /* Details can be found in the TrueType bytecode specification.         */
+
   static void
   af_iup_interp( AF_Point  p1,
                  AF_Point  p2,
@@ -985,6 +1137,9 @@
   }
 
 
+  /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
+  /* hinting instruction.                                             */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
                                     AF_Dimension   dim )
@@ -1050,17 +1205,18 @@
 
       for (;;)
       {
-        FT_ASSERT( point <= end_point &&
+        FT_ASSERT( point <= end_point                 &&
                    ( point->flags & touch_flag ) != 0 );
 
-        /* skip any touched neighbhours */
-        while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
+        /* skip any touched neighbours */
+        while ( point < end_point                    &&
+                ( point[1].flags & touch_flag ) != 0 )
           point++;
 
         last_touched = point;
 
         /* find the next touched point, if any */
-        point ++;
+        point++;
         for (;;)
         {
           if ( point > end_point )
@@ -1080,9 +1236,8 @@
     EndContour:
       /* special case: only one point was touched */
       if ( last_touched == first_touched )
-      {
         af_iup_shift( first_point, end_point, first_touched );
-      }
+
       else /* interpolate the last part */
       {
         if ( last_touched < end_point )
@@ -1112,7 +1267,9 @@
   }
 
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+  /* Apply (small) warp scale and warp delta for given dimension. */
 
   FT_LOCAL_DEF( void )
   af_glyph_hints_scale_dim( AF_GlyphHints  hints,
@@ -1137,6 +1294,6 @@
     }
   }
 
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
 
 /* END */
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index 10e673b..1c52e0d 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (specification).                        */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2010 by                  */
+/*  Copyright 2003-2008, 2010-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,10 +25,10 @@
 
 FT_BEGIN_HEADER
 
- /*
-  *  The definition of outline glyph hints.  These are shared by all
-  *  script analysis routines (until now).
-  */
+  /*
+   *  The definition of outline glyph hints.  These are shared by all
+   *  script analysis routines (until now).
+   */
 
   typedef enum  AF_Dimension_
   {
@@ -55,6 +55,151 @@
   } AF_Direction;
 
 
+  /*
+   *  The following explanations are mostly taken from the article
+   *
+   *    Real-Time Grid Fitting of Typographic Outlines
+   *
+   *  by David Turner and Werner Lemberg
+   *
+   *   http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+   *
+   *
+   *  Segments
+   *
+   *    `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 script.
+   *
+   *    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.
+   *
+   *
+   *  Edges
+   *
+   *    As soon as segments are defined, the auto-hinter groups them into
+   *    edges.  An edge corresponds to a single position on the main
+   *    dimension that collects one or more segments (allowing for a small
+   *    threshold).
+   *
+   *    The auto-hinter first tries to grid fit edges, then to align
+   *    segments on the edges unless it detects that they form a serif.
+   *
+   *    `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
+   *    edges; they are specific to a script.
+   *
+   *
+   *                      A          H
+   *                       |        |
+   *                       |        |
+   *                       |        |
+   *                       |        |
+   *         C             |        |             F
+   *          +------<-----+        +-----<------+
+   *          |             B      G             |
+   *          |                                  |
+   *          |                                  |
+   *          +--------------->------------------+
+   *         D                                    E
+   *
+   *
+   *  Stems
+   *
+   *    Segments need to be `linked' to other ones in order to detect stems.
+   *    A stem is made of two segments that face each other in opposite
+   *    directions and that are sufficiently close to each other.  Using
+   *    vocabulary from the TrueType specification, stem segments form a
+   *    `black distance'.
+   *
+   *    In the above ASCII drawing, the horizontal segments are BC, DE, and
+   *    FG; the vertical segments are AB, CD, EF, and GH.
+   *
+   *    Each segment has at most one `best' candidate to form a black
+   *    distance, or no candidate at all.  Notice that two distinct segments
+   *    can have the same candidate, which frequently means a serif.
+   *
+   *    A stem is recognized by the following condition:
+   *
+   *      best segment_1 = segment_2 && best segment_2 = segment_1
+   *
+   *    The best candidate is stored in field `link' in structure
+   *    `AF_Segment'.
+   *
+   *    Stems are detected by `af_{cjk,latin,...}_hint_edges'.
+   *
+   *    In the above ASCII drawing, the best candidate for both AB and CD is
+   *    GH, while the best candidate for GH is AB.  Similarly, the best
+   *    candidate for EF and GH is AB, while the best candidate for AB is
+   *    GH.
+   *
+   *
+   *  Serifs
+   *
+   *    On the opposite, a serif has
+   *
+   *      best segment_1 = segment_2 && best segment_2 != segment_1
+   *
+   *    where segment_1 corresponds to the serif segment (CD and EF in the
+   *    above ASCII drawing).
+   *
+   *    The best candidate is stored in field `serif' in structure
+   *    `AF_Segment' (and `link' is set to NULL).
+   *
+   *    Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
+   *
+   *
+   *  Touched points
+   *
+   *    A point is called `touched' if it has been processed somehow by the
+   *    auto-hinter.  It basically means that it shouldn't be moved again
+   *    (or moved only under certain constraints to preserve the already
+   *    applied processing).
+   *
+   *
+   *  Flat and round segments
+   *
+   *    Segments are `round' or `flat', depending on the series of points
+   *    that define them.  A segment is round if the next and previous point
+   *    of an extremum (which can be either a single point or sequence of
+   *    points) are both conic or cubic control points.  Otherwise, a
+   *    segment with an extremum is flat.
+   *
+   *
+   *  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
+   *
+   *    - 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)
+   *
+   *    `af_glyph_hints_align_strong_points' is the function which takes
+   *    care of such situations; it is equivalent to the TrueType `IP'
+   *    hinting instruction.
+   *
+   *
+   *  Weak Points
+   *
+   *    Other points in the outline must be interpolated using the
+   *    coordinates of their previous and next unfitted contour neighbours.
+   *    These are called `weak points' and are touched by the function
+   *    `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
+   *    hinting instruction.  Typical candidates are control points and
+   *    points on the contour without a major direction.
+   *
+   *    The major effect is to reduce possible distortion caused by
+   *    alignment of edges and strong points, thus weak points are processed
+   *    after strong points.
+   */
+
+
   /* point hint flags */
   typedef enum  AF_Flags_
   {
@@ -137,9 +282,8 @@
     FT_Pos      score;       /* used during stem matching  */
     FT_Pos      len;         /* used during stem matching  */
 
-    AF_Point    first;       /* first point in edge segment             */
-    AF_Point    last;        /* last point in edge segment              */
-    AF_Point*   contour;     /* ptr to first point of segment's contour */
+    AF_Point    first;       /* first point in edge segment */
+    AF_Point    last;        /* last point in edge segment  */
 
   } AF_SegmentRec;
 
@@ -155,32 +299,31 @@
     FT_Fixed    scale;      /* used to speed up interpolation between edges */
     AF_Width    blue_edge;  /* non-NULL if this is a blue edge              */
 
-    AF_Edge     link;
-    AF_Edge     serif;
-    FT_Short    num_linked;
+    AF_Edge     link;       /* link edge                 */
+    AF_Edge     serif;      /* primary edge for serifs   */
+    FT_Short    num_linked; /* number of linked edges    */
+    FT_Int      score;      /* used during stem matching */
 
-    FT_Int      score;
-
-    AF_Segment  first;
-    AF_Segment  last;
+    AF_Segment  first;      /* first segment in edge */
+    AF_Segment  last;       /* last segment in edge  */
 
   } AF_EdgeRec;
 
 
   typedef struct  AF_AxisHintsRec_
   {
-    FT_Int        num_segments;
-    FT_Int        max_segments;
-    AF_Segment    segments;
+    FT_Int        num_segments; /* number of used segments      */
+    FT_Int        max_segments; /* number of allocated segments */
+    AF_Segment    segments;     /* segments array               */
 #ifdef AF_SORT_SEGMENTS
     FT_Int        mid_segments;
 #endif
 
-    FT_Int        num_edges;
-    FT_Int        max_edges;
-    AF_Edge       edges;
+    FT_Int        num_edges;    /* number of used edges      */
+    FT_Int        max_edges;    /* number of allocated edges */
+    AF_Edge       edges;        /* edges array               */
 
-    AF_Direction  major_dir;
+    AF_Direction  major_dir;    /* either vertical or horizontal */
 
   } AF_AxisHintsRec, *AF_AxisHints;
 
@@ -195,15 +338,13 @@
     FT_Fixed          y_scale;
     FT_Pos            y_delta;
 
-    FT_Pos            edge_distance_threshold;
+    FT_Int            max_points;    /* number of allocated points */
+    FT_Int            num_points;    /* number of used points      */
+    AF_Point          points;        /* points array               */
 
-    FT_Int            max_points;
-    FT_Int            num_points;
-    AF_Point          points;
-
-    FT_Int            max_contours;
-    FT_Int            num_contours;
-    AF_Point*         contours;
+    FT_Int            max_contours;  /* number of allocated contours */
+    FT_Int            num_contours;  /* number of used contours      */
+    AF_Point*         contours;      /* contours array               */
 
     AF_AxisHintsRec   axis[AF_DIMENSION_MAX];
 
@@ -214,7 +355,7 @@
 
     FT_Pos            xmin_delta;    /* used for warping */
     FT_Pos            xmax_delta;
-    
+
   } AF_GlyphHintsRec;
 
 
@@ -222,7 +363,7 @@
 #define AF_HINTS_TEST_OTHER( h, f )   ( (h)->other_flags  & (f) )
 
 
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
 
 #define AF_HINTS_DO_HORIZONTAL( h )                                     \
           ( !_af_debug_disable_horz_hints                            && \
@@ -237,7 +378,7 @@
 
 #define AF_HINTS_DO_BLUES( h )  ( !_af_debug_disable_blue_hints )
 
-#else /* !AF_DEBUG */
+#else /* !FT_DEBUG_AUTOFIT */
 
 #define AF_HINTS_DO_HORIZONTAL( h )                                \
           !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )
@@ -250,7 +391,7 @@
 
 #define AF_HINTS_DO_BLUES( h )  1
 
-#endif /* !AF_DEBUG */
+#endif /* !FT_DEBUG_AUTOFIT */
 
 
   FT_LOCAL( AF_Direction )
@@ -274,12 +415,6 @@
   af_glyph_hints_init( AF_GlyphHints  hints,
                        FT_Memory      memory );
 
-
-
-  /*
-   *  recompute all AF_Point in a AF_GlyphHints from the definitions
-   *  in a source outline
-   */
   FT_LOCAL( void )
   af_glyph_hints_rescale( AF_GlyphHints     hints,
                           AF_ScriptMetrics  metrics );
@@ -304,7 +439,7 @@
   af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
                                     AF_Dimension   dim );
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
   FT_LOCAL( void )
   af_glyph_hints_scale_dim( AF_GlyphHints  hints,
                             AF_Dimension   dim,
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index 1d9e9ea..c232cff 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for Indic scripts (body).               */
 /*                                                                         */
-/*  Copyright 2007 by                                                      */
+/*  Copyright 2007, 2011 by                                                */
 /*  Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.    */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,23 +27,42 @@
 #include "afcjk.h"
 
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
 #include "afwarp.h"
 #endif
 
 
   static FT_Error
-  af_indic_metrics_init( AF_LatinMetrics  metrics,
-                         FT_Face          face )
+  af_indic_metrics_init( AF_CJKMetrics  metrics,
+                         FT_Face        face )
   {
-    /* use CJK routines */
-    return af_cjk_metrics_init( metrics, face );
+    /* skip blue zone init in CJK routines */
+    FT_CharMap  oldmap = face->charmap;
+
+
+    metrics->units_per_em = face->units_per_EM;
+
+    if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
+      face->charmap = NULL;
+    else
+    {
+      af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+#if 0
+      /* either need indic specific blue_chars[] or just skip blue zones */
+      af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars );
+#endif
+      af_cjk_metrics_check_digits( metrics, face );
+    }
+
+    FT_Set_Charmap( face, oldmap );
+
+    return AF_Err_Ok;
   }
 
 
   static void
-  af_indic_metrics_scale( AF_LatinMetrics  metrics,
-                          AF_Scaler        scaler )
+  af_indic_metrics_scale( AF_CJKMetrics  metrics,
+                          AF_Scaler      scaler )
   {
     /* use CJK routines */
     af_cjk_metrics_scale( metrics, scaler );
@@ -51,8 +70,8 @@
 
 
   static FT_Error
-  af_indic_hints_init( AF_GlyphHints    hints,
-                       AF_LatinMetrics  metrics )
+  af_indic_hints_init( AF_GlyphHints  hints,
+                       AF_CJKMetrics  metrics )
   {
     /* use CJK routines */
     return af_cjk_hints_init( hints, metrics );
@@ -60,9 +79,9 @@
 
 
   static FT_Error
-  af_indic_hints_apply( AF_GlyphHints    hints,
-                        FT_Outline*      outline,
-                        AF_LatinMetrics  metrics)
+  af_indic_hints_apply( AF_GlyphHints  hints,
+                        FT_Outline*    outline,
+                        AF_CJKMetrics  metrics )
   {
     /* use CJK routines */
     return af_cjk_hints_apply( hints, outline, metrics );
@@ -84,6 +103,12 @@
     AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ),  /* why this? */
 #endif
     AF_UNIRANGE_REC( 0x0900UL, 0x0DFFUL),    /* Indic Range */
+    AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL),    /* Tibetan */
+    AF_UNIRANGE_REC( 0x1900UL, 0x194FUL),    /* Limbu */
+    AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL),    /* Sundanese */
+    AF_UNIRANGE_REC( 0x1C80UL, 0x1CDFUL),    /* Meetei Mayak */
+    AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL),    /* Syloti Nagri */
+    AF_UNIRANGE_REC( 0x11800UL, 0x118DFUL),  /* Sharada */
     AF_UNIRANGE_REC(      0UL,      0UL)
   };
 
@@ -92,7 +117,7 @@
     AF_SCRIPT_INDIC,
     af_indic_uniranges,
 
-    sizeof( AF_LatinMetricsRec ),
+    sizeof( AF_CJKMetricsRec ),
 
     (AF_Script_InitMetricsFunc) af_indic_metrics_init,
     (AF_Script_ScaleMetricsFunc)af_indic_metrics_scale,
@@ -114,7 +139,7 @@
     AF_SCRIPT_INDIC,
     af_indic_uniranges,
 
-    sizeof( AF_LatinMetricsRec ),
+    sizeof( AF_CJKMetricsRec ),
 
     (AF_Script_InitMetricsFunc) NULL,
     (AF_Script_ScaleMetricsFunc)NULL,
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 8c6c430..d5876ff 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (body).                */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by            */
+/*  Copyright 2003-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,17 +18,28 @@
 
 #include <ft2build.h>
 #include FT_ADVANCES_H
+#include FT_INTERNAL_DEBUG_H
 
 #include "aflatin.h"
 #include "aferrors.h"
 
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
 #include "afwarp.h"
 #endif
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_aflatin
+
+
+  /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
   /*****            L A T I N   G L O B A L   M E T R I C S            *****/
@@ -36,6 +47,10 @@
   /*************************************************************************/
   /*************************************************************************/
 
+
+  /* Find segments and links, compute all stem widths, and initialize */
+  /* standard width and height for the glyph with given charcode.     */
+
   FT_LOCAL_DEF( void )
   af_latin_metrics_init_widths( AF_LatinMetrics  metrics,
                                 FT_Face          face,
@@ -69,8 +84,12 @@
       FT_ZERO( dummy );
 
       dummy->units_per_em = metrics->units_per_em;
-      scaler->x_scale     = scaler->y_scale = 0x10000L;
-      scaler->x_delta     = scaler->y_delta = 0;
+
+      scaler->x_scale = 0x10000L;
+      scaler->y_scale = 0x10000L;
+      scaler->x_delta = 0;
+      scaler->y_delta = 0;
+
       scaler->face        = face;
       scaler->render_mode = FT_RENDER_MODE_NORMAL;
       scaler->flags       = 0;
@@ -161,6 +180,9 @@
   };
 
 
+  /* Find all blue zones.  Flat segments give the reference points, */
+  /* round segments the overshoot positions.                        */
+
   static void
   af_latin_metrics_init_blues( AF_LatinMetrics  metrics,
                                FT_Face          face )
@@ -177,11 +199,11 @@
 
 
     /* we compute the blues simply by loading each character from the    */
-    /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */
+    /* `af_latin_blue_chars[blues]' string, then finding its top-most or */
     /* bottom-most points (depending on `AF_IS_TOP_BLUE')                */
 
-    AF_LOG(( "blue zones computation\n" ));
-    AF_LOG(( "------------------------------------------------\n" ));
+    FT_TRACE5(( "blue zones computation\n" ));
+    FT_TRACE5(( "------------------------------------------------\n" ));
 
     for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
     {
@@ -191,7 +213,7 @@
       FT_Pos*      blue_shoot;
 
 
-      AF_LOG(( "blue %3d: ", bb ));
+      FT_TRACE5(( "blue %3d: ", bb ));
 
       num_flats  = 0;
       num_rounds = 0;
@@ -205,7 +227,7 @@
         FT_Bool     round = 0;
 
 
-        AF_LOG(( "'%c'", *p ));
+        FT_TRACE5(( "'%c'", *p ));
 
         /* load the character in the face -- skip unknown or empty ones */
         glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
@@ -229,7 +251,9 @@
           FT_Int  last  = -1;
 
 
-          for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
+          for ( nn = 0;
+                nn < glyph->outline.n_contours;
+                first = last + 1, nn++ )
           {
             FT_Int  old_best_point = best_point;
             FT_Int  pp;
@@ -268,7 +292,7 @@
               best_last  = last;
             }
           }
-          AF_LOG(( "%5d", best_y ));
+          FT_TRACE5(( "%5d", best_y ));
         }
 
         /* now check whether the point belongs to a straight or round   */
@@ -311,12 +335,12 @@
 
           } while ( next != best_point );
 
-          /* now, set the `round' flag depending on the segment's kind */
+          /* now set the `round' flag depending on the segment's kind */
           round = FT_BOOL(
             FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
             FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
 
-          AF_LOG(( "%c ", round ? 'r' : 'f' ));
+          FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
         }
 
         if ( round )
@@ -325,7 +349,7 @@
           flats[num_flats++]   = best_y;
       }
 
-      AF_LOG(( "\n" ));
+      FT_TRACE5(( "\n" ));
 
       if ( num_flats == 0 && num_rounds == 0 )
       {
@@ -333,7 +357,7 @@
          *  we couldn't find a single glyph to compute this blue zone,
          *  we will simply ignore it then
          */
-        AF_LOG(( "empty\n" ));
+        FT_TRACE5(( "empty\n" ));
         continue;
       }
 
@@ -376,7 +400,8 @@
 
 
         if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
-          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+          *blue_ref   =
+          *blue_shoot = ( shoot + ref ) / 2;
       }
 
       blue->flags = 0;
@@ -391,13 +416,17 @@
       if ( bb == AF_LATIN_BLUE_SMALL_TOP )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
-      AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
     }
 
+    FT_TRACE5(( "\n" ));
+
     return;
   }
 
 
+  /* Check whether all ASCII digits have the same advance width. */
+
   FT_LOCAL_DEF( void )
   af_latin_metrics_check_digits( AF_LatinMetrics  metrics,
                                  FT_Face          face )
@@ -407,7 +436,6 @@
     FT_Fixed  advance, old_advance = 0;
 
 
-    /* check whether all ASCII digits have the same advance width; */
     /* digit `0' is 0x30 in all supported charmaps                 */
     for ( i = 0x30; i <= 0x39; i++ )
     {
@@ -444,6 +472,8 @@
   }
 
 
+  /* Initialize global metrics. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_metrics_init( AF_LatinMetrics  metrics,
                          FT_Face          face )
@@ -458,6 +488,7 @@
       FT_ENCODING_APPLE_ROMAN,
       FT_ENCODING_ADOBE_STANDARD,
       FT_ENCODING_ADOBE_LATIN_1,
+
       FT_ENCODING_NONE  /* end of list */
     };
 
@@ -485,6 +516,9 @@
   }
 
 
+  /* Adjust scaling value, then scale and shift widths   */
+  /* and blue zones (if applicable) for given dimension. */
+
   static void
   af_latin_metrics_scale_dim( AF_LatinMetrics  metrics,
                               AF_Scaler        scaler,
@@ -550,9 +584,7 @@
           else
 #endif
           if ( dim == AF_DIMENSION_VERT )
-          {
             scale = FT_MulDiv( scale, fitted, scaled );
-          }
         }
       }
     }
@@ -571,7 +603,7 @@
       metrics->root.scaler.y_delta = delta;
     }
 
-    /* scale the standard widths */
+    /* scale the widths */
     for ( nn = 0; nn < axis->width_count; nn++ )
     {
       AF_Width  width = axis->widths + nn;
@@ -582,7 +614,7 @@
     }
 
     /* an extra-light axis corresponds to a standard width that is */
-    /* smaller than 0.75 pixels                                    */
+    /* smaller than 5/8 pixels                                     */
     axis->extra_light =
       (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
 
@@ -605,9 +637,17 @@
         dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
         if ( dist <= 48 && dist >= -48 )
         {
-          FT_Pos  delta1, delta2;
+#if 0
+          FT_Pos  delta1;
+#endif
+          FT_Pos  delta2;
 
 
+          /* use discrete values for blue zone widths */
+
+#if 0
+
+          /* generic, original code */
           delta1 = blue->shoot.org - blue->ref.org;
           delta2 = delta1;
           if ( delta1 < 0 )
@@ -628,6 +668,28 @@
           blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
           blue->shoot.fit = blue->ref.fit + delta2;
 
+#else
+
+          /* simplified version due to abs(dist) <= 48 */
+          delta2 = dist;
+          if ( dist < 0 )
+            delta2 = -delta2;
+
+          if ( delta2 < 32 )
+            delta2 = 0;
+          else if ( delta < 48 )
+            delta2 = 32;
+          else
+            delta2 = 64;
+
+          if ( dist < 0 )
+            delta2 = -delta2;
+
+          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
+          blue->shoot.fit = blue->ref.fit - delta2;
+
+#endif
+
           blue->flags |= AF_LATIN_BLUE_ACTIVE;
         }
       }
@@ -635,6 +697,8 @@
   }
 
 
+  /* Scale global values in both directions. */
+
   FT_LOCAL_DEF( void )
   af_latin_metrics_scale( AF_LatinMetrics  metrics,
                           AF_Scaler        scaler )
@@ -655,6 +719,9 @@
   /*************************************************************************/
   /*************************************************************************/
 
+
+  /* Walk over all contours and compute its segments. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_hints_compute_segments( AF_GlyphHints  hints,
                                    AF_Dimension   dim )
@@ -808,7 +875,6 @@
           min_pos = max_pos = point->u;
           segment->first    = point;
           segment->last     = point;
-          segment->contour  = contour;
           on_edge           = 1;
         }
 
@@ -874,6 +940,8 @@
   }
 
 
+  /* Link segments to form stems and serifs. */
+
   FT_LOCAL_DEF( void )
   af_latin_hints_link_segments( AF_GlyphHints  hints,
                                 AF_Dimension   dim )
@@ -899,18 +967,18 @@
       if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
         continue;
 
+      /* search for stems having opposite directions, */
+      /* with seg1 to the `left' of seg2              */
       for ( seg2 = segments; seg2 < segment_limit; seg2++ )
-        if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
         {
           FT_Pos  pos1 = seg1->pos;
           FT_Pos  pos2 = seg2->pos;
+
+
+        if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 )
+        {
+          /* compute distance between the two segments */
           FT_Pos  dist = pos2 - pos1;
-
-
-          if ( dist < 0 )
-            dist = -dist;
-
-          {
             FT_Pos  min = seg1->min_coord;
             FT_Pos  max = seg1->max_coord;
             FT_Pos  len, score;
@@ -922,11 +990,16 @@
             if ( max > seg2->max_coord )
               max = seg2->max_coord;
 
+          /* compute maximum coordinate difference of the two segments */
             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;
 
+            /* and we search for the smallest score */
+            /* of the sum of the two values         */
               if ( score < seg1->score )
               {
                 seg1->score = score;
@@ -943,7 +1016,7 @@
         }
     }
 
-    /* now, compute the `serif' segments */
+    /* now compute the `serif' segments, cf. explanations in `afhints.h' */
     for ( seg1 = segments; seg1 < segment_limit; seg1++ )
     {
       seg2 = seg1->link;
@@ -960,6 +1033,8 @@
   }
 
 
+  /* Link segments to edges, using feature analysis for selection. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_hints_compute_edges( AF_GlyphHints  hints,
                                 AF_Dimension   dim )
@@ -973,7 +1048,9 @@
     AF_Segment    segment_limit = segments + axis->num_segments;
     AF_Segment    seg;
 
+#if 0
     AF_Direction  up_dir;
+#endif
     FT_Fixed      scale;
     FT_Pos        edge_distance_threshold;
     FT_Pos        segment_length_threshold;
@@ -984,11 +1061,13 @@
     scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
                                          : hints->y_scale;
 
+#if 0
     up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
                                           : AF_DIR_RIGHT;
+#endif
 
     /*
-     *  We ignore all segments that are less than 1 pixels in length,
+     *  We ignore all segments that are less than 1 pixel in length
      *  to avoid many problems with serif fonts.  We compute the
      *  corresponding threshold in font units.
      */
@@ -999,20 +1078,21 @@
 
     /*********************************************************************/
     /*                                                                   */
-    /* We will begin by generating a sorted table of edges for the       */
-    /* current direction.  To do so, we simply scan each segment and try */
-    /* to find an edge in our table that corresponds to its position.    */
+    /* We begin by generating a sorted table of edges for the current    */
+    /* direction.  To do so, we simply scan each segment and try to find */
+    /* an edge in our table that corresponds to its position.            */
     /*                                                                   */
     /* If no edge is found, we create and insert a new edge in the       */
     /* sorted table.  Otherwise, we simply add the segment to the edge's */
-    /* list which will be processed in the second step to compute the    */
+    /* list which gets processed in the second step to compute the       */
     /* edge's properties.                                                */
     /*                                                                   */
-    /* Note that the edges table is sorted along the segment/edge        */
+    /* Note that the table of edges is sorted along the segment/edge     */
     /* position.                                                         */
     /*                                                                   */
     /*********************************************************************/
 
+    /* assure that edge distance threshold is at most 0.25px */
     edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
                                          scale );
     if ( edge_distance_threshold > 64 / 4 )
@@ -1023,7 +1103,7 @@
 
     for ( seg = segments; seg < segment_limit; seg++ )
     {
-      AF_Edge  found = 0;
+      AF_Edge  found = NULL;
       FT_Int   ee;
 
 
@@ -1072,9 +1152,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
@@ -1091,9 +1172,9 @@
     /*********************************************************************/
     /*                                                                   */
     /* Good, we will now compute each edge's properties according to     */
-    /* segments found on its position.  Basically, these are:            */
+    /* the segments found on its position.  Basically, these are         */
     /*                                                                   */
-    /*  - edge's main direction                                          */
+    /*  - the edge's main direction                                      */
     /*  - stem edge, serif edge or both (which defaults to stem then)    */
     /*  - rounded edge, straight or both (which defaults to straight)    */
     /*  - link for edge                                                  */
@@ -1126,13 +1207,15 @@
           } while ( seg != edge->first );
       }
 
-      /* now, compute each edge properties */
+      /* now compute each edge properties */
       for ( edge = edges; edge < edge_limit; edge++ )
       {
         FT_Int  is_round    = 0;  /* does it contain round segments?    */
         FT_Int  is_straight = 0;  /* does it contain straight segments? */
+#if 0
         FT_Pos  ups         = 0;  /* number of upwards segments         */
         FT_Pos  downs       = 0;  /* number of downwards segments       */
+#endif
 
 
         seg = edge->first;
@@ -1148,11 +1231,13 @@
           else
             is_straight++;
 
+#if 0
           /* check for segment direction */
           if ( seg->dir == up_dir )
             ups   += seg->max_coord-seg->min_coord;
           else
             downs += seg->max_coord-seg->min_coord;
+#endif
 
           /* check for links -- if seg->serif is set, then seg->link must */
           /* be ignored                                                   */
@@ -1228,7 +1313,7 @@
           edge->dir = 0;  /* both up and down! */
 #endif
 
-        /* gets rid of serifs if link is set                */
+        /* get rid of serifs if link is set                 */
         /* XXX: This gets rid of many unpleasant artefacts! */
         /*      Example: the `c' in cour.pfa at size 13     */
 
@@ -1242,6 +1327,8 @@
   }
 
 
+  /* Detect segments and edges for given dimension. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_hints_detect_features( AF_GlyphHints  hints,
                                   AF_Dimension   dim )
@@ -1256,10 +1343,13 @@
 
       error = af_latin_hints_compute_edges( hints, dim );
     }
+
     return error;
   }
 
 
+  /* Compute all edges which lie within blue zones. */
+
   FT_LOCAL_DEF( void )
   af_latin_hints_compute_blue_edges( AF_GlyphHints    hints,
                                      AF_LatinMetrics  metrics )
@@ -1283,8 +1373,10 @@
 
 
       /* compute the initial threshold as a fraction of the EM size */
+      /* (the value 40 is heuristic)                                */
       best_dist = FT_MulFix( metrics->units_per_em / 40, scale );
 
+      /* assure a minimum distance of 0.5px */
       if ( best_dist > 64 / 2 )
         best_dist = 64 / 2;
 
@@ -1294,7 +1386,7 @@
         FT_Bool       is_top_blue, is_major_dir;
 
 
-        /* skip inactive blue zones (i.e., those that are too small) */
+        /* skip inactive blue zones (i.e., those that are too large) */
         if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
           continue;
 
@@ -1325,9 +1417,10 @@
             best_blue = & blue->ref;
           }
 
-          /* now, compare it to the overshoot position if the edge is     */
-          /* rounded, and if the edge is over the reference position of a */
-          /* top zone, or under the reference position of a bottom zone   */
+          /* 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 )
           {
             FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
@@ -1335,7 +1428,6 @@
 
             if ( is_top_blue ^ is_under_ref )
             {
-              blue = latin->blues + bb;
               dist = edge->fpos - blue->shoot.org;
               if ( dist < 0 )
                 dist = -dist;
@@ -1357,6 +1449,8 @@
   }
 
 
+  /* Initalize hinting engine. */
+
   static FT_Error
   af_latin_hints_init( AF_GlyphHints    hints,
                        AF_LatinMetrics  metrics )
@@ -1370,7 +1464,7 @@
 
     /*
      *  correct x_scale and y_scale if needed, since they may have
-     *  been modified `af_latin_metrics_scale_dim' above
+     *  been modified by `af_latin_metrics_scale_dim' above
      */
     hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
     hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
@@ -1380,7 +1474,7 @@
     /* compute flags depending on render mode, etc. */
     mode = metrics->root.scaler.render_mode;
 
-#if 0 /* #ifdef AF_USE_WARPER */
+#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
     if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
     {
       metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
@@ -1424,7 +1518,7 @@
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
-    return 0;
+    return AF_Err_Ok;
   }
 
 
@@ -1436,8 +1530,8 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  /* snap a given width in scaled coordinates to one of the */
-  /* current standard widths                                */
+  /* Snap a given width in scaled coordinates to one of the */
+  /* current standard widths.                               */
 
   static FT_Pos
   af_latin_snap_width( AF_Width  widths,
@@ -1484,7 +1578,9 @@
   }
 
 
-  /* compute the snapped width of a given stem */
+  /* Compute the snapped width of a given stem, ignoring very thin ones. */
+  /* There is a lot of voodoo in this function; changing the hard-coded  */
+  /* parameters influence the whole hinting process.                     */
 
   static FT_Pos
   af_latin_compute_stem_width( AF_GlyphHints  hints,
@@ -1516,11 +1612,12 @@
       /* smooth hinting process: very lightly quantize the stem width */
 
       /* leave the widths of serifs alone */
-
-      if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+      if ( ( stem_flags & AF_EDGE_SERIF ) &&
+           vertical                       &&
+           ( dist < 3 * 64 )              )
         goto Done_Width;
 
-      else if ( ( base_flags & AF_EDGE_ROUND ) )
+      else if ( base_flags & AF_EDGE_ROUND )
       {
         if ( dist < 80 )
           dist = 64;
@@ -1534,8 +1631,6 @@
 
 
         /* compare to standard width */
-        if ( axis->width_count > 0 )
-        {
           delta = dist - axis->widths[0].cur;
 
           if ( delta < 0 )
@@ -1549,7 +1644,6 @@
 
             goto Done_Width;
           }
-        }
 
         if ( dist < 3 * 64 )
         {
@@ -1575,6 +1669,7 @@
     else
     {
       /* strong hinting process: snap the stem width to integer pixels */
+
       FT_Pos  org_dist = dist;
 
 
@@ -1649,7 +1744,7 @@
   }
 
 
-  /* align one stem edge relative to the previous stem edge */
+  /* Align one stem edge relative to the previous stem edge. */
 
   static void
   af_latin_align_linked_edge( AF_GlyphHints  hints,
@@ -1667,13 +1762,16 @@
 
     stem_edge->pos = base_edge->pos + fitted_width;
 
-    AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
+    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->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
   }
 
 
+  /* Shift the coordinates of the `serif' edge by the same amount */
+  /* as the corresponding `base' edge has been moved already.     */
+
   static void
   af_latin_align_serif_edge( AF_GlyphHints  hints,
                              AF_Edge        base,
@@ -1696,6 +1794,8 @@
   /*************************************************************************/
 
 
+  /* The main grid-fitting routine. */
+
   FT_LOCAL_DEF( void )
   af_latin_hint_edges( AF_GlyphHints  hints,
                        AF_Dimension   dim )
@@ -1705,10 +1805,13 @@
     AF_Edge       edge_limit = edges + axis->num_edges;
     FT_PtrDist    n_edges;
     AF_Edge       edge;
-    AF_Edge       anchor     = 0;
+    AF_Edge       anchor     = NULL;
     FT_Int        has_serifs = 0;
 
 
+    FT_TRACE5(("%s edge hinting\n", dim == AF_DIMENSION_VERT ? "horizontal"
+                                                             : "vertical"));
+
     /* we begin by aligning all stems relative to the blue zone */
     /* if needed -- that's only for horizontal edges            */
 
@@ -1717,7 +1820,7 @@
       for ( edge = edges; edge < edge_limit; edge++ )
       {
         AF_Width  blue;
-        AF_Edge   edge1, edge2;
+        AF_Edge   edge1, edge2; /* these edges form the stem to check */
 
 
         if ( edge->flags & AF_EDGE_DONE )
@@ -1728,9 +1831,9 @@
         edge2 = edge->link;
 
         if ( blue )
-        {
           edge1 = edge;
-        }
+
+        /* flip edges if the other stem is aligned to a blue zone */
         else if ( edge2 && edge2->blue_edge )
         {
           blue  = edge2->blue_edge;
@@ -1741,7 +1844,7 @@
         if ( !edge1 )
           continue;
 
-        AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
+        FT_TRACE5(( "  BLUE: edge %d (opos=%.2f) snapped to (%.2f),"
                  "was (%.2f)\n",
                  edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
                  edge1->pos / 64.0 ));
@@ -1760,7 +1863,7 @@
       }
     }
 
-    /* now we will align all stem edges, trying to maintain the */
+    /* now we align all other stem edges, trying to maintain the */
     /* relative order of stems in the glyph                     */
     for ( edge = edges; edge < edge_limit; edge++ )
     {
@@ -1783,7 +1886,7 @@
       /* this should not happen, but it's better to be safe */
       if ( edge2->blue_edge )
       {
-        AF_LOG(( "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;
@@ -1792,6 +1895,8 @@
 
       if ( !anchor )
       {
+        /* if we reach this if clause, no stem has been aligned yet */
+
         FT_Pos  org_len, org_center, cur_len;
         FT_Pos  cur_pos1, error1, error2, u_off, d_off;
 
@@ -1801,10 +1906,19 @@
                     hints, dim, org_len,
                     (AF_Edge_Flags)edge->flags,
                     (AF_Edge_Flags)edge2->flags );
+
+        /* some voodoo to specially round edges for small stem widths; */
+        /* the idea is to align the center of a stem, then shifting    */
+        /* the stem edges to suitable positions                        */
         if ( cur_len <= 64 )
-          u_off = d_off = 32;
+        {
+          /* width <= 1px */
+          u_off = 32;
+          d_off = 32;
+        }
         else
         {
+          /* 1px < width < 1.5px */
           u_off = 38;
           d_off = 26;
         }
@@ -1812,7 +1926,6 @@
         if ( cur_len < 96 )
         {
           org_center = edge->opos + ( org_len >> 1 );
-
           cur_pos1   = FT_PIX_ROUND( org_center );
 
           error1 = org_center - ( cur_pos1 - u_off );
@@ -1834,7 +1947,7 @@
         else
           edge->pos = FT_PIX_ROUND( edge->opos );
 
-        AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
+        FT_TRACE5(( "  ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
                  "snapped to (%.2f) (%.2f)\n",
                  edge-edges, edge->opos / 64.0,
                  edge2-edges, edge2->opos / 64.0,
@@ -1861,7 +1974,13 @@
                    (AF_Edge_Flags)edge2->flags );
 
         if ( edge2->flags & AF_EDGE_DONE )
+        {
+          FT_TRACE5(( "  ADJUST: edge %d (pos=%.2f) moved to %.2f\n",
+                      edge - edges, edge->pos / 64.0,
+                      ( edge2->pos - cur_len ) / 64.0 ));
+
           edge->pos = edge2->pos - cur_len;
+        }
 
         else if ( cur_len < 96 )
         {
@@ -1871,7 +1990,10 @@
           cur_pos1 = FT_PIX_ROUND( org_center );
 
           if (cur_len <= 64 )
-            u_off = d_off = 32;
+          {
+            u_off = 32;
+            d_off = 32;
+          }
           else
           {
             u_off = 38;
@@ -1894,7 +2016,7 @@
           edge->pos  = cur_pos1 - cur_len / 2;
           edge2->pos = cur_pos1 + cur_len / 2;
 
-          AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
+          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
                    "snapped to (%.2f) and (%.2f)\n",
                    edge-edges, edge->opos / 64.0,
                    edge2-edges, edge2->opos / 64.0,
@@ -1924,7 +2046,7 @@
           edge->pos  = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
           edge2->pos = edge->pos + cur_len;
 
-          AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
+          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
                    "snapped to (%.2f) and (%.2f)\n",
                    edge-edges, edge->opos / 64.0,
                    edge2-edges, edge2->opos / 64.0,
@@ -1936,7 +2058,7 @@
 
         if ( edge > edges && edge->pos < edge[-1].pos )
         {
-          AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
+          FT_TRACE5(( "  BOUND: %d (pos=%.2f) to (%.2f)\n",
                    edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
           edge->pos = edge[-1].pos;
         }
@@ -2031,7 +2153,7 @@
         if ( delta < 64 + 16 )
         {
           af_latin_align_serif_edge( hints, edge->serif, edge );
-          AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
+          FT_TRACE5(( "  SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
                    "aligned to (%.2f)\n",
                    edge-edges, edge->opos / 64.0,
                    edge->serif - edges, edge->serif->opos / 64.0,
@@ -2039,10 +2161,11 @@
         }
         else if ( !anchor )
         {
-          AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
-                   edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
           edge->pos = FT_PIX_ROUND( edge->opos );
           anchor    = edge;
+          FT_TRACE5(( "  SERIF_ANCHOR: edge %d (opos=%.2f)"
+                      " snapped to (%.2f)\n",
+                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
         }
         else
         {
@@ -2067,17 +2190,20 @@
                           FT_MulDiv( edge->opos - before->opos,
                                      after->pos - before->pos,
                                      after->opos - before->opos );
-            AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) "
+
+            FT_TRACE5(( "  SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
                      "from %d (opos=%.2f)\n",
                      edge-edges, edge->opos / 64.0,
-                     edge->pos / 64.0, before - edges,
-                     before->opos / 64.0 ));
+                        edge->pos / 64.0,
+                        before - edges, before->opos / 64.0 ));
           }
           else
           {
             edge->pos = anchor->pos +
                         ( ( edge->opos - anchor->opos + 16 ) & ~31 );
-            AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
+
+            FT_TRACE5(( "  SERIF_LINK2: edge %d (opos=%.2f)"
+                        " snapped to (%.2f)\n",
                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
           }
         }
@@ -2093,9 +2219,13 @@
           edge->pos = edge[1].pos;
       }
     }
+
+    FT_TRACE5(( "\n" ));
   }
 
 
+  /* Apply the complete hinting algorithm to a latin glyph. */
+
   static FT_Error
   af_latin_hints_apply( AF_GlyphHints    hints,
                         FT_Outline*      outline,
@@ -2110,7 +2240,7 @@
       goto Exit;
 
     /* analyze glyph outline */
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
     if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
          AF_HINTS_DO_HORIZONTAL( hints ) )
 #else
@@ -2134,17 +2264,19 @@
     /* grid-fit the outline */
     for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
     {
-#ifdef AF_USE_WARPER
-      if ( ( dim == AF_DIMENSION_HORZ &&
-             metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+      if ( dim == AF_DIMENSION_HORZ                                 &&
+           metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT )
       {
         AF_WarperRec  warper;
         FT_Fixed      scale;
         FT_Pos        delta;
 
 
-        af_warper_compute( &warper, hints, dim, &scale, &delta );
-        af_glyph_hints_scale_dim( hints, dim, scale, delta );
+        af_warper_compute( &warper, hints, (AF_Dimension)dim,
+                           &scale, &delta );
+        af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+                                  scale, delta );
         continue;
       }
 #endif
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index 660b10c..c5c2d13 100644
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (specification).       */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2009 by                        */
+/*  Copyright 2003-2007, 2009, 2011 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -30,8 +30,8 @@
   AF_DECLARE_SCRIPT_CLASS(af_latin_script_class)
 
 
-/* constants are given with units_per_em == 2048 in mind */
-#define AF_LATIN_CONSTANT( metrics, c ) \
+  /* constants are given with units_per_em == 2048 in mind */
+#define AF_LATIN_CONSTANT( metrics, c )                                      \
   ( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
 
 
@@ -76,10 +76,10 @@
 
   enum
   {
-    AF_LATIN_BLUE_ACTIVE     = 1 << 0,
-    AF_LATIN_BLUE_TOP        = 1 << 1,
-    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,  /* result of AF_LATIN_IS_TOP_BLUE */
+    AF_LATIN_BLUE_ADJUSTMENT = 1 << 2,  /* used for scale adjustment      */
+                                        /* optimization                   */
     AF_LATIN_BLUE_FLAG_MAX
   };
 
@@ -98,14 +98,13 @@
     FT_Fixed         scale;
     FT_Pos           delta;
 
-    FT_UInt          width_count;
-    AF_WidthRec      widths[AF_LATIN_MAX_WIDTHS];
-    FT_Pos           edge_distance_threshold;
-    FT_Pos           standard_width;
-    FT_Bool          extra_light;
+    FT_UInt          width_count;                 /* number of used widths */
+    AF_WidthRec      widths[AF_LATIN_MAX_WIDTHS]; /* widths array          */
+    FT_Pos           edge_distance_threshold;   /* used for creating edges */
+    FT_Pos           standard_width;         /* the default stem thickness */
+    FT_Bool          extra_light;         /* is standard width very light? */
 
     /* ignored for horizontal metrics */
-    FT_Bool          control_overshoot;
     FT_UInt          blue_count;
     AF_LatinBlueRec  blues[AF_LATIN_BLUE_MAX];
 
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
index 6546475..23558b8 100644
--- a/src/autofit/aflatin2.c
+++ b/src/autofit/aflatin2.c
@@ -1,10 +1,10 @@
 /***************************************************************************/
 /*                                                                         */
-/*  aflatin.c                                                              */
+/*  aflatin2.c                                                             */
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (body).                */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by            */
+/*  Copyright 2003-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,13 +23,24 @@
 #include "aferrors.h"
 
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
 #include "afwarp.h"
 #endif
 
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_aflatin2
+
+
   FT_LOCAL_DEF( FT_Error )
   af_latin2_hints_compute_segments( AF_GlyphHints  hints,
-                                   AF_Dimension   dim );
+                                    AF_Dimension   dim );
 
   FT_LOCAL_DEF( void )
   af_latin2_hints_link_segments( AF_GlyphHints  hints,
@@ -45,8 +56,8 @@
 
   FT_LOCAL_DEF( void )
   af_latin2_metrics_init_widths( AF_LatinMetrics  metrics,
-                                FT_Face          face,
-                                FT_ULong         charcode )
+                                 FT_Face          face,
+                                 FT_ULong         charcode )
   {
     /* scan the array of segments in each direction */
     AF_GlyphHintsRec  hints[1];
@@ -156,7 +167,8 @@
 #define AF_LATIN_MAX_TEST_CHARACTERS  12
 
 
-  static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES][AF_LATIN_MAX_TEST_CHARACTERS+1] =
+  static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
+                                        [AF_LATIN_MAX_TEST_CHARACTERS+1] =
   {
     "THEZOCQS",
     "HEZLOCUS",
@@ -169,7 +181,7 @@
 
   static void
   af_latin2_metrics_init_blues( AF_LatinMetrics  metrics,
-                               FT_Face          face )
+                                FT_Face          face )
   {
     FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
     FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
@@ -182,12 +194,12 @@
     FT_GlyphSlot  glyph = face->glyph;
 
 
-    /* we compute the blues simply by loading each character from the    */
+    /* we compute the blues simply by loading each character from the     */
     /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
-    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                */
+    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                 */
 
-    AF_LOG(( "blue zones computation\n" ));
-    AF_LOG(( "------------------------------------------------\n" ));
+    FT_TRACE5(( "blue zones computation\n" ));
+    FT_TRACE5(( "------------------------------------------------\n" ));
 
     for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
     {
@@ -197,7 +209,7 @@
       FT_Pos*      blue_shoot;
 
 
-      AF_LOG(( "blue %3d: ", bb ));
+      FT_TRACE5(( "blue %3d: ", bb ));
 
       num_flats  = 0;
       num_rounds = 0;
@@ -210,7 +222,7 @@
         FT_Bool     round;
 
 
-        AF_LOG(( "'%c'", *p ));
+        FT_TRACE5(( "'%c'", *p ));
 
         /* load the character in the face -- skip unknown or empty ones */
         glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
@@ -273,7 +285,7 @@
               best_last  = last;
             }
           }
-          AF_LOG(( "%5d", best_y ));
+          FT_TRACE5(( "%5d", best_y ));
         }
 
         /* now check whether the point belongs to a straight or round   */
@@ -321,7 +333,7 @@
             FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
             FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
 
-          AF_LOG(( "%c ", round ? 'r' : 'f' ));
+          FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
         }
 
         if ( round )
@@ -330,7 +342,7 @@
           flats[num_flats++]   = best_y;
       }
 
-      AF_LOG(( "\n" ));
+      FT_TRACE5(( "\n" ));
 
       if ( num_flats == 0 && num_rounds == 0 )
       {
@@ -338,7 +350,7 @@
          *  we couldn't find a single glyph to compute this blue zone,
          *  we will simply ignore it then
          */
-        AF_LOG(( "empty\n" ));
+        FT_TRACE5(( "empty\n" ));
         continue;
       }
 
@@ -396,7 +408,7 @@
       if ( bb == AF_LATIN_BLUE_SMALL_TOP )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
-      AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
     }
 
     return;
@@ -451,7 +463,7 @@
 
   FT_LOCAL_DEF( FT_Error )
   af_latin2_metrics_init( AF_LatinMetrics  metrics,
-                         FT_Face          face )
+                          FT_Face          face )
   {
     FT_Error    error = AF_Err_Ok;
     FT_CharMap  oldmap = face->charmap;
@@ -492,8 +504,8 @@
 
   static void
   af_latin2_metrics_scale_dim( AF_LatinMetrics  metrics,
-                              AF_Scaler        scaler,
-                              AF_Dimension     dim )
+                               AF_Scaler        scaler,
+                               AF_Dimension     dim )
   {
     FT_Fixed      scale;
     FT_Pos        delta;
@@ -548,7 +560,10 @@
         if ( scaled != fitted )
         {
           scale = FT_MulDiv( scale, fitted, scaled );
-          AF_LOG(( "== scaled x-top = %.2g  fitted = %.2g, scaling = %.4g\n", scaled/64.0, fitted/64.0, (fitted*1.0)/scaled ));
+          FT_TRACE5(( "== scaled x-top = %.2g"
+                      "  fitted = %.2g, scaling = %.4g\n",
+                      scaled / 64.0, fitted / 64.0,
+                      ( fitted * 1.0 ) / scaled ));
         }
 #endif
       }
@@ -579,7 +594,7 @@
     }
 
     /* an extra-light axis corresponds to a standard width that is */
-    /* smaller than 0.75 pixels                                    */
+    /* smaller than 5/8 pixels                                     */
     axis->extra_light =
       (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
 
@@ -624,9 +639,11 @@
           blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
           blue->shoot.fit = blue->ref.fit + delta2;
 
-          AF_LOG(( ">> activating blue zone %d:  ref.cur=%.2g ref.fit=%.2g shoot.cur=%.2g shoot.fit=%.2g\n",
-                   nn, blue->ref.cur/64.0, blue->ref.fit/64.0,
-                   blue->shoot.cur/64.0, blue->shoot.fit/64.0 ));
+          FT_TRACE5(( ">> activating blue zone %d:"
+                      "  ref.cur=%.2g ref.fit=%.2g"
+                      "  shoot.cur=%.2g shoot.fit=%.2g\n",
+                      nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+                      blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
 
           blue->flags |= AF_LATIN_BLUE_ACTIVE;
         }
@@ -637,7 +654,7 @@
 
   FT_LOCAL_DEF( void )
   af_latin2_metrics_scale( AF_LatinMetrics  metrics,
-                          AF_Scaler        scaler )
+                           AF_Scaler        scaler )
   {
     metrics->root.scaler.render_mode = scaler->render_mode;
     metrics->root.scaler.face        = scaler->face;
@@ -659,7 +676,7 @@
 
   FT_LOCAL_DEF( FT_Error )
   af_latin2_hints_compute_segments( AF_GlyphHints  hints,
-                                   AF_Dimension   dim )
+                                    AF_Dimension   dim )
   {
     AF_AxisHints  axis          = &hints->axis[dim];
     FT_Memory     memory        = hints->memory;
@@ -779,7 +796,6 @@
         segment->dir       = first->out_dir;
         segment->first     = first;
         segment->last      = point;
-        segment->contour   = contour;
         segment->pos       = (FT_Short)(( min_u + max_u ) >> 1);
         segment->min_coord = (FT_Short) min_v;
         segment->max_coord = (FT_Short) max_v;
@@ -917,7 +933,7 @@
 
   FT_LOCAL_DEF( void )
   af_latin2_hints_link_segments( AF_GlyphHints  hints,
-                                AF_Dimension   dim )
+                                 AF_Dimension   dim )
   {
     AF_AxisHints  axis          = &hints->axis[dim];
     AF_Segment    segments      = axis->segments;
@@ -1017,7 +1033,7 @@
 
   FT_LOCAL_DEF( FT_Error )
   af_latin2_hints_compute_edges( AF_GlyphHints  hints,
-                                AF_Dimension   dim )
+                                 AF_Dimension   dim )
   {
     AF_AxisHints  axis   = &hints->axis[dim];
     FT_Error      error  = AF_Err_Ok;
@@ -1137,7 +1153,8 @@
 
         /* insert a new edge in the list and */
         /* sort according to the position    */
-        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
+        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir,
+                                        memory, &edge );
         if ( error )
           goto Exit;
 
@@ -1205,8 +1222,10 @@
       {
         FT_Int  is_round    = 0;  /* does it contain round segments?    */
         FT_Int  is_straight = 0;  /* does it contain straight segments? */
+#if 0
         FT_Pos  ups         = 0;  /* number of upwards segments         */
         FT_Pos  downs       = 0;  /* number of downwards segments       */
+#endif
 
 
         seg = edge->first;
@@ -1222,11 +1241,13 @@
           else
             is_straight++;
 
+#if 0
           /* check for segment direction */
           if ( seg->dir == up_dir )
             ups   += seg->max_coord-seg->min_coord;
           else
             downs += seg->max_coord-seg->min_coord;
+#endif
 
           /* check for links -- if seg->serif is set, then seg->link must */
           /* be ignored                                                   */
@@ -1318,7 +1339,7 @@
 
   FT_LOCAL_DEF( FT_Error )
   af_latin2_hints_detect_features( AF_GlyphHints  hints,
-                                  AF_Dimension   dim )
+                                   AF_Dimension   dim )
   {
     FT_Error  error;
 
@@ -1336,7 +1357,7 @@
 
   FT_LOCAL_DEF( void )
   af_latin2_hints_compute_blue_edges( AF_GlyphHints    hints,
-                                     AF_LatinMetrics  metrics )
+                                      AF_LatinMetrics  metrics )
   {
     AF_AxisHints  axis       = &hints->axis[ AF_DIMENSION_VERT ];
     AF_Edge       edge       = axis->edges;
@@ -1442,7 +1463,7 @@
 
   static FT_Error
   af_latin2_hints_init( AF_GlyphHints    hints,
-                       AF_LatinMetrics  metrics )
+                        AF_LatinMetrics  metrics )
   {
     FT_Render_Mode  mode;
     FT_UInt32       scaler_flags, other_flags;
@@ -1463,7 +1484,7 @@
     /* compute flags depending on render mode, etc. */
     mode = metrics->root.scaler.render_mode;
 
-#if 0 /* #ifdef AF_USE_WARPER */
+#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
     if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
     {
       metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
@@ -1524,8 +1545,8 @@
 
   static FT_Pos
   af_latin2_snap_width( AF_Width  widths,
-                       FT_Int    count,
-                       FT_Pos    width )
+                        FT_Int    count,
+                        FT_Pos    width )
   {
     int     n;
     FT_Pos  best      = 64 + 32 + 2;
@@ -1571,10 +1592,10 @@
 
   static FT_Pos
   af_latin2_compute_stem_width( AF_GlyphHints  hints,
-                               AF_Dimension   dim,
-                               FT_Pos         width,
-                               AF_Edge_Flags  base_flags,
-                               AF_Edge_Flags  stem_flags )
+                                AF_Dimension   dim,
+                                FT_Pos         width,
+                                AF_Edge_Flags  base_flags,
+                                AF_Edge_Flags  stem_flags )
   {
     AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
     AF_LatinAxis     axis     = & metrics->axis[dim];
@@ -1739,9 +1760,9 @@
 
   static void
   af_latin2_align_linked_edge( AF_GlyphHints  hints,
-                              AF_Dimension   dim,
-                              AF_Edge        base_edge,
-                              AF_Edge        stem_edge )
+                               AF_Dimension   dim,
+                               AF_Edge        base_edge,
+                               AF_Edge        stem_edge )
   {
     FT_Pos  dist = stem_edge->opos - base_edge->opos;
 
@@ -1753,17 +1774,17 @@
 
     stem_edge->pos = base_edge->pos + fitted_width;
 
-    AF_LOG(( "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->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+    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->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
   }
 
 
   static void
   af_latin2_align_serif_edge( AF_GlyphHints  hints,
-                             AF_Edge        base,
-                             AF_Edge        serif )
+                              AF_Edge        base,
+                              AF_Edge        serif )
   {
     FT_UNUSED( hints );
 
@@ -1784,7 +1805,7 @@
 
   FT_LOCAL_DEF( void )
   af_latin2_hint_edges( AF_GlyphHints  hints,
-                       AF_Dimension   dim )
+                        AF_Dimension   dim )
   {
     AF_AxisHints  axis       = &hints->axis[dim];
     AF_Edge       edges      = axis->edges;
@@ -1796,7 +1817,8 @@
 
 
 
-    AF_LOG(( "==== hinting %s edges =====\n", dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
+    FT_TRACE5(( "==== hinting %s edges =====\n",
+                dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
 
     /* we begin by aligning all stems relative to the blue zone */
     /* if needed -- that's only for horizontal edges            */
@@ -1830,10 +1852,10 @@
         if ( !edge1 )
           continue;
 
-        AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
-                 "was (%.2f)\n",
-                 edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
-                 edge1->pos / 64.0 ));
+        FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
+                    "was (%.2f)\n",
+                    edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
+                    edge1->pos / 64.0 ));
 
         edge1->pos    = blue->fit;
         edge1->flags |= AF_EDGE_DONE;
@@ -1878,7 +1900,7 @@
       /* this should not happen, but it's better to be safe */
       if ( edge2->blue_edge )
       {
-        AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+        FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
 
         af_latin2_align_linked_edge( hints, dim, edge2, edge );
         edge->flags |= AF_EDGE_DONE;
@@ -1929,11 +1951,11 @@
         else
           edge->pos = FT_PIX_ROUND( edge->opos );
 
-        AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
-                 "snapped to (%.2f) (%.2f)\n",
-                 edge-edges, edge->opos / 64.0,
-                 edge2-edges, edge2->opos / 64.0,
-                 edge->pos / 64.0, edge2->pos / 64.0 ));
+        FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
+                    " snapped to (%.2f) (%.2f)\n",
+                    edge-edges, edge->opos / 64.0,
+                    edge2-edges, edge2->opos / 64.0,
+                    edge->pos / 64.0, edge2->pos / 64.0 ));
         anchor = edge;
 
         edge->flags |= AF_EDGE_DONE;
@@ -1945,7 +1967,7 @@
         anchor_drift = ( (anchor->pos - anchor->opos) +
                          (edge2->pos - edge2->opos)) >> 1;
 
-        AF_LOG(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
+        FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
       }
       else
       {
@@ -1965,12 +1987,13 @@
         org_left  = org_pos + ((org_len - cur_len) >> 1);
         org_right = org_pos + ((org_len + cur_len) >> 1);
 
-        AF_LOG(( "ALIGN: left=%.2f right=%.2f ", org_left/64.0, org_right/64.0 ));
+        FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
+                    org_left / 64.0, org_right / 64.0 ));
         cur_center = org_center;
 
         if ( edge2->flags & AF_EDGE_DONE )
         {
-          AF_LOG(( "\n" ));
+          FT_TRACE5(( "\n" ));
           edge->pos = edge2->pos - cur_len;
         }
         else
@@ -1985,14 +2008,14 @@
           /* note: don't even try to fit tiny stems */
           if ( cur_len < 32 )
           {
-            AF_LOG(( "tiny stem\n" ));
+            FT_TRACE5(( "tiny stem\n" ));
             goto AlignStem;
           }
 
           /* if the span is within a single pixel, don't touch it */
           if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) )
           {
-            AF_LOG(( "single pixel stem\n" ));
+            FT_TRACE5(( "single pixel stem\n" ));
             goto AlignStem;
           }
 
@@ -2015,14 +2038,14 @@
               delta = FT_ABS(fit - org);
               displacements[count] = fit - org;
               scores[count++]      = delta;
-              AF_LOG(( "dispA=%.2f (%d) ", (fit - org)/64.0, delta ));
+              FT_TRACE5(( "dispA=%.2f (%d) ", (fit - org) / 64.0, delta ));
 
               org = frac_right;
               fit = (org <= 32) ? 16 : 48;
               delta = FT_ABS(fit - org);
               displacements[count] = fit - org;
               scores[count++]     = delta;
-              AF_LOG(( "dispB=%.2f (%d) ", (fit - org)/64.0, delta ));
+              FT_TRACE5(( "dispB=%.2f (%d) ", (fit - org) / 64.0, delta ));
             }
           }
 
@@ -2032,7 +2055,7 @@
           delta = FT_ABS(fit - org);
           displacements[count] = fit - org;
           scores[count++]      = delta;
-          AF_LOG(( "dispC=%.2f (%d) ", (fit - org)/64.0, delta ));
+          FT_TRACE5(( "dispC=%.2f (%d) ", (fit - org) / 64.0, delta ));
 
           /* snapping the right edge to the grid */
           org   = org_right;
@@ -2040,7 +2063,7 @@
           delta = FT_ABS(fit - org);
           displacements[count] = fit - org;
           scores[count++]      = delta;
-          AF_LOG(( "dispD=%.2f (%d) ", (fit - org)/64.0, delta ));
+          FT_TRACE5(( "dispD=%.2f (%d) ", (fit - org) / 64.0, delta ));
 
           /* now find the best displacement */
           {
@@ -2059,27 +2082,28 @@
 
             cur_center = org_center + best_disp;
           }
-          AF_LOG(( "\n" ));
+          FT_TRACE5(( "\n" ));
         }
 
       AlignStem:
         edge->pos  = cur_center - (cur_len >> 1);
         edge2->pos = edge->pos + cur_len;
 
-        AF_LOG(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f) "
-                 "snapped to (%.2f) and (%.2f), org_len = %.2f cur_len=%.2f\n",
-                 edge-edges, edge->opos / 64.0,
-                 edge2-edges, edge2->opos / 64.0,
-                 edge->pos / 64.0, edge2->pos / 64.0,
-                 org_len / 64.0, cur_len / 64.0 ));
+        FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
+                    " snapped to (%.2f) and (%.2f),"
+                    " org_len=%.2f cur_len=%.2f\n",
+                    edge-edges, edge->opos / 64.0,
+                    edge2-edges, edge2->opos / 64.0,
+                    edge->pos / 64.0, edge2->pos / 64.0,
+                    org_len / 64.0, cur_len / 64.0 ));
 
         edge->flags  |= AF_EDGE_DONE;
         edge2->flags |= AF_EDGE_DONE;
 
         if ( edge > edges && edge->pos < edge[-1].pos )
         {
-          AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
-                   edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+          FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
+                      edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
           edge->pos = edge[-1].pos;
         }
       }
@@ -2179,16 +2203,17 @@
         if ( delta < 64 + 16 )
         {
           af_latin2_align_serif_edge( hints, edge->serif, edge );
-          AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
-                   "aligned to (%.2f)\n",
-                   edge-edges, edge->opos / 64.0,
-                   edge->serif - edges, edge->serif->opos / 64.0,
-                   edge->pos / 64.0 ));
+          FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
+                      " aligned to (%.2f)\n",
+                      edge-edges, edge->opos / 64.0,
+                      edge->serif - edges, edge->serif->opos / 64.0,
+                      edge->pos / 64.0 ));
         }
         else if ( !anchor )
         {
-          AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
-                   edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+          FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
+                      " snapped to (%.2f)\n",
+                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
           edge->pos = FT_PIX_ROUND( edge->opos );
           anchor    = edge;
         }
@@ -2215,15 +2240,19 @@
                           FT_MulDiv( edge->opos - before->opos,
                                      after->pos - before->pos,
                                      after->opos - before->opos );
-            AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) from %d (opos=%.2f)\n",
-                     edge-edges, edge->opos / 64.0, edge->pos / 64.0, before - edges, before->opos / 64.0 ));
+            FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+                        " from %d (opos=%.2f)\n",
+                        edge-edges, edge->opos / 64.0, edge->pos / 64.0,
+                        before - edges, before->opos / 64.0 ));
           }
           else
           {
-              edge->pos = anchor->pos + (( edge->opos - anchor->opos + 16) & ~31);
+            edge->pos = anchor->pos +
+                        ( ( edge->opos - anchor->opos + 16 ) & ~31 );
 
-            AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
-                     edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+            FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
+                        " snapped to (%.2f)\n",
+                        edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
           }
         }
 
@@ -2243,8 +2272,8 @@
 
   static FT_Error
   af_latin2_hints_apply( AF_GlyphHints    hints,
-                        FT_Outline*      outline,
-                        AF_LatinMetrics  metrics )
+                         FT_Outline*      outline,
+                         AF_LatinMetrics  metrics )
   {
     FT_Error  error;
     int       dim;
@@ -2255,7 +2284,7 @@
       goto Exit;
 
     /* analyze glyph outline */
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
     if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
          AF_HINTS_DO_HORIZONTAL( hints ) )
 #else
@@ -2279,7 +2308,7 @@
     /* grid-fit the outline */
     for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
     {
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
       if ( ( dim == AF_DIMENSION_HORZ &&
              metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
       {
@@ -2321,7 +2350,7 @@
 
   static const AF_Script_UniRangeRec  af_latin2_uniranges[] =
   {
-    AF_UNIRANGE_REC( 32UL,  127UL ),    /* XXX: TODO: Add new Unicode ranges here! */
+    AF_UNIRANGE_REC( 32UL,  127UL ),    /* TODO: Add new Unicode ranges here! */
     AF_UNIRANGE_REC( 160UL, 255UL ),
     AF_UNIRANGE_REC( 0UL,   0UL )
   };
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 6dd9f2a..966a0df 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter glyph loading routines (body).                           */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by                  */
+/*  Copyright 2003-2009, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,6 +22,8 @@
 #include "aferrors.h"
 
 
+  /* Initialize glyph loader. */
+
   FT_LOCAL_DEF( FT_Error )
   af_loader_init( AF_Loader  loader,
                   FT_Memory  memory )
@@ -29,13 +31,15 @@
     FT_ZERO( loader );
 
     af_glyph_hints_init( &loader->hints, memory );
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
     _af_debug_hints = &loader->hints;
 #endif
     return FT_GlyphLoader_New( memory, &loader->gloader );
   }
 
 
+  /* Reset glyph loader and compute globals if necessary. */
+
   FT_LOCAL_DEF( FT_Error )
   af_loader_reset( AF_Loader  loader,
                    FT_Face    face )
@@ -64,6 +68,8 @@
   }
 
 
+  /* Finalize glyph loader. */
+
   FT_LOCAL_DEF( void )
   af_loader_done( AF_Loader  loader )
   {
@@ -72,7 +78,7 @@
     loader->face    = NULL;
     loader->globals = NULL;
 
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
     _af_debug_hints = NULL;
 #endif
     FT_GlyphLoader_Done( loader->gloader );
@@ -80,6 +86,10 @@
   }
 
 
+  /* Load a single glyph component.  This routine calls itself */
+  /* recursively, if necessary, and does the main work of      */
+  /* `af_loader_load_glyph.'                                   */
+
   static FT_Error
   af_loader_load_g( AF_Loader  loader,
                     AF_Scaler  scaler,
@@ -169,8 +179,8 @@
                                             &gloader->current.outline,
                                             metrics );
 
-      /* we now need to hint the metrics according to the change in */
-      /* width/positioning that occurred during the hinting process */
+      /* we now need to adjust the metrics according to the change in */
+      /* width/positioning that occurred during the hinting process   */
       if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
       {
         FT_Pos        old_rsb, old_lsb, new_lsb;
@@ -265,7 +275,7 @@
         gloader->current.num_subglyphs = num_subglyphs;
         num_base_subgs                 = gloader->base.num_subglyphs;
 
-        /* now, read each subglyph independently */
+        /* now read each subglyph independently */
         for ( nn = 0; nn < num_subglyphs; nn++ )
         {
           FT_Vector  pp1, pp2;
@@ -305,7 +315,7 @@
           num_points     = gloader->base.outline.n_points;
           num_new_points = num_points - num_base_points;
 
-          /* now perform the transform required for this subglyph */
+          /* now perform the transformation required for this subglyph */
 
           if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
                                    FT_SUBGLYPH_FLAG_XY_SCALE |
@@ -444,7 +454,7 @@
 #endif
 
       slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
-                                              metrics->scaler.y_scale );
+                                             metrics->scaler.y_scale );
 
       slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
       slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
@@ -459,15 +469,13 @@
       slot->format  = FT_GLYPH_FORMAT_OUTLINE;
     }
 
-#ifdef DEBUG_HINTER
-    af_debug_hinter = hinter;
-#endif
-
   Exit:
     return error;
   }
 
 
+  /* Load a glyph. */
+
   FT_LOCAL_DEF( FT_Error )
   af_loader_load_glyph( AF_Loader  loader,
                         FT_Face    face,
diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h
index fa67c10..3f91e1a 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter glyph loading routines (specification).                  */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005 by                                          */
+/*  Copyright 2003-2005, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __AF_LOADER_H__
-#define __AF_LOADER_H__
+#ifndef __AFLOADER_H__
+#define __AFLOADER_H__
 
 #include "afhints.h"
 #include "afglobal.h"
@@ -67,7 +67,7 @@
 
 FT_END_HEADER
 
-#endif /* __AF_LOADER_H__ */
+#endif /* __AFLOADER_H__ */
 
 
 /* END */
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index ec2d707..20b6218 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module implementation (body).                            */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006 by                                    */
+/*  Copyright 2003-2006, 2009, 2011 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,8 +20,7 @@
 #include "afloader.h"
 #include "afpic.h"
 
-#ifdef AF_DEBUG
-  int    _af_debug;
+#ifdef FT_DEBUG_AUTOFIT
   int    _af_debug_disable_horz_hints;
   int    _af_debug_disable_vert_hints;
   int    _af_debug_disable_blue_hints;
@@ -67,14 +66,15 @@
   }
 
 
-  FT_DEFINE_AUTOHINTER_SERVICE(af_autofitter_service,
+  FT_DEFINE_AUTOHINTER_SERVICE(
+    af_autofitter_service,
     NULL,
     NULL,
     NULL,
-    (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph
-  )
+    (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph )
 
-  FT_DEFINE_MODULE(autofit_module_class,
+  FT_DEFINE_MODULE(
+    autofit_module_class,
 
     FT_MODULE_HINTER,
     sizeof ( FT_AutofitterRec ),
@@ -87,8 +87,7 @@
 
     (FT_Module_Constructor)af_autofitter_init,
     (FT_Module_Destructor) af_autofitter_done,
-    (FT_Module_Requester)  NULL
-  )
+    (FT_Module_Requester)  NULL )
 
 
 /* END */
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index 5b9aba6..3aefbc5 100644
--- a/src/autofit/afpic.c
+++ b/src/autofit/afpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for autofit module.  */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2011 by                                          */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,7 +24,8 @@
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from afmodule.c */
-  void FT_Init_Class_af_autofitter_service( FT_Library, FT_AutoHinter_ServiceRec*);
+  void FT_Init_Class_af_autofitter_service( FT_Library,
+                                            FT_AutoHinter_ServiceRec* );
 
   /* forward declaration of PIC init functions from script classes */
 #include "aflatin.h"
@@ -34,10 +35,12 @@
 #include "afindic.h"
 
   void
-  autofit_module_class_pic_free( FT_Library library )
+  autofit_module_class_pic_free( FT_Library  library )
   {
-    FT_PIC_Container* pic_container = &library->pic_container;
-    FT_Memory memory = library->memory;
+    FT_PIC_Container*  pic_container = &library->pic_container;
+    FT_Memory          memory        = library->memory;
+
+
     if ( pic_container->autofit )
     {
       FT_FREE( pic_container->autofit );
@@ -62,28 +65,37 @@
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->autofit = container;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table -                       */
+    /* this is how the module usually expects this data */
     for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )
     {
-      container->af_script_classes[ss] = &container->af_script_classes_rec[ss];
+      container->af_script_classes[ss] =
+        &container->af_script_classes_rec[ss];
     }
-    container->af_script_classes[AF_SCRIPT_CLASSES_COUNT-1] = NULL;
+    container->af_script_classes[AF_SCRIPT_CLASSES_COUNT - 1] = NULL;
     
     /* add call to initialization function when you add new scripts */
     ss = 0;
-    FT_Init_Class_af_dummy_script_class(&container->af_script_classes_rec[ss++]);
+    FT_Init_Class_af_dummy_script_class(
+      &container->af_script_classes_rec[ss++] );
 #ifdef FT_OPTION_AUTOFIT2
-    FT_Init_Class_af_latin2_script_class(&container->af_script_classes_rec[ss++]);
+    FT_Init_Class_af_latin2_script_class(
+      &container->af_script_classes_rec[ss++] );
 #endif
-    FT_Init_Class_af_latin_script_class(&container->af_script_classes_rec[ss++]);
-    FT_Init_Class_af_cjk_script_class(&container->af_script_classes_rec[ss++]);
-    FT_Init_Class_af_indic_script_class(&container->af_script_classes_rec[ss++]);    
+    FT_Init_Class_af_latin_script_class(
+      &container->af_script_classes_rec[ss++] );
+    FT_Init_Class_af_cjk_script_class(
+      &container->af_script_classes_rec[ss++] );
+    FT_Init_Class_af_indic_script_class(
+      &container->af_script_classes_rec[ss++] );
 
-    FT_Init_Class_af_autofitter_service(library, &container->af_autofitter_service);
+    FT_Init_Class_af_autofitter_service(
+      library, &container->af_autofitter_service );
 
-/*Exit:*/
-    if(error)
-      autofit_module_class_pic_free(library);
+/* Exit: */
+
+    if ( error )
+      autofit_module_class_pic_free( library );
     return error;
   }
 
diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h
index 80e62d3..c1632e7 100644
--- a/src/autofit/afpic.h
+++ b/src/autofit/afpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for autofit module.  */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2011 by                                                */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -33,24 +33,29 @@
 
 #include "aftypes.h"
 
-/* increase these when you add new scripts, and update autofit_module_class_pic_init */
+  /* increase these when you add new scripts, */
+  /* and update autofit_module_class_pic_init */
 #ifdef FT_OPTION_AUTOFIT2
-  #define AF_SCRIPT_CLASSES_COUNT     6
+#define AF_SCRIPT_CLASSES_COUNT     6
 #else
-  #define AF_SCRIPT_CLASSES_COUNT     5  
+#define AF_SCRIPT_CLASSES_COUNT     5  
 #endif
-#define AF_SCRIPT_CLASSES_REC_COUNT  (AF_SCRIPT_CLASSES_COUNT-1)    
+#define AF_SCRIPT_CLASSES_REC_COUNT  ( AF_SCRIPT_CLASSES_COUNT - 1 )    
 
   typedef struct AFModulePIC_
   {
-    AF_ScriptClass    af_script_classes[AF_SCRIPT_CLASSES_COUNT];
-    AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
-    FT_AutoHinter_ServiceRec af_autofitter_service;
+    AF_ScriptClass            af_script_classes[AF_SCRIPT_CLASSES_COUNT];
+    AF_ScriptClassRec         af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
+    FT_AutoHinter_ServiceRec  af_autofitter_service;
+
   } AFModulePIC;
 
-#define GET_PIC(lib)                  ((AFModulePIC*)((lib)->pic_container.autofit))
-#define AF_SCRIPT_CLASSES_GET         (GET_PIC(FT_FACE_LIBRARY(globals->face))->af_script_classes)
-#define AF_AF_AUTOFITTER_SERVICE_GET  (GET_PIC(library)->af_autofitter_service)
+#define GET_PIC( lib )                                                     \
+          ( (AFModulePIC*)((lib)->pic_container.autofit) )
+#define AF_SCRIPT_CLASSES_GET                                              \
+          ( GET_PIC( FT_FACE_LIBRARY(globals->face) )->af_script_classes )
+#define AF_AF_AUTOFITTER_SERVICE_GET                                       \
+          ( GET_PIC( library )->af_autofitter_service )
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 5574f0c..44997d1 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter types (specification only).                              */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by                  */
+/*  Copyright 2003-2009, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -53,26 +53,16 @@
   /*************************************************************************/
   /*************************************************************************/
 
-#define xxAF_USE_WARPER  /* only define to use warp hinting */
-#define xxAF_DEBUG
-
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
 
 #include FT_CONFIG_STANDARD_LIBRARY_H
 
-#define AF_LOG( x )  do { if ( _af_debug ) printf x; } while ( 0 )
-
-extern int    _af_debug;
 extern int    _af_debug_disable_horz_hints;
 extern int    _af_debug_disable_vert_hints;
 extern int    _af_debug_disable_blue_hints;
 extern void*  _af_debug_hints;
 
-#else /* !AF_DEBUG */
-
-#define AF_LOG( x )  do { } while ( 0 )        /* nothing */
-
-#endif /* !AF_DEBUG */
+#endif /* FT_DEBUG_AUTOFIT */
 
 
   /*************************************************************************/
@@ -159,36 +149,11 @@
   FT_END_STMNT
 
 
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                    O U T L I N E S                            *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
   /*  opaque handle to glyph-specific hints -- see `afhints.h' for more
    *  details
    */
   typedef struct AF_GlyphHintsRec_*  AF_GlyphHints;
 
-  /*  This structure is used to model an input glyph outline to
-   *  the auto-hinter.  The latter will set the `hints' field
-   *  depending on the glyph's script.
-   */
-  typedef struct  AF_OutlineRec_
-  {
-    FT_Face        face;
-    FT_Outline     outline;
-    FT_UInt        outline_resolution;
-
-    FT_Int         advance;
-    FT_UInt        metrics_resolution;
-
-    AF_GlyphHints  hints;
-
-  } AF_OutlineRec;
-
 
   /*************************************************************************/
   /*************************************************************************/
@@ -241,7 +206,7 @@
   /*************************************************************************/
 
   /*
-   *  The list of know scripts.  Each different script corresponds to the
+   *  The list of known scripts.  Each different script corresponds to the
    *  following information:
    *
    *   - A set of Unicode ranges to test whether the face supports the
@@ -342,55 +307,57 @@
 
   } AF_ScriptClassRec;
 
-/* Declare and define vtables for classes */
+
+  /* Declare and define vtables for classes */
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define AF_DECLARE_SCRIPT_CLASS(script_class)                                \
-  FT_CALLBACK_TABLE const AF_ScriptClassRec                                  \
+#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
+  FT_CALLBACK_TABLE const AF_ScriptClassRec     \
   script_class;
 
-#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size,        \
-                               m_init, m_scale, m_done, h_init, h_apply)     \
-  FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec                              \
-  script_class =                                                             \
-  {                                                                          \
-    script_,                                                                 \
-    ranges,                                                                  \
-                                                                             \
-    m_size,                                                                  \
-                                                                             \
-    m_init,                                                                  \
-    m_scale,                                                                 \
-    m_done,                                                                  \
-                                                                             \
-    h_init,                                                                  \
-    h_apply                                                                  \
+#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, m_size,     \
+                                m_init, m_scale, m_done, h_init, h_apply ) \
+  FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec                            \
+  script_class =                                                           \
+  {                                                                        \
+    script_,                                                               \
+    ranges,                                                                \
+                                                                           \
+    m_size,                                                                \
+                                                                           \
+    m_init,                                                                \
+    m_scale,                                                               \
+    m_done,                                                                \
+                                                                           \
+    h_init,                                                                \
+    h_apply                                                                \
   };
 
-#else 
+#else /* FT_CONFIG_OPTION_PIC */
 
-#define AF_DECLARE_SCRIPT_CLASS(script_class)                                \
-  FT_LOCAL(void)                                                             \
-  FT_Init_Class_##script_class(AF_ScriptClassRec* ac);
+#define AF_DECLARE_SCRIPT_CLASS( script_class )          \
+  FT_LOCAL( void )                                       \
+  FT_Init_Class_##script_class( AF_ScriptClassRec* ac );
 
-#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size,        \
-                               m_init, m_scale, m_done, h_init, h_apply)     \
-  FT_LOCAL_DEF(void)                                                         \
-  FT_Init_Class_##script_class(AF_ScriptClassRec* ac)                        \
-  {                                                                          \
-    ac->script                = script_;                                     \
-    ac->script_uni_ranges     = ranges;                                      \
-                                                                             \
-    ac->script_metrics_size   = m_size;                                      \
-                                                                             \
-    ac->script_metrics_init   = m_init;                                      \
-    ac->script_metrics_scale  = m_scale;                                     \
-    ac->script_metrics_done   = m_done;                                      \
-                                                                             \
-    ac->script_hints_init     = h_init;                                      \
-    ac->script_hints_apply    = h_apply;                                     \
+#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, m_size,     \
+                                m_init, m_scale, m_done, h_init, h_apply ) \
+  FT_LOCAL_DEF( void )                                                     \
+  FT_Init_Class_##script_class( AF_ScriptClassRec* ac )                    \
+  {                                                                        \
+    ac->script               = script_;                                    \
+    ac->script_uni_ranges    = ranges;                                     \
+                                                                           \
+    ac->script_metrics_size  = m_size;                                     \
+                                                                           \
+    ac->script_metrics_init  = m_init;                                     \
+    ac->script_metrics_scale = m_scale;                                    \
+    ac->script_metrics_done  = m_done;                                     \
+                                                                           \
+    ac->script_hints_init    = h_init;                                     \
+    ac->script_hints_apply   = h_apply;                                    \
   }
-#endif
+
+#endif /* FT_CONFIG_OPTION_PIC */
 
 
 /* */
diff --git a/src/autofit/afwarp.c b/src/autofit/afwarp.c
index f5bb9b1..d0d4850 100644
--- a/src/autofit/afwarp.c
+++ b/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter warping algorithm (body).                                */
 /*                                                                         */
-/*  Copyright 2006, 2007 by                                                */
+/*  Copyright 2006, 2007, 2011 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,10 +16,30 @@
 /***************************************************************************/
 
 
+  /*
+   *  The idea of the warping code is to slightly scale and shift a glyph
+   *  within a single dimension so that as much of its segments are aligned
+   *  (more or less) on the grid.  To find out the optimal scaling and
+   *  shifting value, various parameter combinations are tried and scored.
+   */
+
 #include "afwarp.h"
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_afwarp
+
+
+  /* The weights cover the range 0/64 - 63/64 of a pixel.  Obviously, */
+  /* values around a half pixel (which means exactly between two grid */
+  /* lines) gets the worst weight.                                    */
 #if 1
   static const AF_WarpScore
   af_warper_weights[64] =
@@ -43,6 +63,11 @@
 #endif
 
 
+  /* Score segments for a given `scale' and `delta' in the range */
+  /* `xx1' to `xx2', and store the best result in `warper'.  If  */
+  /* the new best score is equal to the old one, prefer the      */
+  /* value with a smaller distortion (around `base_distort').    */
+
   static void
   af_warper_compute_line_best( AF_Warper     warper,
                                FT_Fixed      scale,
@@ -82,12 +107,12 @@
 
       if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
       {
-        AF_LOG(( "invalid indices:\n"
-                 "  min=%d max=%d, xx1=%ld xx2=%ld,\n"
-                 "  x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
-                 idx_min, idx_max, xx1, xx2,
-                 warper->x1min, warper->x1max,
-                 warper->x2min, warper->x2max ));
+        FT_TRACE5(( "invalid indices:\n"
+                    "  min=%d max=%d, xx1=%ld xx2=%ld,\n"
+                    "  x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
+                    idx_min, idx_max, xx1, xx2,
+                    warper->x1min, warper->x1max,
+                    warper->x2min, warper->x2max ));
         return;
       }
     }
@@ -100,6 +125,7 @@
       FT_Int  idx;
 
 
+      /* score the length of the segments for the given range */
       for ( idx = idx_min; idx <= idx_max; idx++, y++ )
         scores[idx] += af_warper_weights[y & 63] * len;
     }
@@ -115,9 +141,9 @@
         AF_WarpScore  distort = base_distort + ( idx - idx0 );
 
 
-        if ( score > warper->best_score           ||
+        if ( score > warper->best_score         ||
              ( score == warper->best_score    &&
-               distort < warper->best_distort )   )
+               distort < warper->best_distort ) )
         {
           warper->best_score   = score;
           warper->best_distort = distort;
@@ -129,6 +155,9 @@
   }
 
 
+  /* Compute optimal scaling and delta values for a given glyph and */
+  /* dimension.                                                     */
+
   FT_LOCAL_DEF( void )
   af_warper_compute( AF_Warper      warper,
                      AF_GlyphHints  hints,
@@ -215,6 +244,7 @@
     warper->t1 = AF_WARPER_FLOOR( warper->x1 );
     warper->t2 = AF_WARPER_CEIL( warper->x2 );
 
+    /* examine a half pixel wide range around the maximum coordinates */
     warper->x1min = warper->x1 & ~31;
     warper->x1max = warper->x1min + 32;
     warper->x2min = warper->x2 & ~31;
@@ -234,10 +264,12 @@
       warper->x2min = warper->x2;
     }
 
+    /* examine (at most) a pixel wide range around the natural width */
     warper->wmin = warper->x2min - warper->x1max;
     warper->wmax = warper->x2max - warper->x1min;
 
 #if 1
+    /* some heuristics to reduce the number of widths to be examined */
     {
       int  margin = 16;
 
@@ -273,6 +305,8 @@
       FT_Pos    xx1, xx2;
 
 
+      /* compute min and max positions for given width,       */
+      /* assuring that they stay within the coordinate ranges */
       xx1 = warper->x1;
       xx2 = warper->x2;
       if ( w >= warper->w0 )
@@ -304,6 +338,7 @@
       else
         base_distort += xx2 - warper->x2;
 
+      /* give base distortion a greater weight while scoring */
       base_distort *= 10;
 
       new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
@@ -329,10 +364,11 @@
     }
   }
 
-#else /* !AF_USE_WARPER */
+#else /* !AF_CONFIG_OPTION_USE_WARPER */
 
-char  af_warper_dummy = 0;  /* make compiler happy */
+  /* ANSI C doesn't like empty source files */
+  typedef int  _af_warp_dummy;
 
-#endif /* !AF_USE_WARPER */
+#endif /* !AF_CONFIG_OPTION_USE_WARPER */
 
 /* END */
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index 83b613e..3883a0a 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module (body).                                           */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007 by                              */
+/*  Copyright 2003-2007, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -34,7 +34,7 @@
 #include "afloader.c"
 #include "afmodule.c"
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
 #include "afwarp.c"
 #endif
 
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 46fcce6..22ec337 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -105,7 +105,7 @@
     int             new_pitch;
     FT_UInt         bpp;
     FT_Int          i, width, height;
-    unsigned char*  buffer;
+    unsigned char*  buffer = NULL;
 
 
     width  = bitmap->width;
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index cb44b8c..5069afb 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    The FreeType private base classes (body).                            */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -131,7 +130,7 @@
   {
     FT_Error   error;
     FT_Memory  memory;
-    FT_Stream  stream;
+    FT_Stream  stream = NULL;
 
 
     *astream = 0;
@@ -156,6 +155,9 @@
                             (const FT_Byte*)args->memory_base,
                             args->memory_size );
     }
+
+#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
+
     else if ( args->flags & FT_OPEN_PATHNAME )
     {
       /* create a normal system stream */
@@ -171,6 +173,9 @@
       FT_FREE( stream );
       stream = args->stream;
     }
+
+#endif
+
     else
       error = FT_Err_Invalid_Argument;
 
@@ -375,7 +380,7 @@
     FT_Driver        driver;
     FT_Driver_Class  clazz;
     FT_Memory        memory;
-    FT_GlyphSlot     slot;
+    FT_GlyphSlot     slot = NULL;
 
 
     if ( !face || !face->driver )
@@ -561,6 +566,7 @@
     FT_Library    library;
     FT_Bool       autohint = FALSE;
     FT_Module     hinter;
+    TT_Face       ttface = (TT_Face)face;
 
 
     if ( !face || !face->size || !face->glyph )
@@ -601,7 +607,8 @@
      * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
      *   have a native font hinter.
      *
-     * - Otherwise, auto-hint for LIGHT hinting mode.
+     * - Otherwise, auto-hint for LIGHT hinting mode or if there isn't
+     *   any hinting bytecode in the TrueType/OpenType font.
      *
      * - Exception: The font is `tricky' and requires the native hinter to
      *   load properly.
@@ -626,8 +633,13 @@
         FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
 
 
-        if ( mode == FT_RENDER_MODE_LIGHT             ||
-             face->internal->ignore_unpatented_hinter )
+        /* the check for `num_locations' assures that we actually    */
+        /* test for instructions in a TTF and not in a CFF-based OTF */
+        if ( mode == FT_RENDER_MODE_LIGHT                       ||
+             face->internal->ignore_unpatented_hinter           ||
+             ( FT_IS_SFNT( face )                             &&
+               ttface->num_locations                          &&
+               ttface->max_profile.maxSizeOfInstructions == 0 ) )
           autohint = TRUE;
       }
     }
@@ -1283,7 +1295,7 @@
   {
     FT_Error   error;
     FT_Memory  memory;
-    FT_Stream  stream;
+    FT_Stream  stream = NULL;
 
 
     if ( !library )
@@ -1458,7 +1470,7 @@
     FT_ULong   offset, length;
     FT_Long    pos;
     FT_Bool    is_sfnt_cid;
-    FT_Byte*   sfnt_ps;
+    FT_Byte*   sfnt_ps = NULL;
 
     FT_UNUSED( num_params );
     FT_UNUSED( params );
@@ -1525,7 +1537,7 @@
   {
     FT_Error   error  = FT_Err_Cannot_Open_Resource;
     FT_Memory  memory = library->memory;
-    FT_Byte*   pfb_data;
+    FT_Byte*   pfb_data = NULL;
     int        i, type, flags;
     FT_Long    len;
     FT_Long    pfb_len, pfb_pos, pfb_lenpos;
@@ -1667,7 +1679,7 @@
                           FT_Face    *aface )
   {
     FT_Memory  memory = library->memory;
-    FT_Byte*   sfnt_data;
+    FT_Byte*   sfnt_data = NULL;
     FT_Error   error;
     FT_Long    flag_offset;
     FT_Long    rlen;
@@ -1869,7 +1881,7 @@
                     " is already checked and"
                     " no font is found\n", i ));
         continue;
-      }  
+      }
 
       if ( errors[i] )
       {
@@ -3148,7 +3160,7 @@
     FT_Error   error = FT_Err_Ok;
     FT_Face    face;
     FT_Memory  memory;
-    FT_CMap    cmap;
+    FT_CMap    cmap = NULL;
 
 
     if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
@@ -3887,6 +3899,7 @@
         error = set_mode( renderer, parameters->tag, parameters->data );
         if ( error )
           break;
+        parameters++;
       }
     }
 
@@ -4150,7 +4163,7 @@
       FT_Renderer  renderer = FT_RENDERER( module );
 
 
-      if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && 
+      if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
            renderer->raster                                         )
         renderer->clazz->raster_class->raster_done( renderer->raster );
     }
diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c
index 501cab5..82b42f0 100644
--- a/src/base/ftpatent.c
+++ b/src/base/ftpatent.c
@@ -269,7 +269,7 @@
 
 
 #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
-    !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER )
+    !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
     if ( face && FT_IS_SFNT( face ) )
     {
       result = !face->internal->ignore_unpatented_hinter;
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index 6df2def..4e7d510 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -159,8 +159,8 @@
     FT_Long       tag_internal, rpos;
     FT_Memory     memory = library->memory;
     FT_Long       temp;
-    FT_Long       *offsets_internal;
-    FT_RFork_Ref  *ref;
+    FT_Long       *offsets_internal = NULL;
+    FT_RFork_Ref  *ref = NULL;
 
 
     error = FT_Stream_Seek( stream, map_offset );
@@ -527,7 +527,7 @@
       Only meaningful on systems with hfs+ drivers (or Macs).
      */
     FT_Error   error;
-    char*      newpath;
+    char*      newpath = NULL;
     FT_Memory  memory;
     FT_Long    base_file_len = ft_strlen( base_file_name );
 
@@ -563,7 +563,7 @@
       Only meaningful on systems with Mac OS X (> 10.1).
      */
     FT_Error   error;
-    char*      newpath;
+    char*      newpath = NULL;
     FT_Memory  memory;
     FT_Long    base_file_len = ft_strlen( base_file_name );
 
diff --git a/src/base/ftstream.c b/src/base/ftstream.c
index 210aaa4..fc2868e 100644
--- a/src/base/ftstream.c
+++ b/src/base/ftstream.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    I/O stream support (body).                                           */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 by       */
+/*  Copyright 2000-2002, 2004-2006, 2008-2011 by                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -354,8 +354,8 @@
   }
 
 
-  FT_BASE_DEF( FT_Short )
-  FT_Stream_GetShort( FT_Stream  stream )
+  FT_BASE_DEF( FT_UShort )
+  FT_Stream_GetUShort( FT_Stream  stream )
   {
     FT_Byte*  p;
     FT_Short  result;
@@ -366,15 +366,15 @@
     result         = 0;
     p              = stream->cursor;
     if ( p + 1 < stream->limit )
-      result       = FT_NEXT_SHORT( p );
+      result       = FT_NEXT_USHORT( p );
     stream->cursor = p;
 
     return result;
   }
 
 
-  FT_BASE_DEF( FT_Short )
-  FT_Stream_GetShortLE( FT_Stream  stream )
+  FT_BASE_DEF( FT_UShort )
+  FT_Stream_GetUShortLE( FT_Stream  stream )
   {
     FT_Byte*  p;
     FT_Short  result;
@@ -385,15 +385,15 @@
     result         = 0;
     p              = stream->cursor;
     if ( p + 1 < stream->limit )
-      result       = FT_NEXT_SHORT_LE( p );
+      result       = FT_NEXT_USHORT_LE( p );
     stream->cursor = p;
 
     return result;
   }
 
 
-  FT_BASE_DEF( FT_Long )
-  FT_Stream_GetOffset( FT_Stream  stream )
+  FT_BASE_DEF( FT_ULong )
+  FT_Stream_GetUOffset( FT_Stream  stream )
   {
     FT_Byte*  p;
     FT_Long   result;
@@ -404,14 +404,14 @@
     result         = 0;
     p              = stream->cursor;
     if ( p + 2 < stream->limit )
-      result       = FT_NEXT_OFF3( p );
+      result       = FT_NEXT_UOFF3( p );
     stream->cursor = p;
     return result;
   }
 
 
-  FT_BASE_DEF( FT_Long )
-  FT_Stream_GetLong( FT_Stream  stream )
+  FT_BASE_DEF( FT_ULong )
+  FT_Stream_GetULong( FT_Stream  stream )
   {
     FT_Byte*  p;
     FT_Long   result;
@@ -422,14 +422,14 @@
     result         = 0;
     p              = stream->cursor;
     if ( p + 3 < stream->limit )
-      result       = FT_NEXT_LONG( p );
+      result       = FT_NEXT_ULONG( p );
     stream->cursor = p;
     return result;
   }
 
 
-  FT_BASE_DEF( FT_Long )
-  FT_Stream_GetLongLE( FT_Stream  stream )
+  FT_BASE_DEF( FT_ULong )
+  FT_Stream_GetULongLE( FT_Stream  stream )
   {
     FT_Byte*  p;
     FT_Long   result;
@@ -440,7 +440,7 @@
     result         = 0;
     p              = stream->cursor;
     if ( p + 3 < stream->limit )
-      result       = FT_NEXT_LONG_LE( p );
+      result       = FT_NEXT_ULONG_LE( p );
     stream->cursor = p;
     return result;
   }
@@ -483,8 +483,8 @@
   }
 
 
-  FT_BASE_DEF( FT_Short )
-  FT_Stream_ReadShort( FT_Stream  stream,
+  FT_BASE_DEF( FT_UShort )
+  FT_Stream_ReadUShort( FT_Stream  stream,
                        FT_Error*  error )
   {
     FT_Byte   reads[2];
@@ -511,7 +511,7 @@
       }
 
       if ( p )
-        result = FT_NEXT_SHORT( p );
+        result = FT_NEXT_USHORT( p );
     }
     else
       goto Fail;
@@ -522,7 +522,7 @@
 
   Fail:
     *error = FT_Err_Invalid_Stream_Operation;
-    FT_ERROR(( "FT_Stream_ReadShort:"
+    FT_ERROR(( "FT_Stream_ReadUShort:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
@@ -530,8 +530,8 @@
   }
 
 
-  FT_BASE_DEF( FT_Short )
-  FT_Stream_ReadShortLE( FT_Stream  stream,
+  FT_BASE_DEF( FT_UShort )
+  FT_Stream_ReadUShortLE( FT_Stream  stream,
                          FT_Error*  error )
   {
     FT_Byte   reads[2];
@@ -558,7 +558,7 @@
       }
 
       if ( p )
-        result = FT_NEXT_SHORT_LE( p );
+        result = FT_NEXT_USHORT_LE( p );
     }
     else
       goto Fail;
@@ -569,7 +569,7 @@
 
   Fail:
     *error = FT_Err_Invalid_Stream_Operation;
-    FT_ERROR(( "FT_Stream_ReadShortLE:"
+    FT_ERROR(( "FT_Stream_ReadUShortLE:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
@@ -577,8 +577,8 @@
   }
 
 
-  FT_BASE_DEF( FT_Long )
-  FT_Stream_ReadOffset( FT_Stream  stream,
+  FT_BASE_DEF( FT_ULong )
+  FT_Stream_ReadUOffset( FT_Stream  stream,
                         FT_Error*  error )
   {
     FT_Byte   reads[3];
@@ -605,7 +605,7 @@
       }
 
       if ( p )
-        result = FT_NEXT_OFF3( p );
+        result = FT_NEXT_UOFF3( p );
     }
     else
       goto Fail;
@@ -616,7 +616,7 @@
 
   Fail:
     *error = FT_Err_Invalid_Stream_Operation;
-    FT_ERROR(( "FT_Stream_ReadOffset:"
+    FT_ERROR(( "FT_Stream_ReadUOffset:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
@@ -624,8 +624,8 @@
   }
 
 
-  FT_BASE_DEF( FT_Long )
-  FT_Stream_ReadLong( FT_Stream  stream,
+  FT_BASE_DEF( FT_ULong )
+  FT_Stream_ReadULong( FT_Stream  stream,
                       FT_Error*  error )
   {
     FT_Byte   reads[4];
@@ -652,7 +652,7 @@
       }
 
       if ( p )
-        result = FT_NEXT_LONG( p );
+        result = FT_NEXT_ULONG( p );
     }
     else
       goto Fail;
@@ -663,7 +663,7 @@
 
   Fail:
     *error = FT_Err_Invalid_Stream_Operation;
-    FT_ERROR(( "FT_Stream_ReadLong:"
+    FT_ERROR(( "FT_Stream_ReadULong:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
@@ -671,8 +671,8 @@
   }
 
 
-  FT_BASE_DEF( FT_Long )
-  FT_Stream_ReadLongLE( FT_Stream  stream,
+  FT_BASE_DEF( FT_ULong )
+  FT_Stream_ReadULongLE( FT_Stream  stream,
                         FT_Error*  error )
   {
     FT_Byte   reads[4];
@@ -699,7 +699,7 @@
       }
 
       if ( p )
-        result = FT_NEXT_LONG_LE( p );
+        result = FT_NEXT_ULONG_LE( p );
     }
     else
       goto Fail;
@@ -710,7 +710,7 @@
 
   Fail:
     *error = FT_Err_Invalid_Stream_Operation;
-    FT_ERROR(( "FT_Stream_ReadLongLE:"
+    FT_ERROR(( "FT_Stream_ReadULongLE:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index 75bcbde..5399efe 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (body).                                        */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 by            */
+/*  Copyright 2002-2006, 2008-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -34,7 +34,7 @@
 
 
     return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
-                                        : FT_STROKER_BORDER_LEFT ;
+                                        : FT_STROKER_BORDER_LEFT;
   }
 
 
@@ -47,20 +47,21 @@
 
 
     return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT
-                                        : FT_STROKER_BORDER_RIGHT ;
+                                        : FT_STROKER_BORDER_RIGHT;
   }
 
 
- /***************************************************************************/
- /***************************************************************************/
- /*****                                                                 *****/
- /*****                       BEZIER COMPUTATIONS                       *****/
- /*****                                                                 *****/
- /***************************************************************************/
- /***************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      BEZIER COMPUTATIONS                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
 
 #define FT_SMALL_CONIC_THRESHOLD  ( FT_ANGLE_PI / 6 )
-#define FT_SMALL_CUBIC_THRESHOLD  ( FT_ANGLE_PI / 6 )
+#define FT_SMALL_CUBIC_THRESHOLD  ( FT_ANGLE_PI / 8 )
+
 #define FT_EPSILON  2
 
 #define FT_IS_SMALL( x )  ( (x) > -FT_EPSILON && (x) < FT_EPSILON )
@@ -69,7 +70,7 @@
   static FT_Pos
   ft_pos_abs( FT_Pos  x )
   {
-    return x >= 0 ? x : -x ;
+    return x >= 0 ? x : -x;
   }
 
 
@@ -114,18 +115,28 @@
     if ( close1 )
     {
       if ( close2 )
-        *angle_in = *angle_out = 0;
+      {
+        /* basically a point;                      */
+        /* do nothing to retain original direction */
+      }
       else
-        *angle_in = *angle_out = FT_Atan2( d2.x, d2.y );
+      {
+        *angle_in  =
+        *angle_out = FT_Atan2( d2.x, d2.y );
+      }
     }
-    else if ( close2 )
+    else /* !close1 */
     {
-      *angle_in = *angle_out = FT_Atan2( d1.x, d1.y );
-    }
-    else
-    {
-      *angle_in  = FT_Atan2( d1.x, d1.y );
-      *angle_out = FT_Atan2( d2.x, d2.y );
+      if ( close2 )
+      {
+        *angle_in  =
+        *angle_out = FT_Atan2( d1.x, d1.y );
+      }
+      else
+      {
+        *angle_in  = FT_Atan2( d1.x, d1.y );
+        *angle_out = FT_Atan2( d2.x, d2.y );
+      }
     }
 
     theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );
@@ -162,6 +173,17 @@
   }
 
 
+  /* Return the average of `angle1' and `angle2'.            */
+  /* This gives correct result even if `angle1' and `angle2' */
+  /* have opposite signs.                                    */
+  static FT_Angle
+  ft_angle_mean( FT_Angle  angle1,
+                 FT_Angle  angle2 )
+  {
+    return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2;
+  }
+
+
   static FT_Bool
   ft_cubic_is_small_enough( FT_Vector*  base,
                             FT_Angle   *angle_in,
@@ -184,34 +206,70 @@
     close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
     close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );
 
-    if ( close1 || close3 )
+    if ( close1 )
     {
       if ( close2 )
       {
-        /* basically a point */
-        *angle_in = *angle_out = *angle_mid = 0;
+        if ( close3 )
+        {
+          /* basically a point;                      */
+          /* do nothing to retain original direction */
+        }
+        else /* !close3 */
+        {
+          *angle_in  =
+          *angle_mid =
+          *angle_out = FT_Atan2( d3.x, d3.y );
+        }
       }
-      else if ( close1 )
+      else /* !close2 */
       {
-        *angle_in  = *angle_mid = FT_Atan2( d2.x, d2.y );
-        *angle_out = FT_Atan2( d3.x, d3.y );
-      }
-      else  /* close2 */
-      {
-        *angle_in  = FT_Atan2( d1.x, d1.y );
-        *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y );
+        if ( close3 )
+        {
+          *angle_in  =
+          *angle_mid =
+          *angle_out = FT_Atan2( d2.x, d2.y );
+        }
+        else /* !close3 */
+        {
+          *angle_in  =
+          *angle_mid = FT_Atan2( d2.x, d2.y );
+          *angle_out = FT_Atan2( d3.x, d3.y );
+        }
       }
     }
-    else if ( close2 )
+    else /* !close1 */
     {
-      *angle_in  = *angle_mid = FT_Atan2( d1.x, d1.y );
-      *angle_out = FT_Atan2( d3.x, d3.y );
-    }
-    else
-    {
-      *angle_in  = FT_Atan2( d1.x, d1.y );
-      *angle_mid = FT_Atan2( d2.x, d2.y );
-      *angle_out = FT_Atan2( d3.x, d3.y );
+      if ( close2 )
+      {
+        if ( close3 )
+        {
+          *angle_in  =
+          *angle_mid =
+          *angle_out = FT_Atan2( d1.x, d1.y );
+        }
+        else /* !close3 */
+        {
+          *angle_in  = FT_Atan2( d1.x, d1.y );
+          *angle_out = FT_Atan2( d3.x, d3.y );
+          *angle_mid = ft_angle_mean( *angle_in, *angle_out );
+        }
+      }
+      else /* !close2 */
+      {
+        if ( close3 )
+        {
+          *angle_in  = FT_Atan2( d1.x, d1.y );
+          *angle_mid =
+          *angle_out = FT_Atan2( d2.x, d2.y );
+        }
+        else /* !close3 */
+        {
+          *angle_in  = FT_Atan2( d1.x, d1.y );
+          *angle_mid = FT_Atan2( d2.x, d2.y );
+          *angle_out = FT_Atan2( d3.x, d3.y );
+        }
+      }
     }
 
     theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in,  *angle_mid ) );
@@ -222,13 +280,13 @@
   }
 
 
- /***************************************************************************/
- /***************************************************************************/
- /*****                                                                 *****/
- /*****                       STROKE BORDERS                            *****/
- /*****                                                                 *****/
- /***************************************************************************/
- /***************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                       STROKE BORDERS                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
 
   typedef enum  FT_StrokeTags_
   {
@@ -239,7 +297,7 @@
 
   } FT_StrokeTags;
 
-#define  FT_STROKE_TAG_BEGIN_END  (FT_STROKE_TAG_BEGIN|FT_STROKE_TAG_END)
+#define  FT_STROKE_TAG_BEGIN_END  ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END )
 
   typedef struct  FT_StrokeBorderRec_
   {
@@ -247,7 +305,7 @@
     FT_UInt     max_points;
     FT_Vector*  points;
     FT_Byte*    tags;
-    FT_Bool     movable;
+    FT_Bool     movable;  /* TRUE for ends of lineto borders */
     FT_Int      start;    /* index of current sub-path start point */
     FT_Memory   memory;
     FT_Bool     valid;
@@ -368,6 +426,12 @@
     }
     else
     {
+      /* don't add zero-length lineto */
+      if ( border->num_points > 0                                          &&
+           FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
+           FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
+        return error;
+
       /* add one point */
       error = ft_stroke_border_grow( border, 1 );
       if ( !error )
@@ -403,6 +467,7 @@
       FT_Vector*  vec = border->points + border->num_points;
       FT_Byte*    tag = border->tags   + border->num_points;
 
+
       vec[0] = *control;
       vec[1] = *to;
 
@@ -411,7 +476,9 @@
 
       border->num_points += 2;
     }
+
     border->movable = FALSE;
+
     return error;
   }
 
@@ -444,7 +511,9 @@
 
       border->num_points += 3;
     }
+
     border->movable = FALSE;
+
     return error;
   }
 
@@ -530,7 +599,7 @@
     if ( border->start >= 0 )
       ft_stroke_border_close( border, FALSE );
 
-    border->start   = border->num_points;
+    border->start = border->num_points;
     border->movable = FALSE;
 
     return ft_stroke_border_lineto( border, to, FALSE );
@@ -673,38 +742,41 @@
       }
     }
 
-    outline->n_points  = (short)( outline->n_points + border->num_points );
+    outline->n_points = (short)( outline->n_points + border->num_points );
 
     FT_ASSERT( FT_Outline_Check( outline ) == 0 );
   }
 
 
- /***************************************************************************/
- /***************************************************************************/
- /*****                                                                 *****/
- /*****                           STROKER                               *****/
- /*****                                                                 *****/
- /***************************************************************************/
- /***************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                           STROKER                             *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
 
 #define FT_SIDE_TO_ROTATE( s )   ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )
 
   typedef struct  FT_StrokerRec_
   {
-    FT_Angle             angle_in;
-    FT_Angle             angle_out;
-    FT_Vector            center;
-    FT_Bool              first_point;
-    FT_Bool              subpath_open;
-    FT_Angle             subpath_angle;
-    FT_Vector            subpath_start;
+    FT_Angle             angle_in;             /* direction into curr join */
+    FT_Angle             angle_out;            /* direction out of join  */
+    FT_Vector            center;               /* current position */
+    FT_Fixed             line_length;          /* length of last lineto */
+    FT_Bool              first_point;          /* is this the start? */
+    FT_Bool              subpath_open;         /* is the subpath open? */
+    FT_Angle             subpath_angle;        /* subpath start direction */
+    FT_Vector            subpath_start;        /* subpath start position */
+    FT_Fixed             subpath_line_length;  /* subpath start lineto len */
+    FT_Bool              handle_wide_strokes;  /* use wide strokes logic? */
 
     FT_Stroker_LineCap   line_cap;
     FT_Stroker_LineJoin  line_join;
+    FT_Stroker_LineJoin  line_join_saved;
     FT_Fixed             miter_limit;
     FT_Fixed             radius;
 
-    FT_Bool              valid;
     FT_StrokeBorderRec   borders[2];
     FT_Library           library;
 
@@ -719,7 +791,7 @@
   {
     FT_Error    error;
     FT_Memory   memory;
-    FT_Stroker  stroker;
+    FT_Stroker  stroker = NULL;
 
 
     if ( !library )
@@ -734,7 +806,9 @@
       ft_stroke_border_init( &stroker->borders[0], memory );
       ft_stroke_border_init( &stroker->borders[1], memory );
     }
+
     *astroker = stroker;
+
     return error;
   }
 
@@ -753,6 +827,14 @@
     stroker->line_join   = line_join;
     stroker->miter_limit = miter_limit;
 
+    /* ensure miter limit has sensible value */
+    if ( stroker->miter_limit < 0x10000 )
+      stroker->miter_limit = 0x10000;
+
+    /* save line join style:                                           */
+    /* line join style can be temporarily changed when stroking curves */
+    stroker->line_join_saved = line_join;
+
     FT_Stroker_Rewind( stroker );
   }
 
@@ -789,7 +871,7 @@
   }
 
 
-  /* creates a circular arc at a corner or cap */
+  /* create a circular arc at a corner or cap */
   static FT_Error
   ft_stroker_arcto( FT_Stroker  stroker,
                     FT_Int      side )
@@ -816,7 +898,7 @@
   }
 
 
-  /* adds a cap at the end of an opened path */
+  /* add a cap at the end of an opened path */
   static FT_Error
   ft_stroker_cap( FT_Stroker  stroker,
                   FT_Angle    angle,
@@ -830,6 +912,7 @@
       /* add a round cap */
       stroker->angle_in  = angle;
       stroker->angle_out = angle + FT_ANGLE_PI;
+
       error = ft_stroker_arcto( stroker, side );
     }
     else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
@@ -882,7 +965,7 @@
       delta.x += stroker->center.x;
       delta.y += stroker->center.y;
 
-      error = ft_stroke_border_lineto( border, &delta, FALSE );   
+      error = ft_stroke_border_lineto( border, &delta, FALSE );
     }
 
   Exit:
@@ -893,40 +976,52 @@
   /* process an inside corner, i.e. compute intersection */
   static FT_Error
   ft_stroker_inside( FT_Stroker  stroker,
-                     FT_Int      side)
+                     FT_Int      side,
+                     FT_Fixed    line_length )
   {
     FT_StrokeBorder  border = stroker->borders + side;
     FT_Angle         phi, theta, rotate;
-    FT_Fixed         length, thcos, sigma;
+    FT_Fixed         length, thcos;
     FT_Vector        delta;
     FT_Error         error = FT_Err_Ok;
+    FT_Bool          intersect;          /* use intersection of lines? */
 
 
     rotate = FT_SIDE_TO_ROTATE( side );
 
-    /* compute median angle */
-    theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
-    if ( theta == FT_ANGLE_PI )
-      theta = rotate;
+    theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
+
+    /* Only intersect borders if between two lineto's and both */
+    /* lines are long enough (line_length is zero for curves). */
+    if ( !border->movable || line_length == 0 )
+      intersect = FALSE;
     else
-      theta = theta / 2;
+    {
+      /* compute minimum required length of lines */
+      FT_Fixed  min_length = ft_pos_abs( FT_MulFix( stroker->radius,
+                                                    FT_Tan( theta ) ) );
 
-    phi = stroker->angle_in + theta;
 
-    thcos = FT_Cos( theta );
-    sigma = FT_MulFix( stroker->miter_limit, thcos );
+      intersect = FT_BOOL( stroker->line_length >= min_length &&
+                           line_length          >= min_length );
+    }
 
-    /* TODO: find better criterion to switch off the optimization */
-    if ( sigma < 0x10000L )
+    if ( !intersect )
     {
       FT_Vector_From_Polar( &delta, stroker->radius,
                             stroker->angle_out + rotate );
       delta.x += stroker->center.x;
       delta.y += stroker->center.y;
+
       border->movable = FALSE;
     }
     else
     {
+      /* compute median angle */
+      phi = stroker->angle_in + theta;
+
+      thcos = FT_Cos( theta );
+
       length = FT_DivFix( stroker->radius, thcos );
 
       FT_Vector_From_Polar( &delta, length, phi + rotate );
@@ -943,7 +1038,8 @@
   /* process an outside corner, i.e. compute bevel/miter/round */
   static FT_Error
   ft_stroker_outside( FT_Stroker  stroker,
-                      FT_Int      side )
+                      FT_Int      side,
+                      FT_Fixed    line_length )
   {
     FT_StrokeBorder  border = stroker->borders + side;
     FT_Error         error;
@@ -954,79 +1050,119 @@
       error = ft_stroker_arcto( stroker, side );
     else
     {
-      /* this is a mitered or beveled corner */
-      FT_Fixed  sigma, radius = stroker->radius;
-      FT_Angle  theta, phi;
-      FT_Fixed  thcos;
-      FT_Bool   miter;
+      /* this is a mitered (pointed) or beveled (truncated) corner */
+      FT_Fixed  sigma = 0, radius = stroker->radius;
+      FT_Angle  theta = 0, phi = 0;
+      FT_Fixed  thcos = 0;
+      FT_Bool   bevel, fixed_bevel;
 
 
       rotate = FT_SIDE_TO_ROTATE( side );
-      miter  = FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_MITER );
 
-      theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
-      if ( theta == FT_ANGLE_PI )
+      bevel =
+        FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL );
+
+      fixed_bevel =
+        FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
+
+      if ( !bevel )
       {
-        theta = rotate;
-        phi   = stroker->angle_in;
-      }
-      else
-      {
-        theta = theta / 2;
-        phi   = stroker->angle_in + theta + rotate;
+        theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
+
+        if ( theta == FT_ANGLE_PI )
+        {
+          theta = rotate;
+          phi   = stroker->angle_in;
+        }
+        else
+        {
+          theta /= 2;
+          phi    = stroker->angle_in + theta + rotate;
+        }
+
+        thcos = FT_Cos( theta );
+        sigma = FT_MulFix( stroker->miter_limit, thcos );
+
+        /* is miter limit exceeded? */
+        if ( sigma < 0x10000L )
+        {
+          /* don't create variable bevels for very small deviations; */
+          /* FT_Sin(x) = 0 for x <= 57                               */
+          if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
+            bevel = TRUE;
+        }
       }
 
-      thcos = FT_Cos( theta );
-      sigma = FT_MulFix( stroker->miter_limit, thcos );
-
-      /* FT_Sin(x) = 0 for x <= 57 */
-      if ( sigma >= 0x10000L || ft_pos_abs( theta ) <= 57 )
-        miter = FALSE;
-
-      if ( miter )  /* this is a miter (broken angle) */
+      if ( bevel )  /* this is a bevel (broken angle) */
       {
-        FT_Vector  middle, delta;
-        FT_Fixed   length;
+        if ( fixed_bevel )
+        {
+          /* the outer corners are simply joined together */
+          FT_Vector  delta;
 
 
-        /* compute middle point */
-        FT_Vector_From_Polar( &middle,
-                              FT_MulFix( radius, stroker->miter_limit ),
-                              phi );
-        middle.x += stroker->center.x;
-        middle.y += stroker->center.y;
+          /* add bevel */
+          FT_Vector_From_Polar( &delta,
+                                radius,
+                                stroker->angle_out + rotate );
+          delta.x += stroker->center.x;
+          delta.y += stroker->center.y;
 
-        /* compute first angle point */
-        length = FT_MulFix( radius,
-                            FT_DivFix( 0x10000L - sigma,
-                                       ft_pos_abs( FT_Sin( theta ) ) ) );
+          border->movable = FALSE;
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
+        }
+        else /* variable bevel */
+        {
+          /* the miter is truncated */
+          FT_Vector  middle, delta;
+          FT_Fixed   length;
 
-        FT_Vector_From_Polar( &delta, length, phi + rotate );
-        delta.x += middle.x;
-        delta.y += middle.y;
 
-        error = ft_stroke_border_lineto( border, &delta, FALSE );
-        if ( error )
-          goto Exit;
+          /* compute middle point */
+          FT_Vector_From_Polar( &middle,
+                                FT_MulFix( radius, stroker->miter_limit ),
+                                phi );
+          middle.x += stroker->center.x;
+          middle.y += stroker->center.y;
 
-        /* compute second angle point */
-        FT_Vector_From_Polar( &delta, length, phi - rotate );
-        delta.x += middle.x;
-        delta.y += middle.y;
+          /* compute first angle point */
+          length = FT_MulFix( radius,
+                              FT_DivFix( 0x10000L - sigma,
+                                         ft_pos_abs( FT_Sin( theta ) ) ) );
 
-        error = ft_stroke_border_lineto( border, &delta, FALSE );
-        if ( error )
-          goto Exit;
+          FT_Vector_From_Polar( &delta, length, phi + rotate );
+          delta.x += middle.x;
+          delta.y += middle.y;
 
-        /* finally, add a movable end point */
-        FT_Vector_From_Polar( &delta, radius, stroker->angle_out + rotate );
-        delta.x += stroker->center.x;
-        delta.y += stroker->center.y;
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
+          if ( error )
+            goto Exit;
 
-        error = ft_stroke_border_lineto( border, &delta, TRUE );
+          /* compute second angle point */
+          FT_Vector_From_Polar( &delta, length, phi - rotate );
+          delta.x += middle.x;
+          delta.y += middle.y;
+
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
+          if ( error )
+            goto Exit;
+
+          /* finally, add an end point; only needed if not lineto */
+          /* (line_length is zero for curves)                     */
+          if ( line_length == 0 )
+          {
+            FT_Vector_From_Polar( &delta,
+                                  radius,
+                                  stroker->angle_out + rotate );
+
+            delta.x += stroker->center.x;
+            delta.y += stroker->center.y;
+
+            error = ft_stroke_border_lineto( border, &delta, FALSE );
+          }
+        }
       }
-
-      else /* this is a bevel (intersection) */
+      else /* this is a miter (intersection) */
       {
         FT_Fixed   length;
         FT_Vector  delta;
@@ -1042,13 +1178,18 @@
         if ( error )
           goto Exit;
 
-        /* now add end point */
-        FT_Vector_From_Polar( &delta, stroker->radius,
-                              stroker->angle_out + rotate );
-        delta.x += stroker->center.x;
-        delta.y += stroker->center.y;
+        /* now add an end point; only needed if not lineto */
+        /* (line_length is zero for curves)                */
+        if ( line_length == 0 )
+        {
+          FT_Vector_From_Polar( &delta,
+                                stroker->radius,
+                                stroker->angle_out + rotate );
+          delta.x += stroker->center.x;
+          delta.y += stroker->center.y;
 
-        error = ft_stroke_border_lineto( border, &delta, TRUE );
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
+        }
       }
     }
 
@@ -1058,7 +1199,8 @@
 
 
   static FT_Error
-  ft_stroker_process_corner( FT_Stroker  stroker )
+  ft_stroker_process_corner( FT_Stroker  stroker,
+                             FT_Fixed    line_length )
   {
     FT_Error  error = FT_Err_Ok;
     FT_Angle  turn;
@@ -1079,12 +1221,12 @@
       inside_side = 1;
 
     /* process the inside side */
-    error = ft_stroker_inside( stroker, inside_side );
+    error = ft_stroker_inside( stroker, inside_side, line_length );
     if ( error )
       goto Exit;
 
     /* process the outside side */
-    error = ft_stroker_outside( stroker, 1 - inside_side );
+    error = ft_stroker_outside( stroker, 1 - inside_side, line_length );
 
   Exit:
     return error;
@@ -1095,7 +1237,8 @@
   /* start of the subpath                                              */
   static FT_Error
   ft_stroker_subpath_start( FT_Stroker  stroker,
-                            FT_Angle    start_angle )
+                            FT_Angle    start_angle,
+                            FT_Fixed    line_length )
   {
     FT_Vector        delta;
     FT_Vector        point;
@@ -1120,9 +1263,11 @@
     border++;
     error = ft_stroke_border_moveto( border, &point );
 
-    /* save angle for last cap */
-    stroker->subpath_angle = start_angle;
-    stroker->first_point   = FALSE;
+    /* save angle, position, and line length for last join */
+    /* (line_length is zero for curves)                    */
+    stroker->subpath_angle       = start_angle;
+    stroker->first_point         = FALSE;
+    stroker->subpath_line_length = line_length;
 
   Exit:
     return error;
@@ -1140,10 +1285,19 @@
     FT_Vector        delta;
     FT_Angle         angle;
     FT_Int           side;
+    FT_Fixed         line_length;
+
 
     delta.x = to->x - stroker->center.x;
     delta.y = to->y - stroker->center.y;
 
+    /* a zero-length lineto is a no-op; avoid creating a spurious corner */
+    if ( delta.x == 0 && delta.y == 0 )
+       goto Exit;
+
+    /* compute length of line */
+    line_length = FT_Vector_Length( &delta );
+
     angle = FT_Atan2( delta.x, delta.y );
     FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );
 
@@ -1153,7 +1307,7 @@
       /* This is the first segment of a subpath.  We need to     */
       /* add a point to each border at their respective starting */
       /* point locations.                                        */
-      error = ft_stroker_subpath_start( stroker, angle );
+      error = ft_stroker_subpath_start( stroker, angle, line_length );
       if ( error )
         goto Exit;
     }
@@ -1161,13 +1315,12 @@
     {
       /* process the current corner */
       stroker->angle_out = angle;
-      error = ft_stroker_process_corner( stroker );
+      error = ft_stroker_process_corner( stroker, line_length );
       if ( error )
         goto Exit;
     }
 
     /* now add a line segment to both the `inside' and `outside' paths */
-
     for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
     {
       FT_Vector  point;
@@ -1176,6 +1329,7 @@
       point.x = to->x + delta.x;
       point.y = to->y + delta.y;
 
+      /* the ends of lineto borders are movable */
       error = ft_stroke_border_lineto( border, &point, TRUE );
       if ( error )
         goto Exit;
@@ -1184,8 +1338,9 @@
       delta.y = -delta.y;
     }
 
-    stroker->angle_in = angle;
-    stroker->center   = *to;
+    stroker->angle_in    = angle;
+    stroker->center      = *to;
+    stroker->line_length = line_length;
 
   Exit:
     return error;
@@ -1203,10 +1358,20 @@
     FT_Vector   bez_stack[34];
     FT_Vector*  arc;
     FT_Vector*  limit = bez_stack + 30;
-    FT_Angle    start_angle;
     FT_Bool     first_arc = TRUE;
 
 
+    /* if all control points are coincident, this is a no-op; */
+    /* avoid creating a spurious corner                       */
+    if ( FT_IS_SMALL( stroker->center.x - control->x ) &&
+         FT_IS_SMALL( stroker->center.y - control->y ) &&
+         FT_IS_SMALL( control->x        - to->x      ) &&
+         FT_IS_SMALL( control->y        - to->y      ) )
+    {
+       stroker->center = *to;
+       goto Exit;
+    }
+
     arc    = bez_stack;
     arc[0] = *to;
     arc[1] = *control;
@@ -1217,11 +1382,15 @@
       FT_Angle  angle_in, angle_out;
 
 
-      angle_in = angle_out = 0;  /* remove compiler warnings */
+      /* initialize with current direction */
+      angle_in = angle_out = stroker->angle_in;
 
       if ( arc < limit                                             &&
            !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )
       {
+        if ( stroker->first_point )
+          stroker->angle_in = angle_in;
+
         ft_conic_split( arc );
         arc += 2;
         continue;
@@ -1231,32 +1400,54 @@
       {
         first_arc = FALSE;
 
-        start_angle = angle_in;
-
         /* process corner if necessary */
         if ( stroker->first_point )
-          error = ft_stroker_subpath_start( stroker, start_angle );
+          error = ft_stroker_subpath_start( stroker, angle_in, 0 );
         else
         {
-          stroker->angle_out = start_angle;
-          error = ft_stroker_process_corner( stroker );
+          stroker->angle_out = angle_in;
+          error = ft_stroker_process_corner( stroker, 0 );
         }
       }
+      else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
+                  FT_SMALL_CONIC_THRESHOLD / 4                             )
+      {
+        /* if the deviation from one arc to the next is too great, */
+        /* add a round corner                                      */
+        stroker->center    = arc[2];
+        stroker->angle_out = angle_in;
+        stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
+
+        error = ft_stroker_process_corner( stroker, 0 );
+
+        /* reinstate line join style */
+        stroker->line_join = stroker->line_join_saved;
+      }
+
+      if ( error )
+        goto Exit;
 
       /* the arc's angle is small enough; we can add it directly to each */
       /* border                                                          */
       {
-        FT_Vector  ctrl, end;
-        FT_Angle   theta, phi, rotate;
-        FT_Fixed   length;
-        FT_Int     side;
+        FT_Vector        ctrl, end;
+        FT_Angle         theta, phi, rotate, alpha0 = 0;
+        FT_Fixed         length;
+        FT_StrokeBorder  border;
+        FT_Int           side;
 
 
         theta  = FT_Angle_Diff( angle_in, angle_out ) / 2;
         phi    = angle_in + theta;
         length = FT_DivFix( stroker->radius, FT_Cos( theta ) );
 
-        for ( side = 0; side <= 1; side++ )
+        /* compute direction of original arc */
+        if ( stroker->handle_wide_strokes )
+          alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y );
+
+        for ( border = stroker->borders, side = 0;
+              side <= 1;
+              side++, border++ )
         {
           rotate = FT_SIDE_TO_ROTATE( side );
 
@@ -1270,8 +1461,70 @@
           end.x += arc[0].x;
           end.y += arc[0].y;
 
-          error = ft_stroke_border_conicto( stroker->borders + side,
-                                            &ctrl, &end );
+          if ( stroker->handle_wide_strokes )
+          {
+            FT_Vector  start;
+            FT_Angle   alpha1;
+
+
+            /* determine whether the border radius is greater than the */
+            /* radius of curvature of the original arc                 */
+            start = border->points[border->num_points - 1];
+
+            alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
+
+            /* is the direction of the border arc opposite to */
+            /* that of the original arc? */
+            if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
+                   FT_ANGLE_PI / 2                             )
+            {
+              FT_Angle   beta, gamma;
+              FT_Vector  bvec, delta;
+              FT_Fixed   blen, sinA, sinB, alen;
+
+
+              /* use the sine rule to find the intersection point */
+              beta  = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y );
+              gamma = FT_Atan2( arc[0].x - end.x,   arc[0].y - end.y );
+
+              bvec.x = end.x - start.x;
+              bvec.y = end.y - start.y;
+
+              blen = FT_Vector_Length( &bvec );
+
+              sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
+              sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
+
+              alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
+
+              FT_Vector_From_Polar( &delta, alen, beta );
+              delta.x += start.x;
+              delta.y += start.y;
+
+              /* circumnavigate the negative sector backwards */
+              border->movable = FALSE;
+              error = ft_stroke_border_lineto( border, &delta, FALSE );
+              if ( error )
+                goto Exit;
+              error = ft_stroke_border_lineto( border, &end, FALSE );
+              if ( error )
+                goto Exit;
+              error = ft_stroke_border_conicto( border, &ctrl, &start );
+              if ( error )
+                goto Exit;
+              /* and then move to the endpoint */
+              error = ft_stroke_border_lineto( border, &end, FALSE );
+              if ( error )
+                goto Exit;
+
+              continue;
+            }
+
+            /* else fall through */
+          }
+
+          /* simply add an arc */
+          error = ft_stroke_border_conicto( border, &ctrl, &end );
           if ( error )
             goto Exit;
         }
@@ -1279,8 +1532,7 @@
 
       arc -= 2;
 
-      if ( arc < bez_stack )
-        stroker->angle_in = angle_out;
+      stroker->angle_in = angle_out;
     }
 
     stroker->center = *to;
@@ -1302,10 +1554,22 @@
     FT_Vector   bez_stack[37];
     FT_Vector*  arc;
     FT_Vector*  limit = bez_stack + 32;
-    FT_Angle    start_angle;
     FT_Bool     first_arc = TRUE;
 
 
+    /* if all control points are coincident, this is a no-op; */
+    /* avoid creating a spurious corner */
+    if ( FT_IS_SMALL( stroker->center.x - control1->x ) &&
+         FT_IS_SMALL( stroker->center.y - control1->y ) &&
+         FT_IS_SMALL( control1->x       - control2->x ) &&
+         FT_IS_SMALL( control1->y       - control2->y ) &&
+         FT_IS_SMALL( control2->x       - to->x       ) &&
+         FT_IS_SMALL( control2->y       - to->y       ) )
+    {
+       stroker->center = *to;
+       goto Exit;
+    }
+
     arc    = bez_stack;
     arc[0] = *to;
     arc[1] = *control2;
@@ -1317,13 +1581,16 @@
       FT_Angle  angle_in, angle_mid, angle_out;
 
 
-      /* remove compiler warnings */
-      angle_in = angle_out = angle_mid = 0;
+      /* initialize with current direction */
+      angle_in = angle_out = angle_mid = stroker->angle_in;
 
       if ( arc < limit                                         &&
            !ft_cubic_is_small_enough( arc, &angle_in,
                                       &angle_mid, &angle_out ) )
       {
+        if ( stroker->first_point )
+          stroker->angle_in = angle_in;
+
         ft_cubic_split( arc );
         arc += 3;
         continue;
@@ -1334,36 +1601,56 @@
         first_arc = FALSE;
 
         /* process corner if necessary */
-        start_angle = angle_in;
-
         if ( stroker->first_point )
-          error = ft_stroker_subpath_start( stroker, start_angle );
+          error = ft_stroker_subpath_start( stroker, angle_in, 0 );
         else
         {
-          stroker->angle_out = start_angle;
-          error = ft_stroker_process_corner( stroker );
+          stroker->angle_out = angle_in;
+          error = ft_stroker_process_corner( stroker, 0 );
         }
-        if ( error )
-          goto Exit;
       }
+      else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
+                  FT_SMALL_CUBIC_THRESHOLD / 4                             )
+      {
+        /* if the deviation from one arc to the next is too great, */
+        /* add a round corner                                      */
+        stroker->center    = arc[3];
+        stroker->angle_out = angle_in;
+        stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
+
+        error = ft_stroker_process_corner( stroker, 0 );
+
+        /* reinstate line join style */
+        stroker->line_join = stroker->line_join_saved;
+      }
+
+      if ( error )
+        goto Exit;
 
       /* the arc's angle is small enough; we can add it directly to each */
       /* border                                                          */
       {
-        FT_Vector  ctrl1, ctrl2, end;
-        FT_Angle   theta1, phi1, theta2, phi2, rotate;
-        FT_Fixed   length1, length2;
-        FT_Int     side;
+        FT_Vector        ctrl1, ctrl2, end;
+        FT_Angle         theta1, phi1, theta2, phi2, rotate, alpha0 = 0;
+        FT_Fixed         length1, length2;
+        FT_StrokeBorder  border;
+        FT_Int           side;
 
 
-        theta1  = ft_pos_abs( angle_mid - angle_in ) / 2;
-        theta2  = ft_pos_abs( angle_out - angle_mid ) / 2;
-        phi1    = (angle_mid + angle_in ) / 2;
-        phi2    = (angle_mid + angle_out ) / 2;
+        theta1  = FT_Angle_Diff( angle_in,  angle_mid ) / 2;
+        theta2  = FT_Angle_Diff( angle_mid, angle_out ) / 2;
+        phi1    = ft_angle_mean( angle_in,  angle_mid );
+        phi2    = ft_angle_mean( angle_mid, angle_out );
         length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );
         length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) );
 
-        for ( side = 0; side <= 1; side++ )
+        /* compute direction of original arc */
+        if ( stroker->handle_wide_strokes )
+          alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y );
+
+        for ( border = stroker->borders, side = 0;
+              side <= 1;
+              side++, border++ )
         {
           rotate = FT_SIDE_TO_ROTATE( side );
 
@@ -1381,16 +1668,81 @@
           end.x += arc[0].x;
           end.y += arc[0].y;
 
-          error = ft_stroke_border_cubicto( stroker->borders + side,
-                                            &ctrl1, &ctrl2, &end );
+          if ( stroker->handle_wide_strokes )
+          {
+            FT_Vector  start;
+            FT_Angle   alpha1;
+
+
+            /* determine whether the border radius is greater than the */
+            /* radius of curvature of the original arc                 */
+            start = border->points[border->num_points - 1];
+
+            alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
+
+            /* is the direction of the border arc opposite to */
+            /* that of the original arc? */
+            if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
+                   FT_ANGLE_PI / 2                             )
+            {
+              FT_Angle   beta, gamma;
+              FT_Vector  bvec, delta;
+              FT_Fixed   blen, sinA, sinB, alen;
+
+
+              /* use the sine rule to find the intersection point */
+              beta  = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y );
+              gamma = FT_Atan2( arc[0].x - end.x,   arc[0].y - end.y );
+
+              bvec.x = end.x - start.x;
+              bvec.y = end.y - start.y;
+
+              blen = FT_Vector_Length( &bvec );
+
+              sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
+              sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
+
+              alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
+
+              FT_Vector_From_Polar( &delta, alen, beta );
+              delta.x += start.x;
+              delta.y += start.y;
+
+              /* circumnavigate the negative sector backwards */
+              border->movable = FALSE;
+              error = ft_stroke_border_lineto( border, &delta, FALSE );
+              if ( error )
+                goto Exit;
+              error = ft_stroke_border_lineto( border, &end, FALSE );
+              if ( error )
+                goto Exit;
+              error = ft_stroke_border_cubicto( border,
+                                                &ctrl2,
+                                                &ctrl1,
+                                                &start );
+              if ( error )
+                goto Exit;
+              /* and then move to the endpoint */
+              error = ft_stroke_border_lineto( border, &end, FALSE );
+              if ( error )
+                goto Exit;
+
+              continue;
+            }
+
+            /* else fall through */
+          }
+
+          /* simply add an arc */
+          error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end );
           if ( error )
             goto Exit;
         }
       }
 
       arc -= 3;
-      if ( arc < bez_stack )
-        stroker->angle_in = angle_out;
+
+      stroker->angle_in = angle_out;
     }
 
     stroker->center = *to;
@@ -1415,9 +1767,21 @@
     stroker->center       = *to;
     stroker->subpath_open = open;
 
+    /* Determine if we need to check whether the border radius is greater */
+    /* than the radius of curvature of a curve, to handle this case       */
+    /* specially.  This is only required if bevel joins or butt caps may  */
+    /* be created, because round & miter joins and round & square caps    */
+    /* cover the negative sector created with wide strokes.               */
+    stroker->handle_wide_strokes =
+      FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND  ||
+               ( stroker->subpath_open                        &&
+                 stroker->line_cap == FT_STROKER_LINECAP_BUTT ) );
+
     /* record the subpath start point for each border */
     stroker->subpath_start = *to;
 
+    stroker->angle_in = 0;
+
     return FT_Err_Ok;
   }
 
@@ -1447,6 +1811,7 @@
         FT_Vector*  src_point = left->points  + left->num_points - 1;
         FT_Byte*    src_tag   = left->tags    + left->num_points - 1;
 
+
         while ( src_point >= left->points + left->start )
         {
           *dst_point = *src_point;
@@ -1456,14 +1821,14 @@
             dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;
           else
           {
-            FT_Byte  ttag = (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
+            FT_Byte  ttag =
+                       (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
 
 
             /* switch begin/end tags if necessary */
             if ( ttag == FT_STROKE_TAG_BEGIN ||
                  ttag == FT_STROKE_TAG_END   )
               dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END;
-
           }
 
           src_point--;
@@ -1498,6 +1863,7 @@
     {
       FT_StrokeBorder  right = stroker->borders;
 
+
       /* All right, this is an opened path, we need to add a cap between */
       /* right & left, add the reverse of left, then add a final cap     */
       /* between left & right.                                           */
@@ -1526,13 +1892,14 @@
       FT_Angle  turn;
       FT_Int    inside_side;
 
+
       /* close the path if needed */
       if ( stroker->center.x != stroker->subpath_start.x ||
            stroker->center.y != stroker->subpath_start.y )
       {
-        error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
-        if ( error )
-          goto Exit;
+         error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
+         if ( error )
+           goto Exit;
       }
 
       /* process the corner */
@@ -1550,19 +1917,23 @@
         if ( turn < 0 )
           inside_side = 1;
 
-        error = ft_stroker_inside( stroker, inside_side );
+        error = ft_stroker_inside( stroker,
+                                   inside_side,
+                                   stroker->subpath_line_length );
         if ( error )
           goto Exit;
 
         /* process the outside side */
-        error = ft_stroker_outside( stroker, 1 - inside_side );
+        error = ft_stroker_outside( stroker,
+                                    1 - inside_side,
+                                    stroker->subpath_line_length );
         if ( error )
           goto Exit;
       }
 
       /* then end our two subpaths */
-      ft_stroke_border_close( stroker->borders + 0, TRUE );
-      ft_stroke_border_close( stroker->borders + 1, FALSE );
+      ft_stroke_border_close( stroker->borders + 0, FALSE );
+      ft_stroke_border_close( stroker->borders + 1, TRUE );
     }
 
   Exit:
@@ -1684,9 +2055,9 @@
 
     FT_Error    error;
 
-    FT_Int   n;         /* index of contour in outline     */
-    FT_UInt  first;     /* index of first point in contour */
-    FT_Int   tag;       /* current point's state           */
+    FT_Int      n;         /* index of contour in outline     */
+    FT_UInt     first;     /* index of first point in contour */
+    FT_Int      tag;       /* current point's state           */
 
 
     if ( !outline || !stroker )
@@ -1851,9 +2222,13 @@
       if ( error )
         goto Exit;
 
-      error = FT_Stroker_EndSubPath( stroker );
-      if ( error )
-        goto Exit;
+      /* don't try to end the path if no segments have been generated */
+      if ( !stroker->first_point )
+      {
+        error = FT_Stroker_EndSubPath( stroker );
+        if ( error )
+          goto Exit;
+      }
 
       first = last + 1;
     }
@@ -1867,9 +2242,10 @@
     return FT_Err_Invalid_Outline;
   }
 
-/* declare an extern to access ft_outline_glyph_class global allocated 
-   in ftglyph.c, and use the FT_OUTLINE_GLYPH_CLASS_GET macro to access 
-   it when FT_CONFIG_OPTION_PIC is defined */
+
+  /* declare an extern to access `ft_outline_glyph_class' globally     */
+  /* allocated  in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
+  /* macro to access it when FT_CONFIG_OPTION_PIC is defined           */
 #ifndef FT_CONFIG_OPTION_PIC
   extern const FT_Glyph_Class  ft_outline_glyph_class;
 #endif
@@ -1883,10 +2259,12 @@
                    FT_Stroker   stroker,
                    FT_Bool      destroy )
   {
-    FT_Error  error = FT_Err_Invalid_Argument;
-    FT_Glyph  glyph = NULL;
-    FT_Library library = stroker->library;
-    FT_UNUSED(library);
+    FT_Error    error   = FT_Err_Invalid_Argument;
+    FT_Glyph    glyph   = NULL;
+    FT_Library  library = stroker->library;
+
+    FT_UNUSED( library );
+
 
     if ( pglyph == NULL )
       goto Exit;
@@ -1907,7 +2285,7 @@
     }
 
     {
-      FT_OutlineGlyph  oglyph  = (FT_OutlineGlyph) glyph;
+      FT_OutlineGlyph  oglyph  = (FT_OutlineGlyph)glyph;
       FT_Outline*      outline = &oglyph->outline;
       FT_UInt          num_points, num_contours;
 
@@ -1957,10 +2335,12 @@
                          FT_Bool      inside,
                          FT_Bool      destroy )
   {
-    FT_Error  error = FT_Err_Invalid_Argument;
-    FT_Glyph  glyph = NULL;
-    FT_Library library = stroker->library;
-    FT_UNUSED(library);
+    FT_Error    error   = FT_Err_Invalid_Argument;
+    FT_Glyph    glyph   = NULL;
+    FT_Library  library = stroker->library;
+
+    FT_UNUSED( library );
+
 
     if ( pglyph == NULL )
       goto Exit;
@@ -1981,7 +2361,7 @@
     }
 
     {
-      FT_OutlineGlyph   oglyph  = (FT_OutlineGlyph) glyph;
+      FT_OutlineGlyph   oglyph  = (FT_OutlineGlyph)glyph;
       FT_StrokerBorder  border;
       FT_Outline*       outline = &oglyph->outline;
       FT_UInt           num_points, num_contours;
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index 66c5d76..7e203be 100644
--- a/src/base/ftsystem.c
+++ b/src/base/ftsystem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    ANSI-specific FreeType low-level system interface (body).            */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2006, 2008, 2009, 2010 by                   */
+/*  Copyright 1996-2002, 2006, 2008-2011 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -137,6 +137,7 @@
   /*                                                                       */
   /*************************************************************************/
 
+#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
 
   /*************************************************************************/
   /*                                                                       */
@@ -267,6 +268,7 @@
     return FT_Err_Ok;
   }
 
+#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
 
 #ifdef FT_DEBUG_MEMORY
 
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 39f04ee..4fd3436 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -328,7 +328,7 @@
     if ( cff && cff->font_info == NULL )
     {
       CFF_FontRecDict  dict   = &cff->top_font.font_dict;
-      PS_FontInfoRec  *font_info;
+      PS_FontInfoRec  *font_info = NULL;
       FT_Memory        memory = face->root.memory;
 
 
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index e99ee70..cb06bdf 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    OpenType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -1159,8 +1158,8 @@
               op = cff_op_flex1;
               break;
             default:
-              /* decrement ip for syntax error message */
-              ip--;
+              FT_TRACE4(( " unknown op (12, %d)\n", v ));
+              break;
             }
           }
           break;
@@ -1213,11 +1212,12 @@
           op = cff_op_hvcurveto;
           break;
         default:
+          FT_TRACE4(( " unknown op (%d)\n", v ));
           break;
         }
 
         if ( op == cff_op_unknown )
-          goto Syntax_Error;
+          continue;
 
         /* check arguments */
         req_args = cff_argument_counts[op];
@@ -1438,9 +1438,14 @@
             FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
                                              : " vlineto\n" ));
 
-            if ( num_args < 1 )
+            if ( num_args < 0 )
               goto Stack_Underflow;
 
+            /* there exist subsetted fonts (found in PDFs) */
+            /* which call `hlineto' without arguments      */
+            if ( num_args == 0 )
+              break;
+
             if ( cff_builder_start_point ( builder, x, y ) ||
                  check_points( builder, num_args )         )
               goto Fail;
@@ -2701,7 +2706,7 @@
                                               glyph_index );
 
       if ( fd_index >= cff->num_subfonts ) 
-        fd_index = cff->num_subfonts - 1;
+        fd_index = (FT_Byte)( cff->num_subfonts - 1 );
 
       top_upm = cff->top_font.font_dict.units_per_em;
       sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 000cbe3..629d38e 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -387,7 +387,7 @@
   {
     FT_Error   error     = CFF_Err_Ok;
     FT_Memory  memory    = idx->stream->memory;
-    FT_Byte**  t;
+    FT_Byte**  t = NULL;
     FT_Byte*   new_bytes = NULL;
 
 
@@ -1269,7 +1269,7 @@
           if ( gid != 0 )
           {
             encoding->codes[j] = (FT_UShort)gid;
-            encoding->count    = j + 1;
+              encoding->count = j + 1;
           }
           else
           {
@@ -1514,7 +1514,7 @@
     if ( dict->cid_registry != 0xFFFFU )
     {
       CFF_IndexRec  fd_index;
-      CFF_SubFont   sub;
+      CFF_SubFont   sub = NULL;
       FT_UInt       idx;
 
 
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index 1cd35c9..cd38676 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (body).                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -162,7 +161,7 @@
     {
       CFF_Face      face     = (CFF_Face)cffsize->face;
       CFF_Font      font     = (CFF_Font)face->extra.data;
-      CFF_Internal  internal;
+      CFF_Internal  internal = NULL;
 
       PS_PrivateRec  priv;
       FT_Memory      memory = cffsize->face->memory;
@@ -421,6 +420,7 @@
         {
           for ( idx = 7; idx < length; idx++ )
             name[idx - 7] = name[idx];
+          length -= 7;
         }
       }
       else
@@ -429,6 +429,51 @@
   }
 
 
+  /* Remove the style part from the family name (if present). */
+
+  static void
+  remove_style( FT_String*        family_name,
+                const FT_String*  style_name )
+  {
+    FT_Int32  family_name_length, style_name_length;
+
+
+    family_name_length = strlen( family_name );
+    style_name_length  = strlen( style_name );
+
+    if ( family_name_length > style_name_length )
+    {
+      FT_Int  idx;
+
+
+      for ( idx = 1; idx <= style_name_length; ++idx )
+      {
+        if ( family_name[family_name_length - idx] !=
+             style_name[style_name_length - idx] )
+          break;
+      }
+
+      if ( idx > style_name_length )
+      {
+        /* family_name ends with style_name; remove it */
+        idx = family_name_length - style_name_length - 1;
+
+        /* also remove special characters     */
+        /* between real family name and style */
+        while ( idx > 0                     &&
+                ( family_name[idx] == '-' ||
+                  family_name[idx] == ' ' ||
+                  family_name[idx] == '_' ||
+                  family_name[idx] == '+' ) )
+          --idx;
+
+        if ( idx > 0 )
+          family_name[idx + 1] = '\0';
+      }
+    }
+  }
+
+
   FT_LOCAL_DEF( FT_Error )
   cff_face_init( FT_Stream      stream,
                  FT_Face        cffface,        /* CFF_Face */
@@ -436,14 +481,14 @@
                  FT_Int         num_params,
                  FT_Parameter*  params )
   {
-    CFF_Face            face = (CFF_Face)cffface;
+    CFF_Face            face        = (CFF_Face)cffface;
     FT_Error            error;
     SFNT_Service        sfnt;
     FT_Service_PsCMaps  psnames;
     PSHinter_Service    pshinter;
     FT_Bool             pure_cff    = 1;
     FT_Bool             sfnt_format = 0;
-    FT_Library library = cffface->driver->root.library;
+    FT_Library          library     = cffface->driver->root.library;
 
 
     sfnt = (SFNT_Service)FT_Get_Module_Interface(
@@ -523,7 +568,7 @@
 
     /* now load and parse the CFF table in the file */
     {
-      CFF_Font         cff;
+      CFF_Font         cff = NULL;
       CFF_FontRecDict  dict;
       FT_Memory        memory = cffface->memory;
       FT_Int32         flags;
@@ -758,6 +803,9 @@
                 /* case, the remaining string in `fullp' will be used as */
                 /* the style name.                                       */
                 style_name = cff_strcpy( memory, fullp );
+
+                /* remove the style part from the family name (if present) */
+                remove_style( cffface->family_name, style_name ); 
               }
               break;
             }
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 0d11a72..b12a8d3 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token stream parser (body)                                       */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 by       */
+/*  Copyright 1996-2004, 2007-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -35,8 +35,6 @@
 #define FT_COMPONENT  trace_cffparse
 
 
-
-
   FT_LOCAL_DEF( void )
   cff_parser_init( CFF_Parser  parser,
                    FT_UInt     code,
@@ -475,9 +473,15 @@
       if ( scaling < 0 || scaling > 9 )
       {
         /* Return default matrix in case of unlikely values. */
+
+        FT_TRACE1(( "cff_parse_font_matrix:"
+                    " strange scaling value for xx element (%d),\n"
+                    "                      "
+                    " using default matrix\n", scaling ));
+
         matrix->xx = 0x10000L;
         matrix->yx = 0;
-        matrix->yx = 0;
+        matrix->xy = 0;
         matrix->yy = 0x10000L;
         offset->x  = 0;
         offset->y  = 0;
@@ -493,6 +497,12 @@
       offset->y  = cff_parse_fixed_scaled( data,   scaling );
 
       *upm = power_tens[scaling];
+
+      FT_TRACE4(( " font matrix: [%f %f %f %f]\n",
+                  (double)matrix->xx / *upm / 65536,
+                  (double)matrix->xy / *upm / 65536,
+                  (double)matrix->yx / *upm / 65536,
+                  (double)matrix->yy / *upm / 65536 ));
     }
 
   Exit:
@@ -518,6 +528,12 @@
       bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
       bbox->yMax = FT_RoundFix( cff_parse_fixed( data   ) );
       error = CFF_Err_Ok;
+
+      FT_TRACE4(( " bbox: [%d %d %d %d]\n",
+                  bbox->xMin / 65536,
+                  bbox->yMin / 65536,
+                  bbox->xMax / 65536,
+                  bbox->yMax / 65536 ));
     }
 
     return error;
@@ -557,8 +573,8 @@
 
     if ( parser->top >= parser->stack + 3 )
     {
-      dict->cid_registry   = (FT_UInt)cff_parse_num ( data++ );
-      dict->cid_ordering   = (FT_UInt)cff_parse_num ( data++ );
+      dict->cid_registry   = (FT_UInt)cff_parse_num( data++ );
+      dict->cid_ordering   = (FT_UInt)cff_parse_num( data++ );
       if ( **data == 30 )
         FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
       dict->cid_supplement = cff_parse_num( data );
@@ -566,6 +582,11 @@
         FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
                    dict->cid_supplement ));
       error = CFF_Err_Ok;
+
+      FT_TRACE4(( " ROS: registry sid %d, ordering sid %d, supplement %d\n",
+                  dict->cid_registry,
+                  dict->cid_ordering,
+                  dict->cid_supplement ));
     }
 
     return error;
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index d405357..665ab6f 100644
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -5,7 +5,7 @@
 /*    Basic OpenType/CFF type definitions and interface (specification     */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2010 by             */
+/*  Copyright 1996-2003, 2006-2008, 2010-2011 by                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -212,8 +212,7 @@
   } CFF_SubFontRec, *CFF_SubFont;
 
 
-  /* maximum number of sub-fonts in a CID-keyed file */
-#define CFF_MAX_CID_FONTS  32
+#define CFF_MAX_CID_FONTS  256
 
 
   typedef struct  CFF_FontRec_
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index 45c7419..5b160ce 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    Auxiliary functions for PostScript fonts (body).                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -188,11 +187,11 @@
     {
       FT_Error   error;
       FT_Offset  new_size = table->capacity;
-      FT_Long    in_offset;
+      FT_PtrDist  in_offset;
 
 
-      in_offset = (FT_Long)((FT_Byte*)object - table->block);
-      if ( (FT_ULong)in_offset >= table->capacity )
+      in_offset = (FT_Byte*)object - table->block;
+      if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity )
         in_offset = -1;
 
       while ( new_size < table->cursor + length )
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index ea31c51..90874f0 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    PostScript Type 1 decoding routines (body).                          */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009    */
-/*            2010 by                                                      */
+/*  Copyright 2000-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -28,6 +27,8 @@
 
 #include "psauxerr.h"
 
+/* ensure proper sign extension */
+#define Fix2Int( f )  ( (FT_Int)(FT_Short)( (f) >> 16 ) )
 
   /*************************************************************************/
   /*                                                                       */
@@ -396,7 +397,7 @@
     FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
                ( decoder->buildchar == NULL )  );
 
-    if ( decoder->len_buildchar > 0 )
+    if ( decoder->buildchar && decoder->len_buildchar > 0 )
       ft_memset( &decoder->buildchar[0],
                  0,
                  sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );
@@ -662,7 +663,7 @@
         if ( large_int )
           FT_TRACE4(( " %ld", value ));
         else
-          FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) ));
+          FT_TRACE4(( " %ld", Fix2Int( value ) ));
 #endif
 
         *top++       = value;
@@ -684,8 +685,8 @@
 
         top -= 2;
 
-        subr_no = (FT_Int)( top[1] >> 16 );
-        arg_cnt = (FT_Int)( top[0] >> 16 );
+        subr_no = Fix2Int( top[1] );
+        arg_cnt = Fix2Int( top[0] );
 
         /***********************************************************/
         /*                                                         */
@@ -724,6 +725,24 @@
 
         switch ( subr_no )
         {
+        case 0:                     /* end flex feature */
+          if ( arg_cnt != 3 )
+            goto Unexpected_OtherSubr;
+
+          if ( decoder->flex_state       == 0 ||
+               decoder->num_flex_vectors != 7 )
+          {
+            FT_ERROR(( "t1_decoder_parse_charstrings:"
+                       " unexpected flex end\n" ));
+            goto Syntax_Error;
+          }
+
+          /* the two `results' are popped by the following setcurrentpoint */
+          top[0] = x;
+          top[1] = y;
+          known_othersubr_result_cnt = 2;
+          break;
+
         case 1:                     /* start flex feature */
           if ( arg_cnt != 0 )
             goto Unexpected_OtherSubr;
@@ -757,24 +776,6 @@
           }
           break;
 
-        case 0:                     /* end flex feature */
-          if ( arg_cnt != 3 )
-            goto Unexpected_OtherSubr;
-
-          if ( decoder->flex_state       == 0 ||
-               decoder->num_flex_vectors != 7 )
-          {
-            FT_ERROR(( "t1_decoder_parse_charstrings:"
-                       " unexpected flex end\n" ));
-            goto Syntax_Error;
-          }
-
-          /* the two `results' are popped by the following setcurrentpoint */
-          top[0] = x;
-          top[1] = y;
-          known_othersubr_result_cnt = 2;
-          break;
-
         case 3:                     /* change hints */
           if ( arg_cnt != 1 )
             goto Unexpected_OtherSubr;
@@ -818,17 +819,18 @@
               goto Syntax_Error;
             }
 
-            /* we want to compute:                                   */
+            /* We want to compute                                    */
             /*                                                       */
-            /*  a0*w0 + a1*w1 + ... + ak*wk                          */
+            /*   a0*w0 + a1*w1 + ... + ak*wk                         */
             /*                                                       */
-            /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
-            /* however, given that w0 + w1 + ... + wk == 1, we can   */
-            /* rewrite it easily as:                                 */
+            /* but we only have a0, a1-a0, a2-a0, ..., ak-a0.        */
             /*                                                       */
-            /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
+            /* However, given that w0 + w1 + ... + wk == 1, we can   */
+            /* rewrite it easily as                                  */
             /*                                                       */
-            /* where k == num_designs-1                              */
+            /*   a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk     */
+            /*                                                       */
+            /* where k == num_designs-1.                             */
             /*                                                       */
             /* I guess that's why it's written in this `compact'     */
             /* form.                                                 */
@@ -862,7 +864,7 @@
             if ( arg_cnt != 1 || blend == NULL )
               goto Unexpected_OtherSubr;
 
-            idx = (FT_Int)( top[0] >> 16 );
+            idx = Fix2Int( top[0] );
 
             if ( idx < 0                                           ||
                  idx + blend->num_designs > decoder->len_buildchar )
@@ -930,7 +932,7 @@
             if ( arg_cnt != 2 || blend == NULL )
               goto Unexpected_OtherSubr;
 
-            idx = (FT_Int)( top[1] >> 16 );
+            idx = Fix2Int( top[1] );
 
             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
               goto Unexpected_OtherSubr;
@@ -951,7 +953,7 @@
             if ( arg_cnt != 1 || blend == NULL )
               goto Unexpected_OtherSubr;
 
-            idx = (FT_Int)( top[0] >> 16 );
+            idx = Fix2Int( top[0] );
 
             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
               goto Unexpected_OtherSubr;
@@ -1009,11 +1011,15 @@
           break;
 
         default:
-          FT_ERROR(( "t1_decoder_parse_charstrings:"
-                     " unknown othersubr [%d %d], wish me luck\n",
-                     arg_cnt, subr_no ));
-          unknown_othersubr_result_cnt = arg_cnt;
-          break;
+          if ( arg_cnt >= 0 && subr_no >= 0 )
+          {
+            FT_ERROR(( "t1_decoder_parse_charstrings:"
+                       " unknown othersubr [%d %d], wish me luck\n",
+                       arg_cnt, subr_no ));
+            unknown_othersubr_result_cnt = arg_cnt;
+            break;
+          }
+          /* fall through */
 
         Unexpected_OtherSubr:
           FT_ERROR(( "t1_decoder_parse_charstrings:"
@@ -1139,8 +1145,8 @@
                                   top[0],
                                   top[1],
                                   top[2],
-                                  (FT_Int)( top[3] >> 16 ),
-                                  (FT_Int)( top[4] >> 16 ) );
+                                  Fix2Int( top[3] ),
+                                  Fix2Int( top[4] ) );
 
         case op_sbw:
           FT_TRACE4(( " sbw" ));
@@ -1324,7 +1330,7 @@
 
             FT_TRACE4(( " callsubr" ));
 
-            idx = (FT_Int)( top[0] >> 16 );
+            idx = Fix2Int( top[0] );
             if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
             {
               FT_ERROR(( "t1_decoder_parse_charstrings:"
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index 9638dfb..55e2d0d 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 by       */
+/*  Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 by */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -651,11 +651,33 @@
   static void
   Set_High_Precision( RAS_ARGS Int  High )
   {
+    /*
+     * `precision_step' is used in `Bezier_Up' to decide when to split a
+     * given y-monotonous Bezier arc that crosses a scanline before
+     * approximating it as a straight segment.  The default value of 32 (for
+     * low accuracy) corresponds to
+     *
+     *   32 / 64 == 0.5 pixels ,
+     *
+     * while for the high accuracy case we have
+     *
+     *   256/ (1 << 12) = 0.0625 pixels .
+     *
+     * `precision_jitter' is an epsilon threshold used in
+     * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
+     * decomposition (after all, we are working with approximations only);
+     * it avoids switching on additional pixels which would cause artifacts
+     * otherwise.
+     *
+     * The value of `precision_jitter' has been determined heuristically.
+     *
+     */
+
     if ( High )
     {
       ras.precision_bits   = 12;
       ras.precision_step   = 256;
-      ras.precision_jitter = 50;
+      ras.precision_jitter = 30;
     }
     else
     {
@@ -2403,6 +2425,14 @@
           return;  /* no drop-out control */
         }
 
+        /* undocumented but confirmed: If the drop-out would result in a  */
+        /* pixel outside of the bounding box, use the pixel inside of the */
+        /* bounding box instead                                           */
+        if ( pxl < 0 )
+          pxl = e1;
+        else if ( TRUNC( pxl ) >= ras.bWidth )
+          pxl = e2;
+
         /* check that the other pixel isn't set */
         e1 = pxl == e1 ? e2 : e1;
 
@@ -2579,6 +2609,14 @@
           return;  /* no drop-out control */
         }
 
+        /* undocumented but confirmed: If the drop-out would result in a  */
+        /* pixel outside of the bounding box, use the pixel inside of the */
+        /* bounding box instead                                           */
+        if ( pxl < 0 )
+          pxl = e1;
+        else if ( TRUNC( pxl ) >= ras.target.rows )
+          pxl = e2;
+
         /* check that the other pixel isn't set */
         e1 = pxl == e1 ? e2 : e1;
 
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index 1ed8af6..d8a89f2 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -161,10 +161,18 @@
     /* compute the control box, and grid fit it */
     FT_Outline_Get_CBox( outline, &cbox );
 
+    /* undocumented but confirmed: bbox values get rounded */
+#if 1
+    cbox.xMin = FT_PIX_ROUND( cbox.xMin );
+    cbox.yMin = FT_PIX_ROUND( cbox.yMin );
+    cbox.xMax = FT_PIX_ROUND( cbox.xMax );
+    cbox.yMax = FT_PIX_ROUND( cbox.yMax );
+#else
     cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
     cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
     cbox.xMax = FT_PIX_CEIL( cbox.xMax );
     cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+#endif
 
     width  = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
     height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index b74679b..247aa67 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level SFNT driver interface (body).                             */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/*  Copyright 1996-2007, 2009-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -117,15 +117,20 @@
                    FT_ULong  *offset,
                    FT_ULong  *length )
   {
-    if ( !tag || !offset || !length )
+    if ( !offset || !length )
       return SFNT_Err_Invalid_Argument;
 
-    if ( idx >= face->num_tables )
-      return SFNT_Err_Table_Missing;
+    if ( !tag )
+      *length = face->num_tables;
+    else
+    {
+      if ( idx >= face->num_tables )
+        return SFNT_Err_Table_Missing;
 
-    *tag    = face->dir_tables[idx].Tag;
-    *offset = face->dir_tables[idx].Offset;
-    *length = face->dir_tables[idx].Length;
+      *tag    = face->dir_tables[idx].Tag;
+      *offset = face->dir_tables[idx].Offset;
+      *length = face->dir_tables[idx].Length;
+    }
 
     return SFNT_Err_Ok;
   }
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 5a1d003..44471f6 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT object management (base).                                       */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
+/*  Copyright 1996-2008, 2010-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -356,7 +356,7 @@
 
       FT_FRAME_START( 8 ),
         FT_FRAME_LONG( version ),
-        FT_FRAME_LONG( count   ),
+        FT_FRAME_LONG( count   ),  /* this is ULong in the specs */
       FT_FRAME_END
     };
 
@@ -390,6 +390,17 @@
       if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
         return error;
 
+      if ( face->ttc_header.count == 0 )
+        return SFNT_Err_Invalid_Table;
+
+      /* a rough size estimate: let's conservatively assume that there   */
+      /* is just a single table info in each subfont header (12 + 16*1 = */
+      /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */
+      /* size of the TTC header plus `28*count' bytes for all subfont    */
+      /* headers                                                         */
+      if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
+        return SFNT_Err_Array_Too_Large;
+
       /* now read the offsets of each font in the file */
       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
         return error;
@@ -536,7 +547,7 @@
     FT_UNUSED( face_index );
 
     /* Check parameters */
-    
+
     {
       FT_Int  i;
 
@@ -571,12 +582,12 @@
 
     /* do we have outlines in there? */
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
-    has_outline   = FT_BOOL( face->root.internal->incremental_interface != 0 ||
-                             tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
-                             tt_face_lookup_table( face, TTAG_CFF )     != 0 );
+    has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
+                           tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
+                           tt_face_lookup_table( face, TTAG_CFF )     != 0 );
 #else
-    has_outline   = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
-                             tt_face_lookup_table( face, TTAG_CFF )  != 0 );
+    has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
+                           tt_face_lookup_table( face, TTAG_CFF )  != 0 );
 #endif
 
     is_apple_sbit = 0;
@@ -651,8 +662,9 @@
         if ( face->format_tag == TTAG_true )
         {
           FT_TRACE2(( "This is an SFNT Mac font.\n" ));
+
           has_outline = 0;
-          error = SFNT_Err_Ok;
+          error       = SFNT_Err_Ok;
         }
         else
         {
@@ -987,40 +999,36 @@
         /*      table cannot be used to compute the text height reliably! */
         /*                                                                */
 
-        /* The ascender/descender/height are computed from the OS/2 table */
-        /* when found.  Otherwise, they're taken from the horizontal      */
-        /* header.                                                        */
-        /*                                                                */
+        /* The ascender and descender are taken from the `hhea' table. */
+        /* If zero, they are taken from the `OS/2' table.              */
 
         root->ascender  = face->horizontal.Ascender;
         root->descender = face->horizontal.Descender;
 
-        root->height    = (FT_Short)( root->ascender - root->descender +
-                                      face->horizontal.Line_Gap );
+        root->height = (FT_Short)( root->ascender - root->descender +
+                                   face->horizontal.Line_Gap );
 
-#if 0
-        /* if the line_gap is 0, we add an extra 15% to the text height --  */
-        /* this computation is based on various versions of Times New Roman */
-        if ( face->horizontal.Line_Gap == 0 )
-          root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
-#endif /* 0 */
-
-#if 0
-        /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
-        /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
-        if ( face->os2.version != 0xFFFFU && root->ascender )
+        if ( !( root->ascender || root->descender ) )
         {
-          FT_Int  height;
+          if ( face->os2.version != 0xFFFFU )
+          {
+            if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
+            {
+              root->ascender  = face->os2.sTypoAscender;
+              root->descender = face->os2.sTypoDescender;
 
+              root->height = (FT_Short)( root->ascender - root->descender +
+                                         face->os2.sTypoLineGap );
+            }
+            else
+            {
+              root->ascender  =  (FT_Short)face->os2.usWinAscent;
+              root->descender = -(FT_Short)face->os2.usWinDescent;
 
-          root->ascender  =  face->os2.sTypoAscender;
-          root->descender = -face->os2.sTypoDescender;
-
-          height = root->ascender + root->descender + face->os2.sTypoLineGap;
-          if ( height > root->height )
-            root->height = height;
+              root->height = (FT_UShort)( root->ascender - root->descender );
+            }
+          }
         }
-#endif /* 0 */
 
         root->max_advance_width  = face->horizontal.advance_Width_Max;
         root->max_advance_height = (FT_Short)( face->vertical_info
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index 20bac73..5fb9aea 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -1213,7 +1213,7 @@
     FT_Memory  memory = stream->memory;
 
     FT_UInt        j,num_ranges;
-    TT_GaspRange   gaspranges;
+    TT_GaspRange   gaspranges = NULL;
 
 
     /* the gasp table is optional */
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 53e6ac7..73ac8b2 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Load the metrics tables common to TTF and OTF fonts (body).          */
 /*                                                                         */
-/*  Copyright 2006, 2007, 2008, 2009 by                                    */
+/*  Copyright 2006-2009, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -163,7 +163,7 @@
     {
       FT_TRACE0(( "tt_face_load_hmtx:"
                   " %cmtx has more metrics than glyphs.\n",
-                  vertical ? "v" : "h" ));
+                  vertical ? 'v' : 'h' ));
 
       /* Adobe simply ignores this problem.  So we shall do the same. */
 #if 0
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index faa8f88..283ba7e 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -1343,7 +1343,7 @@
     /* All right, we have a compound format.  First of all, read */
     /* the array of elements.                                    */
     {
-      TT_SBit_Component  components;
+      TT_SBit_Component  components = NULL;
       TT_SBit_Component  comp;
       FT_UShort          num_components, count;
 
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index a85e160..40de269 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    A new `perfect' anti-aliasing renderer (body).                       */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/*  Copyright 2000-2003, 2005-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -890,14 +890,8 @@
     if ( dx < dy )
       dx = dy;
 
-    if ( dx <= ONE_PIXEL / 4 )
-    {
-      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
-      return;
-    }
-
     level = 0;
-    while ( dx > ONE_PIXEL / 4 )
+    while ( dx > ONE_PIXEL / 6 )
     {
       dx >>= 2;
       level++;
@@ -907,7 +901,7 @@
     levels[0] = level;
     top       = 0;
 
-    while ( top >= 0 )
+    do
     {
       level = levels[top];
       if ( level > 1 )
@@ -940,9 +934,8 @@
       gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
       top--;
       arc -= 2;
-    }
 
-    return;
+    } while ( top >= 0 );
   }
 
 
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index eb12f18..1350a56 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Anti-aliasing renderer interface (body).                             */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by       */
+/*  Copyright 2000-2006, 2009-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -105,7 +105,10 @@
     FT_Error     error;
     FT_Outline*  outline = NULL;
     FT_BBox      cbox;
-    FT_UInt      width, height, height_org, width_org, pitch;
+    FT_UInt      width, height, pitch;
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+    FT_UInt      height_org, width_org;
+#endif
     FT_Bitmap*   bitmap;
     FT_Memory    memory;
     FT_Int       hmul = mode == FT_RENDER_MODE_LCD;
@@ -163,8 +166,10 @@
     bitmap = &slot->bitmap;
     memory = render->root.memory;
 
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     width_org  = width;
     height_org = height;
+#endif
 
     /* release old bitmap buffer */
     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index d723b57..e70a611 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    TrueType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009    */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -135,8 +134,6 @@
   {
     FT_UInt  nn;
     TT_Face  face  = (TT_Face) ttface;
-    FT_Bool  check = FT_BOOL(
-                       !( flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) );
 
 
     /* XXX: TODO: check for sbits */
@@ -149,7 +146,7 @@
         FT_UShort  ah;
 
 
-        TT_Get_VMetrics( face, start + nn, check, &tsb, &ah );
+        TT_Get_VMetrics( face, start + nn, &tsb, &ah );
         advances[nn] = ah;
       }
     }
@@ -161,7 +158,7 @@
         FT_UShort  aw;
 
 
-        TT_Get_HMetrics( face, start + nn, check, &lsb, &aw );
+        TT_Get_HMetrics( face, start + nn, &lsb, &aw );
         advances[nn] = aw;
       }
     }
@@ -249,7 +246,10 @@
     FT_Request_Metrics( size->face, req );
 
     if ( FT_IS_SCALABLE( size->face ) )
+    {
       error = tt_size_reset( ttsize );
+      ttsize->root.metrics = ttsize->metrics;
+    }
 
     return error;
   }
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 3a69b7b..f35521e 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    TrueType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011                                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -47,7 +46,7 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* Composite font flags.                                                 */
+  /* Composite glyph flags.                                                */
   /*                                                                       */
 #define ARGS_ARE_WORDS             0x0001
 #define ARGS_ARE_XY_VALUES         0x0002
@@ -66,22 +65,16 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* Returns the horizontal metrics in font units for a given glyph.  If   */
-  /* `check' is true, take care of monospaced fonts by returning the       */
-  /* advance width maximum.                                                */
+  /* Return the horizontal metrics in font units for a given glyph.        */
   /*                                                                       */
   FT_LOCAL_DEF( void )
   TT_Get_HMetrics( TT_Face     face,
                    FT_UInt     idx,
-                   FT_Bool     check,
                    FT_Short*   lsb,
                    FT_UShort*  aw )
   {
     ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
 
-    if ( check && face->postscript.isFixedPitch )
-      *aw = face->horizontal.advance_Width_Max;
-
     FT_TRACE5(( "  advance width (font units): %d\n", *aw ));
     FT_TRACE5(( "  left side bearing (font units): %d\n", *lsb ));
   }
@@ -89,7 +82,7 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* Returns the vertical metrics in font units for a given glyph.         */
+  /* Return the vertical metrics in font units for a given glyph.          */
   /* Greg Hitchcock from Microsoft told us that if there were no `vmtx'    */
   /* table, typoAscender/Descender from the `OS/2' table would be used     */
   /* instead, and if there were no `OS/2' table, use ascender/descender    */
@@ -97,18 +90,12 @@
   /* apparently does: It uses the ppem value as the advance height, and    */
   /* sets the top side bearing to be zero.                                 */
   /*                                                                       */
-  /* The monospace `check' is probably not meaningful here, but we leave   */
-  /* it in for a consistent interface.                                     */
-  /*                                                                       */
   FT_LOCAL_DEF( void )
   TT_Get_VMetrics( TT_Face     face,
                    FT_UInt     idx,
-                   FT_Bool     check,
                    FT_Short*   tsb,
                    FT_UShort*  ah )
   {
-    FT_UNUSED( check );
-
     if ( face->vertical_info )
       ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
 
@@ -151,13 +138,9 @@
 
 
     TT_Get_HMetrics( face, glyph_index,
-                     (FT_Bool)!( loader->load_flags &
-                                 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
                      &left_bearing,
                      &advance_width );
     TT_Get_VMetrics( face, glyph_index,
-                     (FT_Bool)!( loader->load_flags &
-                                 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
                      &top_bearing,
                      &advance_height );
 
@@ -1656,23 +1639,7 @@
 
     /* get the device-independent horizontal advance; it is scaled later */
     /* by the base layer.                                                */
-    {
-      FT_Pos  advance = loader->linear;
-
-
-      /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
-      /* correctly support DynaLab fonts, which have an incorrect       */
-      /* `advance_Width_Max' field!  It is used, to my knowledge,       */
-      /* exclusively in the X-TrueType font server.                     */
-      /*                                                                */
-      if ( face->postscript.isFixedPitch                                     &&
-           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
-        advance = face->horizontal.advance_Width_Max;
-
-      /* we need to return the advance in font units in linearHoriAdvance, */
-      /* it will be scaled later by the base layer.                        */
-      glyph->linearHoriAdvance = advance;
-    }
+    glyph->linearHoriAdvance = loader->linear;
 
     glyph->metrics.horiBearingX = bbox.xMin;
     glyph->metrics.horiBearingY = bbox.yMax;
@@ -1869,6 +1836,7 @@
   {
     TT_Face    face;
     FT_Stream  stream;
+    FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
 
 
     face   = (TT_Face)glyph->face;
@@ -1887,7 +1855,9 @@
 
       if ( !size->cvt_ready )
       {
-        FT_Error  error = tt_size_ready_bytecode( size );
+        FT_Error  error = tt_size_ready_bytecode( size, pedantic );
+
+
         if ( error )
           return error;
       }
@@ -1917,7 +1887,7 @@
 
         for ( i = 0; i < size->cvt_size; i++ )
           size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
-        tt_size_run_prep( size );
+        tt_size_run_prep( size, pedantic );
       }
 
       /* see whether the cvt program has disabled hinting */
@@ -2047,9 +2017,6 @@
           glyph->linearHoriAdvance = loader.linear;
           glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
                                        loader.vadvance;
-          if ( face->postscript.isFixedPitch                             &&
-               ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
-            glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
         }
 
         return TT_Err_Ok;
diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h
index 958d67d..05f7588 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Glyph Loader (specification).                               */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 by             */
+/*  Copyright 1996-2006, 2008, 2011 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -37,14 +37,12 @@
   FT_LOCAL( void )
   TT_Get_HMetrics( TT_Face     face,
                    FT_UInt     idx,
-                   FT_Bool     check,
                    FT_Short*   lsb,
                    FT_UShort*  aw );
 
   FT_LOCAL( void )
   TT_Get_VMetrics( TT_Face     face,
                    FT_UInt     idx,
-                   FT_Bool     check,
                    FT_Short*   tsb,
                    FT_UShort*  ah );
 
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 47bb9fc..37bbe6d 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -123,7 +123,7 @@
   ft_var_readpackedpoints( FT_Stream  stream,
                            FT_UInt   *point_cnt )
   {
-    FT_UShort *points;
+    FT_UShort *points = NULL;
     FT_Int     n;
     FT_Int     runcnt;
     FT_Int     i;
@@ -622,7 +622,7 @@
     FT_Error             error  = TT_Err_Ok;
     FT_ULong             fvar_start;
     FT_Int               i, j;
-    FT_MM_Var*           mmvar;
+    FT_MM_Var*           mmvar = NULL;
     FT_Fixed*            next_coords;
     FT_String*           next_name;
     FT_Var_Axis*         a;
@@ -1325,7 +1325,7 @@
     FT_Stream   stream = face->root.stream;
     FT_Memory   memory = stream->memory;
     GX_Blend    blend  = face->blend;
-    FT_Vector*  delta_xy;
+    FT_Vector*  delta_xy = NULL;
 
     FT_Error    error;
     FT_ULong    glyph_start;
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index f55b8ee..6c4eed6 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010                                                         */
+/*  Copyright 1996-2011                                                    */
 /*  by David Turner, Robert Wilhelm, and Werner Lemberg.                   */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +16,10 @@
 /***************************************************************************/
 
 
+/* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */
+/* issues; many thanks!                                                */
+
+
 #include <ft2build.h>
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_CALC_H
@@ -665,9 +668,9 @@
     FT_Int  i;
 
 
-    /* XXXX: Will probably disappear soon with all the code range */
-    /*       management, which is now rather obsolete.            */
-    /*                                                            */
+    /* XXX: Will probably disappear soon with all the code range */
+    /*      management, which is now rather obsolete.            */
+    /*                                                           */
     size->num_function_defs    = exec->numFDefs;
     size->num_instruction_defs = exec->numIDefs;
 
@@ -986,8 +989,8 @@
     /*  INS_$83   */  PACK( 0, 0 ),
     /*  INS_$84   */  PACK( 0, 0 ),
     /*  ScanCTRL  */  PACK( 1, 0 ),
-    /*  SDVPTL[0] */  PACK( 2, 0 ),
-    /*  SDVPTL[1] */  PACK( 2, 0 ),
+    /*  SDPVTL[0] */  PACK( 2, 0 ),
+    /*  SDPVTL[1] */  PACK( 2, 0 ),
     /*  GetINFO   */  PACK( 1, 1 ),
     /*  IDEF      */  PACK( 1, 0 ),
     /*  ROLL      */  PACK( 3, 3 ),
@@ -2842,6 +2845,17 @@
     A = p1->x - p2->x;
     B = p1->y - p2->y;
 
+    /* If p1 == p2, SPVTL and SFVTL behave the same as */
+    /* SPVTCA[X] and SFVTCA[X], respectively.          */
+    /*                                                 */
+    /* Confirmed by Greg Hitchcock.                    */
+
+    if ( A == 0 && B == 0 )
+    {
+      A    = 0x4000;
+      aOpc = 0;
+    }
+
     if ( ( aOpc & 1 ) != 0 )
     {
       C =  B;   /* counter clockwise rotation */
@@ -3167,44 +3181,54 @@
     args[0] = CUR.top;
 
 
-#define DO_CINDEX                           \
-  {                                         \
-    FT_Long  L;                             \
-                                            \
-                                            \
-    L = args[0];                            \
-                                            \
-    if ( L <= 0 || L > CUR.args )           \
-      CUR.error = TT_Err_Invalid_Reference; \
-    else                                    \
-      args[0] = CUR.stack[CUR.args - L];    \
+#define DO_CINDEX                             \
+  {                                           \
+    FT_Long  L;                               \
+                                              \
+                                              \
+    L = args[0];                              \
+                                              \
+    if ( L <= 0 || L > CUR.args )             \
+    {                                         \
+      if ( CUR.pedantic_hinting )             \
+        CUR.error = TT_Err_Invalid_Reference; \
+      args[0] = 0;                            \
+    }                                         \
+    else                                      \
+      args[0] = CUR.stack[CUR.args - L];      \
   }
 
 
-#define DO_JROT                          \
-    if ( args[1] != 0 )                  \
-    {                                    \
-      CUR.IP      += args[0];            \
-      if ( CUR.IP < 0 )                  \
-        CUR.error = TT_Err_Bad_Argument; \
-      CUR.step_ins = FALSE;              \
+#define DO_JROT                            \
+    if ( args[1] != 0 )                    \
+    {                                      \
+      if ( args[0] == 0 && CUR.args == 0 ) \
+        CUR.error = TT_Err_Bad_Argument;   \
+      CUR.IP += args[0];                   \
+      if ( CUR.IP < 0 )                    \
+        CUR.error = TT_Err_Bad_Argument;   \
+      CUR.step_ins = FALSE;                \
     }
 
 
-#define DO_JMPR                        \
-    CUR.IP      += args[0];            \
-    if ( CUR.IP < 0 )                  \
-      CUR.error = TT_Err_Bad_Argument; \
+#define DO_JMPR                          \
+    if ( args[0] == 0 && CUR.args == 0 ) \
+      CUR.error = TT_Err_Bad_Argument;   \
+    CUR.IP += args[0];                   \
+    if ( CUR.IP < 0 )                    \
+      CUR.error = TT_Err_Bad_Argument;   \
     CUR.step_ins = FALSE;
 
 
-#define DO_JROF                          \
-    if ( args[1] == 0 )                  \
-    {                                    \
-      CUR.IP      += args[0];            \
-      if ( CUR.IP < 0 )                  \
-        CUR.error = TT_Err_Bad_Argument; \
-      CUR.step_ins = FALSE;              \
+#define DO_JROF                            \
+    if ( args[1] == 0 )                    \
+    {                                      \
+      if ( args[0] == 0 && CUR.args == 0 ) \
+        CUR.error = TT_Err_Bad_Argument;   \
+      CUR.IP += args[0];                   \
+      if ( CUR.IP < 0 )                    \
+        CUR.error = TT_Err_Bad_Argument;   \
+      CUR.step_ins = FALSE;                \
     }
 
 
@@ -4386,17 +4410,19 @@
 
     if ( L <= 0 || L > CUR.args )
     {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
     }
+    else
+    {
+      K = CUR.stack[CUR.args - L];
 
-    K = CUR.stack[CUR.args - L];
+      FT_ARRAY_MOVE( &CUR.stack[CUR.args - L    ],
+                     &CUR.stack[CUR.args - L + 1],
+                     ( L - 1 ) );
 
-    FT_ARRAY_MOVE( &CUR.stack[CUR.args - L    ],
-                   &CUR.stack[CUR.args - L + 1],
-                   ( L - 1 ) );
-
-    CUR.stack[CUR.args - 1] = K;
+      CUR.stack[CUR.args - 1] = K;
+    }
   }
 
 
@@ -5039,12 +5065,8 @@
     if ( BOUNDSL( L, CUR.zp2.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-      {
         CUR.error = TT_Err_Invalid_Reference;
-        return;
-      }
-      else
-        R = 0;
+      R = 0;
     }
     else
     {
@@ -5088,8 +5110,8 @@
 
     CUR_Func_move( &CUR.zp2, L, args[1] - K );
 
-    /* not part of the specs, but here for safety */
-
+    /* UNDOCUMENTED!  The MS rasterizer does that with */
+    /* twilight points (confirmed by Greg Hitchcock)   */
     if ( CUR.GS.gep2 == 0 )
       CUR.zp2.org[L] = CUR.zp2.cur[L];
   }
@@ -5124,10 +5146,7 @@
          BOUNDS( K, CUR.zp1.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-      {
         CUR.error = TT_Err_Invalid_Reference;
-        return;
-      }
       D = 0;
     }
     else
@@ -5173,7 +5192,8 @@
   Ins_SDPVTL( INS_ARG )
   {
     FT_Long    A, B, C;
-    FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */
+    FT_UShort  p1, p2;            /* was FT_Int in pas type ERROR */
+    FT_Int     aOpc = CUR.opcode;
 
 
     p1 = (FT_UShort)args[1];
@@ -5194,9 +5214,20 @@
 
       A = v1->x - v2->x;
       B = v1->y - v2->y;
+
+      /* If v1 == v2, SDPVTL behaves the same as */
+      /* SVTCA[X], respectively.                 */
+      /*                                         */
+      /* Confirmed by Greg Hitchcock.            */
+
+      if ( A == 0 && B == 0 )
+      {
+        A    = 0x4000;
+        aOpc = 0;
+      }
     }
 
-    if ( ( CUR.opcode & 1 ) != 0 )
+    if ( ( aOpc & 1 ) != 0 )
     {
       C =  B;   /* counter clockwise rotation */
       B =  A;
@@ -5214,7 +5245,7 @@
       B = v1->y - v2->y;
     }
 
-    if ( ( CUR.opcode & 1 ) != 0 )
+    if ( ( aOpc & 1 ) != 0 )
     {
       C =  B;   /* counter clockwise rotation */
       B =  A;
@@ -5465,8 +5496,9 @@
 
     if ( CUR.top < CUR.GS.loop )
     {
-      CUR.error = TT_Err_Too_Few_Arguments;
-      return;
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Too_Few_Arguments;
+      goto Fail;
     }
 
     while ( CUR.GS.loop > 0 )
@@ -5489,6 +5521,7 @@
       CUR.GS.loop--;
     }
 
+  Fail:
     CUR.GS.loop = 1;
     CUR.new_top = CUR.args;
   }
@@ -5676,8 +5709,9 @@
 
     if ( CUR.top < CUR.GS.loop )
     {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      goto Fail;
     }
 
     if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
@@ -5697,12 +5731,12 @@
         }
       }
       else
-        /* XXX: UNDOCUMENTED! SHP touches the points */
         MOVE_Zp2_Point( point, dx, dy, TRUE );
 
       CUR.GS.loop--;
     }
 
+  Fail:
     CUR.GS.loop = 1;
     CUR.new_top = CUR.args;
   }
@@ -5757,7 +5791,6 @@
         last_point = 0;
     }
 
-    /* XXX: UNDOCUMENTED! SHC touches the points */
     for ( i = first_point; i <= last_point; i++ )
     {
       if ( zp.cur != CUR.zp2.cur || refp != i )
@@ -5837,8 +5870,9 @@
 
     if ( CUR.top < CUR.GS.loop + 1 )
     {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      goto Fail;
     }
 
 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
@@ -5882,6 +5916,7 @@
       CUR.GS.loop--;
     }
 
+  Fail:
     CUR.GS.loop = 1;
     CUR.new_top = CUR.args;
   }
@@ -5910,9 +5945,9 @@
       return;
     }
 
-    /* XXX: UNDOCUMENTED! behaviour */
-    if ( CUR.GS.gep1 == 0 )   /* if the point that is to be moved */
-                              /* is in twilight zone              */
+    /* UNDOCUMENTED!  The MS rasterizer does that with */
+    /* twilight points (confirmed by Greg Hitchcock)   */
+    if ( CUR.GS.gep1 == 0 )
     {
       CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
       CUR_Func_move_orig( &CUR.zp1, point, args[1] );
@@ -5955,8 +5990,6 @@
       return;
     }
 
-    /* XXX: Is there some undocumented feature while in the */
-    /*      twilight zone? ?                                */
     if ( ( CUR.opcode & 1 ) != 0 )
     {
       cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
@@ -5996,37 +6029,37 @@
     {
       if ( CUR.pedantic_hinting )
         CUR.error = TT_Err_Invalid_Reference;
-      return;
+      goto Fail;
     }
 
-    /* XXX: UNDOCUMENTED!                                */
-    /*                                                   */
-    /* The behaviour of an MIAP instruction is quite     */
-    /* different when used in the twilight zone.         */
-    /*                                                   */
-    /* First, no control value cut-in test is performed  */
-    /* as it would fail anyway.  Second, the original    */
-    /* point, i.e. (org_x,org_y) of zp0.point, is set    */
-    /* to the absolute, unrounded distance found in      */
-    /* the CVT.                                          */
-    /*                                                   */
-    /* This is used in the CVT programs of the Microsoft */
-    /* fonts Arial, Times, etc., in order to re-adjust   */
-    /* some key font heights.  It allows the use of the  */
-    /* IP instruction in the twilight zone, which        */
-    /* otherwise would be `illegal' according to the     */
-    /* specification.                                    */
-    /*                                                   */
-    /* We implement it with a special sequence for the   */
-    /* twilight zone.  This is a bad hack, but it seems  */
-    /* to work.                                          */
+    /* UNDOCUMENTED!                                                      */
+    /*                                                                    */
+    /* The behaviour of an MIAP instruction is quite different when used  */
+    /* in the twilight zone.                                              */
+    /*                                                                    */
+    /* First, no control value cut-in test is performed as it would fail  */
+    /* anyway.  Second, the original point, i.e. (org_x,org_y) of         */
+    /* zp0.point, is set to the absolute, unrounded distance found in the */
+    /* CVT.                                                               */
+    /*                                                                    */
+    /* This is used in the CVT programs of the Microsoft fonts Arial,     */
+    /* Times, etc., in order to re-adjust some key font heights.  It      */
+    /* allows the use of the IP instruction in the twilight zone, which   */
+    /* otherwise would be invalid according to the specification.         */
+    /*                                                                    */
+    /* We implement it with a special sequence for the twilight zone.     */
+    /* This is a bad hack, but it seems to work.                          */
+    /*                                                                    */
+    /* Confirmed by Greg Hitchcock.                                       */
 
     distance = CUR_Func_read_cvt( cvtEntry );
 
     if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
     {
-      CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x );
-      CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ),
+      CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
+                                          CUR.GS.freeVector.x );
+      CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance,
+                                          CUR.GS.freeVector.y ),
       CUR.zp0.cur[point]   = CUR.zp0.org[point];
     }
 
@@ -6042,6 +6075,7 @@
 
     CUR_Func_move( &CUR.zp0, point, distance - org_dist );
 
+  Fail:
     CUR.GS.rp0 = point;
     CUR.GS.rp1 = point;
   }
@@ -6067,7 +6101,7 @@
     {
       if ( CUR.pedantic_hinting )
         CUR.error = TT_Err_Invalid_Reference;
-      return;
+      goto Fail;
     }
 
     /* XXX: Is there some undocumented feature while in the */
@@ -6152,6 +6186,7 @@
 
     CUR_Func_move( &CUR.zp1, point, distance - org_dist );
 
+  Fail:
     CUR.GS.rp1 = CUR.GS.rp0;
     CUR.GS.rp2 = point;
 
@@ -6189,7 +6224,7 @@
     {
       if ( CUR.pedantic_hinting )
         CUR.error = TT_Err_Invalid_Reference;
-      return;
+      goto Fail;
     }
 
     if ( !cvtEntry )
@@ -6208,19 +6243,17 @@
         cvt_dist = -CUR.GS.single_width_value;
     }
 
-    /* XXX: UNDOCUMENTED! -- twilight zone */
-
+    /* UNDOCUMENTED!  The MS rasterizer does that with */
+    /* twilight points (confirmed by Greg Hitchcock)   */
     if ( CUR.GS.gep1 == 0 )
     {
       CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
                              TT_MulFix14( (FT_UInt32)cvt_dist,
                                           CUR.GS.freeVector.x );
-
       CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
                              TT_MulFix14( (FT_UInt32)cvt_dist,
                                           CUR.GS.freeVector.y );
-
-      CUR.zp1.cur[point] = CUR.zp0.cur[point];
+      CUR.zp1.cur[point]   = CUR.zp0.cur[point];
     }
 
     org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
@@ -6244,8 +6277,22 @@
       /*      refer to the same zone.                                  */
 
       if ( CUR.GS.gep0 == CUR.GS.gep1 )
-        if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+      {
+        /* XXX: According to Greg Hitchcock, the following wording is */
+        /*      the right one:                                        */
+        /*                                                            */
+        /*        When the absolute difference between the value in   */
+        /*        the table [CVT] and the measurement directly from   */
+        /*        the outline is _greater_ than the cut_in value, the */
+        /*        outline measurement is used.                        */
+        /*                                                            */
+        /*      This is from `instgly.doc'.  The description in       */
+        /*      `ttinst2.doc', version 1.66, is thus incorrect since  */
+        /*      it implies `>=' instead of `>'.                       */
+
+        if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin )
           cvt_dist = org_dist;
+      }
 
       distance = CUR_Func_round(
                    cvt_dist,
@@ -6274,12 +6321,12 @@
 
     CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
 
+  Fail:
     CUR.GS.rp1 = CUR.GS.rp0;
 
     if ( ( CUR.opcode & 16 ) != 0 )
       CUR.GS.rp0 = point;
 
-    /* XXX: UNDOCUMENTED! */
     CUR.GS.rp2 = point;
   }
 
@@ -6304,7 +6351,7 @@
     {
       if ( CUR.pedantic_hinting )
         CUR.error = TT_Err_Invalid_Reference;
-      return;
+      goto Fail;
     }
 
     while ( CUR.GS.loop > 0 )
@@ -6332,6 +6379,7 @@
       CUR.GS.loop--;
     }
 
+  Fail:
     CUR.GS.loop = 1;
     CUR.new_top = CUR.args;
   }
@@ -6473,8 +6521,9 @@
 
     if ( CUR.top < CUR.GS.loop )
     {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      goto Fail;
     }
 
     /*
@@ -6488,7 +6537,7 @@
     {
       if ( CUR.pedantic_hinting )
         CUR.error = TT_Err_Invalid_Reference;
-      return;
+      goto Fail;
     }
 
     if ( twilight )
@@ -6553,6 +6602,8 @@
 
       CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
     }
+
+  Fail:
     CUR.GS.loop = 1;
     CUR.new_top = CUR.args;
   }
@@ -6845,8 +6896,9 @@
 
       if ( CUR.args < n )
       {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Too_Few_Arguments;
+        n = CUR.args;
       }
 
       CUR.args -= n;
@@ -6862,8 +6914,10 @@
     {
       if ( CUR.args < 2 )
       {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Too_Few_Arguments;
+        CUR.args = 0;
+        goto Fail;
       }
 
       CUR.args -= 2;
@@ -6912,6 +6966,7 @@
           CUR.error = TT_Err_Invalid_Reference;
     }
 
+  Fail:
     CUR.new_top = CUR.args;
   }
 
@@ -6939,8 +6994,9 @@
 
       if ( CUR.args < n )
       {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Too_Few_Arguments;
+        n = CUR.args;
       }
 
       CUR.args -= n;
@@ -6955,8 +7011,10 @@
     {
       if ( CUR.args < 2 )
       {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Too_Few_Arguments;
+        CUR.args = 0;
+        goto Fail;
       }
 
       CUR.args -= 2;
@@ -7004,6 +7062,7 @@
       }
     }
 
+  Fail:
     CUR.new_top = CUR.args;
   }
 
@@ -7465,8 +7524,19 @@
       /* One can also interpret it as the index of the last argument.    */
       if ( CUR.args < 0 )
       {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        goto LErrorLabel_;
+        FT_UShort  i;
+
+
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Too_Few_Arguments;
+          goto LErrorLabel_;
+        }
+
+        /* push zeroes onto the stack */
+        for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ )
+          CUR.stack[i] = 0;
+        CUR.args = 0;
       }
 
       CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
@@ -7503,7 +7573,7 @@
         case 0x04:  /* SFvTCA y */
         case 0x05:  /* SFvTCA x */
           {
-            FT_Short AA, BB;
+            FT_Short  AA, BB;
 
 
             AA = (FT_Short)( ( opcode & 1 ) << 14 );
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 8fe86ad..d77c3c4 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    Objects manager (body).                                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2011                                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -214,16 +213,18 @@
   tt_get_sfnt_checksum( TT_Face    face,
                         FT_UShort  i )
   {
+#if 0 /* if we believe the written value, use following part. */
     if ( face->dir_tables[i].CheckSum )
       return face->dir_tables[i].CheckSum;
+#endif
 
-    else if ( !face->goto_table )
+    if ( !face->goto_table )
       return 0;
 
-    else if ( !face->goto_table( face,
-                                 face->dir_tables[i].Tag,
-                                 face->root.stream,
-                                 NULL ) )
+    if ( face->goto_table( face,
+                           face->dir_tables[i].Tag,
+                           face->root.stream,
+                           NULL ) )
       return 0;
 
     return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
@@ -243,7 +244,7 @@
   tt_check_trickyness_sfnt_ids( TT_Face  face )
   {
 #define TRICK_SFNT_IDS_PER_FACE   3
-#define TRICK_SFNT_IDS_NUM_FACES  5
+#define TRICK_SFNT_IDS_NUM_FACES  13
 
     static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
                                        [TRICK_SFNT_IDS_PER_FACE] = {
@@ -276,16 +277,61 @@
         { 0xfffbfffc, 0x00000008 }, /* cvt  */
         { 0x0a5a0483, 0x00017c39 }, /* fpgm */
         { 0x70020112, 0x00000008 }  /* prep */
+      },
+      { /* NEC fadpop7.ttf */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x40c92555, 0x000000e5 }, /* fpgm */
+        { 0xa39b58e3, 0x0000117c }  /* prep */
+      },
+      { /* NEC fadrei5.ttf */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x33c41652, 0x000000e5 }, /* fpgm */
+        { 0x26d6c52a, 0x00000f6a }  /* prep */
+      },
+      { /* NEC fangot7.ttf */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x6db1651d, 0x0000019d }, /* fpgm */
+        { 0x6c6e4b03, 0x00002492 }  /* prep */
+      },
+      { /* NEC fangyo5.ttf */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x40c92555, 0x000000e5 }, /* fpgm */
+        { 0xde51fad0, 0x0000117c }  /* prep */
+      },
+      { /* NEC fankyo5.ttf */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x85e47664, 0x000000e5 }, /* fpgm */
+        { 0xa6c62831, 0x00001caa }  /* prep */
+      },
+      { /* NEC fanrgo5.ttf */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x2d891cfd, 0x0000019d }, /* fpgm */
+        { 0xa0604633, 0x00001de8 }  /* prep */
+      },
+      { /* NEC fangot5.ttc */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x40aa774c, 0x000001cb }, /* fpgm */
+        { 0x9b5caa96, 0x00001f9a }  /* prep */
+      },
+      { /* NEC fanmin3.ttc */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x0d3de9cb, 0x00000141 }, /* fpgm */
+        { 0xd4127766, 0x00002280 }  /* prep */
       }
     };
 
-    FT_ULong  checksum;
-    int       num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
-    int       i, j, k;
+    FT_ULong   checksum;
+    int        num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
+    FT_Bool    has_cvt, has_fpgm, has_prep;
+    FT_UShort  i;
+    int        j, k;
 
 
     FT_MEM_SET( num_matched_ids, 0,
                 sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES );
+    has_cvt  = FALSE;
+    has_fpgm = FALSE;
+    has_prep = FALSE;
 
     for ( i = 0; i < face->num_tables; i++ )
     {
@@ -295,14 +341,17 @@
       {
       case TTAG_cvt:
         k = TRICK_SFNT_ID_cvt;
+        has_cvt  = TRUE;
         break;
 
       case TTAG_fpgm:
         k = TRICK_SFNT_ID_fpgm;
+        has_fpgm = TRUE;
         break;
 
       case TTAG_prep:
         k = TRICK_SFNT_ID_prep;
+        has_prep = TRUE;
         break;
 
       default:
@@ -323,6 +372,18 @@
         }
     }
 
+    for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
+    {
+      if ( !has_cvt  && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
+        num_matched_ids[j] ++;
+      if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
+        num_matched_ids[j] ++;
+      if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
+        num_matched_ids[j] ++;
+      if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
+        return TRUE;
+    }
+
     return FALSE;
   }
 
@@ -333,14 +394,10 @@
     if ( !face )
       return FALSE;
 
-    /* First, check the face name. */
-    if ( face->family_name )
-    {
-      if ( tt_check_trickyness_family( face->family_name ) )
-        return TRUE;
-      else
-        return FALSE;
-    }
+    /* For first, check the face name for quick check. */
+    if ( face->family_name                               &&
+         tt_check_trickyness_family( face->family_name ) )
+      return TRUE;
 
     /* Type42 fonts may lack `name' tables, we thus try to identify */
     /* tricky fonts by checking the checksums of Type42-persistent  */
@@ -352,6 +409,54 @@
   }
 
 
+  /* Check whether `.notdef' is the only glyph in the `loca' table. */
+  static FT_Bool
+  tt_check_single_notdef( FT_Face  ttface )
+  {
+    FT_Bool   result = FALSE;
+
+    TT_Face   face = (TT_Face)ttface;
+    FT_UInt   asize;
+    FT_ULong  i;
+    FT_ULong  glyph_index = 0;
+    FT_UInt   count       = 0;
+
+
+    for( i = 0; i < face->num_locations; i++ )
+    {
+      tt_face_get_location( face, i, &asize );
+      if ( asize > 0 )
+      {
+        count += 1;
+        if ( count > 1 )
+          break;
+        glyph_index = i;
+      }
+    }
+
+    /* Only have a single outline. */
+    if ( count == 1 )
+    {
+      if ( glyph_index == 0 )
+        result = TRUE;
+      else
+      {
+        /* FIXME: Need to test glyphname == .notdef ? */
+        FT_Error error;
+        char buf[8];
+
+
+        error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
+        if ( !error                                            &&
+             buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
+          result = TRUE;
+      }
+    }
+
+    return result;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -447,6 +552,20 @@
       if ( !error )
         error = tt_face_load_prep( face, stream );
 
+      /* Check the scalable flag based on `loca'. */
+      if ( !ttface->internal->incremental_interface &&
+           ttface->num_fixed_sizes                  &&
+           face->glyph_locations                    &&
+           tt_check_single_notdef( ttface )         )
+      {
+        FT_TRACE5(( "tt_face_init:"
+                    " Only the `.notdef' glyph has an outline.\n"
+                    "             "
+                    " Resetting scalable flag to FALSE.\n" ));
+
+        ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+      }
+
 #else
 
       if ( !error )
@@ -458,6 +577,19 @@
       if ( !error )
         error = tt_face_load_prep( face, stream );
 
+      /* Check the scalable flag based on `loca'. */
+      if ( ttface->num_fixed_sizes          &&
+           face->glyph_locations            &&
+           tt_check_single_notdef( ttface ) )
+      {
+        FT_TRACE5(( "tt_face_init:"
+                    " Only the `.notdef' glyph has an outline.\n"
+                    "             "
+                    " Resetting scalable flag to FALSE.\n" ));
+
+        ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+      }
+
 #endif
 
     }
@@ -570,13 +702,16 @@
   /*    Run the font program.                                              */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    size :: A handle to the size object.                               */
+  /*    size     :: A handle to the size object.                           */
+  /*                                                                       */
+  /*    pedantic :: Set if bytecode execution should be pedantic.          */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
-  tt_size_run_fpgm( TT_Size  size )
+  tt_size_run_fpgm( TT_Size  size,
+                    FT_Bool  pedantic )
   {
     TT_Face         face = (TT_Face)size->root.face;
     TT_ExecContext  exec;
@@ -594,15 +729,17 @@
 
     TT_Load_Context( exec, face, size );
 
-    exec->callTop   = 0;
-    exec->top       = 0;
+    exec->callTop = 0;
+    exec->top     = 0;
 
     exec->period    = 64;
     exec->phase     = 0;
     exec->threshold = 0;
 
     exec->instruction_trap = FALSE;
-    exec->F_dot_P = 0x10000L;
+    exec->F_dot_P          = 0x10000L;
+
+    exec->pedantic_hinting = pedantic;
 
     {
       FT_Size_Metrics*  metrics    = &exec->metrics;
@@ -659,13 +796,16 @@
   /*    Run the control value program.                                     */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    size :: A handle to the size object.                               */
+  /*    size     :: A handle to the size object.                           */
+  /*                                                                       */
+  /*    pedantic :: Set if bytecode execution should be pedantic.          */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
-  tt_size_run_prep( TT_Size  size )
+  tt_size_run_prep( TT_Size  size,
+                    FT_Bool  pedantic )
   {
     TT_Face         face = (TT_Face)size->root.face;
     TT_ExecContext  exec;
@@ -688,6 +828,8 @@
 
     exec->instruction_trap = FALSE;
 
+    exec->pedantic_hinting = pedantic;
+
     TT_Set_CodeRange( exec,
                       tt_coderange_cvt,
                       face->cvt_program,
@@ -766,7 +908,8 @@
   /* Initialize bytecode-related fields in the size object.       */
   /* We do this only if bytecode interpretation is really needed. */
   static FT_Error
-  tt_size_init_bytecode( FT_Size  ftsize )
+  tt_size_init_bytecode( FT_Size  ftsize,
+                         FT_Bool  pedantic )
   {
     FT_Error   error;
     TT_Size    size = (TT_Size)ftsize;
@@ -839,7 +982,7 @@
     }
 
     /* Fine, now run the font program! */
-    error = tt_size_run_fpgm( size );
+    error = tt_size_run_fpgm( size, pedantic );
 
   Exit:
     if ( error )
@@ -850,14 +993,15 @@
 
 
   FT_LOCAL_DEF( FT_Error )
-  tt_size_ready_bytecode( TT_Size  size )
+  tt_size_ready_bytecode( TT_Size  size,
+                          FT_Bool  pedantic )
   {
     FT_Error  error = TT_Err_Ok;
 
 
     if ( !size->bytecode_ready )
     {
-      error = tt_size_init_bytecode( (FT_Size)size );
+      error = tt_size_init_bytecode( (FT_Size)size, pedantic );
       if ( error )
         goto Exit;
     }
@@ -889,7 +1033,7 @@
 
       size->GS = tt_default_graphics_state;
 
-      error = tt_size_run_prep( size );
+      error = tt_size_run_prep( size, pedantic );
       if ( !error )
         size->cvt_ready = 1;
     }
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 30c8669..087b3c2 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/*  Copyright 1996-2009, 2011 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -390,13 +390,16 @@
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
   FT_LOCAL( FT_Error )
-  tt_size_run_fpgm( TT_Size  size );
+  tt_size_run_fpgm( TT_Size  size,
+                    FT_Bool  pedantic );
 
   FT_LOCAL( FT_Error )
-  tt_size_run_prep( TT_Size  size );
+  tt_size_run_prep( TT_Size  size,
+                    FT_Bool  pedantic );
 
   FT_LOCAL( FT_Error )
-  tt_size_ready_bytecode( TT_Size  size );
+  tt_size_ready_bytecode( TT_Size  size,
+                          FT_Bool  pedantic );
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
 
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index 68a5453..818b29d 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType-specific tables loader (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/*  Copyright 1996-2002, 2004-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -110,15 +110,16 @@
       face->num_locations = table_len >> shift;
     }
 
-    if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
+    if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
     {
       FT_TRACE2(( "glyph count mismatch!  loca: %d, maxp: %d\n",
-                  face->num_locations, face->root.num_glyphs ));
+                  face->num_locations - 1, face->root.num_glyphs ));
 
       /* we only handle the case where `maxp' gives a larger value */
-      if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
+      if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
       {
-        FT_Long   new_loca_len = (FT_Long)face->root.num_glyphs << shift;
+        FT_Long   new_loca_len =
+                    ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
 
         TT_Table  entry = face->dir_tables;
         TT_Table  limit = entry + face->num_tables;
@@ -145,7 +146,7 @@
 
         if ( new_loca_len <= dist )
         {
-          face->num_locations = face->root.num_glyphs;
+          face->num_locations = face->root.num_glyphs + 1;
           table_len           = new_loca_len;
 
           FT_TRACE2(( "adjusting num_locations to %d\n",