diff options
Diffstat (limited to 'testing/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch')
-rw-r--r-- | testing/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch | 1602 |
1 files changed, 1602 insertions, 0 deletions
diff --git a/testing/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch b/testing/freetype-infinality/freetype-entire-infinality-patchset-20101114-1.patch new file mode 100644 index 0000000000..aae5faddee --- /dev/null +++ b/testing/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 ); |