shithub: freetype+ttf2subf

Download patch

ref: 00d9f40cf7ec068286792eb352971cd7ed53fc73
parent: 6b5c669b7b300ef3dea4ad956885d0d5f5a25920
author: David Turner <[email protected]>
date: Sun Sep 8 17:29:11 EDT 2002

* src/smooth/ftsmooth.c, src/base/ftobjs.c,
        include/freetype/config/ftmodule.h: updated to correctly support
        sub-pixel rendering

        * include/freetype/cache/ftcimage.h, include/freetype/cache/ftcsbits.h,
        src/cache/ftcimage.c, src/cache/ftcsbit.c: updated to support sub-pixel
        rendering correctly. Definition of FTC_ImageTypeRec that replaces the
        obsolete FTC_ImageDesc, and has slightly different fields. The
        image type is now determined directly by "load_flags" values.

        * src/autohint/ahtypes.h, src/autohint/ahhint.c,
        src/pshinter/pshalgo3.c, src/pshinter/pshalgo3.h: various enhancements
        to the automatic and Postscript hinters !! and sub-pixel hinting now
        works correctly (see demo programs)

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2002-09-08  David Turner  <[email protected]>
+
+        * src/smooth/ftsmooth.c, src/base/ftobjs.c,
+        include/freetype/config/ftmodule.h: updated to correctly support
+        sub-pixel rendering
+
+        * include/freetype/cache/ftcimage.h, include/freetype/cache/ftcsbits.h,
+        src/cache/ftcimage.c, src/cache/ftcsbit.c: updated to support sub-pixel
+        rendering correctly. Definition of FTC_ImageTypeRec that replaces the
+        obsolete FTC_ImageDesc, and has slightly different fields. The
+        image type is now determined directly by "load_flags" values.
+
+        * src/autohint/ahtypes.h, src/autohint/ahhint.c,
+        src/pshinter/pshalgo3.c, src/pshinter/pshalgo3.h: various enhancements
+        to the automatic and Postscript hinters !! and sub-pixel hinting now
+        works correctly (see demo programs)
+
 2002-09-05  Werner Lemberg  <[email protected]>
 
 	* src/cid/cidobjs.c (CID_Size_Init): Renamed to...
--- a/include/freetype/cache/ftcimage.h
+++ b/include/freetype/cache/ftcimage.h
@@ -53,65 +53,43 @@
   /*************************************************************************/
 
 
-#define FTC_IMAGE_FORMAT( x )  ( (x) & 7 )
 
 
-#define ftc_image_format_bitmap    0x0000
-#define ftc_image_format_outline   0x0001
-
-#define ftc_image_format_mask      0x000F
-
-#define ftc_image_flag_monochrome  0x0010
-#define ftc_image_flag_unhinted    0x0020
-#define ftc_image_flag_autohinted  0x0040
-#define ftc_image_flag_unscaled    0x0080
-#define ftc_image_flag_no_sbits    0x0100
-
-  /* monochrome bitmap */
-#define ftc_image_mono             ftc_image_format_bitmap | \
-                                   ftc_image_flag_monochrome
-
-  /* anti-aliased bitmap */
-#define ftc_image_grays            ftc_image_format_bitmap
-
-  /* scaled outline */
-#define ftc_image_outline          ftc_image_format_outline
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Struct>                                                              */
-  /*    FTC_ImageDesc                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A simple structure used to describe a given glyph image category.  */
-  /*    Note that this is different from @FTC_Image_Desc.                  */
-  /*                                                                       */
-  /* <Fields>                                                              */
-  /*    size    :: An @FTC_SizeRec used to describe the glyph's face and   */
-  /*               size.                                                   */
-  /*                                                                       */
-  /*    type    :: The glyph image's type.  Note that it is a 32-bit uint. */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    This type deprecates @FTC_Image_Desc.                              */
-  /*                                                                       */
-  typedef struct  FTC_ImageDesc_
+ /**************************************************************************
+  *
+  * @struct: FTC_ImageTypeRec
+  *
+  * @description:
+  *   a simple structure used to describe the type of glyph image to be
+  *   loaded into the cache
+  *
+  * @fields:
+  *   font  :: An @FTC_FontRec used to describe the glyph's face and size
+  *   flags :: the load flags to be applied when loading the glyph, see
+  *            the @FT_LOAD_XXX constants for details
+  *
+  * @note:
+  *   this type completely replaces the @FTC_Image_Desc structure which is
+  *   now obsolete..
+  */
+  typedef struct  FTC_ImageTypeRec_
   {
     FTC_FontRec  font;
-    FT_UInt32    type;
+    FT_Int32     flags;
 
-  } FTC_ImageDesc;
+  } FTC_ImageTypeRec;
 
+  typedef struct FTC_ImageTypeRec_*   FTC_ImageType;
+
  /* */
 
-#define FTC_IMAGE_DESC_COMPARE( d1, d2 )                    \
+#define FTC_IMAGE_TYPE_COMPARE( d1, d2 )                    \
           ( FTC_FONT_COMPARE( &(d1)->font, &(d2)->font ) && \
-            (d1)->type == (d2)->type                     )
+            (d1)->flags == (d2)->flags                      )
 
-#define FTC_IMAGE_DESC_HASH( d )                    \
+#define FTC_IMAGE_TYPE_HASH( d )                    \
           (FT_UFast)( FTC_FONT_HASH( &(d)->font ) ^ \
-                      ( (d)->type << 4 )          )
+                      ( (d)->flags << 4 )           )
 
 
   /*************************************************************************/
@@ -160,7 +138,7 @@
   /* <Input>                                                               */
   /*    cache  :: A handle to the source glyph image cache.                */
   /*                                                                       */
-  /*    desc   :: A pointer to a glyph image descriptor.                   */
+  /*    type   :: A pointer to a glyph image type descriptor.              */
   /*                                                                       */
   /*    gindex :: The glyph index to retrieve.                             */
   /*                                                                       */
@@ -193,7 +171,7 @@
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FTC_ImageCache_Lookup( FTC_ImageCache  cache,
-                         FTC_ImageDesc*  desc,
+                         FTC_ImageType   type,
                          FT_UInt         gindex,
                          FT_Glyph       *aglyph,
                          FTC_Node       *anode );
@@ -200,6 +178,29 @@
 
   /* */
 
+#define ftc_image_format( x )  ( (x) & 7 )
+
+
+#define ftc_image_format_bitmap    0x0000
+#define ftc_image_format_outline   0x0001
+
+#define ftc_image_format_mask      0x000F
+
+#define ftc_image_flag_monochrome  0x0010
+#define ftc_image_flag_unhinted    0x0020
+#define ftc_image_flag_autohinted  0x0040
+#define ftc_image_flag_unscaled    0x0080
+#define ftc_image_flag_no_sbits    0x0100
+
+  /* monochrome bitmap */
+#define ftc_image_mono             ftc_image_format_bitmap | \
+                                   ftc_image_flag_monochrome
+
+  /* anti-aliased bitmap */
+#define ftc_image_grays            ftc_image_format_bitmap
+
+  /* scaled outline */
+#define ftc_image_outline          ftc_image_format_outline
 
   /*************************************************************************/
   /*                                                                       */
--- a/include/freetype/cache/ftcsbits.h
+++ b/include/freetype/cache/ftcsbits.h
@@ -72,7 +72,7 @@
   /*                                                                       */
   /*    format    :: The format of the glyph bitmap (monochrome or gray).  */
   /*                                                                       */
-  /*    num_grays :: The number of gray levels.                            */
+  /*    max_grays :: maximum gray level value, from 1 to 255               */
   /*                                                                       */
   /*    pitch     :: The number of bytes per bitmap line.  May be positive */
   /*                 or negative.                                          */
@@ -91,8 +91,8 @@
     FT_Char   top;
 
     FT_Byte   format;
-    FT_Short  num_grays;    /* XXX: Should be FT_Byte.  See ftcsbits.c */
-    FT_Char   pitch;
+    FT_Byte   max_grays;
+    FT_Short  pitch;
     FT_Char   xadvance;
     FT_Char   yadvance;
 
@@ -113,8 +113,8 @@
   /*    implemented by @FTC_ImageCache.                                    */
   /*                                                                       */
   typedef struct FTC_SBitCacheRec_*  FTC_SBitCache;
-  
 
+
   /*************************************************************************/
   /*                                                                       */
   /* <Type>                                                                */
@@ -160,7 +160,7 @@
   /* <Input>                                                               */
   /*    cache  :: A handle to the source sbit cache.                       */
   /*                                                                       */
-  /*    desc   :: A pointer to the glyph image descriptor.                 */
+  /*    type   :: A pointer to the glyph image type descriptor.            */
   /*                                                                       */
   /*    gindex :: The glyph index.                                         */
   /*                                                                       */
@@ -195,7 +195,7 @@
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FTC_SBitCache_Lookup( FTC_SBitCache    cache,
-                        FTC_ImageDesc*   desc,
+                        FTC_ImageType    type,
                         FT_UInt          gindex,
                         FTC_SBit        *sbit,
                         FTC_Node        *anode );
--- a/include/freetype/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -9,6 +9,8 @@
 FT_USE_MODULE(ft_raster1_renderer_class)
 FT_USE_MODULE(sfnt_module_class)
 FT_USE_MODULE(ft_smooth_renderer_class)
+FT_USE_MODULE(ft_smooth_lcd_renderer_class)
+FT_USE_MODULE(ft_smooth_lcdv_renderer_class)
 FT_USE_MODULE(tt_driver_class)
 FT_USE_MODULE(t1_driver_class)
 FT_USE_MODULE(t42_driver_class)
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -2009,201 +2009,146 @@
                 FT_Int32  load_flags );
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_NO_SCALE                                                   */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the vector outline being loaded should not be scaled to 26.6       */
-  /*    fractional pixels, but kept in notional units.                     */
-  /*                                                                       */
-#define FT_LOAD_NO_SCALE  0x1
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_NO_HINTING                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the vector outline being loaded should not be fitted to the pixel  */
-  /*    grid but simply scaled to 26.6 fractional pixels.                  */
-  /*                                                                       */
-  /*    This flag is ignored if FT_LOAD_NO_SCALE is set.                   */
-  /*                                                                       */
-#define FT_LOAD_NO_HINTING  0x2
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_RENDER                                                     */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the function should load the glyph and immediately convert it into */
-  /*    a bitmap, if necessary, by calling @FT_Render_Glyph.               */
-  /*                                                                       */
-  /*    Note that by default, @FT_Load_Glyph loads the glyph image in its  */
-  /*    native format.                                                     */
-  /*                                                                       */
-#define FT_LOAD_RENDER  0x4
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_NO_BITMAP                                                  */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the function should not load the bitmap or pixmap of a given       */
-  /*    glyph.  This is useful when you do not want to load the embedded   */
-  /*    bitmaps of scalable formats, as the native glyph image will be     */
-  /*    loaded, and can then be rendered through @FT_Render_Glyph.         */
-  /*                                                                       */
-#define FT_LOAD_NO_BITMAP  0x8
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_VERTICAL_LAYOUT                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the glyph image should be prepared for vertical layout.  This      */
-  /*    basically means that `face.glyph.advance' will correspond to the   */
-  /*    vertical advance height (instead of the default horizontal         */
-  /*    advance width), and that the glyph image will translated to match  */
-  /*    the vertical bearings positions.                                   */
-  /*                                                                       */
-#define FT_LOAD_VERTICAL_LAYOUT  0x10
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_FORCE_AUTOHINT                                             */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the function should try to auto-hint the glyphs, even if a driver  */
-  /*    specific hinter is available.                                      */
-  /*                                                                       */
-  /*    Note that it is ignored if @FT_LOAD_NO_AUTOHINT is also set.       */
-  /*                                                                       */
-#define FT_LOAD_FORCE_AUTOHINT  0x20
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_CROP_BITMAP                                                */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the font driver should try to crop the bitmap (i.e. remove all     */
-  /*    space around its black bits) when loading it.  For now, this       */
-  /*    really only works with embedded bitmaps in TrueType fonts.         */
-  /*                                                                       */
-#define FT_LOAD_CROP_BITMAP  0x40
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_PEDANTIC                                                   */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the glyph loader should perform a pedantic bytecode                */
-  /*    interpretation.  Many popular fonts come with broken glyph         */
-  /*    programs.  When this flag is set, loading them will return an      */
-  /*    error.  Otherwise, errors are ignored by the loader, sometimes     */
-  /*    resulting in ugly glyphs.                                          */
-  /*                                                                       */
-#define FT_LOAD_PEDANTIC  0x80
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH                                */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the glyph loader should ignore the global advance width defined    */
-  /*    in the font.  As far as we know, this is only used by the          */
-  /*    X-TrueType font server, in order to deal correctly with the        */
-  /*    incorrect metrics contained in DynaLab's TrueType CJK fonts.       */
-  /*                                                                       */
+/****************************************************************************
+ *
+ * @enum: FT_LOAD_XXX
+ *
+ * @description:
+ *   a list of bit-field constants, used with @FT_Load_Glyph to indicate
+ *   what kind of operations to perform during glyph loading
+ *
+ * @values:
+ *   FT_LOAD_DEFAULT ::
+ *     corresponding to 0, this value is used a default glyph load. In this
+ *     case, the following will happen:
+ *
+ *     1/ FreeType will look for a bitmap for the glyph corresponding to
+ *        the face's current size. If one is found, the function returns.
+ *        the bitmap data can be accessed from the glyph slot (see note
+ *        below)
+ *
+ *     2/ If no embedded bitmap is searched or found, FreeType looks for
+ *        a scalable outline. If one is found, it is loaded from the font
+ *        file, scaled to device pixels, then "hinted" to the pixel grid
+ *        in order to optimize it. the outline data can be accessed from
+ *        the glyph slot (see note below)
+ *
+ *     Note that by default, the glyph loader doesn't render outlines into
+ *     bitmaps. the following flags are used to modify this default behaviour
+ *     to more specific and useful cases.
+ *
+ *   FT_LOAD_NO_SCALE ::
+ *     indicates that the vector outline being loaded should not be scaled
+ *     to 26.6 fractional pixels, but kept in font units. Note that this
+ *     also disables hinting and the loading of embedded bitmaps. You should
+ *     only use it when you want to retrieve the original glyph outlines
+ *     in font units.
+ *
+ *   FT_LOAD_NO_HINTING ::
+ *     indicates that the glyph outlines should not be hinted after their
+ *     scaling to device pixels. This generally generates "blurrier" glyphs
+ *     in anti-aliased modes.
+ *
+ *     this flag is ignored if @FT_LOAD_NO_SCALE is set
+ *
+ *   FT_LOAD_RENDER ::
+ *     indicates that the glyph outline should be rendered immediately into
+ *     a bitmap before the glyph loader returns. By default, the glyph is
+ *     rendered for the @FT_RENDER_MODE_NORMAL mode, which corresponds to
+ *     8-bit anti-aliased bitmaps using 256 opacity levels. You can use
+ *     either @FT_LOAD_TARGET_MONO or @FT_LOAD_MONOCHROME to render
+ *     1-bit monochrome bitmaps
+ *
+ *     This flag is ignored if @FT_LOAD_NO_SCALE is set
+ *
+ *
+ *   FT_LOAD_NO_BITMAP ::
+ *     indicates that you do not want to look for bitmaps when loading
+ *     the glyph. Only scalable outlines will be loaded when available,
+ *     and scaled/hinted/rendered depending on other bit flags
+ *
+ *     this does not prevent you from rendering outlines to bitmaps
+ *     with @FT_LOAD_RENDER however.
+ *
+ *   FT_LOAD_VERTICAL_LAYOUT:
+ *     indicates that the glyph image should be prepared for vertical
+ *     text layout. This basically means that 'face.glyph.advance' will
+ *     correspond to the vertical advance height (instead of the default
+ *     horizontal advance width), and that the glyph image will be
+ *     translated to match the vertical bearings positions
+ *
+ *   FT_LOAD_FORCE_AUTOHINT ::
+ *     indicates that you want to force the use of the FreeType auto-hinter
+ *     when a glyph outline is loaded. You shouldn't need this in a typical
+ *     application, since it's mostly used to experiment with its algorithm
+ *
+ *   FT_LOAD_CROP_BITMAP ::
+ *     indicates that the glyph loader should try to crop the bitmap (i.e.
+ *     remove all space around its black bits) when loading it. This is
+ *     only useful when loading embedded bitmaps in certain fonts, since
+ *     bitmaps rendered with @FT_LOAD_RENDER are always cropped by default
+ *
+ *   FT_LOAD_PEDANTIC ::
+ *     indicates that the glyph loader should perform pedantic verifications
+ *     during glyph loading. This is mostly used to detect broken glyphs in
+ *     fonts. By default, FreeType will always try to deal with such cases.
+ *
+ *   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
+ *     indicates that the glyph loader should ignore the global advance
+ *     width defined in the font. As far as we know, this is only used by the
+ *     X-TrueType font server, in order to deal correctly with the incorrect
+ *     metrics contained in DynaLab's TrueType CJK fonts.
+ *
+ *   FT_LOAD_NO_RECURSE ::
+ *     this flag is only used internally. It merely indicates that the glyph
+ *     loader should not load composite glyphs recursively. Instead, it should
+ *     set the 'num_subglyph' and 'subglyphs' values of the glyph slot
+ *     accordingly, and set "glyph->format" to @FT_GLYPH_FORMAT_COMPOSITE
+ *
+ *     the description of sub-glyphs is not available to client applications
+ *     for now
+ *
+ *   FT_LOAD_IGNORE_TRANSFORM ::
+ *     indicates that the glyph loader should not try to transform the
+ *     loaded glyph image. This doesn't prevent scaling/hinting/rendering
+ *
+ *   FT_LOAD_MONOCHROME ::
+ *     this flag is used with @FT_LOAD_RENDER to indicate that you want
+ *     to render a 1-bit monochrome glyph bitmap from a vectorial outline.
+ *
+ *     note that this has no effect on the hinting algorithm used by the
+ *     glyph loader. You'd better use @FT_LOAD_TARGET_MONO if you want to
+ *     render monochrome-optimized glyph images instead.
+ *
+ *   FT_LOAD_LINEAR_DESIGN ::
+ *     indicates that the function should return the linearly scaled metrics
+ *     expressed in original font units, instead of the default 16.16 pixel
+ *     values
+ *
+ *   FT_LOAD_NO_AUTOHINT ::
+ *     indicates that the auto-hinter should never be used to hint glyph
+ *     outlines. This doesn't prevent native format-specific hinters from
+ *     being used. This can be important for certain fonts where un-hinted
+ *     output is better than auto-hinted one.
+ *
+ *
+ *
+ *
+ *
+ */
+#define FT_LOAD_NO_SCALE                     0x1
+#define FT_LOAD_NO_HINTING                   0x2
+#define FT_LOAD_RENDER                       0x4
+#define FT_LOAD_NO_BITMAP                    0x8
+#define FT_LOAD_VERTICAL_LAYOUT              0x10
+#define FT_LOAD_FORCE_AUTOHINT               0x20
+#define FT_LOAD_CROP_BITMAP                  0x40
+#define FT_LOAD_PEDANTIC                     0x80
 #define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH  0x200
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_NO_RECURSE                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the glyph loader should not load composite glyph recursively.      */
-  /*    Rather, when a composite glyph is encountered, it should set       */
-  /*    the values of `num_subglyphs' and `subglyphs', as well as set      */
-  /*    `face->glyph.format' to FT_GLYPH_FORMAT_COMPOSITE.                 */
-  /*                                                                       */
-  /*    This is for use by the auto-hinter and possibly other tools.       */
-  /*    For nearly all applications, this flags should be left unset       */
-  /*    when invoking @FT_Load_Glyph.                                      */
-  /*                                                                       */
-  /*    Note that the flag forces the load of unscaled glyphs.             */
-  /*                                                                       */
-#define FT_LOAD_NO_RECURSE  0x400
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_IGNORE_TRANSFORM                                           */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the glyph loader should not try to transform the loaded glyph      */
-  /*    image.                                                             */
-  /*                                                                       */
-#define FT_LOAD_IGNORE_TRANSFORM  0x800
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_MONOCHROME                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Only used with FT_LOAD_RENDER set, it indicates that the returned  */
-  /*    glyph image should be 1-bit monochrome.  This really tells the     */
-  /*    glyph loader to use `FT_RENDER_MODE_MONO' when calling             */
-  /*    @FT_Render_Glyph.                                                  */
-  /*                                                                       */
+#define FT_LOAD_NO_RECURSE                   0x400
+#define FT_LOAD_IGNORE_TRANSFORM             0x800
 #define FT_LOAD_MONOCHROME  0x1000
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Constant>                                                            */
-  /*    FT_LOAD_LINEAR_DESIGN                                              */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A bit-field constant, used with @FT_Load_Glyph to indicate that    */
-  /*    the function should return the linearly scaled metrics expressed   */
-  /*    in original font units, instead of the default 16.16 pixel values. */
-  /*                                                                       */
 #define FT_LOAD_LINEAR_DESIGN  0x2000
-
 
   /* temporary hack! */
 #define FT_LOAD_SBITS_ONLY  0x4000
--- a/src/autohint/ahhint.c
+++ b/src/autohint/ahhint.c
@@ -104,42 +104,42 @@
       sign = 1;
     }
 
-    if ( ( vertical  && hinter->no_vert_snapping ) ||
-         ( !vertical && hinter->no_horz_snapping ) )
+    if ( (  vertical && !hinter->do_vert_snapping ) ||
+         ( !vertical && !hinter->do_horz_snapping ) )
     {
       /* smooth hinting process, very lightly quantize the stem width */
       /*                                                              */
       if ( dist < 64 )
         dist = 64;
-  
+
       {
         FT_Pos  delta = dist - globals->stds[vertical];
-  
-  
+
+
         if ( delta < 0 )
           delta = -delta;
-  
+
         if ( delta < 40 )
         {
           dist = globals->stds[vertical];
-          if ( dist < 32 )
-            dist = 32;
+          if ( dist < 48 )
+            dist = 48;
         }
-  
+
         if ( dist < 3 * 64 )
         {
           delta = ( dist & 63 );
           dist &= -64;
-  
+
           if ( delta < 10 )
             dist += delta;
-  
+
           else if ( delta < 32 )
             dist += 10;
-  
+
           else if ( delta < 54 )
             dist += 54;
-  
+
           else
             dist += delta;
         }
@@ -154,7 +154,7 @@
       if ( vertical )
       {
         dist = ah_snap_width( globals->heights, globals->num_heights, dist );
-  
+
         /* in the case of vertical hinting, always round */
         /* the stem heights to integer pixels            */
         if ( dist >= 64 )
@@ -165,7 +165,7 @@
       else
       {
         dist = ah_snap_width( globals->widths,  globals->num_widths, dist );
-  
+
         if ( hinter->flags & AH_HINTER_MONOCHROME )
         {
           /* monochrome horizontal hinting: snap widths to integer pixels */
@@ -182,7 +182,7 @@
           /* is between 1 and 2 pixels to an integer, otherwise nothing  */
           if ( dist < 48 )
             dist = ( dist + 64 ) >> 1;
-  
+
           else if ( dist < 128 )
             dist = ( dist + 22 ) & -64;
           else
@@ -285,10 +285,10 @@
       int      has_serifs = 0;
 
 
-      if ( hinter->no_horz_hints && !dimension )
+      if ( !hinter->do_horz_hints && !dimension )
         goto Next_Dimension;
 
-      if ( hinter->no_vert_hints && dimension )
+      if ( !hinter->do_vert_hints && dimension )
         goto Next_Dimension;
 
       /* we begin by aligning all stems relative to the blue zone */
@@ -1169,7 +1169,7 @@
       /* perform feature detection */
       ah_outline_detect_features( outline );
 
-      if ( !hinter->no_vert_hints )
+      if ( hinter->do_vert_hints )
       {
         ah_outline_compute_blue_edges( outline, hinter->globals );
         ah_outline_scale_blue_edges( outline, hinter->globals );
@@ -1439,23 +1439,23 @@
     ah_loader_rewind( hinter->loader );
 
     /* reset hinting flags according to load flags and current render target */
-    hinter->no_horz_hints = FT_BOOL( load_flags & FT_LOAD_NO_AUTOHINT );
-    hinter->no_vert_hints = FT_BOOL( load_flags & FT_LOAD_NO_AUTOHINT );
-    
+    hinter->do_horz_hints = !FT_BOOL( load_flags & FT_LOAD_NO_AUTOHINT );
+    hinter->do_vert_hints = !FT_BOOL( load_flags & FT_LOAD_NO_AUTOHINT );
+
 #ifdef DEBUG_HINTER
-    hinter->no_horz_hints = ah_debug_disable_vert;  /* not a bug, the meaning */
-    hinter->no_vert_hints = ah_debug_disable_horz;  /* of h/v is inverted!    */
-#endif    
+    hinter->do_horz_hints = !ah_debug_disable_vert;  /* not a bug, the meaning */
+    hinter->do_vert_hints = !ah_debug_disable_horz;  /* of h/v is inverted!    */
+#endif
 
     /* we snap the width of vertical stems for the monochrome and         */
     /* horizontal LCD rendering targets only.  Corresponds to X snapping. */
-    hinter->no_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_NORMAL ||
-                                        hint_mode == FT_RENDER_MODE_LCD_V  );
+    hinter->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
+                                        hint_mode == FT_RENDER_MODE_LCD  );
 
     /* we snap the width of horizontal stems for the monochrome and     */
     /* vertical LCD rendering targets only.  Corresponds to Y snapping. */
-    hinter->no_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_NORMAL ||
-                                        hint_mode == FT_RENDER_MODE_LCD    );
+    hinter->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO   ||
+                                        hint_mode == FT_RENDER_MODE_LCD_V  );
 
 #if 1
     load_flags  = FT_LOAD_NO_SCALE
--- a/src/autohint/ahtypes.h
+++ b/src/autohint/ahtypes.h
@@ -492,10 +492,10 @@
     FT_Vector         trans_delta;
     FT_Matrix         trans_matrix;
 
-    FT_Bool           no_horz_hints;     /* disable X hinting            */
-    FT_Bool           no_vert_hints;     /* disable Y hinting            */
-    FT_Bool           no_horz_snapping;  /* disable X stem size snapping */
-    FT_Bool           no_vert_snapping;  /* disable Y stem size snapping */
+    FT_Bool           do_horz_hints;     /* disable X hinting            */
+    FT_Bool           do_vert_hints;     /* disable Y hinting            */
+    FT_Bool           do_horz_snapping;  /* disable X stem size snapping */
+    FT_Bool           do_vert_snapping;  /* disable Y stem size snapping */
 
   } AH_HinterRec, *AH_Hinter;
 
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -444,8 +444,8 @@
     hinter   = library->auto_hinter;
     autohint =
       FT_BOOL( hinter                                      &&
-               !( load_flags & ( FT_LOAD_NO_SCALE    | 
-                                 FT_LOAD_NO_HINTING  | 
+               !( load_flags & ( FT_LOAD_NO_SCALE    |
+                                 FT_LOAD_NO_HINTING  |
                                  FT_LOAD_NO_AUTOHINT ) )   &&
                FT_DRIVER_IS_SCALABLE( driver )             &&
                FT_DRIVER_USES_OUTLINES( driver )           );
@@ -553,10 +553,13 @@
          slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
          load_flags & FT_LOAD_RENDER )
     {
-      error = FT_Render_Glyph( slot,
-                               ( load_flags & FT_LOAD_MONOCHROME )
-                                  ? FT_RENDER_MODE_MONO
-                                  : FT_RENDER_MODE_NORMAL );
+      FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
+
+      if ( mode == FT_RENDER_MODE_NORMAL      &&
+           (load_flags & FT_LOAD_MONOCHROME ) )
+        mode = FT_RENDER_MODE_MONO;
+
+      error = FT_Render_Glyph( slot, mode );
     }
 
   Exit:
--- a/src/cache/ftcimage.c
+++ b/src/cache/ftcimage.c
@@ -42,7 +42,7 @@
   typedef struct  FTC_ImageQueryRec_
   {
     FTC_GlyphQueryRec  gquery;
-    FTC_ImageDesc      desc;
+    FTC_ImageTypeRec   type;
 
   } FTC_ImageQueryRec, *FTC_ImageQuery;
 
@@ -54,7 +54,7 @@
   typedef struct  FTC_ImageFamilyRec_
   {
     FTC_GlyphFamilyRec  gfam;
-    FTC_ImageDesc       desc;
+    FTC_ImageTypeRec    type;
 
   } FTC_ImageFamilyRec, *FTC_ImageFamily;
 
@@ -106,41 +106,13 @@
 
     /* we will now load the glyph image */
     error = FTC_Manager_Lookup_Size( FTC_FAMILY( ifam )->cache->manager,
-                                     &ifam->desc.font,
+                                     &ifam->type.font,
                                      &face, &size );
     if ( !error )
     {
       FT_UInt  gindex     = FTC_GLYPH_NODE_GINDEX( inode );
-      FT_UInt  load_flags = FT_LOAD_DEFAULT;
-      FT_UInt  type       = ifam->desc.type;
 
-
-      if ( FTC_IMAGE_FORMAT( type ) == ftc_image_format_bitmap )
-      {
-        load_flags |= FT_LOAD_RENDER;
-        if ( type & ftc_image_flag_monochrome )
-          load_flags |= FT_LOAD_MONOCHROME;
-
-        /* disable embedded bitmaps loading if necessary */
-        if ( type & ftc_image_flag_no_sbits )
-          load_flags |= FT_LOAD_NO_BITMAP;
-      }
-      else if ( FTC_IMAGE_FORMAT( type ) == ftc_image_format_outline )
-      {
-        /* disable embedded bitmaps loading */
-        load_flags |= FT_LOAD_NO_BITMAP;
-
-        if ( type & ftc_image_flag_unscaled )
-          load_flags |= FT_LOAD_NO_SCALE;
-      }
-
-      if ( type & ftc_image_flag_unhinted )
-        load_flags |= FT_LOAD_NO_HINTING;
-
-      if ( type & ftc_image_flag_autohinted )
-        load_flags |= FT_LOAD_FORCE_AUTOHINT;
-
-      error = FT_Load_Glyph( face, gindex, load_flags );
+      error = FT_Load_Glyph( face, gindex, ifam->type.flags );
       if ( !error )
       {
         if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||
@@ -231,16 +203,16 @@
     FT_Face      face;
 
 
-    ifam->desc = iquery->desc;
+    ifam->type = iquery->type;
 
     /* we need to compute "iquery.item_total" now */
     error = FTC_Manager_Lookup_Face( manager,
-                                     iquery->desc.font.face_id,
+                                     iquery->type.font.face_id,
                                      &face );
     if ( !error )
     {
       error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( ifam ),
-                                     FTC_IMAGE_DESC_HASH( &ifam->desc ),
+                                     FTC_IMAGE_TYPE_HASH( &ifam->type ),
                                      1,
                                      face->num_glyphs,
                                      FTC_GLYPH_QUERY( iquery ),
@@ -258,7 +230,7 @@
     FT_Bool  result;
 
 
-    result = FT_BOOL( FTC_IMAGE_DESC_COMPARE( &ifam->desc, &iquery->desc ) );
+    result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &ifam->type, &iquery->type ) );
     if ( result )
       FTC_GLYPH_FAMILY_FOUND( ifam, iquery );
 
@@ -314,7 +286,7 @@
 
   FT_EXPORT_DEF( FT_Error )
   FTC_ImageCache_Lookup( FTC_ImageCache  cache,
-                         FTC_ImageDesc*  desc,
+                         FTC_ImageType   type,
                          FT_UInt         gindex,
                          FT_Glyph       *aglyph,
                          FTC_Node       *anode )
@@ -332,7 +304,7 @@
       *anode  = NULL;
 
     iquery.gquery.gindex = gindex;
-    iquery.desc          = *desc;
+    iquery.type          = *type;
 
     error = ftc_cache_lookup( FTC_CACHE( cache ),
                               FTC_QUERY( &iquery ),
@@ -368,17 +340,55 @@
                           FT_UInt          gindex,
                           FT_Glyph        *aglyph )
   {
-    FTC_ImageDesc  desc0;
+    FTC_ImageTypeRec  type0;
 
 
     if ( !desc )
       return FTC_Err_Invalid_Argument;
 
-    desc0.font = desc->font;
-    desc0.type = (FT_UInt32)desc->image_type;
+    type0.font = desc->font;
 
+    /* convert image type flags to load flags */
+    {
+      FT_UInt  load_flags = FT_LOAD_DEFAULT;
+      FT_UInt  type       = desc->image_type;
+
+
+      /* determine load flags, depending on the font description's */
+      /* image type                                                */
+
+      if ( ftc_image_format( type ) == ftc_image_format_bitmap )
+      {
+        if ( type & ftc_image_flag_monochrome )
+          load_flags |= FT_LOAD_MONOCHROME;
+
+        /* disable embedded bitmaps loading if necessary */
+        if ( type & ftc_image_flag_no_sbits )
+          load_flags |= FT_LOAD_NO_BITMAP;
+      }
+      else
+      {
+        /* we want an outline, don't load embedded bitmaps */
+        load_flags |= FT_LOAD_NO_BITMAP;
+
+        if ( type & ftc_image_flag_unscaled )
+          load_flags |= FT_LOAD_NO_SCALE;
+      }
+
+      /* always render glyphs to bitmaps */
+      load_flags |= FT_LOAD_RENDER;
+
+      if ( type & ftc_image_flag_unhinted )
+        load_flags |= FT_LOAD_NO_HINTING;
+
+      if ( type & ftc_image_flag_autohinted )
+        load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+      type0.flags = load_flags;
+    }
+
     return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
-                                   &desc0,
+                                   &type0,
                                    gindex,
                                    aglyph,
                                    NULL );
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -46,7 +46,7 @@
   typedef struct  FTC_SBitQueryRec_
   {
     FTC_GlyphQueryRec  gquery;
-    FTC_ImageDesc      desc;
+    FTC_ImageTypeRec   type;
 
   } FTC_SBitQueryRec, *FTC_SBitQuery;
 
@@ -60,7 +60,7 @@
   typedef struct  FTC_SBitFamilyRec_
   {
     FTC_GlyphFamilyRec  gfam;
-    FTC_ImageDesc       desc;
+    FTC_ImageTypeRec    type;
 
   } FTC_SBitFamilyRec;
 
@@ -104,8 +104,8 @@
   ftc_sbit_node_done( FTC_SBitNode  snode,
                       FTC_Cache     cache )
   {
-    FTC_SBit   sbit  = snode->sbits;
-    FT_UInt    count = FTC_GLYPH_NODE( snode )->item_count;
+    FTC_SBit   sbit   = snode->sbits;
+    FT_UInt    count  = FTC_GLYPH_NODE( snode )->item_count;
     FT_Memory  memory = cache->memory;
 
 
@@ -142,48 +142,14 @@
 
     sbit = snode->sbits + ( gindex - gnode->item_start );
 
-    error = FTC_Manager_Lookup_Size( manager, &sfam->desc.font,
+    error = FTC_Manager_Lookup_Size( manager, &sfam->type.font,
                                      &face, &size );
     if ( !error )
     {
-      FT_UInt  load_flags = FT_LOAD_DEFAULT;
-      FT_UInt  type       = sfam->desc.type;
-
-
-      /* determine load flags, depending on the font description's */
-      /* image type                                                */
-
-      if ( FTC_IMAGE_FORMAT( type ) == ftc_image_format_bitmap )
-      {
-        if ( type & ftc_image_flag_monochrome )
-          load_flags |= FT_LOAD_MONOCHROME;
-
-        /* disable embedded bitmaps loading if necessary */
-        if ( type & ftc_image_flag_no_sbits )
-          load_flags |= FT_LOAD_NO_BITMAP;
-      }
-      else
-      {
-        FT_ERROR((
-          "ftc_sbit_node_load: cannot load scalable glyphs in an"
-          " sbit cache, please check your arguments!\n" ));
-        error = FTC_Err_Invalid_Argument;
-        goto Exit;
-      }
-
-      /* always render glyphs to bitmaps */
-      load_flags |= FT_LOAD_RENDER;
-
-      if ( type & ftc_image_flag_unhinted )
-        load_flags |= FT_LOAD_NO_HINTING;
-
-      if ( type & ftc_image_flag_autohinted )
-        load_flags |= FT_LOAD_FORCE_AUTOHINT;
-
       /* by default, indicates a `missing' glyph */
       sbit->buffer = 0;
 
-      error = FT_Load_Glyph( face, gindex, load_flags );
+      error = FT_Load_Glyph( face, gindex, sfam->type.flags | FT_LOAD_RENDER );
       if ( !error )
       {
         FT_Int        temp;
@@ -221,13 +187,7 @@
           sbit->xadvance  = (FT_Char)xadvance;
           sbit->yadvance  = (FT_Char)yadvance;
           sbit->format    = (FT_Byte)bitmap->pixel_mode;
-          /* XXX: Fixme: We don't handle the number of gray levels      */
-          /*             consistently -- we say num_grays == 1 for      */
-          /*             monochrome but num_grays == 256 for gray.  It  */
-          /*             would be better to make this variable hold the */
-          /*             highest possible value so that it fits into    */
-          /*             a single byte.                                 */
-          sbit->num_grays = bitmap->num_grays;
+          sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
 
           /* grab the bitmap when possible - this is a hack! */
           if ( slot->flags & FT_GLYPH_OWN_BITMAP )
@@ -380,16 +340,16 @@
     FT_Face      face;
 
 
-    sfam->desc = squery->desc;
+    sfam->type = squery->type;
 
     /* we need to compute "cquery.item_total" now */
     error = FTC_Manager_Lookup_Face( manager,
-                                     squery->desc.font.face_id,
+                                     squery->type.font.face_id,
                                      &face );
     if ( !error )
     {
       error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( sfam ),
-                                     FTC_IMAGE_DESC_HASH( &sfam->desc ),
+                                     FTC_IMAGE_TYPE_HASH( &sfam->type ),
                                      FTC_SBIT_ITEMS_PER_NODE,
                                      face->num_glyphs,
                                      FTC_GLYPH_QUERY( squery ),
@@ -410,7 +370,7 @@
     /* we need to set the "cquery.cset" field or our query for */
     /* faster glyph comparisons in ftc_sbit_node_compare       */
     /*                                                         */
-    result = FT_BOOL( FTC_IMAGE_DESC_COMPARE( &sfam->desc, &squery->desc ) );
+    result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &sfam->type, &squery->type ) );
     if ( result )
       FTC_GLYPH_FAMILY_FOUND( sfam, squery );
 
@@ -481,7 +441,7 @@
 
   FT_EXPORT_DEF( FT_Error )
   FTC_SBitCache_Lookup( FTC_SBitCache   cache,
-                        FTC_ImageDesc*  desc,
+                        FTC_ImageType   type,
                         FT_UInt         gindex,
                         FTC_SBit       *ansbit,
                         FTC_Node       *anode )
@@ -501,7 +461,7 @@
       *anode = NULL;
 
     squery.gquery.gindex = gindex;
-    squery.desc          = *desc;
+    squery.type          = *type;
 
     error = ftc_sbit_cache_lookup( FTC_CACHE( cache ),
                                    FTC_QUERY( &squery ),
@@ -536,17 +496,56 @@
                          FT_UInt          gindex,
                          FTC_SBit        *ansbit )
   {
-    FTC_ImageDesc  desc0;
+    FTC_ImageTypeRec  type0;
 
 
     if ( !desc )
       return FTC_Err_Invalid_Argument;
 
-    desc0.font = desc->font;
-    desc0.type = (FT_UInt32)desc->image_type;
+    type0.font  = desc->font;
+    type0.flags = 0;
 
+    /* convert image type flags to load flags */
+    {
+      FT_UInt  load_flags = FT_LOAD_DEFAULT;
+      FT_UInt  type       = desc->image_type;
+
+
+      /* determine load flags, depending on the font description's */
+      /* image type                                                */
+
+      if ( ftc_image_format( type ) == ftc_image_format_bitmap )
+      {
+        if ( type & ftc_image_flag_monochrome )
+          load_flags |= FT_LOAD_MONOCHROME;
+
+        /* disable embedded bitmaps loading if necessary */
+        if ( type & ftc_image_flag_no_sbits )
+          load_flags |= FT_LOAD_NO_BITMAP;
+      }
+      else
+      {
+        /* we want an outline, don't load embedded bitmaps */
+        load_flags |= FT_LOAD_NO_BITMAP;
+
+        if ( type & ftc_image_flag_unscaled )
+          load_flags |= FT_LOAD_NO_SCALE;
+      }
+
+      /* always render glyphs to bitmaps */
+      load_flags |= FT_LOAD_RENDER;
+
+      if ( type & ftc_image_flag_unhinted )
+        load_flags |= FT_LOAD_NO_HINTING;
+
+      if ( type & ftc_image_flag_autohinted )
+        load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+      type0.flags = load_flags;
+    }
+
     return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,
-                                  &desc0,
+                                  &type0,
                                   gindex,
                                   ansbit,
                                   NULL );
--- a/src/pshinter/pshalgo3.c
+++ b/src/pshinter/pshalgo3.c
@@ -332,6 +332,56 @@
   /*************************************************************************/
   /*************************************************************************/
 
+  static FT_Pos
+  psh3_dimension_quantize_len( PSH_Dimension  dim,
+                               FT_Pos         len,
+                               FT_Bool        do_snapping )
+  {
+    if ( len <= 64 )
+      len = 64;
+    else
+    {
+      FT_Pos  delta = len - dim->stdw.widths[0].cur;
+
+
+      if ( delta < 0 )
+        delta = -delta;
+
+      if ( delta < 40 )
+      {
+        len = dim->stdw.widths[0].cur;
+        if ( len < 48 )
+          len = 48;
+      }
+
+      if ( len < 3 * 64 )
+      {
+        delta = ( len & 63 );
+        len  &= -64;
+
+        if ( delta < 10 )
+          len += delta;
+
+        else if ( delta < 32 )
+          len += 10;
+
+        else if ( delta < 54 )
+          len += 54;
+
+        else
+          len += delta;
+      }
+      else
+        len = ( len + 32 ) & -64;
+    }
+
+    if ( do_snapping )
+      len = ( len + 32 ) & -64;
+
+    return  len;
+  }
+
+
 #ifdef DEBUG_HINTER
 
   static void
@@ -390,7 +440,7 @@
       FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
       FT_Pos  len = FT_MulFix( hint->org_len, scale );
 
-      FT_Int            no_snapping;
+      FT_Int            do_snapping;
       FT_Pos            fit_center;
       FT_Pos            fit_len;
       PSH_AlignmentRec  align;
@@ -397,8 +447,8 @@
 
 
       /* ignore stem alignments when requested through the hint flags */
-      if ( ( dimension == 0 && glyph->no_horz_hints ) ||
-           ( dimension == 1 && glyph->no_vert_hints ) )
+      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
+           ( dimension == 1 && !glyph->do_vert_hints ) )
       {
         hint->cur_pos = pos;
         hint->cur_len = len;
@@ -408,27 +458,11 @@
       }
 
       /* perform stem snapping when requested */
-      no_snapping = ( dimension == 0 && !glyph->no_horz_snapping ) ||
-                    ( dimension == 1 && !glyph->no_vert_snapping );
+      do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||
+                    ( dimension == 1 && glyph->do_vert_snapping );
 
-      if ( !no_snapping )
-      {
-        /* compute fitted width/height */
-        fit_len = 0;
-        if ( hint->org_len )
-        {
-          fit_len = psh_dimension_snap_width( dim, hint->org_len );
-          if ( fit_len < 64 )
-            fit_len = 64;
-          else
-            fit_len = ( fit_len + 32 ) & -64;
-        }
-      }
-      else
-        fit_len = len;
+      hint->cur_len = fit_len = len;
 
-      hint->cur_len = fit_len;
-
       /* check blue zones for horizontal stems */
       align.align     = PSH_BLUE_ALIGN_NONE;
       align.align_bot = align.align_top = 0;
@@ -480,151 +514,64 @@
             pos       = par_cur_center + cur_delta - ( len >> 1 );
           }
 
-          if ( !no_snapping )
+          hint->cur_pos = pos;
+          hint->cur_len = fit_len;
+
+          if ( len <= 64 )
           {
-            /* normal processing */
-            if ( fit_len & 64 )
-            {
-              /* odd number of pixels */
-              fit_center = ( ( pos + ( len >> 1 ) ) & -64 ) + 32;
-            }
-            else
-            {
-              /* even number of pixels */
-              fit_center = ( pos + ( len >> 1 ) + 32 ) & -64;
-            }
-            hint->cur_pos = fit_center - ( fit_len >> 1 );
+            /* the stem is less than one pixel, we will center it */
+            /* around the nearest pixel center                    */
+            /*                                                    */
+            pos = ( pos + ( (len >> 1) & -64 ) );
+            len = 64;
           }
           else
           {
-#ifdef STRONGER
-            if ( len <= 64 )
-            {
-              /* the stem is less than one pixel, we will center it */
-              /* around the nearest pixel center                    */
-              /*                                                    */
-              pos = ( pos + ( (len >> 1) & -64 ) );
-              len = 64;
-            }
-            else
-            {
-              FT_Pos  Delta = len - dim->stdw.widths[0].cur;
+            len = psh3_dimension_quantize_len( dim, len, 0 );
+          }
 
+          /* now that we have a good hinted stem width, try to position */
+          /* the stem along a pixel grid integer coordinate             */
+          hint->cur_pos = pos + psh3_hint_snap_stem_side_delta( pos, len );
+          hint->cur_len = len;
+        }
+      }
 
-              if ( Delta < 0 )
-                Delta = -Delta;
+      if ( do_snapping )
+      {
+        pos = hint->cur_pos;
+        len = hint->cur_len;
 
-              if ( Delta < 40 )
-              {
-                len = dim->stdw.widths[0].cur;
-                if ( len < 32 )
-                  len = 32;
-              }
+        if ( len < 64 )
+          len = 64;
+        else
+          len = ( len + 32 ) & -64;
 
-              if ( len < 3 * 64 )
-              {
-                Delta = ( len & 63 );
-                len &= -64;
+        switch ( align.align )
+        {
+          case PSH_BLUE_ALIGN_TOP:
+            hint->cur_pos = align.align_top - len;
+            hint->cur_len = len;
+            break;
 
-                if ( Delta < 10 )
-                  len += Delta;
+          case PSH_BLUE_ALIGN_BOT:
+            hint->cur_len = len;
+            break;
 
-                else if ( Delta < 32 )
-                  len += 10;
+          case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP:
+            /* don't touch */
+            break;
 
-                else if ( Delta < 54 )
-                  len += 54;
 
-                else
-                  len += Delta;
-              }
-              else
-                len = ( len + 32 ) & -64;
-            }
-
-            /* now that we have a good hinted stem width, try to position */
-            /* the stem along a pixel grid integer coordinate             */
-            hint->cur_pos = pos + psh3_hint_snap_stem_side_delta( pos, len );
+          default:
             hint->cur_len = len;
-
-#else /* !STRONGER */
-
-            /* Stems less than one pixel wide are easy - we want to
-             * make them as dark as possible, so they must fall within
-             * one pixel. If the stem is split between two pixels
-             * then snap the edge that is nearer to the pixel boundary
-             * to the pixel boundary
-             */
-            if (len <= 64)
-            {
-              if ( ( pos + len + 63 ) / 64  != pos / 64 + 1 )
-                pos += psh3_hint_snap_stem_side_delta ( pos, len );
-            }
-            /* Position stems other to minimize the amount of mid-grays.
-             * There are, in general, two positions that do this,
-             * illustrated as A) and B) below.
-             *
-             *   +                   +                   +                   +
-             *
-             * A)             |--------------------------------|
-             * B)   |--------------------------------|
-             * C)       |--------------------------------|
-             *
-             * Position A) (split the excess stem equally) should be better
-             * for stems of width N + f where f < 0.5.
-             *
-             * Position B) (split the deficiency equally) should be better
-             * for stems of width N + f where f > 0.5.
-             *
-             * It turns out though that minimizing the total number of touched
-             * pixels is also important, so position C), with one edge
-             * aligned with a pixel boundary is actually preferable
-             * to A).  There are also more possible positions for C) than
-             * for A) or B), so there will be less distortion of the overall
-             * character shape.
-             */
+            if ( len & 64 )
+              pos = ( ( pos + ( len >> 1 ) ) & -64 ) + 32;
             else
-            {
-              FT_Fixed frac_len = len & 63;
-              FT_Fixed center = pos + ( len >> 1 );
+              pos = ( pos + ( len >> 1 ) + 32 ) & -64;
 
-              FT_Fixed delta_a, delta_b;
-
-
-              if ( len & 64 )
-              {
-                delta_a = ( center & -64 ) + 32 - center;
-                delta_b = ( ( center + 32 ) & - 64 ) - center;
-              }
-              else
-              {
-                delta_a = ( ( center + 32 ) & - 64 ) - center;
-                delta_b = ( center & -64 ) + 32 - center;
-              }
-
-              /* We choose between B) and C) above based on the amount
-               * of fractional stem width: for small amounts, choose
-               * C) always; for large amounts, B) always; inbetween,
-               * pick whichever one involves less stem movement.
-               */
-              if ( frac_len < 32 )
-                pos += psh3_hint_snap_stem_side_delta ( pos, len );
-              else if ( frac_len < 48 )
-              {
-                FT_Fixed  side_delta =
-                            psh3_hint_snap_stem_side_delta( pos, len );
-
-                if ( ABS( side_delta ) < ABS( delta_b ) )
-                  pos += side_delta;
-                else
-                  pos += delta_b;
-              }
-              else
-                pos += delta_b;
-            }
-            hint->cur_pos = pos;
-#endif /* !STRONGER */
-          }
+            hint->cur_pos = pos - ( len >> 1 );
+            hint->cur_len = len;
         }
       }
 
@@ -1761,18 +1708,18 @@
 
 #endif /* DEBUG_HINTER */
 
-    glyph->no_horz_hints = 0;
-    glyph->no_vert_hints = 0;
-
-    glyph->no_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_NORMAL ||
-                                       hint_mode == FT_RENDER_MODE_LCD_V  );
-
-    glyph->no_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_NORMAL ||
-                                       hint_mode == FT_RENDER_MODE_LCD    );
-
     error = psh3_glyph_init( glyph, outline, ps_hints, globals );
     if ( error )
       goto Exit;
+
+    glyph->do_horz_hints = 1;
+    glyph->do_vert_hints = 1;
+
+    glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
+                                       hint_mode == FT_RENDER_MODE_LCD  );
+
+    glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO  ||
+                                       hint_mode == FT_RENDER_MODE_LCD_V );
 
     for ( dimension = 0; dimension < 2; dimension++ )
     {
--- a/src/pshinter/pshalgo3.h
+++ b/src/pshinter/pshalgo3.h
@@ -30,7 +30,7 @@
 
   /* handle to Hint structure */
   typedef struct PSH3_HintRec_*  PSH3_Hint;
- 
+
   /* hint bit-flags */
   typedef enum
   {
@@ -217,10 +217,10 @@
     FT_Int              major_dir;
     FT_Int              minor_dir;
 
-    FT_Bool             no_horz_hints;
-    FT_Bool             no_vert_hints;
-    FT_Bool             no_horz_snapping;
-    FT_Bool             no_vert_snapping;
+    FT_Bool             do_horz_hints;
+    FT_Bool             do_vert_hints;
+    FT_Bool             do_horz_snapping;
+    FT_Bool             do_vert_snapping;
 
   } PSH3_GlyphRec, *PSH3_Glyph;
 
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -249,9 +249,15 @@
                         FT_UInt       mode,
                         FT_Vector*    origin )
   {
-    return ft_smooth_render_generic( render, slot, mode, origin,
-                                     FT_RENDER_MODE_LCD,
-                                     3, 0 );
+    FT_Error  error;
+
+    error = ft_smooth_render_generic( render, slot, mode, origin,
+                                      FT_RENDER_MODE_LCD,
+                                      3, 0 );
+    if ( !error )
+      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
+
+    return error;
   }
 
 
@@ -262,9 +268,15 @@
                           FT_UInt       mode,
                           FT_Vector*    origin )
   {
-    return ft_smooth_render_generic( render, slot, mode, origin,
-                                     FT_RENDER_MODE_LCD_V,
-                                     0, 3 );
+    FT_Error  error;
+
+    error = ft_smooth_render_generic( render, slot, mode, origin,
+                                      FT_RENDER_MODE_LCD_V,
+                                      0, 3 );
+    if ( !error )
+      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
+
+    return error;
   }