summaryrefslogtreecommitdiffstats
path: root/unmaintained/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'unmaintained/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch')
-rw-r--r--unmaintained/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch1602
1 files changed, 1602 insertions, 0 deletions
diff --git a/unmaintained/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch b/unmaintained/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch
new file mode 100644
index 000000000..aae5fadde
--- /dev/null
+++ b/unmaintained/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch
@@ -0,0 +1,1602 @@
+freetype-entire-infinality-patchset (excludes the TT subpixel patches)
+-------------------------------------------------------------------
+
+This patch contains all the patches I used to distribute separately.
+It made more sense to lump these all together into a single file
+now that there are runtime options. It's also easier for me to maintain. ;)
+
+I recommend that if you are using this patch that you use
+
+ /etc/fonts/local.conf
+
+that I provide at: http://www.infinality.net/files/local.conf
+You will also need: http://www.infinality.net/files/infinality-settings
+
+The second one will need to be included in your profile with something like:
+
+ . ~/path/to/the/file/infinality-settings
+
+It should be adjusted to your personal tastes as an end-user.
+
+
+DISCLAIMERS:
+
+This patch will almost certainly result in a performance hit when
+freetype is rendering the glyphs. The good news is that fontconfig
+caches the glyphs so it's only the first time they are displayed that there
+could be a performance issue.
+
+I expect that if you compile freetype with this patch along with my
+TT subpixel hinting patch, you will have a complete build that works the
+way I expect it to. However, I have not tested all compile configurations
+for errors. I intend to at some point. This patch may make your system crash,
+have memory leaks, not compile, or render fonts in a way that you don't like.
+Either way, when you use this patch, you should recognize that it
+is ALPHA / BETA quality. That said, I intend to run these patches on my
+personal system, so they had better be pretty stable!
+
+
+Changelog
+
+2010-11-14
+ - All patches can now be enabled at runtime with ENVIRONMENT_VARIABLES.
+ See the file infinality-settings (and below) for how to enable these.
+ Effects that used to work now **REQUIRE** these in order to be turned on
+ at runtime. This lets end users have full control over what they want
+ without requiring different compiles.
+
+ - Added option to auto-embolden thin/light fonts.
+
+ - Further refinement of the stem calculations for enhanced autohint.
+
+ - Adjustable FIR filter at runtime.
+
+ - Stem alignment ability to align glyph bitmaps to pixel boundaries.
+
+ - Adjustable gamma correction prior to the FIR filter for LCD rendering.
+ This can be used to make small ppem text more readable, or for whatever
+ else you want to use it for.
+
+ - A height tweak on the enhanced autohint that makes Arial, Segoe, Times
+ and others render more similarly to Windows.
+
+ - Separated out the option to maintain the original width of glyphs
+ when doing fake emboldening.
+
+
+
+##################################################################
+# The environment variables below should be copied to a file in
+# /etc/profile.d/ for system-wide effects and/or included in
+# ~/.bashrc or ~/.bash_profile for per-user effects:
+#
+# . ~/path/to/the/file/infinality-settings
+#
+# Of course, the per-user settings will override the system-wide
+# settings.
+
+
+
+##################################################################
+# INFINALITY_FT_FILTER_PARAMS
+#
+# This is a modified version of the patch here:
+# http://levelsofdetail.kendeeter.com/2008/12/dynamic_fir_filter_patch.html
+#
+# Allows you to adjust the FIR filter at runtime instead of at
+# compile time. The idea is to have values add up to one, and be
+# symmetrical around the middle value. Here are some samples
+# of various filter parameters:
+#
+# Strong Extra Smooth "0.15 0.2 0.3 0.2 0.15" (extra smooth, natural weight)
+# Extra Smooth "0.20 0.20 0.30 0.20 0.20" (extra smooth, extra weight)
+# Smooth "0.15 0.20 0.32 0.20 0.15" (smooth, natural weight)
+# Stronger Gibson "0.11 0.22 0.38 0.22 0.11" (smooth, extra weight)
+# Gibson "0.11 0.22 0.33 0.22 0.11" (smooth, natural weight)
+# Freetype Light "0.00 0.33 0.34 0.33 0.00" (sharp, natural weight)
+# Freetype Default "0.06 0.25 0.44 0.25 0.06" (sharp, extra weight) *default
+# Extra Sharp "0.00 0.35 0.35 0.35 0.00" (extra sharp, extra weight)
+#
+# Default: [Freetype's default]
+# Recommended: "0.11 0.22 0.38 0.22 0.11"
+#
+# Example 1: export INFINALITY_FT_FILTER_PARAMS="0.11 0.22 0.38 0.22 0.11"
+#
+
+export INFINALITY_FT_FILTER_PARAMS="0.11 0.22 0.38 0.22 0.11"
+
+
+
+
+##################################################################
+# INFINALITY_FT_STEM_ALIGNMENT_TYPE
+#
+# This performs analysis on each glyph and determines the best
+# subpixel orientation for the glyph. The glyph is not scaled in
+# any way, just moved left or right by a subpixel amount. This
+# results in subtley cleaner looking fonts, at the expense of
+# proper distances between glyphs. This is only active for sizes
+# 10 px or greater and does not apply to bold or italic fonts.
+#
+# Possible values:
+# full - Allows a glyph to be moved to the LEFT or RIGHT by 1 subpixel
+# Best alignment, Worst positioning
+# medium,medium1 - Only allows a glyph to be moved to the LEFT by 1 subpixel
+# Good alignment, Good positioning
+# medium2 - Only allows a glyph to be moved to the RIGHT by 1 subpixel
+# Good alignment, Good positioning
+# slight,slight1 - A stricter version of medium
+# Minor alignment, Best positioning
+# slight2 - A stricter version of medium2
+# Minor alignment, Best positioning
+# infinality - medium1 when stem < 5 subpixels, full when >= 5 subpixels
+# none - Don't do any alignment
+#
+# Default: none
+# Recommended: medium
+
+export INFINALITY_FT_STEM_ALIGNMENT_TYPE=medium
+
+
+
+
+
+##################################################################
+# INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT
+#
+# Cause the height of horizontal stems to snap to integer pixels
+# when using light auto-hinting. (This happens automatically
+# when using full auto-hinting)
+#
+# This produces an effect similar to the way Windows renders fonts
+# without requiring the font to contain bytecode instructions.
+#
+# Possible values:
+# true - enable stem snapping
+# false - do not enable stem snapping
+#
+# Default: false
+# Recommended: true
+
+export INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT=true
+
+
+
+
+##################################################################
+# INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT
+#
+# Embolden particularly light or thin fonts, like DejaVu Sans Light,
+# Inconsolata, Freemono, Courier New, etc. up until stem width is
+# 1 pixel wide. This makes these fonts easier to read at lower
+# ppems. Only applies when the autohinter is being used.
+#
+# Possible values:
+# true - enable emboldening of light fonts
+# false - do not enable emboldening of light fonts
+#
+# Default: false
+# Recommended: true
+
+export INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT=true
+
+
+
+
+##################################################################
+# INFINALITY_FT_PSEUDO_GAMMA
+#
+# This does a weighted gamma correction at the LCD filter phase
+# prior to the LCD filter.
+#
+# The first value indicates a px value, the second indicates a
+# "gamma" value. All sizes < the px value will be corrected
+# on a weighted scale based on the second value.
+#
+# Values .1 < 1.0 will darken the glyph
+# Values > 1.0 will lighten the glyph
+#
+# Example 1: Darken glyphs that are less than 10 px. With some fonts
+# even 5 or 6px is readable!
+# export INFINALITY_FT_PSEUDO_GAMMA="10 .6"
+#
+# Example 2: Lighten all glyphs (below 100px)
+# export INFINALITY_FT_PSEUDO_GAMMA="100 1.5"
+#
+# Default: [No gamma correction]
+# Recommended: "9 .7"
+
+export INFINALITY_FT_PSEUDO_GAMMA="9 .7"
+
+
+
+
+##################################################################
+# INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS
+#
+# This will slightly stretch some glyphs vertically between 9px
+# and 14px (inclusive). Some people may find this more
+# aesthetically pleasing. This only applies to fonts that are
+# using autohint.
+#
+# Possible values:
+# true - enable height adjustment
+# false - do not enable height adjustment
+#
+# Default: false
+
+export INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS=true
+
+
+
+
+##################################################################
+# INFINALITY_FT_ENHANCED_EMBOLDEN
+#
+# When doing artificial emboldening, only embolden in the X
+# direction, skipping the Y direction. Most people will find this
+# more aesthetically pleasing than the default behavior.
+#
+# Possible values:
+# true - enable enhanced emboldening
+# false - no not enable enhanced emboldening
+#
+# Default: false
+# Recommended: true
+
+export INFINALITY_FT_ENHANCED_EMBOLDEN=true
+
+
+
+
+##################################################################
+# INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH
+#
+# When doing artificial emboldening, don't change the glyph width.
+#
+# Possible values:
+# true - maintain width
+# false - do not maintain width
+#
+# Default: false
+# Recommended: true
+
+export INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH=true
+
+
+
+
+##################################################################
+# INFINALITY_FT_AUTO_AUTOHINT
+#
+# Automatically use autohint when rendering a font that contains
+# no truetype instructions, regardless of what the calling
+# program asks for. The truetype hinter will not do a good job
+# on these.
+#
+# Possible values:
+# true - automatically use autohint
+# false - do not automatically use autohint
+#
+# Default: false
+# Recommended: true
+
+export INFINALITY_FT_AUTO_AUTOHINT=true
+
+
+
+
+
+
+INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT details
+---------------------------------------------
+
+This patch is intended to make freetype's autohinter round down widths of
+horizontal stems to whole pixel values. This dramatically reduces the
+graininess of the rendering at small sizes, at the expense of being true to the
+glyph.
+
+Put simply, it makes freetype's autohinter render fonts similarly
+to well-hinted TrueType fonts, even on fonts that contain no instructions.
+So, as far as I can tell, this makes it 100% patent-free.
+
+The most dramatic results are on sans-serif fonts like Lucida Grande,
+Arial, Helvetica Neue, Inconsolata, Droid Sans, Trebuchet MS, etc.
+
+
+It is recommended to use this with antialiasing on, and fonts set to
+slight hinting:
+
+ <match target="font" >
+ <edit mode="assign" name="rgba" >
+ <const>rgb</const>
+ </edit>
+ <edit mode="assign" name="hinting" >
+ <bool>true</bool>
+ </edit>
+ <edit mode="assign" name="autohint" >
+ <bool>true</bool>
+ </edit>
+ <edit mode="assign" name="antialias" >
+ <bool>true</bool>
+ </edit>
+ <edit mode="assign" name="hintstyle" >
+ <const>hintslight</const>
+ </edit>
+ <edit name="lcdfilter" mode="assign">
+ <const>lcddefault</const>
+ </edit>
+ </match>
+
+
+
+
+diff -Nur freetype-2.4.3.orig/configure freetype-2.4.3.new/configure
+--- freetype-2.4.3.orig/configure 2010-10-03 13:05:26.000000000 -0500
++++ freetype-2.4.3.new/configure 2010-11-14 18:17:36.593491866 -0600
+@@ -13,6 +13,8 @@
+ # Call the `configure' script located in `builds/unix'.
+ #
+
++export LDFLAGS="$LDFLAGS -lm"
++
+ rm -f config.mk builds/unix/unix-def.mk builds/unix/unix-cc.mk
+
+ if test "x$GNUMAKE" = x; then
+diff -Nur freetype-2.4.3.orig/include/freetype/internal/ftobjs.h freetype-2.4.3.new/include/freetype/internal/ftobjs.h
+--- freetype-2.4.3.orig/include/freetype/internal/ftobjs.h 2010-07-18 11:07:31.000000000 -0500
++++ freetype-2.4.3.new/include/freetype/internal/ftobjs.h 2010-11-07 11:18:19.681501081 -0600
+@@ -762,6 +770,10 @@
+ FT_Library library );
+
+
++ typedef void (*FT_Bitmap_LcdStemAlignFunc)( FT_Bitmap* bitmap,
++ FT_Render_Mode render_mode,
++ FT_GlyphSlot slot );
++
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+@@ -862,6 +874,7 @@
+ FT_Int lcd_extra; /* number of extra pixels */
+ FT_Byte lcd_weights[7]; /* filter weights, if any */
+ FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
++ FT_Bitmap_LcdStemAlignFunc lcd_stem_align_func;
+ #endif
+
+ #ifdef FT_CONFIG_OPTION_PIC
+diff -Nur freetype-2.4.3.orig/src/autofit/aflatin.c freetype-2.4.3.new/src/autofit/aflatin.c
+--- freetype-2.4.3.orig/src/autofit/aflatin.c 2010-09-11 01:23:02.000000000 -0500
++++ freetype-2.4.3.new/src/autofit/aflatin.c 2010-11-14 18:55:57.678647844 -0600
+@@ -21,6 +21,7 @@
+
+ #include "aflatin.h"
+ #include "aferrors.h"
++#include "strings.h"
+
+
+ #ifdef AF_USE_WARPER
+@@ -495,6 +496,29 @@
+ AF_LatinAxis axis;
+ FT_UInt nn;
+
++ int checked_adjust_heights_env = 0;
++ FT_Bool adjust_heights = FALSE;
++
++ if ( checked_adjust_heights_env == 0 )
++ {
++ char *adjust_heights_env = getenv( "INFINALITY_FT_AUTOFIT_ADJUST_HEIGHTS" );
++ if ( adjust_heights_env != NULL )
++ {
++ if ( strcasecmp(adjust_heights_env, "default" ) != 0 )
++ {
++ if ( strcasecmp(adjust_heights_env, "true") == 0)
++ adjust_heights = TRUE;
++ else if ( strcasecmp(adjust_heights_env, "1") == 0)
++ adjust_heights = TRUE;
++ else if ( strcasecmp(adjust_heights_env, "on") == 0)
++ adjust_heights = TRUE;
++ else if ( strcasecmp(adjust_heights_env, "yes") == 0)
++ adjust_heights = TRUE;
++ }
++ }
++ checked_adjust_heights_env = 1;
++ }
++
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+@@ -522,21 +546,46 @@
+ {
+ AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT];
+ AF_LatinBlue blue = NULL;
+-
++ int threshold = 40;
+
+ for ( nn = 0; nn < Axis->blue_count; nn++ )
+ {
+- if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
++ if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT
++ || ( adjust_heights && Axis->blues[nn].flags & AF_LATIN_BLUE_TOP )
++ )
+ {
+ blue = &Axis->blues[nn];
+ break;
+ }
+ }
+
++ if ( adjust_heights
++ && metrics->root.scaler.face->size->metrics.x_ppem < 15
++ && metrics->root.scaler.face->size->metrics.x_ppem > 8 )
++ threshold = 52;
++
++ /* NEED TO FIND A WAY TO ADJUST CAPS AND LOWER SEPARATELY */
++ /* The below does not work */
++ /* if (Axis->blues[nn].flags & AF_LATIN_BLUE_SMALL_TOP )
++ {
++ if (metrics->root.scaler.face->size->metrics.x_ppem < 15)
++ threshold = 22;
++ else threshold = 40;
++ break;
++ }
++ if ( Axis->blues[nn].flags & AF_LATIN_BLUE_CAPITAL_TOP )
++ {
++ if (metrics->root.scaler.face->size->metrics.x_ppem < 15)
++ threshold = 40;
++ else threshold = 40;
++ break;
++ }
++ */
++
+ if ( blue )
+ {
+ FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
+- FT_Pos fitted = ( scaled + 40 ) & ~63;
++ FT_Pos fitted = ( scaled + threshold ) & ~63;
+
+
+ if ( scaled != fitted )
+@@ -1340,7 +1389,8 @@
+ if ( dist < 0 )
+ dist = -dist;
+
+- dist = FT_MulFix( dist, scale );
++ /* round down to pixels */
++ dist = FT_MulFix( dist, scale ) & ~63;
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+@@ -1500,9 +1550,33 @@
+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );
+
+
+- if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
+- axis->extra_light )
+- return width;
++ int checked_stem_snap_env = 0;
++ FT_Bool stem_snap_light = FALSE;
++
++ if ( checked_stem_snap_env == 0 )
++ {
++ char *stem_snap_env = getenv( "INFINALITY_FT_AUTOFIT_STEM_SNAP_LIGHT" );
++ if ( stem_snap_env != NULL )
++ {
++ if ( strcasecmp(stem_snap_env, "default" ) != 0 )
++ {
++ if ( strcasecmp(stem_snap_env, "true") == 0)
++ stem_snap_light = TRUE;
++ else if ( strcasecmp(stem_snap_env, "1") == 0)
++ stem_snap_light = TRUE;
++ else if ( strcasecmp(stem_snap_env, "on") == 0)
++ stem_snap_light = TRUE;
++ else if ( strcasecmp(stem_snap_env, "yes") == 0)
++ stem_snap_light = TRUE;
++ }
++ }
++ checked_stem_snap_env = 1;
++ }
++
++ if ( !stem_snap_light )
++ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
++ axis->extra_light )
++ return width;
+
+ if ( dist < 0 )
+ {
+@@ -1510,8 +1584,67 @@
+ sign = 1;
+ }
+
+- if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
+- ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
++ if ( stem_snap_light
++ && (
++ ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) )
++ || ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) )
++ {
++ dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
++
++ if ( metrics->root.scaler.face->size->metrics.x_ppem > 9
++ && axis->width_count > 0
++ && abs ( axis->widths[0].cur - dist ) < 32
++ && axis->widths[0].cur > 52 )
++ {
++ if ( strstr(metrics->root.scaler.face->style_name, "Regular")
++ || strstr(metrics->root.scaler.face->style_name, "Book")
++ || strstr(metrics->root.scaler.face->style_name, "Medium")
++ || strcmp(metrics->root.scaler.face->style_name, "Italic") == 0
++ || strcmp(metrics->root.scaler.face->style_name, "Oblique") == 0 )
++ {
++ /* regular weight */
++ if ( axis->widths[0].cur < 64 ) dist = 64 ;
++ else if (axis->widths[0].cur < 88) dist = 64;
++ else if (axis->widths[0].cur < 160) dist = 128;
++ else if (axis->widths[0].cur < 240) dist = 190;
++ else dist = ( dist ) & ~63;
++ }
++ else
++ {
++ /* bold gets a different threshold */
++ if ( axis->widths[0].cur < 64 ) dist = 64 ;
++ else if (axis->widths[0].cur < 108) dist = 64;
++ else if (axis->widths[0].cur < 160) dist = 128;
++ else if (axis->widths[0].cur < 222) dist = 190;
++ else if (axis->widths[0].cur < 288) dist = 254;
++ else dist = ( dist + 16 ) & ~63;
++ }
++
++ /* fix any unusually low values */
++ if (dist < ( axis->widths[0].cur & ~63 ) )
++ dist = (axis->widths[0].cur & ~63);
++
++ /* fix any unusually high values */
++ if (dist > ( ( axis->widths[0].cur + 64 ) & ~63 ) )
++ dist = ( ( axis->widths[0].cur + 64 ) & ~63 );
++
++ if (dist < 64 ) dist = 64 ;
++
++ }
++ if (dist < 52)
++ {
++ if (metrics->root.scaler.face->size->metrics.x_ppem < 9 )
++ {
++ /*dist = 64 - (64 - dist) / 2 ;*/
++ if (dist < 31) dist = 31;
++ }
++ else
++ dist = 52;
++ }
++
++ }
++ else if ( !stem_snap_light && (( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
++ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) )
+ {
+ /* smooth hinting process: very lightly quantize the stem width */
+
+@@ -1569,7 +1702,7 @@
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+- else
++ else if (!stem_snap_light)
+ {
+ /* strong hinting process: snap the stem width to integer pixels */
+ FT_Pos org_dist = dist;
+@@ -1577,6 +1710,8 @@
+
+ dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
+
++ if ( stem_snap_light ) goto Done_Width;
++
+ if ( vertical )
+ {
+ /* in the case of vertical hinting, always round */
+@@ -2100,7 +2235,30 @@
+ {
+ FT_Error error;
+ int dim;
++ int e_strength = 0;
++
++ int checked_embolden_light_env = 0;
++ FT_Bool embolden_light = FALSE;
+
++ if ( checked_embolden_light_env == 0 )
++ {
++ char *embolden_light_env = getenv( "INFINALITY_FT_AUTOFIT_EMBOLDEN_LIGHT" );
++ if ( embolden_light_env != NULL )
++ {
++ if ( strcasecmp(embolden_light_env, "default" ) != 0 )
++ {
++ if ( strcasecmp(embolden_light_env, "true") == 0)
++ embolden_light = TRUE;
++ else if ( strcasecmp(embolden_light_env, "1") == 0)
++ embolden_light = TRUE;
++ else if ( strcasecmp(embolden_light_env, "on") == 0)
++ embolden_light = TRUE;
++ else if ( strcasecmp(embolden_light_env, "yes") == 0)
++ embolden_light = TRUE;
++ }
++ }
++ checked_embolden_light_env = 1;
++ }
+
+ error = af_glyph_hints_reload( hints, outline );
+ if ( error )
+@@ -2146,8 +2304,15 @@
+ }
+ #endif
+
+- if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
+- ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
++ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) )
++ {
++ af_latin_hint_edges( hints, (AF_Dimension)dim );
++ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
++ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
++ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
++ }
++
++ if ( ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
+ {
+ af_latin_hint_edges( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
+@@ -2157,6 +2322,34 @@
+ }
+ af_glyph_hints_save( hints, outline );
+
++ /* if the font is particularly thin, embolden it, up to 1 px */
++ if ( embolden_light
++ && metrics->axis->widths[0].cur <= 80
++ && !( dim == AF_DIMENSION_VERT )
++ && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) )
++ {
++ if ( metrics->axis->widths[0].cur
++ / metrics->root.scaler.face->size->metrics.x_ppem < 5 )
++ {
++ /* weakest at width 80, stronger at lower widths */
++ e_strength = 40 * ( 80 - metrics->axis->widths[0].cur)/80 ;
++ /* Don't do low ppems as much */
++ if ( metrics->root.scaler.face->size->metrics.x_ppem < 9 )
++ e_strength -=
++ ( 9 - metrics->root.scaler.face->size->metrics.x_ppem ) * 10;
++ }
++
++ /* Embolden small fonts on a sliding scale. Better readability. */
++ if ( e_strength > 0
++ && ( strstr(metrics->root.scaler.face->style_name, "Regular")
++ || strstr(metrics->root.scaler.face->style_name, "Book")
++ || strstr(metrics->root.scaler.face->style_name, "Light")
++ || strstr(metrics->root.scaler.face->style_name, "Medium")
++ || strcmp(metrics->root.scaler.face->style_name, "Italic") == 0
++ || strcmp(metrics->root.scaler.face->style_name, "Oblique") == 0 ) )
++ FT_Outline_Embolden(outline,e_strength);
++ }
++
+ Exit:
+ return error;
+ }
+diff -Nur freetype-2.4.3.orig/src/autofit/afloader.c freetype-2.4.3.new/src/autofit/afloader.c
+--- freetype-2.4.3.orig/src/autofit/afloader.c 2009-07-03 08:28:24.000000000 -0500
++++ freetype-2.4.3.new/src/autofit/afloader.c 2010-10-22 22:22:04.073099288 -0500
+@@ -180,8 +180,8 @@
+ AF_Edge edge2 = edge1 +
+ axis->num_edges - 1; /* rightmost edge */
+
+-
+- if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
++/* dont hint metrics - temporary until different hinting can be done */
++ if ( FALSE && axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
+ {
+ old_rsb = loader->pp2.x - edge2->opos;
+ old_lsb = edge1->opos;
+@@ -214,7 +214,8 @@
+ slot->lsb_delta = loader->pp1.x - pp1x_uh;
+ slot->rsb_delta = loader->pp2.x - pp2x_uh;
+ }
+- else
++/* dont hint metrics - temporary until different hinting can be done */
++ else if (FALSE)
+ {
+ FT_Pos pp1x = loader->pp1.x;
+ FT_Pos pp2x = loader->pp2.x;
+diff -Nur freetype-2.4.3.orig/src/base/ftlcdfil.c freetype-2.4.3.new/src/base/ftlcdfil.c
+--- freetype-2.4.3.orig/src/base/ftlcdfil.c 2010-04-01 03:18:57.000000000 -0500
++++ freetype-2.4.3.new/src/base/ftlcdfil.c 2010-11-14 18:33:58.300770778 -0600
+@@ -21,9 +21,659 @@
+ #include FT_IMAGE_H
+ #include FT_INTERNAL_OBJECTS_H
+
++#include <math.h>
++#include <string.h>
++#include <strings.h>
+
+ #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
++/*
++int sinc( int val ) {
++ if (val == 0.0)
++ return(1.0);
++ return 256.0 * (sin(3.14*(double) (val/256.0))/(3.14*(double) (val/256.0)));
++}
++
++int sigmoidal( int val ) {
++ int val2;
++ val2 = 256.0 /(1.0+exp(-(10.0*(val/256.0-.5))));
++ return window(val2);
++}
++
++int window ( int val )
++{
++ if (val < 0 ) return 0;
++ if (val > 255) return 255;
++ else return val;
++}
++*/
++int gamma2 ( int val, float value ) {
++ return 256 * (1.0 - pow((1.0 - (float)val/ 256.0) , 1.0/value));
++}
++/*
++int gamma3 ( int val, float value ) {
++ 1- (x-1)^10
++}
++*/
++/*
++int gamma ( int val ) {
++ return 256 * (1.0 - pow((1.0 - (float)val/ 256.0) , 1.5));
++}
++
++int brick (int val) {
++ if (val > 50) return val;
++ else return 0;
++}
++
++int brick2 (int val) {
++ if (val > 100) return val;
++ if (val > 50) return 100;
++ else return 0;
++}
++
++int none (int val) {
++ return val;
++}
++
++float pixmoid (int val1, int val2, int val3, int testval)
++{
++ int avg;
++ int result;
++
++ avg = (val1 + val2 + val3)/3;
++
++ if ( avg < 128 )
++ {
++ if (testval > 128) result = avg;
++ else result = testval;
++ }
++ else
++ {
++ if (testval < 128) result = avg;
++ else result = testval;
++ }
++
++ return none(result);
++}
++
++float pixmoid2 (int val1, int val2, int val3, int testval)
++{
++ int avg;
++ int result;
++
++ avg = (val1 + val2 + val3)/3;
++
++ if ( avg > 160 ) return 255;
++ else if ( avg < 100 ) return 0;
++ else return testval;
++
++ return none(result);
++
++}
++*/
++/*
++bool Resample(FT_Byte* line, int newWidth, int newHeight)
++{
++
++ unsigned char* newData = new unsigned char [newWidth * newHeight * 3];
++
++ double scaleWidth = (double)newWidth / (double)_width;
++ double scaleHeight = (double)newHeight / (double)_height;
++
++ for(int cy = 0; cy < newHeight; cy++)
++ {
++ for(int cx = 0; cx < newWidth; cx++)
++ {
++ int pixel = (cy * (newWidth *3)) + (cx*3);
++ int nearestMatch = (((int)(cy / scaleHeight)
++ * (_width *3)) + ((int)(cx / scaleWidth) *3) );
++
++ newData[pixel ] = _data[nearestMatch ];
++ newData[pixel + 1] = _data[nearestMatch + 1];
++ newData[pixel + 2] = _data[nearestMatch + 2];
++ }
++ }
++
++ delete[] _data;
++ _data = newData;
++ _width = newWidth;
++ _height = newHeight;
++
++ return true;
++}*/
++
++
++ /* Stem alignment for bitmaps; A hack with very nice results */
++ /* Ideally this could be implemented on the outline, prior to
++ * rasterization */
++ static void
++ _lcd_stem_align ( FT_Bitmap* bitmap,
++ FT_Render_Mode mode,
++ FT_GlyphSlot slot )
++ {
++ /*FT_Byte* weights = library->lcd_weights;*/
++ FT_UInt width = (FT_UInt)bitmap->width;
++ FT_UInt height = (FT_UInt)bitmap->rows;
++
++ FT_UInt h;
++
++ FT_UInt alignment_type = 0;
++ FT_UInt checked_alignment_type = 0;
++ float pseudo_gamma_value = 1;
++ float pseudo_gamma_lt = 0;
++ FT_UInt checked_pseudo_gamma_value = 0;
++
++ if ( checked_alignment_type == 0)
++ {
++ char *alignment_type_env = getenv( "INFINALITY_FT_STEM_ALIGNMENT_TYPE" );
++ if ( alignment_type_env != NULL )
++ {
++ /*sscanf ( alignment_type_env, "%d", &alignment_type );*/
++ if (strcasecmp(alignment_type_env, "full") == 0) alignment_type = 1;
++ else if (strcasecmp(alignment_type_env, "medium") == 0) alignment_type = 2;
++ else if (strcasecmp(alignment_type_env, "medium1") == 0) alignment_type = 2;
++ else if (strcasecmp(alignment_type_env, "slight") == 0) alignment_type = 3;
++ else if (strcasecmp(alignment_type_env, "slight1") == 0) alignment_type = 3;
++ else if (strcasecmp(alignment_type_env, "medium2") == 0) alignment_type = 4;
++ else if (strcasecmp(alignment_type_env, "slight2") == 0) alignment_type = 5;
++ else if (strcasecmp(alignment_type_env, "infinality") == 0) alignment_type = 6;
++ else if (strcasecmp(alignment_type_env, "infinality1") == 0) alignment_type = 6;
++ else alignment_type = 0;
++
++ if ( /*strstr(slot.metrics->root.scaler.face->style_name, "Regular")
++ || strstr(slot.metrics->root.scaler.face->style_name, "Book")
++ || strstr(slot.metrics->root.scaler.face->style_name, "Medium")
++ ||*/ strcasestr(slot->face->style_name, "Italic")
++ || strcasestr(slot->face->style_name, "Oblique") )
++ alignment_type = 0;
++ if ( strcasestr(slot->face->style_name, "Bold") )
++ alignment_type = 0;
++ }
++ checked_alignment_type = 1;
++ }
++
++ if ( checked_pseudo_gamma_value == 0 )
++ {
++ char *pseudo_gamma_value_env = getenv( "INFINALITY_FT_PSEUDO_GAMMA" );
++ if ( pseudo_gamma_value_env != NULL )
++ {
++ float f1, f2;
++
++ if ( strcasecmp(pseudo_gamma_value_env, "default" ) != 0)
++ {
++ sscanf ( pseudo_gamma_value_env, "%f %f", &f1, &f2 );
++ pseudo_gamma_lt = f1;
++ pseudo_gamma_value = f2;
++ }
++ if ( pseudo_gamma_value < .1 ) pseudo_gamma_value = 1;
++ if ( pseudo_gamma_lt < 0 ) pseudo_gamma_lt = 1;
++ }
++ checked_pseudo_gamma_value = 1;
++ }
++
++ /*printf("%s,%s ", slot->face->family_name, slot->face->style_name);*/
++ /*printf("%d ", slot->face->size->metrics.x_ppem);*/
++
++ /* set gamma value to 1 if out of range */
++ if ( slot->face->size->metrics.x_ppem >= pseudo_gamma_lt )
++ {
++ pseudo_gamma_value = 1;
++ }
++
++ /* don't do alignment for < 10 */
++ if ( slot->face->size->metrics.x_ppem < 10 )
++ {
++ alignment_type = 0;
++ }
++
++ if ( mode == FT_RENDER_MODE_LCD )
++ {
++ if (width >= 4 && alignment_type != 0 )
++ {
++ FT_Byte* line = bitmap->buffer;
++ FT_Byte* lineabove = bitmap->buffer;
++ FT_Byte* linebelow = bitmap->buffer;
++
++ FT_UInt vsums[width], vtotals[width], offsetruns[width / 2][width/2];
++ FT_UInt offsetrank[width/2], offsetchosen, stemwidths[width], stemwidthsmax;
++ FT_UInt stemwidth, vstems = 0;
++
++ FT_UInt shift = 0;
++ FT_UInt xx;
++
++ FT_ULong rtotal = 0, vweight = 0, wtotal = 0;
++ FT_UInt lreached = 0, rreached = 0, rr = 0, ll = 0, testwidth;
++ FT_UInt lwidth = 0, loffset = 0, offset = 0, htotal = 0, windowstart;
++ FT_UInt windowelement;
++
++ line = bitmap->buffer;
++ rreached = 0; lreached = width, ll = width;
++
++ lwidth = 0;
++ loffset = 0;
++
++
++ /* initialize variables - can this be done inline??? */
++ for ( testwidth = 3; testwidth < 4; testwidth += 1 )
++ {
++ for ( offset = 0; offset < 3; offset +=1 )
++ {
++ offsetruns[offset][testwidth] = 0;
++ offsetrank[offset] = 0;
++ }
++ }
++ for ( xx = 0; xx < width; xx += 1 )
++ {
++ stemwidths[xx] = 0;
++ }
++
++
++ for ( h = (FT_UInt)bitmap->rows; h > 0; h--, line += bitmap->pitch )
++ {
++
++ if (rr > rreached) rreached = rr;
++ if (ll < lreached) lreached = ll;
++
++ rr = width;
++ ll = 0;
++ rtotal = 0;
++ htotal = 0;
++
++ /*stemwidthsmax = 0;*/
++ stemwidth = 0;
++
++
++ /* Calculate various sums and stem widths of glyph */
++ for ( xx = 0; xx < width; xx += 1 )
++ {
++ if (line[xx] >= 128)
++ {
++ stemwidth += 1;
++ /*if (stemwidth > stemwidthsmax) stemwidthsmax = stemwidth;*/ /* necessary ? */
++ }
++ else
++ {
++ if (xx > 0 && line[xx - 1] >= 128) stemwidths[stemwidth] += 1;
++ stemwidth = 0;
++ }
++
++ if (h == (FT_UInt)bitmap->rows) vsums[xx] = 0;
++ if ( h == (FT_UInt)bitmap->rows ) vtotals[xx] = 0;
++
++ if (line[xx] == 0) vsums[xx] -= 255;
++ else vsums[xx] += line[xx];
++ if (vsums[xx] < 0) vsums[xx] = 0;
++
++ if (ll == 0 && line[xx] != 0) ll = (xx);
++
++ if (line[xx] != 0) rr = (xx);
++
++ if (xx < width / 2) vweight -= line[xx];
++ else vweight += line[xx];
++
++ htotal += line [xx];
++ vtotals[xx] += line[xx];
++ }
++
++ if ( h < (FT_UInt)bitmap->rows ) lineabove = line - bitmap->pitch;
++ if ( h > 1 ) linebelow = line + bitmap->pitch;
++
++
++ /* Determine the offset at which the most weight of the glyph exists */
++ /* This is currently hard-coded at 3, but the code is here to adjust */
++ for ( testwidth = 3; testwidth < 4; testwidth += 1 )
++ {
++ /* test the widths at each of these offsets */
++ for ( offset = 0; offset < 3; offset +=1 )
++ {
++ /* test window of size testwidth, starting at offset */
++ rtotal = 0;
++ for ( windowstart = offset; windowstart < width;
++ windowstart += testwidth )
++ {
++ /* calculate total for this window */
++ wtotal = 0;
++ for ( windowelement = windowstart;
++ windowelement < windowstart + testwidth; windowelement += 1 )
++ if ( windowelement < width)
++ {
++ wtotal += line[windowelement];
++
++ /* Assign extra value to this subpixel under certain conditions */
++ if ( line[windowelement] == 255 )
++ {
++ /* favor if full pixels above and below */
++ if ( h < (FT_UInt)bitmap->rows
++ && lineabove[windowelement] == 255 )
++ wtotal += 10;
++ if ( h > 1 && linebelow[windowelement] == 255 )
++ wtotal += 10;
++
++ /* favor if full pixels next to them */
++ if ( windowelement > 0 && line[windowelement-1] == 255 )
++ {
++ wtotal += 10;
++ if ( windowelement > 1 && line[windowelement-2] == 255 )
++ {
++ wtotal += 10;
++ if ( windowelement > 2 && line[windowelement-3] == 255 )
++ wtotal += 10;
++ }
++ }
++ if ( windowelement < width - 1 && line[windowelement+1] == 255 )
++ {
++ wtotal += 10;
++ if ( windowelement < width - 2 && line[windowelement+2] == 255 )
++ {
++ wtotal += 10;
++ if ( windowelement < width - 3 && line[windowelement+3] == 255 )
++ wtotal += 10;
++ }
++ }
++ }
++ }
++ /* divide window total by number of subpixel samples */
++ /* add to total for this run */
++ rtotal += (wtotal * wtotal) / testwidth;
++ }
++ /* dont count horizontal stems */
++ /*if (rtotal < ( 255 * testwidth ) * (255 * testwidth) * (width / testwidth) / (testwidth * 2) )*/
++ if ( rtotal < ( 255 * 255 * width / 2 ) )
++ offsetruns[offset][testwidth] += rtotal;
++ }
++
++ /* determine the best offset for this width and increment its counter */
++ offsetchosen = 0;
++ for ( offset = 0; offset < 2; offset +=1 )
++ {
++ if ( offsetruns[offset][testwidth] < offsetruns[offset + 1][testwidth] ){
++ offsetrank[offset + 1] += 1;
++ offsetchosen = offset;
++ }
++ }
++ if (offsetchosen == 0) offsetrank[0] += 1;
++ }
++ }
++
++ /* Use the best offset */
++ loffset = 0;
++ for ( offset = 0; offset < 2; offset +=1 )
++ {
++ if ( offsetrank[offset] < offsetrank[offset + 1] ){
++ loffset = offset + 1;
++ }
++ }
++
++ /* Use the best width */
++ lwidth = 0;
++ stemwidthsmax = 0;
++
++ for ( xx = 0; xx < width - 1; xx +=1 )
++ {
++ if ( stemwidthsmax < stemwidths[xx + 1] ){
++ lwidth = xx + 1;
++ stemwidthsmax = stemwidths[xx + 1];
++ }
++ }
++
++ /* currently unused */
++ rreached = width - rreached;
++
++ /* Set the number of vertical stem components */
++ for ( xx = 0; xx < width; xx += 1 )
++ {
++ if ( height > 0 && vsums[xx] / height > 110 )
++ vstems++;
++ }
++
++
++ /******************** CALCULATE GLYPH ALIGNMENT *********************/
++ /*printf(" %d,%d,%d,%d,%d,%d,%d\n", width, height, lreached,
++ rreached, lwidth,vstems,alignment_type );*/
++
++ shift = 0;
++
++ /* infinality1 alignment - combination of below */
++ if ( alignment_type == 6 )
++ {
++ if ( lwidth < 5 ) alignment_type = 2;
++ else alignment_type = 1;
++ }
++
++ /* strong alignment - shift glyph left or right one subpixel */
++ if ( alignment_type == 1 /*&& vstems > 0*/ )
++ {
++ if ( lwidth < 5)
++ {
++ /* lower widths should use this */
++ if (loffset % 3 == 0) shift = -1;
++ if (loffset % 3 == 1) shift = 1;
++ if (loffset % 3 == 2) shift = 0;
++ }
++ else if ( lwidth < 6 )
++ {
++ /* medium widths should use this */
++ if (loffset % 3 == 0) shift = 1;
++ if (loffset % 3 == 1) shift = 0;
++ if (loffset % 3 == 2) shift = -1;
++ }
++ else if ( lwidth < 20 )
++ {
++ /* higher widths should use this */
++ if (loffset % 3 == 0) shift = 1;
++ if (loffset % 3 == 1) shift = -1;
++ if (loffset % 3 == 2) shift = 0;
++ }
++ }
++
++ /* medium alignment - shift glyph ONLY LEFT one subpixel
++ * - a compromise to prevent spacing issues */
++ else if ( alignment_type == 2 /*&& vstems > 0*/ ){
++
++ if ( lwidth < 5 )
++ {
++ /* medium alignment - use next highest value instead */
++ if ( loffset == 1 && offsetrank[0] > offsetrank[2] ) loffset = 0;
++
++ if ( loffset % 3 == 0 ) shift = -1;
++ /*if (loffset % 3 == 1 ) shift = 1;*/
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ else if (lwidth < 6 )
++ {
++ /* medium alignment - use next highest value instead */
++ if ( loffset == 0 && offsetrank[2] > offsetrank[1] ) loffset = 2;
++ /*if (loffset % 3 == 0 ) shift = 1;*/
++ if ( loffset % 3 == 1 ) shift = 0;
++ if ( loffset % 3 == 2 ) shift = -1;
++ }
++ else if ( lwidth < 20 )
++ {
++ /* medium alignment - use next highest value instead */
++ if ( loffset == 0 && offsetrank[1] > offsetrank[2] ) loffset = 1;
++ /*if (loffset % 3 == 0 ) shift = 1;*/
++ if ( loffset % 3 == 1 ) shift = -1;
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ }
++
++ /* medium alignment 2 - shift glyph ONLY RIGHT one subpixel
++ * - a compromise to prevent spacing issues */
++ else if ( alignment_type == 4 ){
++ if ( lwidth < 5 )
++ {
++ /* medium alignment - use next highest value instead */
++ if ( loffset == 0 && offsetrank[1] > offsetrank[2] ) loffset = 1;
++
++ /*if ( loffset % 3 == 0 ) shift = -1;*/
++ if ( loffset % 3 == 1 ) shift = 1;
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ else if ( lwidth < 6 )
++ {
++ /* medium alignment - use next highest value instead */
++ if ( loffset == 2 && offsetrank[0] > offsetrank[1] ) loffset = 0;
++ if ( loffset % 3 == 0 ) shift = 1;
++ if ( loffset % 3 == 1 ) shift = 0;
++ /*if ( loffset % 3 == 2 ) shift = -1;*/
++ }
++ else if ( lwidth < 20 )
++ {
++ /* medium alignment - use next highest value instead */
++ if ( loffset == 1 && offsetrank[0] > offsetrank[2] ) loffset = 0;
++ if ( loffset % 3 == 0 ) shift = 1;
++ /*if (loffset % 3 == 1 ) shift = -1;*/
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ }
++
++ /* light alignment - shift glyph ONLY LEFT one subpixel
++ * - a compromise to prevent spacing issues */
++ else if ( alignment_type == 3 ){
++ if ( lwidth < 5 )
++ {
++ if ( loffset % 3 == 0 ) shift = -1;
++ /*if ( loffset % 3 == 1 ) shift = 1;*/
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ else if ( lwidth < 6 )
++ {
++ /*if ( loffset % 3 == 0 ) shift = 1;*/
++ if ( loffset % 3 == 1 ) shift = 0;
++ if ( loffset % 3 == 2 ) shift = -1;
++ }
++ else if ( lwidth < 20 )
++ {
++ /*if ( loffset % 3 == 0 ) shift = 1;*/
++ if ( loffset % 3 == 1 ) shift = -1;
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ }
++
++ /* light alignment 2 - shift glyph ONLY RIGHT one subpixel
++ * - a compromise to prevent spacing issues */
++ else if ( alignment_type == 5 ){
++ if ( lwidth < 5 )
++ {
++ /*if ( loffset % 3 == 0 ) shift = -1;*/
++ if ( loffset % 3 == 1 ) shift = 1;
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ else if ( lwidth < 6 )
++ {
++ if ( loffset % 3 == 0 ) shift = 1;
++ if ( loffset % 3 == 1 ) shift = 0;
++ /*if ( loffset % 3 == 2 ) shift = -1;*/
++ }
++ else if ( lwidth < 20 )
++ {
++ if ( loffset % 3 == 0 ) shift = 1;
++ /*if ( loffset % 3 == 1 ) shift = -1;*/
++ if ( loffset % 3 == 2 ) shift = 0;
++ }
++ }
++
++ /******************** ALIGN GLYPHS *********************/
++ if (shift == -1)
++ {
++ line = bitmap->buffer;
++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--,
++ line += bitmap->pitch )
++ {
++ FT_UInt xx;
++
++ for ( xx = 0; xx < width - 1; xx += 1 )
++ {
++ line[xx] = line[xx+1];
++ }
++ line[width - 1] = 1;
++ }
++ }
++
++ else if (shift == -2)
++ {
++ line = bitmap->buffer;
++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--,
++ line += bitmap->pitch )
++ {
++ FT_UInt xx;
++
++ for ( xx = 0; xx < width - 2; xx += 1 )
++ {
++ line[xx] = line[xx+2];
++ }
++ line[width - 2] = 1;
++ line[width - 1] = 1;
++ }
++ }
++ else if (shift == 1)
++ {
++ line = bitmap->buffer;
++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--,
++ line += bitmap->pitch )
++ {
++ FT_UInt xx;
++
++ for ( xx = width - 1; xx > 0; xx -= 1 )
++ {
++ line[xx] = line[xx-1];
++ }
++ line[0] = 1;
++ }
++ }
++ else if (shift == 2)
++ {
++ line = bitmap->buffer;
++ for ( height = (FT_UInt)bitmap->rows; height > 0; height--,
++ line += bitmap->pitch )
++ {
++ FT_UInt xx;
++
++ for ( xx = width; xx > 1; xx -= 1 )
++ {
++ line[xx] = line[xx-2];
++ }
++ line[0] = 1;
++ line[1] = 1;
++ }
++ }
++ }
++
++ if ( pseudo_gamma_value != 1 )
++ {
++ FT_Byte* line = bitmap->buffer;
++ float ppem = (float)slot->face->size->metrics.x_ppem;
++
++ if (ppem >= 5 )
++ for (height = (FT_UInt)bitmap->rows; height > 0; height--, line += bitmap->pitch )
++ {
++ FT_UInt xx;
++
++ for ( xx = 0; xx < width; xx += 1 )
++ {
++ /*normal*/
++ /*line[xx] = gamma2 ( line[xx], pseudo_gamma_value );*/
++
++ /* sloped */
++ /*line[xx] = gamma2 ( line[xx], pseudo_gamma_value - 5
++ * (1-pseudo_gamma_value)/(pseudo_gamma_lt -5)
++ + ((1-pseudo_gamma_value)/(pseudo_gamma_lt -5)) * ppem );*/
++
++ /* 1/3-sloped */
++ line[xx] = gamma2 ( line[xx], pseudo_gamma_value - 5
++ * ((1-pseudo_gamma_value)/(3*(pseudo_gamma_lt -5)))
++ * + ((1-pseudo_gamma_value)/(3*(pseudo_gamma_lt -5))) * ppem );
++ }
++ }
++ }
++ }
++ }
++
++
++
++
++
++
+ /* define USE_LEGACY to implement the legacy filter */
+ #define USE_LEGACY
+
+@@ -287,9 +1017,31 @@
+ { 0x00, 0x55, 0x56, 0x55, 0x00 };
+ /* the values here sum up to a value larger than 256, */
+ /* providing a cheap gamma correction */
+- static const FT_Byte default_filter[5] =
++ static FT_Byte default_filter[5] =
+ { 0x10, 0x40, 0x70, 0x40, 0x10 };
+
++ int checked_filter_params_env = 0;
++
++ if ( checked_filter_params_env == 0 )
++ {
++ char *filter_params = getenv( "INFINALITY_FT_FILTER_PARAMS" );
++ if ( filter_params != NULL )
++ {
++ float f1, f2, f3, f4, f5;
++
++ if ( strcasecmp(filter_params, "default" ) != 0)
++ {
++ sscanf ( filter_params, "%f %f %f %f %f", &f1, &f2, &f3, &f4, &f5 );
++
++ default_filter[0] = (FT_Byte) (f1 * 255.0f + 0.5f);
++ default_filter[1] = (FT_Byte) (f2 * 255.0f + 0.5f);
++ default_filter[2] = (FT_Byte) (f3 * 255.0f + 0.5f);
++ default_filter[3] = (FT_Byte) (f4 * 255.0f + 0.5f);
++ default_filter[4] = (FT_Byte) (f5 * 255.0f + 0.5f);
++ }
++ }
++ checked_filter_params_env = 1;
++ }
+
+ if ( !library )
+ return FT_Err_Invalid_Argument;
+@@ -304,17 +1056,20 @@
+ case FT_LCD_FILTER_DEFAULT:
+ #if defined( FT_FORCE_LEGACY_LCD_FILTER )
+
++ library->lcd_stem_align_func = _lcd_stem_align;
+ library->lcd_filter_func = _ft_lcd_filter_legacy;
+ library->lcd_extra = 0;
+
+ #elif defined( FT_FORCE_LIGHT_LCD_FILTER )
+
++ library->lcd_stem_align_func = _lcd_stem_align;
+ ft_memcpy( library->lcd_weights, light_filter, 5 );
+ library->lcd_filter_func = _ft_lcd_filter_fir;
+ library->lcd_extra = 2;
+
+ #else
+
++ library->lcd_stem_align_func = _lcd_stem_align;
+ ft_memcpy( library->lcd_weights, default_filter, 5 );
+ library->lcd_filter_func = _ft_lcd_filter_fir;
+ library->lcd_extra = 2;
+@@ -325,6 +1080,7 @@
+
+ case FT_LCD_FILTER_LIGHT:
+ ft_memcpy( library->lcd_weights, light_filter, 5 );
++ library->lcd_stem_align_func = _lcd_stem_align;
+ library->lcd_filter_func = _ft_lcd_filter_fir;
+ library->lcd_extra = 2;
+ break;
+@@ -332,6 +1088,7 @@
+ #ifdef USE_LEGACY
+
+ case FT_LCD_FILTER_LEGACY:
++ library->lcd_stem_align_func = _lcd_stem_align;
+ library->lcd_filter_func = _ft_lcd_filter_legacy;
+ library->lcd_extra = 0;
+ break;
+diff -Nur freetype-2.4.3.orig/src/base/ftobjs.c freetype-2.4.3.new/src/base/ftobjs.c
+--- freetype-2.4.3.orig/src/base/ftobjs.c 2010-08-06 13:02:15.000000000 -0500
++++ freetype-2.4.3.new/src/base/ftobjs.c 2010-11-14 15:43:02.906303324 -0600
+@@ -562,6 +562,45 @@
+ FT_Bool autohint = FALSE;
+ FT_Module hinter;
+
++ TT_Face face2=(TT_Face)face;
++ int checked_auto_autohint_env;
++ FT_Bool auto_autohint = FALSE;
++
++ if ( !checked_auto_autohint_env )
++ {
++ char *auto_autohint_env = getenv( "INFINALITY_FT_AUTO_AUTOHINT" );
++ if ( auto_autohint_env != NULL )
++ {
++ if ( strcasecmp(auto_autohint_env, "default" ) != 0 )
++ {
++ if ( strcasecmp(auto_autohint_env, "true") == 0) auto_autohint = TRUE;
++ else if ( strcasecmp(auto_autohint_env, "1") == 0) auto_autohint = TRUE;
++ else if ( strcasecmp(auto_autohint_env, "on") == 0) auto_autohint = TRUE;
++ else if ( strcasecmp(auto_autohint_env, "yes") == 0) auto_autohint = TRUE;
++ }
++ }
++ checked_auto_autohint_env = 1;
++ }
++/*printf("%d,%d ", load_flags, FT_LOAD_TARGET_NORMAL);
++10000001000101000
++0#define FT_LOAD_DEFAULT 0x0
++0#define FT_LOAD_NO_SCALE 0x1
++0#define FT_LOAD_NO_HINTING 0x2
++1#define FT_LOAD_RENDER 0x4
++0#define FT_LOAD_NO_BITMAP 0x8
++1#define FT_LOAD_VERTICAL_LAYOUT 0x10
++0#define FT_LOAD_FORCE_AUTOHINT 0x20
++0#define FT_LOAD_CROP_BITMAP 0x40
++0#define FT_LOAD_PEDANTIC 0x80
++1#define FT_LOAD_ADVANCE_ONLY 0x100
++0#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200
++0#define FT_LOAD_NO_RECURSE 0x400
++0#define FT_LOAD_IGNORE_TRANSFORM 0x800
++0#define FT_LOAD_MONOCHROME 0x1000
++0#define FT_LOAD_LINEAR_DESIGN 0x2000
++0#define FT_LOAD_SBITS_ONLY 0x4000
++1#define FT_LOAD_NO_AUTOHINT 0x8000U
++*/
+
+ if ( !face || !face->size || !face->glyph )
+ return FT_Err_Invalid_Face_Handle;
+@@ -627,8 +666,11 @@
+
+
+ if ( mode == FT_RENDER_MODE_LIGHT ||
+- face->internal->ignore_unpatented_hinter )
++ face->internal->ignore_unpatented_hinter ||
++ ( auto_autohint && face2->max_profile.maxSizeOfInstructions == 0 ) )
++ {
+ autohint = TRUE;
++ }
+ }
+ }
+
+diff -Nur freetype-2.4.3.orig/src/base/ftoutln.c freetype-2.4.3.new/src/base/ftoutln.c
+--- freetype-2.4.3.orig/src/base/ftoutln.c 2010-06-27 08:03:58.000000000 -0500
++++ freetype-2.4.3.new/src/base/ftoutln.c 2010-11-14 09:06:38.779916717 -0600
+@@ -888,6 +888,28 @@
+ FT_Int c, n, first;
+ FT_Int orientation;
+
++ int checked_enhanced_embolden_env = 0;
++ FT_Bool enhanced_embolden = FALSE;
++
++ if ( checked_enhanced_embolden_env == 0 )
++ {
++ char *enhanced_embolden_env = getenv( "INFINALITY_FT_ENHANCED_EMBOLDEN" );
++ if ( enhanced_embolden_env != NULL )
++ {
++ if ( strcasecmp(enhanced_embolden_env, "default" ) != 0 )
++ {
++ if ( strcasecmp(enhanced_embolden_env, "true") == 0)
++ enhanced_embolden = TRUE;
++ else if ( strcasecmp(enhanced_embolden_env, "1") == 0)
++ enhanced_embolden = TRUE;
++ else if ( strcasecmp(enhanced_embolden_env, "on") == 0)
++ enhanced_embolden = TRUE;
++ else if ( strcasecmp(enhanced_embolden_env, "yes") == 0)
++ enhanced_embolden = TRUE;
++ }
++ }
++ checked_enhanced_embolden_env = 1;
++ }
+
+ if ( !outline )
+ return FT_Err_Invalid_Argument;
+@@ -957,7 +979,8 @@
+ }
+
+ outline->points[n].x = v_cur.x + strength + in.x;
+- outline->points[n].y = v_cur.y + strength + in.y;
++ if ( !enhanced_embolden )
++ outline->points[n].y = v_cur.y + strength + in.y;
+
+ v_prev = v_cur;
+ v_cur = v_next;
+diff -Nur freetype-2.4.3.orig/src/base/ftsynth.c freetype-2.4.3.new/src/base/ftsynth.c
+--- freetype-2.4.3.orig/src/base/ftsynth.c 2010-09-11 01:28:32.000000000 -0500
++++ freetype-2.4.3.new/src/base/ftsynth.c 2010-11-14 09:19:16.860168106 -0600
+@@ -88,9 +88,28 @@
+ FT_Error error;
+ FT_Pos xstr, ystr;
+
++ int checked_enhanced_embolden_env = 0;
++ FT_Bool enhanced_embolden = FALSE;
++
++ if ( checked_enhanced_embolden_env == 0 )
++ {
++ char *enhanced_embolden_env = getenv( "INFINALITY_FT_EMBOLDEN_MAINTAIN_WIDTH" );
++ if ( enhanced_embolden_env != NULL )
++ {
++ if ( strcasecmp(enhanced_embolden_env, "default" ) != 0 )
++ {
++ if ( strcasecmp(enhanced_embolden_env, "true") == 0) enhanced_embolden = TRUE;
++ else if ( strcasecmp(enhanced_embolden_env, "1") == 0) enhanced_embolden = TRUE;
++ else if ( strcasecmp(enhanced_embolden_env, "on") == 0) enhanced_embolden = TRUE;
++ else if ( strcasecmp(enhanced_embolden_env, "yes") == 0) enhanced_embolden = TRUE;
++ }
++ }
++ checked_enhanced_embolden_env = 1;
++ }
++
+
+ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
+- slot->format != FT_GLYPH_FORMAT_BITMAP )
++ slot->format != FT_GLYPH_FORMAT_BITMAP )
+ return;
+
+ /* some reasonable strength */
+@@ -108,7 +127,7 @@
+ xstr = xstr * 2;
+ ystr = xstr;
+ }
+- else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
++ else if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
+ {
+ /* round to full pixels */
+ xstr &= ~63;
+@@ -146,7 +165,8 @@
+ slot->metrics.width += xstr;
+ slot->metrics.height += ystr;
+ slot->metrics.horiBearingY += ystr;
+- slot->metrics.horiAdvance += xstr;
++ /* Don't add any horiAdvance - Personal preference */
++ if ( !enhanced_embolden ) slot->metrics.horiAdvance += xstr;
+ slot->metrics.vertBearingX -= xstr / 2;
+ slot->metrics.vertBearingY += ystr;
+ slot->metrics.vertAdvance += ystr;
+diff -Nur freetype-2.4.3.orig/src/smooth/ftsmooth.c freetype-2.4.3.new/src/smooth/ftsmooth.c
+--- freetype-2.4.3.orig/src/smooth/ftsmooth.c 2010-08-09 19:47:47.000000000 -0500
++++ freetype-2.4.3.new/src/smooth/ftsmooth.c 2010-11-07 11:17:08.693652341 -0600
+@@ -283,6 +283,9 @@
+ vec->y /= 3;
+ }
+
++ if ( slot->library->lcd_stem_align_func )
++ slot->library->lcd_stem_align_func ( bitmap, mode, slot );
++
+ if ( slot->library->lcd_filter_func )
+ slot->library->lcd_filter_func( bitmap, mode, slot->library );