Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- freetype-entire-infinality-patchset-20111223-01.patch
- -------------------------------------------------------------------
- (excludes the TT subpixel patches, which are required )
- This should patch to a subpixel-patched Freetype 2.4.8. Additional
- required files are also contained in the zipfile here:
- http://www.infinality.net/blog/infinality-freetype-patches/
- You will need to include this file in your profile with something like:
- /etd/profile.d/infinality-settings.sh
- You'll need a file named (for 64 bit)
- /etc/ld.so.conf.d/freetype-infinality-x86_64.conf that contains:
- /usr/lib64/freetype-infinality
- Or a file named (for 32 bit)
- /etc/ld.so.conf.d/freetype-infinality-i386.conf that contains:
- /usr/lib/freetype-infinality
- Please see each file for more detailed information.
- If you are using this patch, you should also use the fontconfig configuration
- also found at the above link.
- The fedora packages I provide take care of all this for you.
- 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!
- Changes for 2011-12-23:
- Fixes / Tweaks:
- * Courier New Hack for '2'.
- * Tweak Arial 16px a bit.
- * Various tweaks on Courier New, Times NR, Arial, Verdana and others that
- create a general improvement in appearance at certain ppems.
- * Fixes on some Cyrillic glyphs.
- * Pragmata Pro and Pragmata added to patches.
- * Be a little more conservative in the way "known settings" of fonts are done.
- * Many small improvements to the subpixel hinting patch.
- * Fix a crasher in the Windows sharpening algorithm.
- * Noticible improvement on spacing in Tahoma 11px, Arial 11px, and other Arial
- clones. Me likey.
- * Code fixes to prevent some warnings and possible crashes. (Thanks banta)
- * Fix Opera and Firefox crashes. slot->face->style_name and
- slot->face->family_name need to be checked for not NULL before using.
- Changes for 2011-11-17:
- Features:
- * Added a post-render, pre-lcd-filter filter that attempts to duplicate windows
- sharpness / graininess. Controlled by
- INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH.
- * Added a fringe filter, intended mostly for autohint (but still effective
- for certain cases of TT hinting). This attempts to remove gray fringes that
- sometimes occur on horizontal stems and angled serifs and doodads
- (Times, Segoe '1', etc.)
- * Added a grayscale filter.
- * Added brightness/contrast filter.
- * Substantial improvements in the stem alignment algorithm! Wow!
- * Stem alignment now also happens on grayscale antialiased fonts (rgba=none).
- Fixes / Tweaks:
- * Changes inside of local.conf, which are documented there.
- * Removed an artificial shift of 1/8 pixel to the right on stem aligned glyphs
- which should result in sharper looking alignment.
- * Added XFT_SETTINGS into infinality-settings.sh. This means it will require
- less configuration on the end-user side.
- * Fixed code to not touch bold, thin, narrow or italic faces for scale or
- alignment (until they can be properly accounted for).
- * Added -lm dependency to the code again. (It seems to sneak off now and then)
- * Changed autohinter horizontal stem stem snapping from on/off to use a value
- between 0 and 100.
- * Functions getenv() and system() were crashing evince in _lcd_stem_align()
- at odd times. A workaround has been put in place.
- * Moved _lcd_stem_align and all other filters into ftsmooth.c, which is a better place.
- * Use malloc() in _lcd_stem_align for allocating structs and arrays of structs
- instead of what I learned in C++ class 10+ years ago. Should prevent abiword
- from crashing with large pt sizes like 3000. (A workaround has been put
- in place to automatically skip alignment on any ppem > 100. This will
- prevent the crashes until the real solution can be figured out.)
- * Fix some compiler warnings. Some are still present.
- * Added "m" control to alignment algorithm. This will cause all stems to m
- (or other 3-pronged glyphs) to get aligned to pixels. It still needs a bit
- of work, as it makes the best looking glyph size change. This is because
- the glyph now needs to snap stems to only even or odd pixels, not single ones.
- * Added rules to allow "compatible widths" (i.e. widths if the font were being
- bitmap TT hinted) on a glyph by glyph basis and tweaked certain fonts like
- arial, verdana, times new roman, segoe ui, and trebuchet to use them.
- * Don't stem align anything below 9 ppem because it is not consistently good.
- * When doing stem alignment, automatically align stems to center of pixel or
- start of pixel when necessary. When horizontal stems start snapping to 2 px,
- so should the vertical ones in order for it to look nice.
- * A Verdana 12 hack to make it render more like Windows. This notoriously
- poor looking ppem now looks as good as Verdana 13 without needing fontconfig
- replacement.
- * Courier New now looks good, and possibly better than Windows rendering, with
- TT or autohint rendering. By the way, the hinters of Courier New should
- either be commended or executed.
- * Improvements in overshoot artifact and fringe correction- Freesans at large
- ppem looks nice now. Overshoots on letters like 6, g, s, 3, etc. will
- now be rounded to integer pixels.
- * Wrap all infinality code within a macro that is set in ftoption.h:
- #ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET. Makes it easier to identify
- in the code and allows for easy compliation with or without the patches set.
- * Variable renaming for more clarity, in code and in environment variables.
- * Move stretching code into Freetype instead of relying on programs to handle
- fontconfig matrix (they SUCK at it... *cough* Chrome *cough*).
- * Additional modifications to the TT subpixel rendering rules for corrections
- to Georgia, DejaVu Sans, Times New Roman, Courier New and a couple others.
- * A general improvement in the way autohinted fonts render, particularly on
- ones that normally look fragile or thin. Examples include Optima, Freemono,
- Freeserif, Raleway, MgOpen, etc. I'm doing what Windows does, which is
- brightness/contrast adjustment, except you don't see rainbows.
- Changes for 2011-06-04:
- MISSING
- ====================================================================
- ============= ANYTHING BELOW HERE MAY BE INACCURATE NOW ============
- ====================================================================
- Changes for 2010-11-14:
- * Rule tweaks on various fonts. Fixed the Cyrillic y issue and e issue
- with Trebuchet, and the ^ issue with Arial. Other issues
- (firefox and @font-face) are still present to a degree.
- * A couple new rules to deal with various issues. (work in progress)
- * Additional commenting.
- * Some cleanup of obsolete code.
- * Added some debugging code for potential future enhancements. Please
- ignore the mess.
- Changes for 2010-10-22:
- * I'm refocusing on just getting the subpixel looking nice, so I've stripped
- back the rendering modes to just 2. The standard SUBPIXEL_HINTING and
- the ADDITIONAL_TWEAKS. The rules structure is still in place. I recommend
- using ADDITIONAL_TWEAKS mode.
- * Fixed an issue with monochrome rendering that made fonts look really bad.
- There is still an issue with them, but they are at least tolerable to
- look at now.
- * Added some testing code for detecting inline delta functions. Not sure
- if this is useful yet.
- * Added more rules to deal with certain artifacts on various fonts, like the
- issue with < > and ^. Created some "exception" rules for certain rules.
- * Reverted back to older rounding functions. The new experimental ones I
- was trying were causing artifacts on some fonts.
- * Some code cleanup.
- Changes for 2010-10-08:
- * Fix PDF crashes.
- Changes for 2010-10-04:
- * Update to freetype-2.4.3
- Changes for 2010-10-03:
- * There are lots of changes for this one, some big, some small, and some
- that still are not implemented. Not sure if I can remember them all
- but I will try! THIS IS A POINT RELEASE THAT IS NOT
- INTENDED TO WORK 100%. Some fonts and compile options may be broken
- and the code may be inefficient and/or not syntactiacally correct.
- That said, I do plan on using this on my system right away.
- * There are now "rendering modes" for the subpixel hinting, with the idea
- that this will enventually be able to be controlled by fontconfig. The 4
- modes of enhanced hinting defined so far are:
- 1) NATIVE HINTING - this is what freetype TT interpreter does by default.
- 2) FIXED NATIVE HINTING - A slighly tweaked version of the above that
- does "better" native rendering when displaying on LCD, for those
- that still seem to like incorrect, thin fonts, which were only ever
- there due to technical limitations.
- 3) SUBPIXEL OPTIMIZED HINTING - this is straight up subpixel hinting with
- very few tweaks. Just enough to get it working.
- 4) COMPATIBILITY MODE HINTING - this is the sweet spot I'm working on
- that will hopefully supplant #3 because it will work so well with all
- fonts. The idea here is to tweak all available fonts so that each
- renders well.
- All of these modes either turn on or off switches in the interpreter
- to make the fonts render properly for each mode. Right now these are only
- compile-time options.
- * Subpixel-related code has been broken out into its own files, so as to not
- clutter up the existing code.
- * The rasterizer now pays attention to the additional bits of MS rasterizer
- v. 37, meaning that it can now indicate to fonts that it can handle
- subpixel rendering.
- * The rounding functions have been adapted to accept a grid resolution
- variable, which lets them work on pixel and subpixel boundaries
- automatically. Y still needs to be implemented.
- * Additional conditions have been added to the switches, to further refine
- how they are applied to different fonts.
- * What all this means qualitatively is that legacy fonts now render much
- better. There are still some that need a bit of love, like Courier New.
- - Courier New has some fixes, and some breakage (Ghost pixels above bold
- fonts, too thin on regular font)
- - Times New Roman has some fixes and breakage (serifs, particularly)
- - Tahoma and Trebuchet MS have been cleaned up
- - Arial now snaps to grid better, but that causes breakage on a few glyphs
- - Verdana 13 is now set to grid fit, but some glyhs are broken (mwxyz)
- - Geneva and Geneva CY no longer look like turds
- - Lucida Sans Unicode now looks arguably better than Lucida Grande
- Changes for 2010-09-16:
- * The changes from 2010-09-14 regarding subpixel when LIGHT hinting enabled
- have been reverted due to problems. The old behavior is back.
- * Disable grayscale when subpixel is enabled. This results in better
- behavior of some TT instructions within some fonts, like Times New Roman.
- * Some modification of the tweaks, in light of above.
- Changes for 2010-09-14:
- /************************** NO LONGER IN PLACE *****************************/
- * Subpixel hinting is now used when the LIGHT hinting method and the TT
- hinting is called. If FULL hinting is requested it will do the usual
- behavior of the TT hinter.
- This allows for all previously existing behavior, plus the new subpixel
- hinting behavior, all in the same compile, and it makes sense in that
- the slight hinting of the autohinter is essentially doing the same thing
- as this, which is not forcing X-direction hints.
- Previously, even if TT was selected, but LIGHT hinting was used, the
- autohinter would still be forced. Other than this, autohint is not affected.
- /***************************************************************************/
- * Added a couple more conditionals around things to test whether subpixel
- hinting is enabled. There were a few missing that ended up causing some
- goofy hinting if subpixel was not enabled, but compiled in.
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' configure.orig configure
- --- configure.orig 2010-10-05 05:25:56.000000000 -0500
- +++ configure 2011-11-17 21:00:16.199774763 -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 -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' include/freetype/config/ftoption.h.orig include/freetype/config/ftoption.h
- --- include/freetype/config/ftoption.h.orig 2011-11-17 20:59:44.149885785 -0600
- +++ include/freetype/config/ftoption.h 2011-11-17 21:00:16.225773867 -0600
- @@ -473,6 +473,19 @@
- /*************************************************************************/
- + /* */
- + /* Define FT_CONFIG_OPTION_INFINALITY_PATCHSET if you want to enable */
- + /* all additional infinality patches, which are configured via env */
- + /* variables. */
- + /* */
- + /* This option requires TT_CONFIG_OPTION_SUBPIXEL_HINTING and */
- + /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS to be */
- + /* defined. */
- + /* */
- +#define FT_CONFIG_OPTION_INFINALITY_PATCHSET
- +
- +
- + /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** S F N T D R I V E R C O N F I G U R A T I O N ****/
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' include/freetype/ftoutln.h.orig include/freetype/ftoutln.h
- --- include/freetype/ftoutln.h.orig 2011-04-12 17:25:07.000000000 -0500
- +++ include/freetype/ftoutln.h 2011-12-12 18:30:36.308161754 -0600
- @@ -349,6 +349,10 @@
- FT_Outline_Embolden( FT_Outline* outline,
- FT_Pos strength );
- + FT_EXPORT( FT_Error )
- + FT_Outline_Embolden_XY( FT_Outline* outline,
- + FT_Pos strength_x,
- + FT_Pos strength_y );
- /*************************************************************************/
- /* */
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/autofit/aflatin.c.orig src/autofit/aflatin.c
- --- src/autofit/aflatin.c.orig 2011-06-20 12:03:27.000000000 -0500
- +++ src/autofit/aflatin.c 2011-12-12 18:11:57.518724747 -0600
- @@ -22,6 +22,7 @@
- #include "aflatin.h"
- #include "aferrors.h"
- +#include "strings.h"
- #ifdef AF_CONFIG_OPTION_USE_WARPER
- @@ -528,7 +529,30 @@
- FT_Pos delta;
- AF_LatinAxis axis;
- FT_UInt nn;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int checked_adjust_heights_env = 0;
- + FT_Bool adjust_heights = FALSE;
- + if ( checked_adjust_heights_env == 0 )
- + {
- + char *adjust_heights_env = getenv( "INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_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;
- + }
- +#endif
- if ( dim == AF_DIMENSION_HORZ )
- {
- @@ -537,8 +561,8 @@
- }
- else
- {
- - scale = scaler->y_scale;
- - delta = scaler->y_delta;
- + scale = scaler->y_scale /* * 1.033*/;
- + delta = scaler->y_delta /*- 16*/;
- }
- axis = &metrics->axis[dim];
- @@ -556,7 +580,7 @@
- {
- AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT];
- AF_LatinBlue blue = NULL;
- -
- + int threshold = 40;
- for ( nn = 0; nn < Axis->blue_count; nn++ )
- {
- @@ -566,12 +590,16 @@
- break;
- }
- }
- -
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( adjust_heights
- + && metrics->root.scaler.face->size->metrics.x_ppem < 15
- + && metrics->root.scaler.face->size->metrics.x_ppem > 5 )
- + threshold = 52;
- +#endif
- 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 )
- {
- @@ -626,7 +654,6 @@
- AF_LatinBlue blue = &axis->blues[nn];
- FT_Pos dist;
- -
- blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
- blue->ref.fit = blue->ref.cur;
- blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
- @@ -635,7 +662,12 @@
- /* a blue zone is only active if it is less than 3/4 pixels tall */
- dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
- +
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* Do always, in order to prevent fringes */
- +#else
- if ( dist <= 48 && dist >= -48 )
- +#endif
- {
- #if 0
- FT_Pos delta1;
- @@ -686,7 +718,12 @@
- delta2 = -delta2;
- blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* Round to prevent fringes */
- + blue->shoot.fit = FT_PIX_ROUND( blue->ref.fit - delta2 );
- +#else
- blue->shoot.fit = blue->ref.fit - delta2;
- +#endif
- #endif
- @@ -1432,6 +1469,8 @@
- if ( dist < 0 )
- dist = -dist;
- + /* round down to pixels */
- + /*dist = FT_MulFix( dist, scale ) & ~63;*/
- dist = FT_MulFix( dist, scale );
- if ( dist < best_dist )
- {
- @@ -1594,20 +1633,95 @@
- FT_Pos dist = width;
- FT_Int sign = 0;
- FT_Int vertical = ( dim == AF_DIMENSION_VERT );
- -
- -
- - if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
- - axis->extra_light )
- - return width;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + FT_Int infinality_dist = 0;
- +
- +
- +
- + FT_UInt autohint_snap_stem_height = 0;
- + FT_UInt checked_autohint_snap_stem_height = 0;
- +
- + if ( checked_autohint_snap_stem_height == 0)
- + {
- + char *autohint_snap_stem_height_env = getenv( "INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT" );
- + if ( autohint_snap_stem_height_env != NULL )
- + {
- + sscanf ( autohint_snap_stem_height_env, "%u", &autohint_snap_stem_height );
- + if (autohint_snap_stem_height > 100 ) autohint_snap_stem_height = 100;
- + else if (autohint_snap_stem_height < 0 ) autohint_snap_stem_height = 0;
- + }
- + checked_autohint_snap_stem_height = 1;
- + }
- +
- + if ( autohint_snap_stem_height == 0 )
- +#endif
- + if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
- + axis->extra_light )
- + return width;
- if ( dist < 0 )
- {
- dist = -width;
- sign = 1;
- }
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* Calculate snap value differently than standard freetype */
- + if ( /* stem_snap_light*/ autohint_snap_stem_height > 0
- + && (
- + ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) )
- + || ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) )
- + {
- + infinality_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 - infinality_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 ) infinality_dist = 64 ;
- + else if (axis->widths[0].cur < 88) infinality_dist = 64;
- + else if (axis->widths[0].cur < 160) infinality_dist = 128;
- + else if (axis->widths[0].cur < 240) infinality_dist = 190;
- + else infinality_dist = ( infinality_dist ) & ~63;
- + }
- + else
- + {
- + /* bold gets a different threshold */
- + if ( axis->widths[0].cur < 64 ) infinality_dist = 64 ;
- + else if (axis->widths[0].cur < 108) infinality_dist = 64;
- + else if (axis->widths[0].cur < 160) infinality_dist = 128;
- + else if (axis->widths[0].cur < 222) infinality_dist = 190;
- + else if (axis->widths[0].cur < 288) infinality_dist = 254;
- + else infinality_dist = ( infinality_dist + 16 ) & ~63;
- + }
- +
- + }
- + if (infinality_dist < 52)
- + {
- + if (metrics->root.scaler.face->size->metrics.x_ppem < 9 )
- + {
- - if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
- - ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
- + if (infinality_dist < 32) infinality_dist = 32;
- + }
- + else
- + infinality_dist = 64;
- + }
- + }
- + else if ( autohint_snap_stem_height < 100
- + && (( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
- + ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) )
- +#else
- +
- + if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
- + ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
- +#endif
- {
- /* smooth hinting process: very lightly quantize the stem width */
- @@ -1666,7 +1780,10 @@
- dist = ( dist + 32 ) & ~63;
- }
- }
- - else
- + else
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( autohint_snap_stem_height < 100 )
- +#endif
- {
- /* strong hinting process: snap the stem width to integer pixels */
- @@ -1674,7 +1791,9 @@
- dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
- -
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( autohint_snap_stem_height > 0 ) goto Done_Width;
- +#endif
- if ( vertical )
- {
- /* in the case of vertical hinting, always round */
- @@ -1737,6 +1856,23 @@
- }
- Done_Width:
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if (axis->widths[0].cur > 42 )
- + /* weighted average */
- + dist = (dist * (100 - autohint_snap_stem_height) + infinality_dist * autohint_snap_stem_height ) / 100;
- +
- + {
- + int factor = 100;
- + if (axis->standard_width < 100)
- + factor = axis->standard_width;
- +
- + if (metrics->root.scaler.face->size->metrics.x_ppem >=9 && dist < 52 ) dist += ((52 - dist) * factor) / 100;
- + if (metrics->root.scaler.face->size->metrics.x_ppem <9 && dist < 32 ) dist += ((32 - dist) * factor) / 100;
- +
- + if (axis->standard_width > 100 && metrics->root.scaler.face->size->metrics.x_ppem >=11 && dist < 64 ) dist = 64;
- + if (axis->standard_width > 100 && metrics->root.scaler.face->size->metrics.x_ppem >=9 && dist < 52 ) dist = 52;
- + }
- +#endif
- if ( sign )
- dist = -dist;
- @@ -1759,6 +1895,8 @@
- (AF_Edge_Flags)base_edge->flags,
- (AF_Edge_Flags)stem_edge->flags );
- +/* if fitted_width causes stem_edge->pos to land basically on top of an existing
- + * stem_edge->pos, then add or remove 64. Need to figure out a way to do this */
- stem_edge->pos = base_edge->pos + fitted_width;
- @@ -2233,8 +2371,32 @@
- {
- FT_Error error;
- int dim;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int emboldening_strength = 0;
- -
- + int checked_use_various_tweaks_env = 0;
- + FT_Bool use_various_tweaks = FALSE;
- +
- + if ( checked_use_various_tweaks_env == 0 )
- + {
- + char *use_various_tweaks_env = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" );
- + if ( use_various_tweaks_env != NULL )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "true") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "1") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "on") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "yes") == 0)
- + use_various_tweaks = TRUE;
- + }
- + }
- + checked_use_various_tweaks_env = 1;
- + }
- +#endif
- error = af_glyph_hints_reload( hints, outline );
- if ( error )
- goto Exit;
- @@ -2291,7 +2453,54 @@
- }
- }
- af_glyph_hints_save( hints, outline );
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- +#if 0
- + if( metrics->root.scaler.face->style_name )
- + {
- + if ( strcasestr(metrics->root.scaler.face->style_name, "Bold")
- + || strcasestr(metrics->root.scaler.face->style_name, "Black")
- + || strcasestr(metrics->root.scaler.face->style_name, "Narrow")
- + && metrics->root.scaler.face->size->metrics.x_ppem < 15
- + || strcasestr(metrics->root.scaler.face->style_name, "Condensed")
- + && metrics->root.scaler.face->size->metrics.x_ppem < 20 )
- + goto Exit;
- + }
- + if( metrics->root.scaler.face->family_name )
- + {
- + if ( strcasestr(metrics->root.scaler.face->family_name, "Bold")
- + || strcasestr(metrics->root.scaler.face->family_name, "Black")
- + || strcasestr(metrics->root.scaler.face->family_name, "Narrow")
- + && metrics->root.scaler.face->size->metrics.x_ppem < 15
- + || strcasestr(metrics->root.scaler.face->family_name, "Condensed")
- + && metrics->root.scaler.face->size->metrics.x_ppem < 20 )
- + goto Exit;
- + }
- + /* if the font is particularly thin, embolden it, up to 1 px */
- + if ( use_various_tweaks
- + && metrics->axis->widths[0].cur <= FT_MulDiv ( autohint_minimum_stem_width, 64, 100)
- + && !( 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 )
- + {
- + emboldening_strength = FT_MulDiv ( autohint_minimum_stem_width, 64, 100) - metrics->axis->widths[0].cur;
- + if ( metrics->root.scaler.face->size->metrics.x_ppem < 9 )
- + emboldening_strength -= 10;
- + if ( metrics->root.scaler.face->size->metrics.x_ppem < 7 )
- + emboldening_strength -= 10;
- + }
- + if ( emboldening_strength < 0 ) emboldening_strength = 0;
- + FT_Outline_Embolden(outline,emboldening_strength);
- + }
- +#endif
- + /* Save this width for use in ftsmooth.c. This is a shameful hack */
- + const char* c1 = "CUR_WIDTH";
- + char c2[8];
- + snprintf(c2,8,"%ld",metrics->axis->widths[0].cur);
- + setenv(c1, c2, 1);
- +#endif
- Exit:
- return error;
- }
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/autofit/afloader.c.orig src/autofit/afloader.c
- --- src/autofit/afloader.c.orig 2011-04-18 09:24:17.000000000 -0500
- +++ src/autofit/afloader.c 2011-11-28 21:51:34.373981498 -0600
- @@ -190,8 +190,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;
- @@ -224,7 +224,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;
- @@ -410,6 +411,9 @@
- #endif
- FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
- + /* slot->metrics.horiBearingX_o = bbox.xMin;
- + slot->metrics.width_o = bbox.xMax - bbox.xMin; */
- +
- bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
- bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
- bbox.xMax = FT_PIX_CEIL( bbox.xMax );
- @@ -456,6 +460,7 @@
- slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
- metrics->scaler.y_scale );
- + /* slot->metrics.horiAdvance_o = slot->metrics.horiAdvance;*/
- slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
- slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/base/ftlcdfil.c.orig src/base/ftlcdfil.c
- --- src/base/ftlcdfil.c.orig 2010-04-01 03:18:57.000000000 -0500
- +++ src/base/ftlcdfil.c 2011-11-30 20:05:45.371694287 -0600
- @@ -21,6 +21,9 @@
- #include FT_IMAGE_H
- #include FT_INTERNAL_OBJECTS_H
- +#include <math.h>
- +#include <string.h>
- +#include <strings.h>
- #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- @@ -287,10 +290,51 @@
- { 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 };
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int checked_filter_params_env = 0;
- + if ( checked_filter_params_env == 0 )
- + {
- + char *filter_params = getenv( "INFINALITY_FT_FILTER_PARAMS" );
- + if ( filter_params != NULL && strcmp(filter_params, "") != 0 )
- + {
- + float f1, f2, f3, f4, f5;
- +
- + if ( strcasecmp(filter_params, "default" ) != 0)
- + {
- + int args_assigned = 0;
- + args_assigned = sscanf ( filter_params, "%f %f %f %f %f", &f1, &f2, &f3, &f4, &f5 );
- + if ( args_assigned == 5 )
- + {
- + if ( f1 + f2 + f3 + f4 + f5 > 5 )
- + {
- + /* Assume we were given integers instead of floats */
- + /* 0 to 100 */
- + default_filter[0] = (FT_Byte) (f1 * 2.55f + 0.5f);
- + default_filter[1] = (FT_Byte) (f2 * 2.55f + 0.5f);
- + default_filter[2] = (FT_Byte) (f3 * 2.55f + 0.5f);
- + default_filter[3] = (FT_Byte) (f4 * 2.55f + 0.5f);
- + default_filter[4] = (FT_Byte) (f5 * 2.55f + 0.5f);
- + }
- + else
- + {
- + /* Assume we were given floating point values */
- + /* 0 to 1.0 */
- + 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;
- + }
- +#endif
- if ( !library )
- return FT_Err_Invalid_Argument;
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/base/ftobjs.c.orig src/base/ftobjs.c
- --- src/base/ftobjs.c.orig 2011-10-15 02:32:41.000000000 -0500
- +++ src/base/ftobjs.c 2011-11-17 21:00:16.231773659 -0600
- @@ -567,8 +567,27 @@
- FT_Bool autohint = FALSE;
- FT_Module hinter;
- TT_Face ttface = (TT_Face)face;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int checked_use_various_tweaks_env = FALSE;
- + FT_Bool use_various_tweaks = FALSE;
- + if ( !checked_use_various_tweaks_env )
- + {
- + char *use_various_tweaks_env = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" );
- + if ( use_various_tweaks_env != NULL )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "true") == 0) use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "1") == 0) use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "on") == 0) use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "yes") == 0) use_various_tweaks = TRUE;
- + }
- + }
- + checked_use_various_tweaks_env = 1;
- + }
- +#endif
- if ( !face || !face->size || !face->glyph )
- return FT_Err_Invalid_Face_Handle;
- @@ -648,8 +667,22 @@
- if ( autohint )
- {
- FT_AutoHinter_Service hinting;
- -
- -
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( use_various_tweaks )
- + {
- + load_flags = 66088;
- + /* attempt to force slight hinting here, but doesn't work */
- + /* the above hack does though, until I can figure out the below */
- +
- + /*load_flags &= ~FT_RENDER_MODE_NORMAL;
- + load_flags &= ~FT_LOAD_TARGET_NORMAL;
- + load_flags &= ~FT_LOAD_NO_AUTOHINT;
- + load_flags |= FT_RENDER_MODE_LIGHT;
- + load_flags |= FT_LOAD_TARGET_LIGHT;
- + load_flags |= FT_LOAD_FORCE_AUTOHINT;*/
- + /*printf("%d ", load_flags);*/
- + }
- +#endif
- /* try to load embedded bitmaps first if available */
- /* */
- /* XXX: This is really a temporary hack that should disappear */
- @@ -687,6 +720,10 @@
- }
- else
- {
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + char* c1 = "CUR_WIDTH";
- + char* c2 = "0";
- +#endif
- error = driver->clazz->load_glyph( slot,
- face->size,
- glyph_index,
- @@ -694,6 +731,10 @@
- if ( error )
- goto Exit;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + setenv(c1, c2, 1);
- +#endif
- +
- if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
- {
- /* check that the loaded outline is correct */
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/base/ftoutln.c.orig src/base/ftoutln.c
- --- src/base/ftoutln.c.orig 2010-06-27 08:03:58.000000000 -0500
- +++ src/base/ftoutln.c 2011-12-23 19:37:59.293160172 -0600
- @@ -887,8 +887,30 @@
- FT_Angle rotate, angle_in, angle_out;
- FT_Int c, n, first;
- FT_Int orientation;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int checked_use_various_tweaks_env = 0;
- + FT_Bool use_various_tweaks = FALSE;
- -
- + if ( checked_use_various_tweaks_env == 0 )
- + {
- + char *use_various_tweaks_env = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" );
- + if ( use_various_tweaks_env != NULL )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "true") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "1") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "on") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "yes") == 0)
- + use_various_tweaks = TRUE;
- + }
- + }
- + checked_use_various_tweaks_env = 1;
- + }
- +#endif
- if ( !outline )
- return FT_Err_Invalid_Argument;
- @@ -957,6 +979,9 @@
- }
- outline->points[n].x = v_cur.x + strength + in.x;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( !use_various_tweaks )
- +#endif
- outline->points[n].y = v_cur.y + strength + in.y;
- v_prev = v_cur;
- @@ -969,6 +994,99 @@
- return FT_Err_Ok;
- }
- +
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* documentation is in ftoutln.h */
- +
- + FT_EXPORT_DEF( FT_Error )
- + FT_Outline_Embolden_XY( FT_Outline* outline,
- + FT_Pos strength_x,
- + FT_Pos strength_y )
- + {
- + FT_Vector* points;
- + FT_Vector v_prev, v_first, v_next, v_cur;
- + FT_Angle rotate, angle_in, angle_out;
- + FT_Int c, n, first;
- + FT_Int orientation;
- +
- + if ( !outline )
- + return FT_Err_Invalid_Argument;
- +
- + orientation = FT_Outline_Get_Orientation( outline );
- + if ( orientation == FT_ORIENTATION_NONE )
- + {
- + if ( outline->n_contours )
- + return FT_Err_Invalid_Argument;
- + else
- + return FT_Err_Ok;
- + }
- +
- + if ( orientation == FT_ORIENTATION_TRUETYPE )
- + rotate = -FT_ANGLE_PI2;
- + else
- + rotate = FT_ANGLE_PI2;
- +
- + points = outline->points;
- +
- + first = 0;
- + for ( c = 0; c < outline->n_contours; c++ )
- + {
- + int last = outline->contours[c];
- +
- +
- + v_first = points[first];
- + v_prev = points[last];
- + v_cur = v_first;
- +
- + for ( n = first; n <= last; n++ )
- + {
- + FT_Vector in, out;
- + FT_Angle angle_diff;
- + FT_Pos d, dy;
- + FT_Fixed scale;
- +
- +
- + if ( n < last )
- + v_next = points[n + 1];
- + else
- + v_next = v_first;
- +
- + /* compute the in and out vectors */
- + in.x = v_cur.x - v_prev.x;
- + in.y = v_cur.y - v_prev.y;
- +
- + out.x = v_next.x - v_cur.x;
- + out.y = v_next.y - v_cur.y;
- +
- + angle_in = FT_Atan2( in.x, in.y );
- + angle_out = FT_Atan2( out.x, out.y );
- + angle_diff = FT_Angle_Diff( angle_in, angle_out );
- + scale = FT_Cos( angle_diff / 2 );
- +
- + if ( scale < 0x4000L && scale > -0x4000L )
- + in.x = in.y = 0;
- + else
- + {
- + d = FT_DivFix( strength_x, scale );
- + dy = FT_DivFix( strength_y, scale );
- +
- + FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );
- + FT_Vector_From_Polar( &in, dy, angle_in + angle_diff / 2 - rotate );
- + }
- +
- + outline->points[n].x = v_cur.x + strength_x + in.x;
- + outline->points[n].y = v_cur.y + strength_y + in.y;
- +
- + v_prev = v_cur;
- + v_cur = v_next;
- + }
- +
- + first = last + 1;
- + }
- +
- + return FT_Err_Ok;
- + }
- +#endif
- /* documentation is in ftoutln.h */
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/base/ftsynth.c.orig src/base/ftsynth.c
- --- src/base/ftsynth.c.orig 2010-09-11 01:28:32.000000000 -0500
- +++ src/base/ftsynth.c 2011-12-01 19:00:13.275375244 -0600
- @@ -87,7 +87,26 @@
- FT_Face face = slot->face;
- FT_Error error;
- FT_Pos xstr, ystr;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int checked_use_various_tweaks_env = 0;
- + FT_Bool use_various_tweaks = FALSE;
- + if ( checked_use_various_tweaks_env == 0 )
- + {
- + char *use_various_tweaks_env = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" );
- + if ( use_various_tweaks_env != NULL )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "true") == 0) use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "1") == 0) use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "on") == 0) use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "yes") == 0) use_various_tweaks = TRUE;
- + }
- + }
- + checked_use_various_tweaks_env = 1;
- + }
- +#endif
- if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
- slot->format != FT_GLYPH_FORMAT_BITMAP )
- @@ -146,6 +165,9 @@
- slot->metrics.width += xstr;
- slot->metrics.height += ystr;
- slot->metrics.horiBearingY += ystr;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( !use_various_tweaks )
- +#endif
- slot->metrics.horiAdvance += xstr;
- slot->metrics.vertBearingX -= xstr / 2;
- slot->metrics.vertBearingY += ystr;
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/smooth/ftsmooth.c.orig src/smooth/ftsmooth.c
- --- src/smooth/ftsmooth.c.orig 2011-05-29 23:46:55.000000000 -0500
- +++ src/smooth/ftsmooth.c 2011-12-23 19:38:36.591875446 -0600
- @@ -26,6 +26,16 @@
- #include "ftsmerrs.h"
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- +#include <math.h>
- +#include "../../include/freetype/ftbitmap.h"
- +#include "strings.h"
- +#include "../autofit/aflatin.h"
- +#include "../../include/freetype/ftoutln.h"
- +
- +#define verbose FALSE
- +#define STVALUES if (verbose) printf ("scale:%f translate:%ld ", *scale_value, *translate_value);
- +#endif
- /* initialize renderer -- init its raster */
- static FT_Error
- @@ -34,65 +44,2818 @@
- FT_Library library = FT_MODULE_LIBRARY( render );
- - render->clazz->raster_class->raster_reset( render->raster,
- - library->raster_pool,
- - library->raster_pool_size );
- + render->clazz->raster_class->raster_reset( render->raster,
- + library->raster_pool,
- + library->raster_pool_size );
- +
- + return 0;
- + }
- +
- +
- + /* sets render-specific mode */
- + static FT_Error
- + ft_smooth_set_mode( FT_Renderer render,
- + FT_ULong mode_tag,
- + FT_Pointer data )
- + {
- + /* we simply pass it to the raster */
- + return render->clazz->raster_class->raster_set_mode( render->raster,
- + mode_tag,
- + data );
- + }
- +
- + /* transform a given glyph image */
- + static FT_Error
- + ft_smooth_transform( FT_Renderer render,
- + FT_GlyphSlot slot,
- + const FT_Matrix* matrix,
- + const FT_Vector* delta )
- + {
- + FT_Error error = Smooth_Err_Ok;
- +
- +
- + if ( slot->format != render->glyph_format )
- + {
- + error = Smooth_Err_Invalid_Argument;
- + goto Exit;
- + }
- +
- + if ( matrix )
- + FT_Outline_Transform( &slot->outline, matrix );
- +
- + if ( delta )
- + FT_Outline_Translate( &slot->outline, delta->x, delta->y );
- +
- + Exit:
- + return error;
- + }
- +
- +
- + /* return the glyph's control box */
- + static void
- + ft_smooth_get_cbox( FT_Renderer render,
- + FT_GlyphSlot slot,
- + FT_BBox* cbox )
- + {
- + FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
- +
- + if ( slot->format == render->glyph_format )
- + FT_Outline_Get_CBox( &slot->outline, cbox );
- + }
- +
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + static FT_Fixed FT_FixedFromFloat(float f)
- + {
- + short value = f;
- + unsigned short fract = (f - value) * 0xFFFF;
- + return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
- + }
- +
- +
- + /* ChromeOS sharpening algorithm */
- + /* soften the sub-pixel anti-aliasing and sharpen */
- + static void
- + _ft_lcd_chromeos_sharpen( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_Byte cutoff,
- + double gamma_value )
- + {
- + static FT_Bool initialized_gamma = FALSE;
- + static unsigned short gamma_ramp[256];
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- + int ii;
- +
- + if (!initialized_gamma)
- + {
- + initialized_gamma = TRUE;
- + /* linear to voltage */
- + for ( ii = 0; ii < 256; ii++ )
- + {
- + gamma_ramp[ii] = (unsigned char)
- + ( pow( (double)ii/255.0, gamma_value ) * 255.0f );
- + if (gamma_ramp[ii] < cutoff) {
- + gamma_ramp[ii] = 0;
- + }
- + }
- + }
- +
- + /* horizontal in-place sub-pixel sharpening filter */
- + if ( mode == FT_RENDER_MODE_LCD)
- + {
- + FT_Byte* line = bitmap->buffer;
- + for ( ; height > 0; height--, line += bitmap->pitch )
- + {
- + FT_UInt xx;
- + for ( xx = 0; xx < width; xx++ )
- + {
- + line[xx] = gamma_ramp[line[xx]];
- + }
- + }
- + }
- + }
- +
- + /* simple linear scale to handle various sliding values */
- + float
- + sliding_scale ( int min_value,
- + int max_value,
- + float min_amount,
- + float max_amount,
- + int cur_value )
- + {
- +
- + float m = (min_amount - max_amount) / (float)(min_value - max_value);
- + float result = (((float)cur_value * m) + (max_amount - max_value * m)) ;
- +
- + if (min_amount < max_amount)
- + {
- + if (result < min_amount) return min_amount;
- + if (result > max_amount) return max_amount;
- + }
- + else
- + {
- + if (result < max_amount) return max_amount;
- + if (result > min_amount) return min_amount;
- + }
- +
- + return result;
- + }
- +
- +
- + /* brightness and contrast adjustment on the bitmap */
- + static FT_Bool
- + _ft_bitmap_bc ( FT_Bitmap* bitmap,
- + float brightness,
- + float contrast )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- + FT_Byte* line = bitmap->buffer;
- + FT_UInt xx;
- +
- + if ( brightness == 0 && contrast == 0 ) return FALSE;
- +
- + for (height = (FT_UInt)bitmap->rows;
- + height > 0;
- + height--, line += bitmap->pitch )
- + {
- + for ( xx = 0; xx < width - 1; xx += 1 )
- + {
- + if ( line[xx] > 0)
- + {
- + float value = (float)(255 - line[xx]) / 256.0;
- + FT_Int result = 0;
- +
- + if (brightness < 0.0) value = value * ( 1.0 + brightness);
- + else value = value + ((1.0 - value) * brightness);
- + value = (value - 0.5) * (tan ((contrast + 1.0) * 3.141592/4.0) ) + 0.5;
- +
- + result = (FT_Int)(255.0 - (value) * 256.0);
- +
- + if (result < 0) result = 0;
- + if (result > 255) result = 255;
- +
- + line[xx] = result;
- + }
- + }
- + }
- + return TRUE;
- + }
- +
- +
- + /* Filter to mimic Windows-style sharpening */
- + /* Determined via 100% experimentation. */
- + static void
- + _ft_lcd_windows_sharpen( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_UInt strength,
- + FT_Library library )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- +
- + FT_Byte* new_line;
- + FT_Byte* line = bitmap->buffer;
- +
- + FT_Bitmap new_bitmap;
- +
- + FT_Bitmap_New(&new_bitmap);
- +
- + FT_Bitmap_Copy(library, bitmap, &new_bitmap);
- + new_line = (&new_bitmap)->buffer;
- +
- + if (strength > 0)
- + for (height = (FT_UInt)bitmap->rows;
- + height > 0;
- + height--, line += bitmap->pitch, new_line += bitmap->pitch )
- + {
- + FT_UInt xx, threshold = 128;
- + FT_Byte* prevline = line - bitmap->pitch;
- + FT_Byte* nextline = line + bitmap->pitch;
- +
- + FT_Byte* new_prevline = new_line - bitmap->pitch;
- + FT_Byte* new_nextline = new_line + bitmap->pitch;
- +
- + for ( xx = 1; xx < width - 1; xx += 1 )
- + {
- + /* subpixel grid sp11 sp21 sp31 */
- + /* where sp22 is sp12 sp22 sp32 */
- + /* current subpixel. sp13 sp23 sp33 */
- +
- + FT_Int prevtotal, nexttotal, lefttotal, righttotal, sidesdiff,
- + prevdiff, nextdiff, sp11, sp21, sp31, sp12, sp22, sp32,
- + sp13, sp23, sp33;
- +
- + sp12 = line [xx-1];
- + sp22 = line [xx];
- + sp32 = line [xx+1];
- +
- + if (height == bitmap->rows)
- + {
- + prevtotal = sp11 = sp21 = sp31 = 0;
- + prevdiff = sp22;
- + lefttotal = sp12 + sp13;
- + righttotal = sp32 + sp33;
- + }
- + else
- + {
- + prevtotal = prevline[xx-1] + prevline[xx] + prevline[xx+1];
- + sp11 = prevline [xx-1];
- + sp21 = prevline [xx];
- + sp31 = prevline [xx+1];
- + prevdiff = sp22 - sp21;
- + lefttotal = sp11 + sp12 + sp13;
- + righttotal = sp31 + sp32 + sp33;
- + }
- +
- +
- + if (height == 1)
- + {
- + nexttotal = sp13 = sp23 = sp33 = 0;
- + nextdiff = sp22;
- + lefttotal = sp11 + sp12;
- + righttotal = sp31 + sp32;
- + }
- + else
- + {
- + nexttotal = nextline[xx-1] + nextline[xx] + nextline[xx+1];
- + sp13 = nextline [xx-1];
- + sp23 = nextline [xx];
- + sp33 = nextline [xx+1];
- + nextdiff = sp23 - sp22;
- + lefttotal = sp11 + sp12 + sp13;
- + righttotal = sp31 + sp32 + sp33;
- + }
- +
- + sidesdiff = lefttotal - righttotal;
- + if (sidesdiff < 0) sidesdiff *= -1;
- + if (prevdiff < 0) prevdiff *= -1;
- + if (nextdiff < 0) nextdiff *= -1;
- +
- + /* if the current pixel is less than threshold, and greater than 0 */
- + if ( sp22 <= threshold && sp22 > 0 )
- + {
- + /* A pixel is horizontally isolated if: */
- + /* 1: All upper adjecent pixels are >= threshold */
- + if ( prevtotal >= nexttotal && abs (sp11 - sp12) > 5 && abs (sp21 - sp22) > 5 && abs (sp31 - sp32) > 5 /* not a vert stem end */
- + && sp11 >= threshold
- + && sp21 >= threshold
- + && sp31 >= threshold && abs (sp23 - sp22) > 15 /* not on a vert stem */
- + )
- + {
- + /* darken upper adjacent subpixel; lighten current */
- + if (height != (FT_UInt)bitmap->rows) new_prevline[xx] += ((255 - new_prevline[xx]) * strength) / 100 ;
- + new_line[xx] -= (new_line[xx] * strength) / 100;
- +
- + if (height != 1 && height != (FT_UInt)bitmap->rows) if (new_nextline[xx] > 155 + (100 - strength)) new_prevline[xx] = 255;
- +
- + }
- + else if ( nexttotal > prevtotal && abs (sp13 - sp12) > 5 && abs (sp23 - sp22) > 5 && abs (sp33 - sp32) > 5
- + /* 2: All lower adjecent pixels are >= threshold */
- + && sp13 >= threshold
- + && sp23 >= threshold
- + && sp33 >= threshold && abs (sp22 - sp21) > 15
- + )
- + {
- + /* darken lower adjacent subpixel; lighten current */
- + if (height != 1) new_nextline[xx] += (255 - new_nextline[xx]) * strength / 100 ;
- + new_line[xx] -= (new_line[xx] * strength) / 100;
- +
- + if (height != 1) if (new_nextline[xx] > 155 + (100 - strength)) new_nextline[xx] = 255;
- +
- + }
- + }
- + else if ( sp22 > threshold && sp22 < 255 )
- + {
- + if ( sp11 <= threshold && abs (sp13 - sp12) > 5 && abs (sp23 - sp22) > 5 && abs (sp33 - sp32) > 5
- + && sp21 <= threshold
- + && sp31 <= threshold
- + && prevtotal <= nexttotal && abs (sp22 - sp21) > 15
- + )
- + {
- + /* bring this subpixel 1/3 of the way to 255 at 100% strength */
- + new_line[xx] += (strength * (255 - new_line[xx]))/100 ;
- + if (height != (FT_UInt)bitmap->rows) new_prevline[xx] -= (new_prevline[xx] * strength) / 300;
- + }
- + else if (
- + sp13 <= threshold && abs (sp11 - sp12) > 5 && abs (sp21 - sp22) > 5 && abs (sp31 - sp32) > 5
- + && sp23 <= threshold
- + && sp33 <= threshold &&
- + nexttotal < prevtotal && abs (sp23 - sp22) > 15
- +
- + )
- + {
- + new_line[xx] += (strength * (255 - new_line[xx]))/100 ;
- + if (height != 1) new_nextline[xx] -= (new_nextline[xx] * strength) / 300;
- + }
- + }
- + }
- + }
- + FT_Bitmap_Copy(library, &new_bitmap, bitmap);
- + FT_Bitmap_Done(library, &new_bitmap);
- + }
- +
- +
- + static void
- + _ft_lcd_darken_x ( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_UInt strength,
- + FT_Library library )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- +
- + FT_Byte* new_line;
- + FT_Byte* line = bitmap->buffer;
- +
- + FT_Bitmap new_bitmap;
- +
- + int factor1,factor2;
- + int bias = 0;
- +
- + FT_Bitmap_New(&new_bitmap);
- +
- + FT_Bitmap_Copy(library, bitmap, &new_bitmap);
- + new_line = (&new_bitmap)->buffer;
- +
- + if (strength > 0)
- + for (height = (FT_UInt)bitmap->rows;
- + height > 0;
- + height--, line += bitmap->pitch, new_line += bitmap->pitch )
- + {
- + FT_UInt xx;
- + FT_Byte* prevline = line - bitmap->pitch;
- + FT_Byte* nextline = line + bitmap->pitch;
- +
- + for ( xx = 1; xx < width - 1; xx += 1 )
- + {
- + /* subpixel grid sp11 sp21 sp31 */
- + /* where sp22 is sp12 sp22 sp32 */
- + /* current subpixel. sp13 sp23 sp33 */
- +
- + FT_Int sp21, sp12, sp22, sp32, sp23;
- +
- + sp12 = line [xx-1];
- + sp22 = line [xx];
- + sp32 = line [xx+1];
- +
- + if (height == bitmap->rows)
- + {
- + sp21 = 0;
- + }
- + else
- + {
- + sp21 = prevline [xx];
- + }
- +
- + if (height == 1)
- + {
- + sp23 = 0;
- +
- + }
- + else
- + {
- + sp23 = nextline [xx];
- + }
- +
- + /* darken subpixel if neighbor above and below are much less than */
- + /* safer but less effective */
- + factor1 = 5;
- + factor2 = 5;
- +
- + /* make matches in the middle of glyph slightly darker */
- + /*if (height > 1 && height < (FT_UInt)bitmap->rows) bias = 1;*/
- +
- + if ( sp22 > factor1 * sp21 && sp22 > factor1 * sp23 && sp22 > factor2 && sp12 > 16 && sp32 > 16 )
- + if (new_line[xx] < (strength * 255) / 100 )
- + new_line[xx] = (strength * 255) / 100 + bias * (255 - (strength * 255) / 100) / 3;
- +
- + }
- + }
- + FT_Bitmap_Copy(library, &new_bitmap, bitmap);
- + FT_Bitmap_Done(library, &new_bitmap);
- + }
- +
- +
- + static void
- + _ft_lcd_darken_y ( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_UInt strength,
- + FT_Library library )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- +
- + FT_Byte* new_line;
- + FT_Byte* line = bitmap->buffer;
- +
- + FT_Bitmap new_bitmap;
- +
- + FT_Bitmap_New(&new_bitmap);
- +
- + FT_Bitmap_Copy(library, bitmap, &new_bitmap);
- + new_line = (&new_bitmap)->buffer;
- +
- + if (strength > 0)
- + for (height = (FT_UInt)bitmap->rows;
- + height > 0;
- + height--, line += bitmap->pitch, new_line += bitmap->pitch )
- + {
- +
- + FT_UInt xx;
- + for ( xx = 1; xx < width - 1; xx += 1 )
- + {
- + if (line[xx] > line[xx-1] && line[xx] > line[xx+1])
- + {
- + if (new_line[xx] > 0) new_line[xx] += (strength * (255 - new_line[xx])) / 100;
- + new_line[xx-1] += (strength * (255 - line[xx-1])) / 100;
- + new_line[xx+1] += (strength * (255 - line[xx+1])) / 100;
- + }
- + }
- + }
- + FT_Bitmap_Copy(library, &new_bitmap, bitmap);
- + FT_Bitmap_Done(library, &new_bitmap);
- + }
- +
- +
- + static void
- + _ft_bitmap_cap ( FT_Bitmap* bitmap,
- + FT_UInt strength,
- + FT_Library library )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- +
- + FT_Byte* new_line;
- + FT_Byte* line = bitmap->buffer;
- +
- + FT_UInt cur_value = 0;
- +
- + FT_Bitmap new_bitmap;
- +
- + FT_Bitmap_New(&new_bitmap);
- +
- + FT_Bitmap_Copy(library, bitmap, &new_bitmap);
- + new_line = (&new_bitmap)->buffer;
- +
- + if (strength > 0)
- + for (height = (FT_UInt)bitmap->rows;
- + height > 0;
- + height--, line += bitmap->pitch, new_line += bitmap->pitch )
- + {
- +
- + FT_UInt xx;
- + for ( xx = 1; xx < width - 1; xx += 1 )
- + {
- + cur_value = (new_line[xx-1] + new_line[xx] + new_line[xx+1]) / 3;
- + if (cur_value > (strength * 255) / 100 )
- + {
- + FT_UInt new_factor = (strength * 255) / 100;
- + new_line[xx] = (new_line[xx] * new_factor) / cur_value;
- + new_line[xx+1] = (new_line[xx+1] * new_factor) / cur_value;
- + new_line[xx-1] = (new_line[xx-1] * new_factor) / cur_value;
- + }
- + }
- + }
- + FT_Bitmap_Copy(library, &new_bitmap, bitmap);
- + FT_Bitmap_Done(library, &new_bitmap);
- + }
- +
- +
- + int
- + gamma2 ( int val, float value )
- + {
- + return 256 * (1.0 - pow((1.0 - (float)val/ 256.0) , 1.0/value));
- + }
- +
- +
- +
- + static void
- + _ft_bitmap_embolden ( FT_Bitmap* bitmap,
- + FT_UInt strength,
- + FT_Library library )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- +
- + FT_Byte* new_line;
- + FT_Byte* line = bitmap->buffer;
- + FT_Bitmap new_bitmap;
- + FT_UInt xx;
- +
- + FT_Bitmap_New(&new_bitmap);
- +
- + FT_Bitmap_Copy(library, bitmap, &new_bitmap);
- +
- + new_line = (&new_bitmap)->buffer;
- +
- + if (strength > 0)
- + for (height = (FT_UInt)bitmap->rows;
- + height > 0;
- + height--, line += bitmap->pitch, new_line += bitmap->pitch )
- + {
- +
- + for ( xx = 1; xx < width - 1; xx += 1 )
- + {
- +
- + FT_Int new_value = 0;
- +
- + new_value = (strength * line [xx-1]) / 100 + gamma2(line [xx], .75) + (strength * line [xx+1]) / 100;
- + if (new_value > 255) new_value = 255;
- +
- + new_line[xx] = new_value;
- +
- + }
- + }
- + FT_Bitmap_Copy(library, &new_bitmap, bitmap);
- + FT_Bitmap_Done(library, &new_bitmap);
- + }
- +
- +
- +
- + static void
- + _ft_bitmap_gamma ( FT_Bitmap* bitmap,
- + float strength )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- +
- + FT_Byte* line = bitmap->buffer;
- +
- + FT_UInt xx;
- +
- + if (strength > 0)
- + for (height = (FT_UInt)bitmap->rows;
- + height > 0;
- + height--, line += bitmap->pitch )
- + {
- +
- + for ( xx = 1; xx < width - 1; xx += 1 )
- + {
- + if (abs(line[xx-1] - line[xx]) < 20 || abs(line[xx+1] - line[xx]) < 20)
- + line [xx] = gamma2(line [xx], strength) ;
- +
- + }
- +
- + }
- + }
- +
- +
- + /* Fringe filter */
- + static void
- + _ft_lcd_fringe_filter ( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_UInt strength,
- + FT_Library library )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- + FT_Byte* new_line;
- + FT_Byte* line = bitmap->buffer;
- +
- + FT_Bitmap new_bitmap;
- + FT_Bitmap_New(&new_bitmap);
- +
- +
- + line = bitmap->buffer;
- + FT_Bitmap_Copy(library, bitmap, &new_bitmap);
- + new_line = (&new_bitmap)->buffer;
- + for (height = (FT_UInt)bitmap->rows ; height > 0; height--, line += bitmap->pitch, new_line += bitmap->pitch )
- + {
- + /* Threshold set to 1/2 pixel intensity */
- + FT_UInt xx, threshold = 128;
- +
- + /* Hack to make this work when bitmap is at first or last line */
- + FT_Int fudge = bitmap->pitch * (height == (FT_UInt)bitmap->rows);
- +
- +
- + FT_Byte* prevline = line - bitmap->pitch + fudge;
- + FT_Byte* nextline = line + bitmap->pitch;
- +
- + for ( xx = 1; xx < width - 1; xx += 1 )
- + {
- + /* subpixel grid sp11 sp21 sp31 */
- + /* where sp22 is sp12 sp22 sp32 */
- + /* current subpixel. sp13 sp23 sp33 */
- +
- + FT_Int prevtotal, nexttotal, lefttotal, righttotal, sidesdiff,
- + leftdiff, rightdiff, prevdiff, nextdiff, sp11, sp21, sp31,
- + sp12, sp22, sp32, sp13, sp23, sp33;
- +
- + sp12 = line [xx-1];
- + sp22 = line [xx];
- + sp32 = line [xx+1];
- +
- + /* if at max height fake out some values */
- + if (height == (FT_UInt)bitmap->rows)
- + {
- + prevtotal = sp11 = sp21 = sp31 = 0;
- + prevdiff = sp22;
- + lefttotal = sp12 + sp13;
- + righttotal = sp32 + sp33;
- + }
- + else
- + {
- + prevtotal = prevline[xx-1] + prevline[xx] + prevline[xx+1];
- + sp11 = prevline [xx-1];
- + sp21 = prevline [xx];
- + sp31 = prevline [xx+1];
- + prevdiff = sp22 - sp21;
- + lefttotal = sp11 + sp12 + sp13;
- + righttotal = sp31 + sp32 + sp33;
- + }
- +
- + /* if at min height fake out some values */
- + if (height == 1)
- + {
- + nexttotal = sp13 = sp23 = sp33 = 0;
- + nextdiff = sp22;
- + lefttotal = sp11 + sp12;
- + righttotal = sp31 + sp32;
- + }
- + else
- + {
- + nexttotal = nextline[xx-1] + nextline[xx] + nextline[xx+1];
- + sp13 = nextline [xx-1];
- + sp23 = nextline [xx];
- + sp33 = nextline [xx+1];
- + nextdiff = sp23 - sp22;
- + lefttotal = sp11 + sp12 + sp13;
- + righttotal = sp31 + sp32 + sp33;
- + }
- +
- + sidesdiff = lefttotal - righttotal;
- + leftdiff = sp22 - sp12;
- + rightdiff = sp32 - sp22;
- + if (sidesdiff < 0) sidesdiff *= -1;
- + if (prevdiff < 0) prevdiff *= -1;
- + if (nextdiff < 0) nextdiff *= -1;
- + if (leftdiff < 0) leftdiff *= -1;
- + if (rightdiff < 0) rightdiff *= -1;
- +
- + /* if the current subpixel is less than threshold, and varies only
- + slightly to left or right, lighten it */
- + if ( sp22 <= threshold && sp22 > 0 && (leftdiff < 10 || rightdiff < 10 ) )
- + {
- + /* A pixel is horizontally isolated if: */
- + /* 1: All upper adjecent subpixels are >= threshold and all lower
- + adjacent ones are essentially white */
- + if ( prevtotal >= nexttotal
- + && sp11 >= threshold
- + && sp21 >= threshold
- + && sp31 >= threshold
- + && sp13 < 2
- + && sp23 < 2
- + && sp33 < 2
- + )
- +
- + {
- + new_line[xx] -= (new_line[xx] * strength) / 100;
- + if (leftdiff < 10) new_line[xx-1] -= (new_line[xx-1] * strength) / 200; /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */
- + if (rightdiff < 10) new_line[xx+1] -= (new_line[xx+1] * strength) / 200; /* OPPORTUNITY FOR IMPROVEMENT */
- + }
- + else if ( nexttotal > prevtotal
- + /* 2: the inverse of above */
- + && sp13 >= threshold
- + && sp23 >= threshold
- + && sp33 >= threshold
- + && sp11 < 2
- + && sp21 < 2
- + && sp31 < 2
- + )
- + {
- + new_line[xx] -= (new_line[xx] * strength) / 100;
- + if (leftdiff < 10) new_line[xx-1] -= (new_line[xx-1] * strength) / 200; /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */
- + if (rightdiff < 10) new_line[xx+1] -= (new_line[xx+1] * strength) / 200; /* OPPORTUNITY FOR IMPROVEMENT */
- + }
- + }
- + /* otherwise if the current subpixel is more than threshold, and varies
- + slightly to left or right, darken it */
- + else if ( sp22 > threshold && sp22 < 255 && (leftdiff < 10 || rightdiff < 10 ) )
- + {
- + if ( sp11 <= 2
- + && sp21 <= 2
- + && sp31 <= 2
- + && sp13 >= threshold
- + && sp23 >= threshold
- + && sp33 >= threshold
- + &&
- + prevtotal < nexttotal
- + )
- +
- + {
- + new_line[xx] += ((255 - new_line[xx]) * strength) / 100;
- + }
- + else if (
- + sp13 <= 2
- + && sp23 <= 2
- + && sp33 <= 2 &&
- + nexttotal < prevtotal
- + && sp11 >= threshold
- + && sp21 >= threshold
- + && sp31 >= threshold
- +
- + )
- + {
- + new_line[xx] += ((255 - new_line[xx]) * strength) / 100;
- + }
- + }
- + }
- + }
- + FT_Bitmap_Copy(library, &new_bitmap, bitmap);
- + FT_Bitmap_Done(library, &new_bitmap);
- + }
- +
- +
- + /* Grayscale filter */
- + static void
- + _ft_lcd_grayscale_filter ( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_UInt strength,
- + FT_Library library )
- + {
- +
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- + FT_Byte* 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 += 3 )
- + {
- + FT_UInt total = line [xx] + line [xx + 1] + line [xx + 2];
- + line[xx] = ( (100-strength) * line[xx] + strength * (total / 3) ) / 100;
- + line[xx+1] = ( (100-strength) * line[xx+1] + strength * (total / 3) ) / 100;
- + line[xx+2] = ( (100-strength) * line[xx+2] + strength * (total / 3) ) / 100;
- + }
- + }
- + }
- +
- +
- +
- + /*************************************************************************/
- + /* */
- + /* */
- + /* */
- + /* */
- + /* */
- + /* */
- +
- +
- + typedef struct SA_Rule_
- + {
- + const char family[32];
- + const int ppem[5];
- + } SA_Rule;
- +
- +#define STEM_WIDTH_2_PPEM 18
- +#define MAX_PPEM 100
- +
- +
- +
- +/* "Font name", {ppem where stem width becomes 1,
- + * ppem where stem width becomes 2... etc.} */
- +/* 100 means auto-calculate */
- +#define SNAPPING_STEM_WIDTHS_RULES_SIZE 21
- + SA_Rule SNAPPING_STEM_WIDTHS_Rules
- + [SNAPPING_STEM_WIDTHS_RULES_SIZE] =
- + {
- + { "Andale Mono", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Arial Narrow", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Calibri", {10, 19, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Cantarell", {10, 22, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Century Gothic", {10, 22, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Comfortaa", {10, 19, 22, MAX_PPEM, MAX_PPEM} },
- + { "Consolas", {10, 20, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Corbel", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Futura", {10, 14, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Gill Sans", {10, 17, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Helvetica CY", {10, 23, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Inconsolata", {10, 23, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Liberation Sans Narrow", {10, 22, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Liberation Sans", {10, 19, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Lucida Grande", {10, 16, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Lucida Sans Unicode", {10, 16, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Luxi Sans", {10, 17, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Open Sans", {10, 20, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Rokkitt", {10, 21, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Segoe UI", {10, 23, MAX_PPEM, MAX_PPEM, MAX_PPEM} },
- + { "Trebuchet MS", {10, 17, STEM_WIDTH_2_PPEM, MAX_PPEM, MAX_PPEM} },
- + };
- +
- +
- +/* "Font name", {ppem, scale_up=1|scale_down=0} */
- +#define SNAPPING_STEM_SCALING_RULES_SIZE 31
- + SA_Rule SNAPPING_STEM_SCALING_Rules
- + [SNAPPING_STEM_SCALING_RULES_SIZE] =
- + {
- + { "Andale Mono", {11, 1,} },
- + { "Bitstream Vera Sans", {12, 1,} },
- + { "Calibri", {15, 1,} },
- + { "Calibri", {17, 1,} },
- + { "Calibri", {18, 1,} },
- + { "Candara", {14, 1,} },
- + { "Candara", {17, 1,} },
- + { "Canwell", {13, 0,} },
- + { "Comfortaa", {11, 0,} },
- + { "Consolas", {11, 1,} },
- + { "DejaVu Sans", {12, 1,} },
- + { "Freesans", {16, 0,} },
- + { "Freeserif", {13, 1,} },
- + { "Freeserif", {17, 1,} },
- + { "Inconsolata", {12, 1,} },
- + { "Inconsolata", {15, 1,} },
- + { "Lucida Grande", {13, 1,} },
- + { "Myriad Pro", {14, 1,} },
- + { "Myriad Pro", {17, 1,} },
- + { "Nina", {11, 0,} },
- + { "Nina", {12, 0,} },
- + { "Nina", {13, 0,} },
- + { "Optima", {17, 1,} },
- + { "Raleway", {15, 0,} },
- + { "Samba", {11, 0,} },
- + { "Times New Roman", {17, 1,} },
- + { "Trebuchet MS", {17, 0,} },
- + { "Trebuchet MS", {13, 0,} },
- + { "Trebuchet MS", {20, 1,} },
- + { "Verdana", {12, 1,} },
- + { "Verdana", {15, 1,} },
- + };
- +
- +
- +/* "Font name", {ppem, scale_up=1|scale_down=0} */
- +#define SNAPPING_M_RULES_SIZE 7
- + SA_Rule SNAPPING_M_Rules
- + [SNAPPING_M_RULES_SIZE] =
- + {
- + { "Courier New", {13, 1,} },
- + { "Courier New", {14, 1,} },
- + { "Droid Sans Mono", {12, 0,} },
- + { "Bitstream Vera Sans", {12, 0,} },
- + { "DejaVu Sans", {12, 0,} },
- + { "Essential PragmataPro", {13, 0,} },
- + { "Essential PragmataPro", {14, 0,} },
- + };
- +
- +
- +/* "Font name", {ppem, ppem} */
- +#define SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE 1
- + SA_Rule SNAPPING_SYNTHESIZE_STEMS_Rules
- + [SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE] =
- + {
- + { "---", {13, 13,} },
- + };
- +
- +
- +/* "Font name", {ppem, ppem} */
- +#define SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE 1
- + SA_Rule SNAPPING_NO_BEARING_CORRECTION_Rules
- + [SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE] =
- + {
- + { "Times New Roman", {0, 100,} },
- + };
- +
- +
- +/* "Font name", {ppem, ppem} */
- +#define SNAPPING_EDGE_DETECTION_RULES_SIZE 8
- + SA_Rule SNAPPING_EDGE_DETECTION_Rules
- + [SNAPPING_EDGE_DETECTION_RULES_SIZE] =
- + {
- + { "Tahoma", {11, 11,} },
- + { "Courier New", {10, 12,} },
- + { "Arial", {11, 11,} },
- + { "Arial", {13, 13,} },
- + { "Liberation Sans", {11, 11,} },
- + { "FreeSans", {11, 11,} },
- + { "FreeSans", {13, 13,} },
- + { "Palatino Linotype", {0, 100,} },
- + };
- +
- +/* "Font name", {ppem, translate_value} */
- +#define SNAPPING_STEM_TRANSLATING_RULES_SIZE 6
- + SA_Rule SNAPPING_STEM_TRANSLATING_Rules
- + [SNAPPING_STEM_TRANSLATING_RULES_SIZE] =
- + {
- + { "Arial", {11, 32,} },
- + { "Arial Unicode MS", {11, 32,} },
- + { "FreeSans", {11, 32,} },
- + { "Arimo", {11, 32,} },
- + { "Liberation Sans", {11, 32,} },
- + { "Tahoma", {11, 32,} },
- + };
- +
- +/* "Font name", {ppem, translate_value} */
- +#define SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE 72
- + SA_Rule SNAPPING_STEM_TRANSLATING_ONLY_Rules
- + [SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE] =
- + {
- + { "Arial Unicode MS", {10, 16,} },
- + { "Arial Unicode MS", {8, 32,} },
- + { "Arial Unicode MS", {9, 32,} },
- + { "Arial", {10, 16,} },
- + { "Arial", {8, 32,} },
- + { "Arial", {9, 32,} },
- + { "Arial", {16, -24,} },
- + { "Arimo", {10, 8,} },
- + { "Arimo", {8, 32,} },
- + { "Arimo", {9, 32,} },
- + { "Bitstream Vera Sans", {8, 16,} },
- + { "Calibri", {10, 16,} },
- + { "Calibri", {15, 0,} },
- + { "Candara", {10, 16,} },
- + { "Cantarell", {11, 0} },
- + { "Cantarell", {12, 0} },
- + { "Consolas", {8, 32,} },
- + { "Consolas", {9, 32,} },
- + { "Corbel", {10, 16,} },
- + { "Dejavu Sans Mono", {7, 16,} },
- + { "Dejavu Sans Mono", {8, 32,} },
- + { "Dejavu Sans Mono", {9, 16,} },
- + { "Dejavu Sans", {8, 16,} },
- + { "Dejavu Sans", {15, -20,} },
- + { "Droid Sans", {8, 16,} },
- + { "Droid Sans", {9, 16,} },
- + { "Freesans", {10, 16,} },
- + { "Freesans", {9, 8,} },
- + { "Georgia", {13, 16,} },
- + { "Georgia", {14, 16,} },
- + { "Georgia", {15, 0,} },
- + { "Inconsolata", {10, 24,} },
- + { "Inconsolata", {9, 32,} },
- + { "Liberation Sans", {10, 8,} },
- + { "Liberation Sans", {8, 32,} },
- + { "Liberation Sans", {9, 32,} },
- + { "Lucida Grande", {13, 24,} },
- + { "Lucida Grande", {14, 24,} },
- + { "Lucida Grande", {8, 16,} },
- + { "Lucida Grande", {9, 16,} },
- + { "Lucida Sans Unicode", {13, 24,} },
- + { "Lucida Sans Unicode", {14, 24,} },
- + { "Lucida Sans Unicode", {8, 16,} },
- + { "Lucida Sans Unicode", {9, 16,} },
- + { "Microsoft Sans Serif", {10, 16,} },
- + { "Microsoft Sans Serif", {8, 32,} },
- + { "Microsoft Sans Serif", {9, 32,} },
- + { "Myriad Pro", {10, 16,} },
- + { "Myriad Pro", {11, 0,} },
- + { "Myriad Pro", {9, 16,} },
- + { "Open Sans", {10, 16,} },
- + { "Open Sans", {9, 16,} },
- + { "Optima", {10, 0} },
- + { "Optima", {11, 0} },
- + { "Optima", {12, 0} },
- + { "Segoe UI", {10, 0,} },
- + { "Segoe UI", {7, 32,} },
- + { "Segoe UI", {8, 16,} },
- + { "Segoe UI", {9, 24,} },
- + { "Tahoma", {7, 32,} },
- + { "Tahoma", {8, 32,} },
- + { "Tahoma", {9, 32,} },
- + { "Times New Roman", {17, 8,} },
- + { "Trebuchet MS", {10, 16,} },
- + { "Trebuchet MS", {11, 0,} },
- + { "Trebuchet MS", {8, 32,} },
- + { "Trebuchet MS", {9, 32,} },
- + { "Verdana", {8, 16,} },
- + { "Verdana", {15, 16,} },
- + { "Verdana", {14, 32,} },
- + { "Verdana", {18, 32,} },
- + { "Verdana", {19, 24,} },
- + };
- +
- +
- +/* "Font name", {start ppem, end ppem} */
- +#define ALWAYS_USE_100_RULES_SIZE 46
- + SA_Rule ALWAYS_USE_100_Rules
- + [ALWAYS_USE_100_RULES_SIZE] =
- + {
- + { "Andale Mono", {0, MAX_PPEM,} },
- + { "Arial Unicode MS", {0, MAX_PPEM,} },
- + { "Arial", {0, MAX_PPEM,} },
- + { "Arimo", {0, MAX_PPEM,} },
- + { "Bitstream Vera Sans Mono", {0, MAX_PPEM,} },
- + { "Bitstream Vera Sans", {10, 14,} },
- + { "Bitstream Vera Sans", {16, 17,} },
- + { "Calibri", {23, MAX_PPEM,} },
- + { "Consolas", {0, MAX_PPEM,} },
- + { "Courier New", {12, 12,} },
- + { "Courier", {0, MAX_PPEM,} },
- + { "Cousine", {0, MAX_PPEM,} },
- + { "DejaVu Sans Mono", {0, MAX_PPEM,} },
- + { "DejaVu Sans", {10, 14,} },
- + { "DejaVu Sans", {16, 17,} },
- + { "Droid Sans", {12, 12,} },
- + { "Droid Sans", {15, 15,} },
- + { "FreeMono", {0, MAX_PPEM,} },
- + { "FreeSans", {0, MAX_PPEM,} },
- + { "Liberation Mono", {0, MAX_PPEM,} },
- + { "Lucida Console", {0, MAX_PPEM,} },
- + { "Luxi Sans", {13, 13,} },
- + { "Microsoft Sans Serif", {0, MAX_PPEM,} },
- + { "Monaco", {0, MAX_PPEM,} },
- + { "Segoe UI", {11, 12,} },
- + { "Segoe UI", {14, 14,} },
- + { "Tahoma", {11, 11,} },
- + { "Tahoma", {14, MAX_PPEM,} },
- + { "Times New Roman", {14, 14,} },
- + { "Times New Roman", {16, 16,} },
- + { "Trebuchet MS", {13, 13,} },
- + { "Ubuntu", {12, 13,} },
- + { "Ubuntu", {15, 15,} },
- + { "Verdana", {0, 14,} },
- + { "Verdana", {16, MAX_PPEM,} },
- + { "Pragmata", {0, MAX_PPEM,} },
- + { "Essential PragmataPro", {0, MAX_PPEM,} },
- + };
- +
- +
- +
- +
- +#define AUTOHINT_BRIGHTNESS_RULES_SIZE 3
- + SA_Rule BRIGHTNESS_Rules
- + [AUTOHINT_BRIGHTNESS_RULES_SIZE] =
- + {
- + { "Baskerville", {0, -20,} },
- + { "Garamond", {0, -20,} },
- + { "Optima", {0, -20,} },
- + };
- +
- +#define AUTOHINT_CONTRAST_RULES_SIZE 3
- + SA_Rule CONTRAST_Rules
- + [AUTOHINT_CONTRAST_RULES_SIZE] =
- + {
- + { "Baskerville", {0, 25,} },
- + { "Garamond", {0, 25,} },
- + { "Optima", {0, 25,} },
- + };
- +
- +#if 0
- +#define STEM_SPACING_RULES_SIZE 3
- + SA_Rule STEM_SPACING_Rules
- + [STEM_SPACING_RULES_SIZE] =
- + {
- + { "Tahoma", {10, 12, 18, 18, 30} },
- + { "Arial", {10, 11, 23, 25, 30} },
- + { "Freesans", {10, 12, 18, 18, 30} },
- + };
- +
- +#define STEM_START_RULES_SIZE 3
- + SA_Rule STEM_START_Rules
- + [STEM_START_RULES_SIZE] =
- + {
- + { "Tahoma", {14, 17, 30, 100, 100} },
- + { "Arial", {11, 18, 23, 30, 30} },
- + { "Freesans", {10, 18, 18, 25, 30} },
- + };
- +#endif
- +
- + typedef struct Stem_Data_
- + {
- + FT_Int stem_width;
- + FT_Int stem_spacing;
- + FT_Int stem_start;
- + FT_Int stem_scaling;
- + FT_Int stem_translating_only;
- + FT_Int stem_translating;
- + FT_Int brightness;
- + FT_Int contrast;
- + FT_Bool use_100;
- + FT_Bool synth_stems;
- + FT_Bool edge_detection;
- + FT_Bool bearing_correction;
- + FT_Int m;
- + } Stem_Data;
- +
- +
- + typedef struct Stem_Segment_
- + {
- + FT_Long x1;
- + FT_Long x2;
- + FT_Int y;
- + } Stem_Segment;
- +
- + typedef struct Stem_Center_
- + {
- + FT_Long x;
- + FT_Long y;
- + FT_Long w;
- + FT_Long x1;
- + FT_Long x2;
- + } Stem_Center;
- +
- + typedef struct Stem_
- + {
- + FT_Long center;
- + FT_Long count;
- + FT_Long rcount; /* used to count within a range in possible stems */
- + FT_Long width;
- + FT_Long height;
- + FT_Short zone; /* 1 2 or 3 */
- + FT_Bool generated;
- + } Stem;
- +
- +
- + static void
- + swap_stem ( Stem* s1, Stem* s2 )
- + {
- + Stem s;
- + s.center = s1->center;
- + s.count = s1->count;
- + s.rcount = s1->rcount;
- + s.width = s1->width;
- + s.zone = s1->zone;
- + s.generated = s1->generated;
- +
- + s1->center = s2->center;
- + s1->count = s2->count;
- + s1->rcount = s2->rcount;
- + s1->width = s2->width;
- + s1->zone = s2->zone;
- + s1->generated = s2->generated;
- +
- + s2->center = s.center;
- + s2->count = s.count;
- + s2->rcount = s.rcount;
- + s2->width = s.width;
- + s2->zone = s.zone;
- + s2->generated = s.generated;
- + }
- +
- +
- + FT_LOCAL_DEF( void )
- + sa_fill_known_stem_values (
- + FT_String* family,
- + int ppem,
- + FT_String* style,
- + FT_UInt num_stems,
- + Stem_Data* known_stem_values )
- + {
- + FT_Int i, j;
- + if (verbose) printf("%s ", family);
- +
- + i = 0;
- + while ( i < SNAPPING_STEM_WIDTHS_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_STEM_WIDTHS_Rules[i].family, family ) == 0 ) )
- + {
- + j = 0;
- + known_stem_values->stem_width = 1;
- +
- + while (j < 4)
- + {
- + if (SNAPPING_STEM_WIDTHS_Rules[i].ppem[j] == MAX_PPEM )
- + {
- + known_stem_values->stem_width = -1; /* use default */
- + j = 5;
- + i = SNAPPING_STEM_WIDTHS_RULES_SIZE;
- + }
- + else if (ppem < SNAPPING_STEM_WIDTHS_Rules[i].ppem[j])
- + {
- + known_stem_values->stem_width = j;
- + j = 5;
- + i = SNAPPING_STEM_WIDTHS_RULES_SIZE;
- + }
- + j++;
- + }
- + }
- + i++;
- + }
- +
- + i = 0;
- + while ( i < SNAPPING_STEM_SCALING_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_STEM_SCALING_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->stem_scaling = -1; /* default */
- +
- + if (ppem == SNAPPING_STEM_SCALING_Rules[i].ppem[0])
- + {
- + known_stem_values->stem_scaling = SNAPPING_STEM_SCALING_Rules[i].ppem[1];
- + i = SNAPPING_STEM_SCALING_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- +
- + i = 0;
- + while ( i < SNAPPING_M_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_M_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->m = -1; /* default */
- +
- + if (ppem == SNAPPING_M_Rules[i].ppem[0])
- + {
- + known_stem_values->m = SNAPPING_M_Rules[i].ppem[1];
- + i = SNAPPING_M_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- + i = 0;
- + while ( i < SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->stem_translating_only = -1024; /* default */
- +
- + if (ppem == SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].ppem[0]
- + || SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].ppem[0] == 0)
- + {
- + known_stem_values->stem_translating_only = SNAPPING_STEM_TRANSLATING_ONLY_Rules[i].ppem[1];
- + i = SNAPPING_STEM_TRANSLATING_ONLY_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- + i = 0;
- + while ( i < SNAPPING_STEM_TRANSLATING_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_STEM_TRANSLATING_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->stem_translating = 0; /* default */
- +
- + if (ppem == SNAPPING_STEM_TRANSLATING_Rules[i].ppem[0]
- + || SNAPPING_STEM_TRANSLATING_Rules[i].ppem[0] == 0)
- + {
- + known_stem_values->stem_translating = SNAPPING_STEM_TRANSLATING_Rules[i].ppem[1];
- + i = SNAPPING_STEM_TRANSLATING_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- +
- + i = 0;
- + while ( i < ALWAYS_USE_100_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( ALWAYS_USE_100_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->use_100 = FALSE; /* default */
- +
- + if (ppem >= ALWAYS_USE_100_Rules[i].ppem[0] && ppem <= ALWAYS_USE_100_Rules[i].ppem[1] )
- + {
- + known_stem_values->use_100 = TRUE;
- + i = ALWAYS_USE_100_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- +
- + i = 0;
- + while ( i < SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_SYNTHESIZE_STEMS_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->synth_stems = FALSE; /* default */
- +
- + if (ppem >= SNAPPING_SYNTHESIZE_STEMS_Rules[i].ppem[0] && ppem <= SNAPPING_SYNTHESIZE_STEMS_Rules[i].ppem[1] )
- + {
- + known_stem_values->synth_stems = TRUE;
- + i = SNAPPING_SYNTHESIZE_STEMS_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- +
- + i = 0;
- + while ( i < SNAPPING_EDGE_DETECTION_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_EDGE_DETECTION_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->edge_detection = FALSE; /* default */
- +
- + if (ppem >= SNAPPING_EDGE_DETECTION_Rules[i].ppem[0] && ppem <= SNAPPING_EDGE_DETECTION_Rules[i].ppem[1] )
- + {
- + known_stem_values->edge_detection = TRUE;
- + i = SNAPPING_EDGE_DETECTION_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- +
- + i = 0;
- + while ( i < SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( SNAPPING_NO_BEARING_CORRECTION_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->bearing_correction = TRUE; /* default */
- +
- + if (ppem >= SNAPPING_NO_BEARING_CORRECTION_Rules[i].ppem[0] && ppem <= SNAPPING_NO_BEARING_CORRECTION_Rules[i].ppem[1] )
- + {
- + known_stem_values->bearing_correction = FALSE;
- + i = SNAPPING_NO_BEARING_CORRECTION_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- +
- +#if 0
- + i = 0;
- + while ( i < AUTOHINT_BRIGHTNESS_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( BRIGHTNESS_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->brightness = 0.0;
- +
- + if (ppem == BRIGHTNESS_Rules[i].ppem[0] || BRIGHTNESS_Rules[i].ppem[0] == 0)
- + {
- + known_stem_values->brightness = BRIGHTNESS_Rules[i].ppem[1];
- + i = AUTOHINT_BRIGHTNESS_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- + i = 0;
- + while ( i < AUTOHINT_CONTRAST_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( CONTRAST_Rules[i].family, family ) == 0 ) )
- + {
- + known_stem_values->contrast = 0.0;
- +
- + if (ppem == CONTRAST_Rules[i].ppem[0] || CONTRAST_Rules[i].ppem[0] == 0)
- + {
- + known_stem_values->contrast = CONTRAST_Rules[i].ppem[1];
- + i = AUTOHINT_CONTRAST_RULES_SIZE;
- + }
- + }
- + i++;
- + }
- +
- + for ( i = 0; i <= STEM_SPACING_RULES_SIZE; i++ )
- + {
- + if ( family &&
- + ( strcasecmp( STEM_SPACING_Rules[i].family, family ) == 0 ) )
- + {
- + j = 0;
- + known_stem_values->stem_spacing = 2; /* default */
- +
- + while (j < 4)
- + {
- + if (ppem < STEM_SPACING_Rules[i].ppem[j])
- + {
- + known_stem_values->stem_spacing = j;
- + j = 5;
- + }
- + j++;
- + }
- + }
- + }
- +
- +
- + for ( i = 0; i <= STEM_START_RULES_SIZE; i++ )
- + {
- + if ( family &&
- + ( strcasecmp( STEM_START_Rules[i].family, family ) == 0 ) )
- + {
- + j = 0;
- + known_stem_values->stem_start = 1; /* default */
- +
- + while (j < 4)
- + {
- + if (ppem < STEM_START_Rules[i].ppem[j])
- + {
- + known_stem_values->stem_start = j;
- + j = 5;
- + }
- + j++;
- + }
- + }
- + }
- +#endif
- + }
- +
- +
- + FT_LOCAL_DEF( FT_Int )
- + get_contrast (
- + FT_String* family,
- + int ppem)
- + {
- + FT_Int i;
- + if (verbose) printf("%s ", family);
- +
- + i = 0;
- + while ( i < AUTOHINT_CONTRAST_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( CONTRAST_Rules[i].family, family ) == 0 ) )
- + {
- + if (ppem == CONTRAST_Rules[i].ppem[0] || CONTRAST_Rules[i].ppem[0] == 0)
- + {
- + return CONTRAST_Rules[i].ppem[1];
- + }
- + }
- + i++;
- + }
- + return 0;
- + }
- +
- +
- + FT_LOCAL_DEF( FT_Int )
- + get_brightness (
- + FT_String* family,
- + int ppem)
- + {
- + FT_Int i;
- + if (verbose) printf("%s ", family);
- +
- + i = 0;
- + while ( i < AUTOHINT_BRIGHTNESS_RULES_SIZE )
- + {
- + if ( family &&
- + ( strcasecmp( BRIGHTNESS_Rules[i].family, family ) == 0 ) )
- + {
- + if (ppem == BRIGHTNESS_Rules[i].ppem[0] || BRIGHTNESS_Rules[i].ppem[0] == 0)
- + {
- + return BRIGHTNESS_Rules[i].ppem[1];
- + }
- + }
- + i++;
- + }
- + return 0;
- + }
- +
- +
- + /* Stem alignment for bitmaps; A hack with very nice results */
- + /* Ideally this could be implemented on the outline, prior to
- + * rasterization. Possible future enhancement is to use the
- + * warper code to achieve this */
- + static void
- + _lcd_stem_align ( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_GlyphSlot slot,
- + FT_Long* translate_value,
- + float* scale_value,
- + FT_UInt alignment_strength,
- + FT_UInt fitting_strength,
- + float* embolden_value
- + )
- + {
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- +
- + Stem_Segment* segments;
- + Stem_Segment* leftmost_segment;
- + Stem_Segment* rightmost_segment;
- + Stem_Segment* leftmost_segment_not_extrema;
- + Stem_Segment* rightmost_segment_not_extrema;
- + Stem* stems;
- + Stem* possible_stems;
- + Stem* leftmost_stem;
- + Stem* rightmost_stem;
- + Stem_Data* known_stem_values;
- + Stem_Center* centers;
- + FT_Long leftmost_point = width * 256;
- + FT_Long rightmost_point = 0;
- + FT_Long leftmost_point_not_extrema = width * 256;
- + FT_Long rightmost_point_not_extrema = 0;
- + FT_Long num_segments = 0;
- + FT_Long num_centers = 0;
- + FT_Long stem_centers[width * 256];
- + FT_UInt h;
- + FT_ULong valid_stems = 0, valid_possible_stems = 0;
- + FT_Long center, stem_matches, stem_matches_ledge;
- + FT_Long stem_matches_redge, next_center, last_matching_center;
- + FT_Long last_matching_ledge, last_matching_redge, this_center;
- + FT_Int max_strength;
- + FT_Byte* line = bitmap->buffer;
- + FT_UInt current_value = 0;
- + FT_UInt xx;
- + FT_Long linearHoriAdvance = slot->linearHoriAdvance >> 10;
- +
- + FT_Int m_horiBearingX = slot->metrics.horiBearingX;
- + FT_Int m_horiAdvance = slot->metrics.horiAdvance;
- + FT_Int m_width = slot->metrics.width;
- + FT_Pos one_pixel = 768;
- + FT_Pos one_third_pixel = 256;
- + FT_Int columns_per_pixel = 3;
- + /*FT_Int extra_columns = 6;*/
- +
- + /* on / off flags for testing different features */
- + FT_Bool strategy_translate_using_closest_stem = TRUE;
- + FT_Bool strategy_scale_to_closest_centers = FALSE;
- + FT_Bool strategy_scale_to_closest_centers_up_only = FALSE;
- + FT_Bool strategy_always_use_distance_ceiling = FALSE;
- + FT_Bool strategy_auto_change_center_offset = TRUE;
- + FT_Bool strategy_use_m_control = FALSE;
- + FT_Bool strategy_correct_out_of_bounds_outlines = FALSE; /*this needs work.. breaks some glyphs like verdana 12 */
- + FT_Bool strategy_also_use_edge_detection_for_stems = FALSE;
- + FT_Bool strategy_use_strengths = TRUE;
- + FT_Bool strategy_synthesize_stems = FALSE;
- + FT_Bool strategy_bearing_correction = TRUE;
- + FT_Bool strategy_use_d_correction = TRUE;
- + FT_Bool strategy_fit_to_width = FALSE;
- + /*FT_Bool strategy_center_glyph = FALSE;*/
- + FT_Bool strategy_use_verdana_12_hack = TRUE;
- + FT_Bool has_serifs = FALSE;
- + FT_Bool autohinted = FALSE;
- +
- + const FT_Int MIN_PPEM = 7;
- + /*const FT_Int MAX_PPEM = 100;*/
- + const FT_Int MAX_STEMS = 3;
- + FT_Int ppem = 0;
- +
- + int checked_use_known_settings_on_selected_fonts_env = 0;
- + FT_Bool use_known_settings_on_selected_fonts = FALSE;
- +
- + int cur_width;
- + char *cur_width_env = getenv( "CUR_WIDTH" );
- +
- + if ( cur_width_env != NULL ){
- + sscanf ( cur_width_env, "%d", &cur_width );
- + if (cur_width != 0) autohinted = TRUE;
- + }
- +
- + /* An incoming scale value of 1.1 indicates to do certain things */
- + /*if (*scale_value == 1.1) strategy_use_verdana_12_hack = TRUE;*/
- +
- + /* reset to default */
- + *scale_value = 1.0;
- +
- + if ( checked_use_known_settings_on_selected_fonts_env == 0 )
- + {
- + char *use_known_settings_on_selected_fonts_env = getenv( "INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS" );
- + if ( use_known_settings_on_selected_fonts_env != NULL )
- + {
- + if ( strcasecmp(use_known_settings_on_selected_fonts_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_known_settings_on_selected_fonts_env, "true") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "1") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "on") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "yes") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + }
- + }
- + checked_use_known_settings_on_selected_fonts_env = 1;
- + }
- +
- +
- + /* Simply return in odd cases where these don't seem to be set */
- + /* Flash and some pdf viewers will crash otherwise */
- + if ( !slot->face || !slot->face->size || !slot->face->size->metrics.x_ppem )
- + return;
- + if ( slot->face->size->metrics.x_ppem > MAX_PPEM ) return;
- + /*if ( width < 4 ) return;*/
- +
- + if ( slot->face->size->metrics.x_ppem < MIN_PPEM ) return;
- +
- + if ( !FT_IS_SCALABLE( slot->face ) ) return;
- +
- + ppem = slot->face->size->metrics.x_ppem;
- +
- +
- + /* only perform alignment on styles we know, that aren't bold or italic */
- + /* perhaps detection could be added on those that are not set? */
- + /* Require certain ppems for narrow and light fonts */
- + if( slot->face->style_name )
- + {
- + if ( strcasestr(slot->face->style_name, "Italic")
- + || strcasestr(slot->face->style_name, "Oblique")
- + || strcasestr(slot->face->style_name, "Script")
- + || strcasestr(slot->face->style_name, "Handwriting")
- + || strcasestr(slot->face->style_name, "Bold")
- + || strcasestr(slot->face->style_name, "Black")
- + || ( ( strcasestr(slot->face->style_name, "Extra Thin")
- + || strcasestr(slot->face->style_name, "Extra Light") )
- + && ppem < 10 )
- + || ( strcasestr(slot->face->style_name, "Thin")
- + && ppem < 10 )
- + || ( strcasestr(slot->face->style_name, "Light")
- + && ppem < 10 )
- + || ( strcasestr(slot->face->style_name, "Narrow")
- + && ppem < 15 )
- + || ( strcasestr(slot->face->style_name, "Condensed")
- + && ppem < 20 ) )
- + return;
- + }
- +
- + if( slot->face->family_name )
- + {
- + if ( strcasestr(slot->face->family_name, "Italic")
- + || strcasestr(slot->face->family_name, "Oblique")
- + || strcasestr(slot->face->family_name, "Script")
- + || strcasestr(slot->face->family_name, "Handwriting")
- + || strcasestr(slot->face->family_name, "Bold")
- + || strcasestr(slot->face->family_name, "Black")
- + || ( ( strcasestr(slot->face->family_name, "Extra Thin")
- + || strcasestr(slot->face->family_name, "Extra Light") )
- + && ppem < 10 )
- + || ( strcasestr(slot->face->family_name, "Thin")
- + && ppem < 10 )
- + || ( strcasestr(slot->face->family_name, "Light")
- + && ppem < 10 )
- + || ( strcasestr(slot->face->family_name, "Narrow")
- + && ppem < 15 )
- + || ( strcasestr(slot->face->family_name, "Condensed")
- + && ppem < 20 ) )
- + return;
- + }
- + else if ( slot->face->style_flags )
- + {
- + if ( slot->face->style_flags & FT_STYLE_FLAG_ITALIC
- + || slot->face->style_flags & FT_STYLE_FLAG_BOLD
- + || FT_IS_TRICKY( slot->face ) )
- + return;
- + }
- + else return;
- +
- + if( slot->face->family_name )
- + {
- + if ( strcasestr(slot->face->family_name, "Courier")
- + || strcasestr(slot->face->family_name, "Serif")
- + || strcasestr(slot->face->family_name, "Times"))
- + has_serifs = TRUE;
- + }
- +
- + if ( mode != FT_RENDER_MODE_LCD )
- + {
- + columns_per_pixel = 1;
- + one_pixel = 256;
- + one_third_pixel = 85;
- + /*extra_columns = 0;*/
- + /* until this can be figured out just return */
- + /* There are issues with missing glyphs */
- + return;
- + }
- +
- + known_stem_values = (Stem_Data*) malloc (columns_per_pixel * sizeof(Stem_Data)); /* only look at top 3 for now */
- + known_stem_values->stem_spacing = -1;
- + known_stem_values->stem_width = -1;
- + known_stem_values->stem_start = -1;
- + known_stem_values->stem_scaling = -1;
- + known_stem_values->stem_translating_only = -1024;
- + known_stem_values->stem_translating = 0;
- + known_stem_values->brightness = 0;
- + known_stem_values->contrast = 0;
- + known_stem_values->use_100 = FALSE;
- + known_stem_values->m = -1;
- + known_stem_values->synth_stems = FALSE;
- + known_stem_values->bearing_correction = TRUE;
- +
- + if (use_known_settings_on_selected_fonts)
- + {
- + sa_fill_known_stem_values ( slot->face->family_name,
- + ppem, slot->face->style_name,
- + valid_stems, known_stem_values );
- + if (verbose)
- + printf ("width:%d,spacing:%d,start:%d,scaling:%d,translate:%d ",
- + known_stem_values->stem_width, known_stem_values->stem_spacing,
- + known_stem_values->stem_start, known_stem_values->stem_scaling,
- + known_stem_values->stem_translating_only) ;
- + }
- +
- + /* translate value may be set for < 10 */
- + if (use_known_settings_on_selected_fonts && known_stem_values->stem_translating_only > -1024 )
- + {
- + *translate_value = known_stem_values->stem_translating_only;
- + return;
- + }
- +
- + if (use_known_settings_on_selected_fonts && known_stem_values->bearing_correction == FALSE )
- + {
- + strategy_bearing_correction = FALSE;
- + }
- +
- + if ( known_stem_values->use_100 || known_stem_values->m >= 0)
- + {
- + alignment_strength = fitting_strength = 100;
- + strategy_use_m_control = TRUE;
- + }
- +
- + if ( known_stem_values->edge_detection )
- + {
- + strategy_also_use_edge_detection_for_stems = TRUE;
- + }
- +
- + if ( ppem < 9 ) return;
- + if ( ppem > 20 ) strategy_use_m_control = TRUE;
- +
- + /* Allocate */
- + segments = (Stem_Segment*) malloc( (1) * sizeof (Stem_Segment));
- + leftmost_segment = (Stem_Segment*) malloc( sizeof (Stem_Segment));
- + leftmost_segment_not_extrema = (Stem_Segment*) malloc( sizeof (Stem_Segment));
- + rightmost_segment = (Stem_Segment*) malloc( sizeof (Stem_Segment));
- + rightmost_segment_not_extrema = (Stem_Segment*) malloc( sizeof (Stem_Segment));
- +
- + stems = (Stem*) malloc (MAX_STEMS * sizeof(Stem));
- + possible_stems = (Stem*) malloc (MAX_STEMS * sizeof(Stem));
- + leftmost_stem = (Stem*) malloc ( sizeof(Stem));
- + rightmost_stem = (Stem*) malloc ( sizeof(Stem));
- + centers = (Stem_Center*) malloc ( (1) * sizeof(Stem_Center));
- +
- + if (verbose) printf("\n");
- +
- + /* Initialize */
- + for ( xx = 0; xx < width * 256; xx += 1 )
- + {
- + stem_centers[xx] = 0;
- + }
- + for ( xx = 0; xx < num_segments; xx += 1 )
- + {
- + segments[xx].x1 = 0;
- + segments[xx].x2 = 0;
- + segments[xx].y = 0;
- + }
- + rightmost_segment->x1 = 0;
- + rightmost_segment->x2 = 0;
- + rightmost_segment->y = 0;
- + leftmost_segment->x1 = 99999999;
- + leftmost_segment->x2 = 0;
- + leftmost_segment->y = 0;
- +
- + rightmost_segment_not_extrema->x1 = 0;
- + rightmost_segment_not_extrema->x2 = 0;
- + rightmost_segment_not_extrema->y = 0;
- + leftmost_segment_not_extrema->x1 = 99999999;
- + leftmost_segment_not_extrema->x2 = 0;
- + leftmost_segment_not_extrema->y = 0;
- +
- + /* Locate stem centers for later processing */
- + for ( h = (FT_UInt)bitmap->rows; h > 0; h--, line += bitmap->pitch )
- + {
- + current_value = 0;
- + /* Calculate various sums and stem widths of glyph */
- + for ( xx = 0; xx < width; xx += 1 )
- + {
- + /* Reallocate */
- + segments = (Stem_Segment*) realloc( segments, (num_segments + 1) * sizeof (Stem_Segment));
- +
- + /* if line is white, and now has color, it's the start of a stem */
- + if (current_value == 0 && line[xx] > 0)
- + {
- + /* start of stem */
- + segments[num_segments].x1 = 256 * (xx) + (255 - line[xx]);
- + segments[num_segments].y = h;
- + }
- +
- + /* otherwise, if it's currently black and the new value is 0, it's the end of a stem */
- + else if ( ( current_value > 0 && line[xx] == 0 )
- + || ( current_value > 0 && xx == width - 1 ) )
- + {
- + FT_Long stem_center_x/*, stem_width*/;
- + segments[num_segments].x2 = 256 * (xx-1) + line[xx-1];
- +
- + if (xx == width - 1) segments[num_segments].x2 += line[xx];
- +
- + /*stem center is average of start and end of stem */
- + stem_center_x = (segments[num_segments].x2 + segments[num_segments].x1) / 2;
- + /*stem_width = segments[num_segments].x2 - segments[num_segments].x1;*/
- + /* Reallocate */
- + centers = (Stem_Center*) realloc ( centers, (num_centers + 1) * sizeof(Stem_Center));
- + centers[num_centers].x = stem_center_x;
- + centers[num_centers].y = h;
- + centers[num_centers].x1 = segments[num_segments].x1;
- + centers[num_centers].x2 = segments[num_segments].x2;
- +
- + num_centers++;
- +
- + stem_centers[stem_center_x] += 1;
- +
- + /* Find left and rightmost points for later calculations */
- + /* OR - Favor ones that aren't on the top or bottom if possible to prevent v and w from getting caught later */
- + if ( segments[num_segments].x1 < leftmost_segment->x1
- + || ( segments[num_segments].y > 1 && segments[num_segments].y < height
- + && segments[num_segments].x1 == leftmost_segment->x1 ) )
- + {
- + leftmost_segment->x1 = segments[num_segments].x1;
- + leftmost_segment->x2 = segments[num_segments].x2;
- + leftmost_segment->y = h;
- + }
- + if (segments[num_segments].x2 > rightmost_segment->x2
- + || ( segments[num_segments].y > 1 && segments[num_segments].y < height
- + && segments[num_segments].x1 == rightmost_segment->x1 ) )
- + {
- + rightmost_segment->x1 = segments[num_segments].x1;
- + rightmost_segment->x2 = segments[num_segments].x2;
- + rightmost_segment->y = h;
- + }
- +
- + if (segments[num_segments].x1 < leftmost_segment_not_extrema->x1
- + || ( segments[num_segments].y > 1 && segments[num_segments].y < height
- + && segments[num_segments].x1 == leftmost_segment_not_extrema->x1
- + && h < (FT_UInt)bitmap->rows && h > 0 ) )
- + {
- + leftmost_segment_not_extrema->x1 = segments[num_segments].x1;
- + leftmost_segment_not_extrema->x2 = segments[num_segments].x2;
- + leftmost_segment_not_extrema->y = h;
- + }
- + if (segments[num_segments].x2 > rightmost_segment_not_extrema->x2
- + || ( segments[num_segments].y > 1 && segments[num_segments].y < height
- + && segments[num_segments].x1 == rightmost_segment_not_extrema->x1
- + && h < (FT_UInt)bitmap->rows && h > 0 ) )
- + {
- + rightmost_segment_not_extrema->x1 = segments[num_segments].x1;
- + rightmost_segment_not_extrema->x2 = segments[num_segments].x2;
- + rightmost_segment_not_extrema->y = h;
- + }
- +
- + if (segments[num_segments].x1 < leftmost_point)
- + {
- + leftmost_point = segments[num_segments].x1;
- + }
- + if (segments[num_segments].x2 > rightmost_point)
- + {
- + rightmost_point = segments[num_segments].x2;
- + }
- +
- + if (segments[num_segments].x1 < leftmost_point_not_extrema
- + && h < (FT_UInt)bitmap->rows && h > 0)
- + {
- + leftmost_point_not_extrema = segments[num_segments].x1;
- + }
- + if (segments[num_segments].x2 > rightmost_point_not_extrema
- + && h < (FT_UInt)bitmap->rows && h > 0)
- + {
- + rightmost_point_not_extrema = segments[num_segments].x2;
- + }
- +
- + num_segments++;
- + }
- + /* else - other conditions - need some error checking here */
- +
- + current_value = line[xx];
- + }
- + }
- +
- + /* initialize */
- + for ( xx = 0; xx < MAX_STEMS; xx +=1 )
- + {
- + stems[xx].center = 0;
- + stems[xx].count = 0;
- + stems[xx].width = 0;
- + stems[xx].height = 0;
- + possible_stems[xx].center = 0;
- + possible_stems[xx].count = 0;
- + possible_stems[xx].width = 0;
- + possible_stems[xx].height = 0;
- + }
- + valid_stems = 0;
- + valid_possible_stems = 0;
- +
- + /* Determine which centers belong to stems */
- + center = 0;
- +
- + while ( center < num_centers )
- + {
- + /* slope at within which to consider a point part of a stem */
- + /*const FT_UInt slope = 1;
- + const FT_UInt topslope = (256 * 3) / 10; */
- + FT_Int deviation1 = 5; /* 10 to 20 wiith 4 matches seems good, but 1 or 2 with 3 stems needs to somehow get included */
- + FT_Int deviation2=-1, requirement1 = 4, stem_match_requirement = 3;
- + FT_Int best_height = 0, center_difference_in_height;
- + FT_Int center_difference_in_width, valid_center_average;
- + FT_Int smallest_width_ledge, smallest_width_redge;
- + FT_Int x1_difference_in_width, x2_difference_in_width;
- + FT_Bool large_gap_found = FALSE, no_gap_found = FALSE;
- + FT_Bool large_gap_found_ledge = FALSE, no_gap_found_ledge = FALSE;
- + FT_Bool large_gap_found_redge = FALSE, no_gap_found_redge = FALSE;
- + FT_Bool stem_detected = FALSE;
- + FT_Int set_width_to, set_center_to;
- +
- + /* seems to not do damage */
- + /* May not be effective */
- + requirement1 = height / 4;
- + if (requirement1 < 5) requirement1 = 5;
- + deviation1 = 20;
- + deviation2 = 20;
- +
- + if (columns_per_pixel == 1)
- + {
- + deviation1 = deviation2 = 10;
- + }
- +
- + if ((FT_Int)bitmap->rows <= 6) deviation1 = 25;
- + if ((FT_Int)bitmap->rows <= 6) deviation2 = 25;
- +
- + if (columns_per_pixel == 1 && (FT_Int)bitmap->rows <= 6)
- + {
- + deviation1 = deviation2 = 12;
- + }
- +
- + /* THIS WORKS, BUT NEED TO PUNISH DIAGONALS like W */
- + /*requirement2 = height / 5;
- + if (requirement2 < 3) requirement2 = 3;
- + deviation2 = 1 ;*/
- + valid_center_average = 0;
- + /* if (deviation2 < 1) deviation2 = 1;*/
- +
- + large_gap_found = large_gap_found_ledge = large_gap_found_redge = FALSE;
- + no_gap_found = no_gap_found_ledge = no_gap_found_redge = FALSE;
- + stem_detected = FALSE;
- +
- + if (ppem < 11)
- + {
- + requirement1 = 4;
- + }
- + if (ppem > 18 )
- + {
- + stem_match_requirement = height / 4;
- + if (stem_match_requirement < 3) stem_match_requirement = 3;
- + }
- +
- + smallest_width_ledge = smallest_width_redge = width * 256;
- + stem_matches = 0;
- + stem_matches_ledge = 0;
- + stem_matches_redge = 0;
- + last_matching_center = -1;
- + last_matching_ledge = -1;
- + last_matching_redge = -1;
- +
- + /* set currently looked at center to center value */
- + this_center = center;
- + next_center = 0;
- +
- + /* For each center, compare with all other centers to see if others match the properties of this one */
- + while ( next_center < num_centers )
- + {
- +
- + /* calculate differences */
- + center_difference_in_width = abs (centers[this_center].x - centers[next_center].x);
- + center_difference_in_height = abs (centers[this_center].y - centers[next_center].y);
- + x1_difference_in_width = abs (centers[this_center].x1 - centers[next_center].x1);
- + x2_difference_in_width = abs (centers[this_center].x2 - centers[next_center].x2);
- +
- +
- + /* property - stem center points that align */
- + /* if the center is within range, the center is less than 1/2 the height away, and at least one edge is also within range */
- + if ( center_difference_in_width < center_difference_in_height * deviation1
- + && center_difference_in_height <= (FT_Int)bitmap->rows / 2
- + /* prevents w from getting caught ---- but also kills m */
- + && (x1_difference_in_width < center_difference_in_height * deviation2
- + || x2_difference_in_width < center_difference_in_height * deviation2 )
- +
- + )
- + {
- + stem_matches += 1;
- + valid_center_average += centers[next_center].x;
- + /* try to find where the matching centers are far apart */
- + if (last_matching_center >= 0
- + && abs(centers[last_matching_center].y - centers[next_center].y) >= (FT_Int)bitmap->rows / 2)
- + large_gap_found = TRUE;
- + /* try to find where matching centers are next to each other */
- + if (last_matching_center >= 0
- + && abs(centers[last_matching_center].y - centers[next_center].y) == 1)
- + no_gap_found = TRUE;
- + last_matching_center = next_center;
- + }
- +
- + if (strategy_also_use_edge_detection_for_stems){
- + /* property - stem left edge points that align */
- + /* if the center is within range, the center is less than 1/2 the height away */
- + if ( x1_difference_in_width < center_difference_in_height * deviation1
- + && center_difference_in_height <= (FT_Int)bitmap->rows / 2 )
- + {
- + stem_matches_ledge += 1;
- + /* may not need for edges */
- + /*valid_center_average += centers[next_center].x; */
- +
- + if (centers[next_center].x2 - centers[next_center].x1 < smallest_width_ledge )
- + smallest_width_ledge = centers[next_center].x2 - centers[next_center].x1;
- +
- + /* try to find where the matching centers are far apart */
- + if (last_matching_ledge >= 0
- + && abs(centers[last_matching_ledge].y - centers[next_center].y) >= (FT_Int)bitmap->rows / 2)
- + large_gap_found_ledge = TRUE;
- + /* try to find where matching centers are next to each other */
- + if (last_matching_ledge >= 0
- + && abs(centers[last_matching_ledge].y - centers[next_center].y) == 1)
- + no_gap_found_ledge = TRUE;
- + last_matching_ledge = next_center;
- + }
- + }
- +
- + if (strategy_also_use_edge_detection_for_stems){
- + /* property - stem right edge points that align */
- + /* if the center is within range, the center is less than 1/2 the height away */
- + if ( x2_difference_in_width < center_difference_in_height * deviation1
- + && center_difference_in_height <= (FT_Int)bitmap->rows / 2 )
- + {
- + stem_matches_redge += 1;
- + /* may not need for edges */
- + /*valid_center_average += centers[next_center].x; */
- +
- + if (centers[next_center].x2 - centers[next_center].x1 < smallest_width_redge )
- + smallest_width_redge = centers[next_center].x2 - centers[next_center].x1;
- +
- + /* try to find where the matching centers are far apart */
- + if (last_matching_redge >= 0
- + && abs(centers[last_matching_redge].y - centers[next_center].y) >= (FT_Int)bitmap->rows / 2)
- + large_gap_found_redge = TRUE;
- + /* try to find where matching centers are next to each other */
- + if (last_matching_redge >= 0
- + && abs(centers[last_matching_redge].y - centers[next_center].y) == 1)
- + no_gap_found_redge = TRUE;
- + last_matching_redge = next_center;
- + }
- + }
- +
- + next_center++;
- + }
- +
- + if (stem_matches > 0 ) valid_center_average /= stem_matches;
- +
- + best_height = stem_matches;
- +
- + /* new version */
- + if ( ( stem_matches >= stem_match_requirement
- + || ( ( (FT_Int)bitmap->rows <= 6 || ppem < 11)
- + && stem_matches >= 2
- + && abs(valid_center_average - centers[center].x) < deviation1 /2 )
- + /* try to catch tightly aligned stuff where the matching centers are next to each other only */
- + || ( stem_matches == 2
- + && abs(valid_center_average - centers[center].x) <= deviation1 /2
- + && no_gap_found && ppem < 18 ) /* catches things like times 16 u but gets a lot of w's too */
- + /* stem width is less than 1/3 of the bitmap width, or bitmap_width is small */
- + )
- + &&
- + ( centers[center].x2 - centers[center].x1 < (m_horiAdvance * 12) / 2
- + || m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) )
- + {
- + stem_detected = TRUE;
- + set_width_to = centers[center].x2 - centers[center].x1;
- + best_height = stem_matches;
- + set_center_to = centers[center].x;
- +
- + }
- + /* see if edges found anything */
- + if (strategy_also_use_edge_detection_for_stems && !stem_detected)
- + {
- + if ((
- + /* Require no gap for edges */
- + stem_matches_ledge >= stem_match_requirement && no_gap_found_ledge
- + /* stem width is less than 1/3 of the bitmap width, or bitmap_width is small */
- + ) && ( centers[center].x2 - centers[center].x1 < (m_horiAdvance * 12) / 2
- + || m_horiAdvance * 12 <= columns_per_pixel * one_pixel)
- + /* The stem occurs on the left side of glyph only */
- + && centers[center].x < (m_horiAdvance * 12) / 2
- +
- + )
- + {
- + stem_detected = TRUE;
- + set_width_to = smallest_width_ledge;
- + best_height = stem_matches_ledge;
- + set_center_to = centers[center].x1 + set_width_to / 2;
- + stem_matches = stem_matches_ledge;
- + }
- + else if ((
- + /* Require no gap for edges */
- + stem_matches_redge >= stem_match_requirement && no_gap_found_redge
- + /* stem width is less than 1/3 of the bitmap width, or bitmap_width is small */
- + ) && ( centers[center].x2 - centers[center].x1 < (m_horiAdvance * 12) / 2
- + || m_horiAdvance * 12 <= columns_per_pixel * one_pixel)
- + /* The stem occurs on the right side of glyph only */
- + && centers[center].x > (m_horiAdvance * 12) / 2
- + )
- + {
- + stem_detected = TRUE;
- + set_width_to = smallest_width_redge;
- + best_height = stem_matches_redge;
- + set_center_to = centers[center].x2 - set_width_to / 2;
- + stem_matches = stem_matches_redge;
- + }
- + }
- +
- +
- + /*store and/or replace highest occurrences with 3 or more centers */
- + /* because this matched, it will become the top dog regardless */
- + if ( stem_detected )
- + if ( stem_matches > possible_stems[0].height )
- + {
- + /* if this is the first stem just go ahead */
- + if (valid_possible_stems == 0)
- + {
- + valid_possible_stems = 1;
- + possible_stems[0].center = set_center_to;
- + possible_stems[0].count = stem_matches;
- + possible_stems[0].width = set_width_to;
- + possible_stems[0].height = stem_matches;
- + }
- +
- + /* otherwise, if there is already a stem */
- + else if (valid_possible_stems == 1 )
- + {
- + /* if the stem is within the range of existing one, replace existing one */
- +
- + /* if the stem isn't within the range of this one swap it with next one first */
- + if (abs(set_center_to - possible_stems[0].center) >= one_pixel * 2)
- + {
- + swap_stem ( &possible_stems[0], &possible_stems[1] );
- + valid_possible_stems = 2;
- + }
- + possible_stems[0].center = set_center_to;
- + possible_stems[0].count = stem_matches;
- + possible_stems[0].width = set_width_to;
- + possible_stems[0].height = stem_matches;
- + }
- +
- + /* otherwise if there are already 2 stems */
- + else if (valid_possible_stems >= 2 )
- + {
- + /* if the stem is within the range of existing one, replace existing one */
- + if ( abs(set_center_to - possible_stems[0].center) <= one_pixel * 2)
- + {
- + possible_stems[0].center = set_center_to;
- + possible_stems[0].count = stem_matches;
- + possible_stems[0].width = set_width_to;
- + possible_stems[0].height = stem_matches;
- + }
- + /* if the stem isn't within the range of this one */
- + else
- + {
- + /* see if within range of next one and swap if so and proceed overwriting it */
- + if ( abs(set_center_to - possible_stems[1].center) <= one_pixel * 2)
- + {
- + swap_stem ( &possible_stems[0], &possible_stems[1] );
- + }
- +
- + /* otherwise see if in range of third one */
- + else if ( abs(set_center_to - possible_stems[2].center) <= one_pixel * 2)
- + {
- + swap_stem ( &possible_stems[0], &possible_stems[2] );
- + }
- +
- + /* otherwise this is the new top dog, so demote everything */
- + else
- + {
- + swap_stem ( &possible_stems[1], &possible_stems[2] );
- + swap_stem ( &possible_stems[0], &possible_stems[1] );
- + valid_possible_stems += 1;
- + }
- + possible_stems[0].center = set_center_to;
- + possible_stems[0].count = stem_matches;
- + possible_stems[0].width = set_width_to;
- + possible_stems[0].height = stem_matches;
- + }
- + }
- + }
- +
- + else if ( stem_matches > possible_stems[1].height && set_center_to != 0)
- + {
- +
- + /* make sure it doesn't match the first stem */
- + if ( abs(set_center_to - possible_stems[0].center) >= one_pixel * 2 )
- + {
- +
- + /* if this is the second stem */
- + if (valid_possible_stems == 1) valid_possible_stems = 2;
- +
- + /* otherwise if there is already a stem here */
- + else if (valid_possible_stems >= 2 )
- + {
- + /* if it doesn't match the second stem, proceed to swap out with the third */
- + /* if it does, replace it */
- + if ( abs(set_center_to - possible_stems[1].center) >= one_pixel * 2 )
- + {
- + swap_stem ( &possible_stems[1], &possible_stems[2] );
- + valid_possible_stems +=1;
- + }
- + }
- + possible_stems[1].center = set_center_to;
- + possible_stems[1].count = stem_matches;
- + possible_stems[1].width = set_width_to;
- + possible_stems[1].height = stem_matches;
- + }
- + }
- +
- + else if ( stem_matches > possible_stems[2].height && set_center_to != 0)
- + {
- + /* if it doesn't match the first or second one */
- + if ( abs(set_center_to - possible_stems[0].center) >= one_pixel * 2
- + && abs(set_center_to - possible_stems[1].center) >= one_pixel * 2)
- +
- + {
- + if (valid_possible_stems == 2)
- + {
- + valid_possible_stems += 1;
- + }
- + possible_stems[2].center = set_center_to;
- + possible_stems[2].count = stem_matches;
- + possible_stems[2].width = set_width_to;
- + possible_stems[1].height = stem_matches;
- + }
- + }
- + if (valid_possible_stems > 3) valid_possible_stems = 3;
- +
- + center++;
- + }
- +
- + /* promote to stem */
- + if (valid_possible_stems > 0)
- + {
- + stems[0].center = possible_stems[0].center;
- + stems[0].count = possible_stems[0].count;
- + stems[0].width = possible_stems[0].width;
- + stems[0].height = possible_stems[0].height;
- + stems[0].generated = FALSE;
- + valid_stems++;
- + }
- +
- + if (valid_stems == 1 && valid_possible_stems > 1)
- + {
- + stems[1].center = possible_stems[1].center;
- + stems[1].count = possible_stems[1].count;
- + stems[1].width = possible_stems[1].width;
- + stems[1].height = possible_stems[1].height;
- + stems[1].generated = FALSE;
- + valid_stems++;
- + }
- +
- + if (valid_stems == 2 && valid_possible_stems > 2 && possible_stems[2].center != 0 )
- + {
- + stems[2].center = possible_stems[2].center;
- + stems[2].count = possible_stems[2].count;
- + stems[2].width = possible_stems[2].width;
- + stems[2].height = possible_stems[2].height;
- + stems[2].generated = FALSE;
- + valid_stems++;
- + }
- +
- + /* sort stems in x direction */
- + if ( valid_stems == 3)
- + {
- + if (stems[0].center > stems[1].center)
- + swap_stem ( &stems[0], &stems[1] );
- + if (stems[0].center > stems[2].center)
- + swap_stem ( &stems[1], &stems[2] );
- + if (stems[1].center > stems[2].center)
- + swap_stem ( &stems[1], &stems[2] );
- + if (stems[0].center > stems[1].center)
- + swap_stem ( &stems[0], &stems[1] );
- +
- + /* only look at first and last stem for now */
- + swap_stem ( &stems[1], &stems[2] );
- + }
- +
- + if (strategy_use_verdana_12_hack
- + && strcasestr(slot->face->family_name, "Verdana")
- + && ppem == 12
- + && valid_stems == 1
- + && (stems[0].center + m_horiBearingX * 12 - one_pixel < m_horiAdvance * 4
- + ||stems[0].center + m_horiBearingX * 12 - one_pixel > m_horiAdvance * 8) )
- + {
- + if (stems[0].center + m_horiBearingX * 12 - one_pixel < m_horiAdvance * 4)
- + {
- + stems[1].center = rightmost_point - one_pixel / 2;
- + stems[1].width = 1;
- + stems[1].generated = TRUE;
- + valid_stems += 1;
- + }
- + else
- + {
- + stems[1].center = leftmost_point + one_pixel / 2;
- + stems[1].width = 1;
- + stems[1].generated = TRUE;
- + valid_stems += 1;
- + }
- + strategy_always_use_distance_ceiling = TRUE;
- + }
- +
- + /* synthesize stems - Works, but needs work */
- + if ( (strategy_synthesize_stems || known_stem_values->synth_stems) && valid_stems == 0 && ppem > 10 )
- + {
- + /* if the leftmost segment's leftmost point is the same as the glyph's leftmost point, and it is of reasonable width, and is not on the top or bottom of the bitmap */
- + if (leftmost_segment_not_extrema->x1 == leftmost_point_not_extrema
- + && abs(leftmost_segment_not_extrema->x2 - leftmost_segment_not_extrema->x1)
- + < (rightmost_point_not_extrema - leftmost_point_not_extrema)/3
- + && leftmost_segment_not_extrema->y
- + < height && leftmost_segment_not_extrema->y > 1 )
- + {
- + stems[valid_stems].center = (leftmost_segment_not_extrema->x2 + leftmost_segment_not_extrema->x1) / 2;
- + stems[valid_stems].width = leftmost_segment_not_extrema->x2 - leftmost_segment_not_extrema->x1;
- + stems[valid_stems].generated = TRUE;
- + valid_stems += 1;
- + }
- +
- +
- + if (rightmost_segment_not_extrema->x2 == rightmost_point_not_extrema
- + && abs(rightmost_segment_not_extrema->x2 - rightmost_segment_not_extrema->x1)
- + < (rightmost_point_not_extrema - leftmost_point_not_extrema)/3
- + && rightmost_segment_not_extrema->y < height && rightmost_segment_not_extrema->y > 1 )
- + {
- + stems[valid_stems].center = (rightmost_segment_not_extrema->x2 + rightmost_segment_not_extrema->x1) / 2;
- + stems[valid_stems].width = rightmost_segment_not_extrema->x2 - rightmost_segment_not_extrema->x1;
- + stems[valid_stems].generated = TRUE;
- + valid_stems += 1;
- + }
- +
- + }
- +
- + /* sort stems in x direction */
- + if (valid_stems > 1 && stems[0].center > stems[1].center)
- + swap_stem ( &stems[0], &stems[1] );
- +
- + if ( valid_stems == 0 && known_stem_values->stem_translating != 0 )
- + {
- + *translate_value += known_stem_values->stem_translating;
- +
- + if (strategy_use_strengths )
- + {
- + /* consider 1/2 pixel the max when strength is at 100%, unless translate is already greater than that */
- + FT_Int strength_cutoff = 32;
- + if (abs(*translate_value) > strength_cutoff) strength_cutoff = *translate_value;
- + max_strength = (strength_cutoff * alignment_strength) / 100;
- + if (*translate_value < -max_strength) *translate_value = -max_strength;
- + else if (*translate_value > max_strength) *translate_value = max_strength;
- + }
- + }
- + else
- + /* Start snapping */
- + {
- + FT_Int center_offset;
- + FT_Int modulus;
- + FT_Int delta, delta2;
- + FT_Long stem_distance = 1, new_distance = 1;
- + FT_Int distance_floor, distance_ceiling;
- + FT_Int translate_value2 = 0;
- + FT_Int main_stem = 0;
- + FT_Int lbearing = m_horiBearingX * 12;
- + FT_Int bitmap_stem_location = stems[0].center;
- + FT_Int advance_stem_location = bitmap_stem_location + lbearing - one_pixel;
- + FT_Int advance_width = m_horiAdvance * 12;
- + FT_Int original_advance_width = 12 * (slot->linearHoriAdvance >> 10);
- + FT_Int glyph_width = rightmost_point - leftmost_point;
- + FT_Int stem_width = stems[0].width;
- + FT_Int advance_leftmost_location = leftmost_point + lbearing - one_pixel;
- + FT_Int advance_rightmost_location = rightmost_point + lbearing - one_pixel;
- +
- +#define proposed_transformed_point(point) \
- + point * (float)(new_distance) / (float)(stem_distance) \
- + + *translate_value * 12 - ( stems[main_stem].center * (float)(new_distance) \
- + / (float)(stem_distance) - stems[main_stem].center)
- +
- +#define proposed_translated_point(point) point + *translate_value * 12
- +
- + center_offset = one_pixel / 2; /* half pixel */
- + modulus = one_pixel; /* whole pixel */
- +
- + /* Determine center_offset via known values */
- + if (known_stem_values->stem_width >= 0)
- + {
- + if (known_stem_values->stem_width % 2 == 0)
- + {
- + center_offset = 0;
- + }
- + else
- + {
- + center_offset = one_pixel / 2;
- + }
- + }
- + /* otherwise do intelligent guessing, if set */
- + else if ( strategy_auto_change_center_offset
- + && ppem >= STEM_WIDTH_2_PPEM
- + && stems[0].width < one_pixel * 1.45)
- + {
- + center_offset = one_pixel / 2;
- + }
- + else if ( strategy_auto_change_center_offset
- + && ppem >= STEM_WIDTH_2_PPEM
- + && stems[0].width >= one_pixel * 1.45
- + && stems[0].width < one_pixel * 2.6)
- + {
- + center_offset = 0;
- + }
- + else if ( strategy_auto_change_center_offset
- + && ppem >= STEM_WIDTH_2_PPEM
- + && stems[0].width >= one_pixel * 2.6
- + && stems[0].width < one_pixel * 3.6)
- + {
- + center_offset = one_pixel / 2;
- + }
- + else if ( strategy_auto_change_center_offset && ppem >= STEM_WIDTH_2_PPEM )
- + center_offset = (one_pixel * ((((int)(stems[0].width + one_pixel / 2)) / one_pixel ) % 2) ) / 2;
- +
- + /* Snap to closest translate and scale values by default */
- + if (valid_stems >= 1)
- + {
- + /* closest snapping point for stem 0 */
- + delta = (stems[0].center + center_offset) % (modulus);
- +
- + if (delta < modulus / 2 ) *translate_value = ( - delta ) / (columns_per_pixel * 4); /* snap left */
- + else *translate_value = (modulus -delta) / (columns_per_pixel * 4); /* snap right */
- + }
- +
- + if (strategy_use_d_correction)
- + {
- + /* if the only stem is in the last 1/3 of glyph width, the advance is
- + * 6 pixels, the ppem 11, and doing so doesn't violate bitmap boundaries,
- + * force it to snap right */
- + if (valid_stems == 1 && advance_stem_location > (advance_width * 2) / 3
- + && advance_width == 6 * one_pixel
- + && rightmost_point + modulus - delta <= ( width - (columns_per_pixel * 2) / 3) * 256
- + && ppem == 11
- + )
- + *translate_value = (modulus -delta) / (columns_per_pixel * 4);
- + }
- +
- + if (strategy_use_strengths )
- + {
- + /* consider 1/2 pixel the max when strength is at 100%, unless translate is already greater than that */
- + FT_Int strength_cutoff = 32;
- + if (abs(*translate_value) > strength_cutoff) strength_cutoff = *translate_value;
- + max_strength = (strength_cutoff * alignment_strength) / 100;
- + if (*translate_value < -max_strength) *translate_value = -max_strength;
- + else if (*translate_value > max_strength) *translate_value = max_strength;
- + }
- +
- + /* If 2 stems is detected, scale distance between in order to land on pixels */
- + if ( valid_stems >= 2)
- + {
- + stem_distance = abs(stems[1].center - stems[0].center);
- +
- + delta = stem_distance % ( modulus );
- + new_distance = stem_distance - delta;
- +
- + distance_floor = stem_distance - delta;
- + distance_ceiling = stem_distance + (modulus - delta);
- +
- + if (delta < modulus / 2 ) new_distance = distance_floor;
- + else new_distance = distance_ceiling;
- +
- + if ( columns_per_pixel == 3 && valid_stems == 3 && strategy_use_m_control && valid_stems == 3
- + && (width - 2 * columns_per_pixel) > 6 * columns_per_pixel
- + && ppem > 8
- + && (advance_stem_location - advance_leftmost_location) < stems[main_stem].width * 2 )
- + {
- + FT_Int mod_factor = 2; /*Possibly use 2 only when compatible widths is on? */
- +
- + if (verbose) printf ("USING M CONTROL ");
- + distance_floor = stem_distance - stem_distance % ( modulus * mod_factor) ;
- + distance_ceiling = distance_floor + modulus * mod_factor;
- +
- + new_distance = distance_ceiling;
- +
- + /* force certain ideal situations */
- + /* these 2 are mostly safe to do */
- + if (distance_ceiling + one_pixel * columns_per_pixel == advance_width
- + && (stem_width < one_pixel * 1.25 ))
- + new_distance = distance_ceiling;
- + /* NEED TO FIGURE OUT A WAY TO DETERMINE WHETHER THAT NUDGE IS UP OR DOWN */
- + else if (stem_distance + one_pixel * 2.6 >= advance_width
- + && (stem_width < one_pixel * 1.25 ))
- + new_distance = distance_ceiling;
- +
- + if (proposed_transformed_point(leftmost_point) < one_third_pixel * 2
- + || proposed_transformed_point(rightmost_point) > (width -2 ) * one_third_pixel)
- + new_distance = distance_floor;
- +
- + /* NEED TO IGNORE SERIF Ms HERE */
- + /* perhaps check bitmap boundaries instead??? */
- + if (strategy_bearing_correction && new_distance == distance_ceiling)
- + {
- + /* Correct if bearings are made substantially worse (more than 1/3 a pixel beyond advance) */
- + if (proposed_transformed_point(advance_rightmost_location) > advance_width + one_third_pixel
- + && proposed_transformed_point(advance_rightmost_location) > advance_rightmost_location
- + && -proposed_transformed_point(advance_leftmost_location ) < advance_rightmost_location - advance_width
- + )
- + new_distance = distance_floor;
- + }
- +
- + if ( known_stem_values->m >= 0 )
- + {
- + if ( known_stem_values->m == 0 ) new_distance = distance_floor;
- + else new_distance = distance_ceiling;
- + }
- +
- + if ( (rightmost_point - leftmost_point) - ((rightmost_point * *scale_value) - (leftmost_point * *scale_value)) >= one_pixel * 1.5 )
- + {
- + *scale_value = 1.0;
- + *translate_value = 0;
- + goto Exit;
- + }
- +
- + }
- + else if ( columns_per_pixel == 1 && valid_stems == 3 && strategy_use_m_control && valid_stems == 3
- + && width >= 6 * columns_per_pixel
- + && ppem > 8
- + && (advance_stem_location - advance_leftmost_location) < stems[main_stem].width * 2 )
- + {
- + FT_Int mod_factor = 2; /*Possibly use 2 only when compatible widths is on? */
- +
- + if (verbose) printf ("USING M CONTROL ");
- + distance_floor = stem_distance - stem_distance % ( modulus * mod_factor) ;
- + distance_ceiling = distance_floor + modulus * mod_factor;
- +
- + new_distance = distance_ceiling;
- +
- + /* force certain ideal situations */
- + /* these 2 are mostly safe to do */
- + if (distance_ceiling + one_pixel * columns_per_pixel == advance_width
- + && (stem_width < one_pixel * 1.25 )) new_distance = distance_ceiling;
- + /* NEED TO FIGURE OUT A WAY TO DETERMINE WHETHER THAT NUDGE IS UP OR DOWN */
- + else if (stem_distance + one_pixel * 2.6 >= advance_width
- + && (stem_width < one_pixel * 1.25 ))
- + new_distance = distance_ceiling;
- +
- + if (proposed_transformed_point(leftmost_point) < 0
- + || proposed_transformed_point(rightmost_point) > (width) * one_pixel - 2*one_third_pixel)
- + new_distance = distance_floor;
- +
- + /* NEED TO IGNORE SERIF Ms HERE */
- + /* perhaps check bitmap boundaries instead??? */
- + if (strategy_bearing_correction && new_distance == distance_ceiling)
- + {
- + /* Correct if bearings are made substantially worse (more than 1/3 a pixel beyond advance) */
- + if (proposed_transformed_point(advance_rightmost_location) > advance_width + one_third_pixel
- + && proposed_transformed_point(advance_rightmost_location) > advance_rightmost_location
- + && -proposed_transformed_point(advance_leftmost_location ) < advance_rightmost_location - advance_width
- + )
- + new_distance = distance_floor;
- + }
- +
- + if ( known_stem_values->m >= 0 )
- + {
- + if ( known_stem_values->m == 0 ) new_distance = distance_floor;
- + else new_distance = distance_ceiling;
- + }
- +
- +
- + if ( (rightmost_point - leftmost_point) - ((rightmost_point * *scale_value) - (leftmost_point * *scale_value)) >= one_pixel * 1.5 )
- + {
- + *scale_value = 1.0;
- + *translate_value = 0;
- + goto Exit;
- + }
- +
- + }
- + else
- + {
- + if (strategy_fit_to_width)
- + {
- + new_distance = advance_width - 3 * one_pixel;
- + }
- + else if (known_stem_values->stem_scaling >= 0)
- + {
- + if (known_stem_values->stem_scaling > 0) new_distance = distance_ceiling;
- + else new_distance = distance_floor;
- +
- + /* enforce advance width boundaries */
- + /* TOO RESTRICTIVE ON SERIF FONTS */
- + if ( proposed_transformed_point(advance_rightmost_location) >= advance_width
- + || proposed_transformed_point(advance_leftmost_location) <= 0
- + ) new_distance = distance_floor;
- +
- + /* enforce literal bitmap boundaries if there is no translate room */
- + if ( ( proposed_transformed_point(rightmost_point) >= width * 256
- + || proposed_transformed_point(leftmost_point ) <= one_pixel )
- + && new_distance + one_pixel * 3 > advance_width )
- + new_distance = distance_floor;
- +
- + }
- + else if (strategy_translate_using_closest_stem)
- + {
- + /* closest snapping point for stem 1 */
- + delta2 = (stems[1].center + center_offset) % (modulus);
- +
- + if (delta2 < modulus / 2 ) translate_value2 = ( - delta2 ) / (columns_per_pixel * 4); /* snap left */
- + else translate_value2 = (modulus -delta2) / (columns_per_pixel * 4); /* snap right */
- +
- + if (abs(translate_value2) < abs(*translate_value))
- + {
- + *translate_value = translate_value2;
- + main_stem = 1;
- + }
- +
- + }
- + else if (strategy_scale_to_closest_centers)
- + {
- + /* closest snapping point for stem 0 */
- + delta = (stems[0].center + center_offset) % (modulus);
- + delta2 = (stems[1].center + center_offset) % (modulus);
- +
- + if (delta < modulus / 2 ) new_distance = delta + stem_distance; /* stretch left */
- + else new_distance = delta - modulus + stem_distance; /* stretch right */
- +
- + if (delta2 < modulus / 2 ) new_distance -= delta2; /* stretch left */
- + else new_distance += modulus - delta2; /* stretch right */
- +
- + }
- + else if (strategy_scale_to_closest_centers_up_only)
- + {
- + FT_Int net_change = 0;
- +
- + /* closest snapping point for stem 0 */
- + delta = (stems[0].center + center_offset) % (modulus);
- + delta2 = (stems[1].center + center_offset) % (modulus);
- +
- + if (delta < modulus / 2 ) net_change = delta; /* stretch left */
- + else net_change = -(modulus - delta); /* stretch right */
- +
- + if (delta2 < modulus / 2 ) net_change -= delta2; /* stretch left */
- + else net_change += modulus - delta2; /* stretch right */
- +
- + if (net_change > 0
- + && proposed_transformed_point(advance_rightmost_location) < advance_width
- + && proposed_transformed_point(advance_leftmost_location) > 0
- + ) new_distance = distance_ceiling;
- + }
- +
- + else if (strategy_always_use_distance_ceiling)
- + {
- + if ( proposed_transformed_point(advance_rightmost_location) < advance_width
- + && proposed_transformed_point(advance_leftmost_location) > 0
- + )
- + new_distance = distance_ceiling;
- + }
- + }
- +
- + if (strategy_use_strengths)
- + {
- + FT_Int strength_cutoff = center_offset;
- + delta2 = new_distance - stem_distance;
- + if (abs(delta2) > strength_cutoff) strength_cutoff = delta2;
- +
- + max_strength = (strength_cutoff * fitting_strength) / 100;
- + if (delta2 < -max_strength ) new_distance = stem_distance - max_strength;
- + else if (delta2 > max_strength) new_distance = stem_distance + max_strength;
- + }
- +
- + *scale_value = (float)(new_distance + 0) / (float)(stem_distance + 0 );
- + *translate_value = *translate_value - ((float)(stems[main_stem].center * (float)new_distance) / (float)stem_distance - stems[main_stem].center) / 12;
- - return 0;
- - }
- + if (valid_stems == 2) *embolden_value = (64.0 / *scale_value - 64.0);
- + if (valid_stems == 3) *embolden_value = (64.0 / *scale_value - 64.0) / 1.5;
- + }
- + if (verbose) printf ("%lu stems:", valid_stems);
- - /* sets render-specific mode */
- - static FT_Error
- - ft_smooth_set_mode( FT_Renderer render,
- - FT_ULong mode_tag,
- - FT_Pointer data )
- - {
- - /* we simply pass it to the raster */
- - return render->clazz->raster_class->raster_set_mode( render->raster,
- - mode_tag,
- - data );
- - }
- + if (valid_stems == 1 && verbose)
- + printf ("1 stem: bitmapwidth:%d glyphwidth:%f glyph_width:%f center:%f bearing:%f advance:%f lhadvance:%f stemwidth:%f %d %d",
- + (width - 6) / columns_per_pixel,
- + (float)m_width / 64.0,
- + (float)glyph_width / (float)one_pixel,
- + (float)((float)advance_stem_location) / (float)one_pixel,
- + (float)m_horiBearingX / 64.0,
- + (float)m_horiAdvance / 64.0,
- + (float)linearHoriAdvance / 64.0,
- + (float)stems[0].width / (float)one_pixel,
- + advance_width, original_advance_width
- + );
- + else if (valid_stems >= 2 && verbose)
- + printf ("%lu stems: bitmapwidth:%d center1:%f center2:%f difference:%f bearing:%f advance:%f advstemloc:%f ",
- + valid_stems,
- + (width - 6) / columns_per_pixel,
- + ((float)advance_stem_location) / (float)one_pixel,
- + ((float)advance_stem_location + (float)abs(stems[1].center - stems[0].center)) / (float)one_pixel,
- + ((float)abs(stems[1].center - stems[0].center)) / (float)one_pixel,
- + (float)m_horiBearingX / 64.0,
- + (float)m_horiAdvance / 64.0,
- + (float)advance_stem_location / (float)one_pixel);
- - /* transform a given glyph image */
- - static FT_Error
- - ft_smooth_transform( FT_Renderer render,
- - FT_GlyphSlot slot,
- - const FT_Matrix* matrix,
- - const FT_Vector* delta )
- - {
- - FT_Error error = Smooth_Err_Ok;
- + if (strategy_bearing_correction)
- + {
- + /* Correct if negative bearings are made substantially worse (more than 1/3 a pixel) */
- + if (proposed_transformed_point(advance_rightmost_location) > advance_width
- + && proposed_transformed_point(advance_rightmost_location) > advance_rightmost_location
- + && -proposed_transformed_point(advance_leftmost_location ) < advance_rightmost_location - advance_width
- + && *translate_value > one_third_pixel / (columns_per_pixel * 4) )
- + {
- + *translate_value -=64 ;
- + if (verbose) printf ("TRANSLATING -64 ");
- + }
- + }
- + if ( strategy_use_verdana_12_hack
- + && strcasestr(slot->face->family_name, "Verdana")
- + && ppem == 12
- + && *scale_value == 1.0 && valid_stems == 0
- + && height < 8
- + && advance_rightmost_location * 1.1 < advance_width )
- + *scale_value = 1.1;
- - if ( slot->format != render->glyph_format )
- - {
- - error = Smooth_Err_Invalid_Argument;
- goto Exit;
- +
- }
- - if ( matrix )
- - FT_Outline_Transform( &slot->outline, matrix );
- + Exit:
- - if ( delta )
- - FT_Outline_Translate( &slot->outline, delta->x, delta->y );
- +#define transformed_point( point ) point * *scale_value + *translate_value * 12
- +
- + if (strategy_correct_out_of_bounds_outlines)
- + {
- + /* Correct if outside bitmap */
- + if (transformed_point(rightmost_point) >= width * 256 - 2 * one_third_pixel
- + && transformed_point(leftmost_point ) > one_pixel + 2 * one_third_pixel )
- + {
- + *translate_value -=64 ;
- + }
- + else if (transformed_point(leftmost_point) <= one_pixel / 2
- + && transformed_point(rightmost_point ) <= width * 256 -(one_pixel + one_pixel / 2) )
- + {
- + *translate_value += 64;
- + }
- + }
- +
- + STVALUES
- +
- + free(segments);
- + free(leftmost_segment);
- + free(rightmost_segment);
- +
- + free(known_stem_values);
- + free(stems);
- + free(possible_stems);
- + free(leftmost_stem);
- + free(rightmost_stem);
- +
- + free(centers);
- - Exit:
- - return error;
- }
- - /* return the glyph's control box */
- + /* Gamma correction */
- static void
- - ft_smooth_get_cbox( FT_Renderer render,
- - FT_GlyphSlot slot,
- - FT_BBox* cbox )
- + _ft_lcd_gamma_correction_correction ( FT_Bitmap* bitmap,
- + FT_Render_Mode mode,
- + FT_GlyphSlot slot,
- + float gamma_correction_lt,
- + float gamma_correction_value)
- {
- - FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
- + if ( gamma_correction_value != 1.0 )
- + {
- + FT_UInt width = (FT_UInt)bitmap->width;
- + FT_UInt height = (FT_UInt)bitmap->rows;
- + FT_Byte* line = bitmap->buffer;
- + float ppem = (float)slot->face->size->metrics.x_ppem;
- - if ( slot->format == render->glyph_format )
- - FT_Outline_Get_CBox( &slot->outline, cbox );
- + if ( !slot->face || !slot->face->size ) return;
- +
- + 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], gamma_correction_value );*/
- +
- + /* sloped */
- + /*line[xx] = gamma2 ( line[xx], gamma_correction_value - 5
- + * (1-gamma_correction_value)/(gamma_correction_lt -5)
- + + ((1-gamma_correction_value)/(gamma_correction_lt -5)) * ppem );*/
- +
- + /* 1/3-sloped */
- + line[xx] = gamma2 ( line[xx], gamma_correction_value - 5
- + * ((1-gamma_correction_value)/(3*(gamma_correction_lt -5)))
- + * + ((1-gamma_correction_value)/(3*(gamma_correction_lt -5))) * ppem );
- + }
- + }
- + }
- }
- +#endif
- +
- /* convert a slot's glyph image into a bitmap */
- static FT_Error
- @@ -104,19 +2867,406 @@
- {
- FT_Error error;
- FT_Outline* outline = NULL;
- + FT_Outline* outline_orig = NULL;
- FT_BBox cbox;
- - FT_UInt width, height, pitch;
- + FT_UInt width=0, height=0, pitch=0, ppem;
- #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- FT_UInt height_org, width_org;
- #endif
- - FT_Bitmap* bitmap;
- - FT_Memory memory;
- + FT_Bitmap* bitmap = 0;
- + FT_Memory memory = 0;
- FT_Int hmul = mode == FT_RENDER_MODE_LCD;
- FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
- - FT_Pos x_shift, y_shift, x_left, y_top;
- + FT_Pos x_shift = 0, y_shift = 0, x_left = 0, y_top = 0;
- FT_Raster_Params params;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + FT_Matrix scaleMat;
- + FT_Long translate_value = 0;
- + float scale_value = 1.0;
- + FT_Int align_called = 0;
- +
- +
- + int chromeos_style_sharpening_strength = 0;
- + int checked_chromeos_style_sharpening_strength = 0;
- + int alignment_strength = 0;
- + int fitting_strength = 0;
- + FT_UInt checked_alignment_strength = 0;
- + FT_UInt checked_fitting_strength = 0;
- + FT_UInt checked_fringe_filter_strength = 0;
- + int fringe_filter_strength = 0;
- + FT_UInt checked_grayscale_filter_strength = 0;
- + int grayscale_filter_strength = 0;
- +
- + FT_UInt checked_autohint_horizontal_stem_darken_strength = 0;
- + int autohint_horizontal_stem_darken_strength = 0;
- +
- + FT_UInt checked_autohint_vertical_stem_darken_strength = 0;
- + int autohint_vertical_stem_darken_strength = 0;
- +
- + int windows_style_sharpening_strength = 0;
- + FT_UInt checked_windows_style_sharpening_strength = 0;
- + float gamma_correction_value = 1;
- + float gamma_correction_lt = 0;
- + FT_UInt checked_gamma_correction_value = 0;
- +
- + FT_Int brightness_value = 0.0;
- + FT_UInt checked_brightness_value = 0;
- +
- + FT_Int contrast_value = 0.0;
- + FT_UInt checked_contrast_value = 0;
- +
- + FT_Int snapping_sliding_scale_value = 0;
- + FT_UInt checked_snapping_sliding_scale_value = 0;
- +
- + FT_Int global_embolden_x_value = 0;
- + FT_UInt checked_global_embolden_x_value = 0;
- +
- + FT_Int global_embolden_y_value = 0;
- + FT_UInt checked_global_embolden_y_value = 0;
- +
- + FT_Int bold_embolden_x_value = 0;
- + FT_UInt checked_bold_embolden_x_value = 0;
- +
- + FT_Int bold_embolden_y_value = 0;
- + FT_UInt checked_bold_embolden_y_value = 0;
- +
- + FT_Byte chromeos_cutoff;
- + double chromeos_gamma_value;
- +
- + float embolden_value = 0.0;
- + FT_Bool autohinted = FALSE;
- +
- + FT_UInt autohint_minimum_stem_height = 0;
- + FT_UInt checked_autohint_minimum_stem_height = 0;
- +
- + int checked_use_various_tweaks_env = 0;
- + FT_Bool use_various_tweaks = FALSE;
- +
- + int cur_width;
- + char *cur_width_env = getenv( "CUR_WIDTH" );
- +
- + const FT_Int MIN_PPEM = 1;
- + /*const FT_Int MAX_PPEM = 100; */
- +
- + int checked_use_known_settings_on_selected_fonts_env = 0;
- + FT_Bool use_known_settings_on_selected_fonts = FALSE;
- +
- + if ( slot->face && slot->face->size && slot->face->size->metrics.x_ppem )
- + ppem = slot->face->size->metrics.x_ppem;
- + else ppem = 0;
- +
- + if ( cur_width_env != NULL ){
- + sscanf ( cur_width_env, "%d", &cur_width );
- + if (cur_width != 0) autohinted = TRUE;
- + }
- +
- + if ( checked_use_known_settings_on_selected_fonts_env == 0 )
- + {
- + char *use_known_settings_on_selected_fonts_env = getenv( "INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS" );
- + if ( use_known_settings_on_selected_fonts_env != NULL )
- + {
- + if ( strcasecmp(use_known_settings_on_selected_fonts_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_known_settings_on_selected_fonts_env, "true") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "1") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "on") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "yes") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + }
- + }
- + checked_use_known_settings_on_selected_fonts_env = 1;
- + }
- +
- + if ( checked_use_various_tweaks_env == 0 )
- + {
- + char *use_various_tweaks_env = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" );
- + if ( use_various_tweaks_env != NULL )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "true") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "1") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "on") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "yes") == 0)
- + use_various_tweaks = TRUE;
- + }
- + }
- + checked_use_various_tweaks_env = 1;
- + }
- +
- + if ( checked_autohint_minimum_stem_height == 0)
- + {
- + char *autohint_minimum_stem_height_env = getenv( "INFINALITY_FT_AUTOHINT_MINIMUM_STEM_WIDTH" );
- + if ( autohint_minimum_stem_height_env != NULL )
- + {
- + sscanf ( autohint_minimum_stem_height_env, "%u", &autohint_minimum_stem_height );
- + if (autohint_minimum_stem_height > 100 ) autohint_minimum_stem_height = 100;
- + else if (autohint_minimum_stem_height < 0 ) autohint_minimum_stem_height = 0;
- + }
- + checked_autohint_minimum_stem_height = 1;
- + }
- +
- + if ( checked_snapping_sliding_scale_value == 0)
- + {
- + char *snapping_sliding_scale_env = getenv ( "INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE" );
- + if ( snapping_sliding_scale_env != NULL )
- + {
- + sscanf ( snapping_sliding_scale_env, "%d", &snapping_sliding_scale_value );
- + if (snapping_sliding_scale_value > MAX_PPEM ) snapping_sliding_scale_value = 0;
- + else if (snapping_sliding_scale_value < 0 ) snapping_sliding_scale_value = 0;
- +
- + if (snapping_sliding_scale_value < 11 && snapping_sliding_scale_value > 0 ) snapping_sliding_scale_value = 11;
- + }
- + checked_snapping_sliding_scale_value = 1;
- + }
- +
- + if ( checked_alignment_strength == 0)
- + {
- + char *alignment_strength_env = getenv ( "INFINALITY_FT_STEM_ALIGNMENT_STRENGTH" );
- + if ( alignment_strength_env != NULL )
- + {
- + sscanf ( alignment_strength_env, "%d", &alignment_strength );
- + if (alignment_strength > 100 ) alignment_strength = 100;
- + else if (alignment_strength < 0 ) alignment_strength = 0;
- + }
- + if (alignment_strength > 100 ) alignment_strength = 100;
- + checked_alignment_strength = 1;
- + if (snapping_sliding_scale_value != 0)
- + alignment_strength = sliding_scale ( 10, snapping_sliding_scale_value, alignment_strength, 100, ppem);
- + }
- +
- + if ( checked_fitting_strength == 0)
- + {
- + char *fitting_strength_env = getenv( "INFINALITY_FT_STEM_FITTING_STRENGTH" );
- + if ( fitting_strength_env != NULL )
- + {
- + sscanf ( fitting_strength_env, "%d", &fitting_strength );
- + if (fitting_strength > 100 ) fitting_strength = 100;
- + else if (fitting_strength < 0 ) fitting_strength = 0;
- + }
- + if (fitting_strength > 100 ) fitting_strength = 100;
- + checked_fitting_strength = 1;
- + if (snapping_sliding_scale_value != 0)
- + fitting_strength = sliding_scale ( 10, snapping_sliding_scale_value, fitting_strength, 100, ppem);
- + }
- +
- + if ( checked_chromeos_style_sharpening_strength == 0)
- + {
- + char *chromeos_style_sharpening_strength_env = getenv( "INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH" );
- + if ( chromeos_style_sharpening_strength_env != NULL )
- + {
- + sscanf ( chromeos_style_sharpening_strength_env, "%d", &chromeos_style_sharpening_strength );
- + if (chromeos_style_sharpening_strength > 100 )
- + chromeos_style_sharpening_strength = 100;
- + else if (chromeos_style_sharpening_strength < 0 )
- + chromeos_style_sharpening_strength = 0;
- + }
- + if (ppem > 10)
- + chromeos_style_sharpening_strength =
- + (chromeos_style_sharpening_strength * ppem) / 10;
- + if (chromeos_style_sharpening_strength > 100 )
- + chromeos_style_sharpening_strength = 100;
- + checked_chromeos_style_sharpening_strength = 1;
- + }
- +
- +
- + if ( checked_brightness_value == 0)
- + {
- + char *brightness_env = getenv( "INFINALITY_FT_BRIGHTNESS" );
- + if ( brightness_env != NULL )
- + {
- + sscanf ( brightness_env, "%d", &brightness_value );
- + if (brightness_value > 100 )
- + brightness_value = 100;
- + else if (brightness_value < -100 )
- + brightness_value = 0;
- + }
- + checked_brightness_value = 1;
- + }
- +
- + if ( checked_contrast_value == 0)
- + {
- + char *contrast_env = getenv( "INFINALITY_FT_CONTRAST" );
- + if ( contrast_env != NULL )
- + {
- + sscanf ( contrast_env, "%d", &contrast_value );
- + if (contrast_value > 100 )
- + contrast_value = 100;
- + else if (contrast_value < -100 )
- + contrast_value = 100;
- + }
- + checked_contrast_value = 1;
- + }
- +
- + if ( checked_windows_style_sharpening_strength == 0)
- + {
- + char *windows_style_sharpening_strength_env = getenv( "INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH" );
- + if ( windows_style_sharpening_strength_env != NULL )
- + {
- + sscanf ( windows_style_sharpening_strength_env, "%d", &windows_style_sharpening_strength );
- + if (windows_style_sharpening_strength > 100 ) windows_style_sharpening_strength = 100;
- + else if (windows_style_sharpening_strength < 0 ) windows_style_sharpening_strength = 0;
- + }
- + /* Decrease the effect slightly in order to have a more linear increase in sharpness */
- + windows_style_sharpening_strength =
- + (( windows_style_sharpening_strength * windows_style_sharpening_strength ) / 100 + windows_style_sharpening_strength) / 2;
- + checked_windows_style_sharpening_strength = 1;
- + }
- +
- + if ( checked_gamma_correction_value == 0 )
- + {
- + char *gamma_correction_value_env = getenv( "INFINALITY_FT_GAMMA_CORRECTION" );
- + if ( gamma_correction_value_env != NULL )
- + {
- + float f1, f2;
- +
- + if ( strcasecmp(gamma_correction_value_env, "default" ) != 0)
- + {
- + sscanf ( gamma_correction_value_env, "%f %f", &f1, &f2 );
- + gamma_correction_lt = f1;
- + gamma_correction_value = f2 / 100.0;
- + }
- + if ( gamma_correction_value < .01 ) gamma_correction_value = 1.0;
- + }
- + checked_gamma_correction_value = 1;
- + }
- +
- + /* set gamma value to 1 if out of range */
- + if ( slot->face && slot->face->size && slot->face->size->metrics.x_ppem )
- + {
- + if ( slot->face->size->metrics.x_ppem >= gamma_correction_lt )
- + {
- + gamma_correction_value = 1;
- + }
- + }
- + else gamma_correction_value = 1;
- +
- +
- + if ( checked_fringe_filter_strength == 0)
- + {
- + char *fringe_filter_strength_env = getenv( "INFINALITY_FT_FRINGE_FILTER_STRENGTH" );
- + if ( fringe_filter_strength_env != NULL )
- + {
- + sscanf ( fringe_filter_strength_env, "%d", &fringe_filter_strength );
- + if (fringe_filter_strength > 100 ) fringe_filter_strength = 100;
- + else if (fringe_filter_strength < 0 ) fringe_filter_strength = 0;
- + }
- + checked_fringe_filter_strength = 1;
- + }
- +
- +
- + if ( checked_grayscale_filter_strength == 0)
- + {
- + char *grayscale_filter_strength_env = getenv( "INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH" );
- + if ( grayscale_filter_strength_env != NULL )
- + {
- + sscanf ( grayscale_filter_strength_env, "%d", &grayscale_filter_strength );
- + if (grayscale_filter_strength > 100 ) grayscale_filter_strength = 100;
- + else if (grayscale_filter_strength < 0 ) grayscale_filter_strength = 0;
- + }
- + checked_grayscale_filter_strength = 1;
- + }
- +
- +
- + if ( checked_autohint_horizontal_stem_darken_strength == 0)
- + {
- + char *autohint_horizontal_stem_darken_strength_env = getenv( "INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH" );
- + if ( autohint_horizontal_stem_darken_strength_env != NULL )
- + {
- + sscanf ( autohint_horizontal_stem_darken_strength_env, "%d", &autohint_horizontal_stem_darken_strength );
- + if (autohint_horizontal_stem_darken_strength > 100 ) autohint_horizontal_stem_darken_strength = 100;
- + else if (autohint_horizontal_stem_darken_strength < 0 ) autohint_horizontal_stem_darken_strength = 0;
- + }
- + checked_autohint_horizontal_stem_darken_strength = 1;
- + }
- +
- + if ( checked_autohint_vertical_stem_darken_strength == 0)
- + {
- + char *autohint_vertical_stem_darken_strength_env = getenv( "INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH" );
- + if ( autohint_vertical_stem_darken_strength_env != NULL )
- + {
- + sscanf ( autohint_vertical_stem_darken_strength_env, "%d", &autohint_vertical_stem_darken_strength );
- + if (autohint_vertical_stem_darken_strength > 100 ) autohint_vertical_stem_darken_strength = 100;
- + else if (autohint_horizontal_stem_darken_strength < 0 ) autohint_vertical_stem_darken_strength = 0;
- + }
- + checked_autohint_vertical_stem_darken_strength = 1;
- + }
- +
- + if ( checked_global_embolden_x_value == 0)
- + {
- + char *global_embolden_x_env = getenv ( "INFINALITY_FT_GLOBAL_EMBOLDEN_X_VALUE" );
- + if ( global_embolden_x_env != NULL )
- + {
- + sscanf ( global_embolden_x_env, "%d", &global_embolden_x_value );
- + if (global_embolden_x_value > 128 ) global_embolden_x_value = 128;
- + else if (global_embolden_x_value < -128 ) global_embolden_x_value = -128;
- + }
- + checked_global_embolden_x_value = 1;
- + }
- +
- + if ( checked_global_embolden_y_value == 0)
- + {
- + char *global_embolden_y_env = getenv ( "INFINALITY_FT_GLOBAL_EMBOLDEN_Y_VALUE" );
- + if ( global_embolden_y_env != NULL )
- + {
- + sscanf ( global_embolden_y_env, "%d", &global_embolden_y_value );
- + if (global_embolden_y_value > 128 ) global_embolden_y_value = 128;
- + else if (global_embolden_y_value < -128 ) global_embolden_y_value = -128;
- + }
- + checked_global_embolden_y_value = 1;
- + }
- +
- +
- + if ( checked_bold_embolden_x_value == 0)
- + {
- + char *bold_embolden_x_env = getenv ( "INFINALITY_FT_BOLD_EMBOLDEN_X_VALUE" );
- + if ( bold_embolden_x_env != NULL )
- + {
- + sscanf ( bold_embolden_x_env, "%d", &bold_embolden_x_value );
- + if (bold_embolden_x_value > 128 ) bold_embolden_x_value = 128;
- + else if (bold_embolden_x_value < -128 ) bold_embolden_x_value = -128;
- +
- + }
- + checked_bold_embolden_x_value = 1;
- + }
- +
- + if ( checked_bold_embolden_y_value == 0)
- + {
- + char *bold_embolden_y_env = getenv ( "INFINALITY_FT_BOLD_EMBOLDEN_Y_VALUE" );
- + if ( bold_embolden_y_env != NULL )
- + {
- + sscanf ( bold_embolden_y_env, "%d", &bold_embolden_y_value );
- + if (bold_embolden_y_value > 128 ) bold_embolden_y_value = 128;
- + else if (bold_embolden_y_value < -128 ) bold_embolden_y_value = -128;
- +
- + }
- + checked_bold_embolden_y_value = 1;
- + }
- +
- +
- +
- + if( use_various_tweaks && slot->face && slot->face->style_name )
- + {
- + /* needs to also check for artifical italics */
- + if ( strcasestr(slot->face->style_name, "Italic")
- + || strcasestr(slot->face->style_name, "Oblique") )
- + {
- + windows_style_sharpening_strength = 0;
- + chromeos_style_sharpening_strength = 0;
- + }
- + }
- +
- + /*if (fitting_strength == 100) scale_value = 1.1;*/
- +
- +#endif
- /* check glyph image format */
- if ( slot->format != render->glyph_format )
- @@ -129,92 +3279,174 @@
- if ( mode != required_mode )
- return Smooth_Err_Cannot_Render_Glyph;
- - outline = &slot->outline;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- +RERENDER:
- + if (align_called == 1){
- - /* translate the outline to the new origin if needed */
- - if ( origin )
- - FT_Outline_Translate( outline, origin->x, origin->y );
- + scaleMat.xx = FT_FixedFromFloat(scale_value);
- + scaleMat.xy = 0;
- + scaleMat.yx = 0;
- + scaleMat.yy = (1 << 16);
- - /* compute the control box, and grid fit it */
- - FT_Outline_Get_CBox( outline, &cbox );
- + FT_Outline_Copy(outline_orig, outline);
- - cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- - cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- - cbox.xMax = FT_PIX_CEIL( cbox.xMax );
- - cbox.yMax = FT_PIX_CEIL( cbox.yMax );
- -
- - if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
- - {
- - FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
- - " xMin = %d, xMax = %d\n",
- - cbox.xMin >> 6, cbox.xMax >> 6 ));
- - return Smooth_Err_Raster_Overflow;
- + if (scale_value != 1.0)
- + FT_Outline_Transform( outline, &scaleMat );
- +
- + FT_Outline_Translate( outline, translate_value+0, 0 );
- +
- + FT_Outline_Embolden( outline, embolden_value );
- }
- else
- - width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
- -
- - if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
- {
- - FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
- - " yMin = %d, yMax = %d\n",
- - cbox.yMin >> 6, cbox.yMax >> 6 ));
- - return Smooth_Err_Raster_Overflow;
- +#endif
- + outline = &slot->outline;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* Need to get this PRIOR to embolden, otherwise bad things happen */
- + FT_Outline_Get_CBox( outline, &cbox );
- +
- + /* Various hacks that need to be turned into a new rule set */
- + if ( !autohinted
- + && use_known_settings_on_selected_fonts
- + && mode == FT_RENDER_MODE_LCD && slot->face->family_name && slot->face->style_name
- + && ( strcasestr(slot->face->family_name, "Courier New" )
- + && ( strcasestr(slot->face->style_name, "Regular" )
- + || strcasestr(slot->face->style_name, "Italic" ) ) ) )
- + FT_Outline_Embolden( outline, 24 );
- +
- + if (!autohinted
- + && use_known_settings_on_selected_fonts
- + && mode == FT_RENDER_MODE_LCD && slot->face->family_name && slot->face->style_name
- + && strcasestr(slot->face->family_name, "Times New Roman" )
- + && strcasestr(slot->face->style_name, "Italic" ) )
- + FT_Outline_Embolden( outline, 12 );
- +
- + if ( use_known_settings_on_selected_fonts
- + && autohinted && mode == FT_RENDER_MODE_LCD && slot->face->family_name && slot->face->style_name
- + && strcasestr(slot->face->family_name, "FreeSerif" )
- + && strcasestr(slot->face->style_name, "Italic" ) )
- + FT_Outline_Embolden( outline, 8 );
- +
- + if( global_embolden_x_value != 0 || global_embolden_y_value != 0 )
- + FT_Outline_Embolden_XY( outline, global_embolden_x_value, global_embolden_y_value );
- +
- + if( (bold_embolden_x_value != 0 || bold_embolden_y_value != 0)
- + && (slot->face->style_name
- + && ( strcasestr(slot->face->style_name, "Bold")
- + || strcasestr(slot->face->style_name, "Black") )
- + || ( slot->face->style_flags
- + && slot->face->style_flags & FT_STYLE_FLAG_BOLD ) ) )
- + FT_Outline_Embolden_XY( outline, bold_embolden_x_value, bold_embolden_y_value );
- +
- + FT_Outline_Copy(outline, outline_orig);
- }
- - else
- - height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
- - bitmap = &slot->bitmap;
- - memory = render->root.memory;
- + /* translate the outline to the new origin if needed */
- + if (align_called == 0)
- + {
- + FT_Pos enlarge_cbox = 0;
- -#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- - width_org = width;
- - height_org = height;
- -#endif
- + /* enlarge for grayscale rendering */
- + if ( mode == FT_RENDER_MODE_NORMAL ) enlarge_cbox = 64;
- - /* release old bitmap buffer */
- - if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
- - {
- - FT_FREE( bitmap->buffer );
- - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
- - }
- + if ( origin )
- + FT_Outline_Translate( outline, origin->x, origin->y );
- - /* allocate new one */
- - pitch = width;
- - if ( hmul )
- - {
- - width = width * 3;
- - pitch = FT_PAD_CEIL( width, 4 );
- - }
- + /* compute the control box, and grid fit it */
- + /*FT_Outline_Get_CBox( outline, &cbox );*/
- +
- + cbox.xMin = FT_PIX_FLOOR( cbox.xMin - enlarge_cbox );
- + cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- + cbox.xMax = FT_PIX_CEIL( cbox.xMax + enlarge_cbox );
- + cbox.yMax = FT_PIX_CEIL( cbox.yMax );
- +#else
- + if ( origin )
- + FT_Outline_Translate( outline, origin->x, origin->y );
- +
- + /* compute the control box, and grid fit it */
- + FT_Outline_Get_CBox( outline, &cbox );
- +
- + cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- + cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- + cbox.xMax = FT_PIX_CEIL( cbox.xMax );
- + cbox.yMax = FT_PIX_CEIL( cbox.yMax );
- +#endif
- - if ( vmul )
- - height *= 3;
- + if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
- + {
- + FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
- + " xMin = %d, xMax = %d\n",
- + cbox.xMin >> 6, cbox.xMax >> 6 ));
- + return Smooth_Err_Raster_Overflow;
- + }
- + else
- + width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
- - x_shift = (FT_Int) cbox.xMin;
- - y_shift = (FT_Int) cbox.yMin;
- - x_left = (FT_Int)( cbox.xMin >> 6 );
- - y_top = (FT_Int)( cbox.yMax >> 6 );
- + if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
- + {
- + FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
- + " yMin = %d, yMax = %d\n",
- + cbox.yMin >> 6, cbox.yMax >> 6 ));
- + return Smooth_Err_Raster_Overflow;
- + }
- + else
- + height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
- -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- + bitmap = &slot->bitmap;
- + memory = render->root.memory;
- - if ( slot->library->lcd_filter_func )
- - {
- - FT_Int extra = slot->library->lcd_extra;
- +#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- + width_org = width;
- + height_org = height;
- +#endif
- + /* release old bitmap buffer */
- + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
- + {
- + FT_FREE( bitmap->buffer );
- + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
- + }
- + /* allocate new one */
- + pitch = width;
- if ( hmul )
- {
- - x_shift -= 64 * ( extra >> 1 );
- - width += 3 * extra;
- - pitch = FT_PAD_CEIL( width, 4 );
- - x_left -= extra >> 1;
- + width = width * 3;
- + pitch = FT_PAD_CEIL( width, 4 );
- }
- if ( vmul )
- + height *= 3;
- +
- + x_shift = (FT_Int) cbox.xMin;
- + y_shift = (FT_Int) cbox.yMin;
- + x_left = (FT_Int)( cbox.xMin >> 6 );
- + y_top = (FT_Int)( cbox.yMax >> 6 );
- +
- +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- +
- + if ( slot->library->lcd_filter_func )
- {
- - y_shift -= 64 * ( extra >> 1 );
- - height += 3 * extra;
- - y_top += extra >> 1;
- + FT_Int extra = slot->library->lcd_extra;
- +
- +
- + if ( hmul )
- + {
- + x_shift -= 64 * ( extra >> 1 );
- + width += 3 * extra;
- + pitch = FT_PAD_CEIL( width, 4 );
- + x_left -= extra >> 1;
- + }
- +
- + if ( vmul )
- + {
- + y_shift -= 64 * ( extra >> 1 );
- + height += 3 * extra;
- + y_top += extra >> 1;
- + }
- }
- +#endif
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- }
- #endif
- @@ -239,6 +3471,9 @@
- bitmap->pitch = pitch;
- /* translate outline to render it into the bitmap */
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if (align_called == 0)
- +#endif
- FT_Outline_Translate( outline, -x_shift, -y_shift );
- if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
- @@ -288,9 +3523,104 @@
- vec->y /= 3;
- }
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( ppem <= MAX_PPEM && ppem >= MIN_PPEM )
- + {
- + if ( align_called == 0 && (alignment_strength > 0 || fitting_strength > 0))
- + _lcd_stem_align ( bitmap, mode, slot, &translate_value, &scale_value,
- + alignment_strength, fitting_strength, &embolden_value );
- +
- + if ((translate_value != 0 || scale_value != 1.0) && align_called == 0)
- + {
- + align_called = 1;
- + goto RERENDER;
- + }
- +
- + if ( mode == FT_RENDER_MODE_LCD )
- + {
- +
- + if (fringe_filter_strength > 0 /*&& autohinted*/)
- + _ft_lcd_fringe_filter( bitmap, mode, fringe_filter_strength, slot->library );
- +
- + if ( gamma_correction_lt > 0 && gamma_correction_value != 1.0 )
- + _ft_lcd_gamma_correction_correction( bitmap, mode, slot, gamma_correction_lt, gamma_correction_value );
- +
- + chromeos_cutoff = (FT_Byte)(0.5 * 255.0) * (chromeos_style_sharpening_strength / 100.0);
- + chromeos_gamma_value = 1;
- +
- + if (chromeos_style_sharpening_strength > 0)
- + _ft_lcd_chromeos_sharpen( bitmap, mode, chromeos_cutoff, chromeos_gamma_value );
- +
- + if (ppem > 8)
- + if (windows_style_sharpening_strength > 0)
- + _ft_lcd_windows_sharpen( bitmap, mode, windows_style_sharpening_strength, slot->library );
- +
- + if (autohinted && (cur_width * 100) / 64 > autohint_horizontal_stem_darken_strength
- + && autohint_horizontal_stem_darken_strength != 0)
- + autohint_horizontal_stem_darken_strength = (cur_width * 100) / 64;
- +
- + if (autohint_horizontal_stem_darken_strength > 100)
- + autohint_horizontal_stem_darken_strength = 100;
- +
- + /* only do on autohinted fonts */
- + /* Necessary to do on some non-thin fonts, which is why it is outside */
- + /* of the below conditional */
- + if (autohint_horizontal_stem_darken_strength > 0 && autohinted )
- + _ft_lcd_darken_x ( bitmap, mode, autohint_horizontal_stem_darken_strength, slot->library );
- +
- + /* Enhance thin fonts */
- + if (autohinted)
- + {
- + /* if forcibly set use that, otherwise make a good estimate */
- + if ( !_ft_bitmap_bc ( bitmap, (float)get_brightness(slot->face->family_name, ppem) / 300.0,
- + (float)get_contrast(slot->face->family_name, ppem) / 300.0))
- + {
- + FT_Bool is_fixed_name = FALSE;
- + if ( slot->face->family_name
- + && strcasestr(slot->face->family_name, "Mono") )
- + is_fixed_name = TRUE;
- +
- + /* Darken vertical stems */
- + _ft_lcd_darken_y ( bitmap, mode, autohint_vertical_stem_darken_strength, slot->library);
- +
- + /* Adjust brightness and contrast automatically based on stem width */
- + if (cur_width != 0 && cur_width < 30 ) cur_width = 30;
- + if (cur_width >= 30 && cur_width <= 60 )
- + {
- + float ppem_factor = sliding_scale ( 5, 11, 0.0, 1.0, ppem);
- + float brightness_factor = sliding_scale ( 30, 52, -.3, 0.0, cur_width);
- + float contrast_factor = sliding_scale ( 30, 52, .45, 0.0, cur_width);
- + _ft_bitmap_bc ( bitmap, ppem_factor * brightness_factor, ppem_factor * contrast_factor);
- +
- + /* Only cap variable width thin-stemmed fonts */
- + if (!FT_IS_FIXED_WIDTH( slot->face ) && !is_fixed_name)
- + _ft_bitmap_cap ( bitmap, (cur_width * 150) / 64, slot->library );
- + }
- + }
- + }
- +
- +
- + if ( slot->library->lcd_filter_func )
- + slot->library->lcd_filter_func( bitmap, mode, slot->library );
- +
- + if (grayscale_filter_strength > 0)
- + _ft_lcd_grayscale_filter( bitmap, mode, grayscale_filter_strength, slot->library );
- +
- + }
- +
- + /* Global values */
- + if (brightness_value != 0 || contrast_value != 0)
- + _ft_bitmap_bc ( bitmap, (float)brightness_value / 300.0, (float)contrast_value / 300.0);
- +
- + FT_Outline_Done( slot->library, outline_orig );
- + }
- + else if ( mode == FT_RENDER_MODE_LCD && slot->library->lcd_filter_func )
- + slot->library->lcd_filter_func( bitmap, mode, slot->library );
- +#else
- if ( slot->library->lcd_filter_func )
- slot->library->lcd_filter_func( bitmap, mode, slot->library );
- +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
- #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /* render outline into bitmap */
- @@ -449,7 +3779,7 @@
- FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,
- -
- +
- FT_MODULE_RENDERER,
- sizeof( FT_RendererRec ),
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/truetype/ttgload.c.orig src/truetype/ttgload.c
- --- src/truetype/ttgload.c.orig 2011-12-23 19:40:19.001348135 -0600
- +++ src/truetype/ttgload.c 2011-12-23 19:27:37.964564475 -0600
- @@ -830,9 +830,51 @@
- loader->pp4 = zone->cur[zone->n_points - 1];
- }
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
- + FT_Outline_Embolden(&loader->gloader->current.outline, -24);
- +
- + else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
- + FT_Outline_Embolden(&loader->gloader->current.outline, 24);
- +#endif
- return TT_Err_Ok;
- }
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + FT_LOCAL_DEF( float )
- + scale_test_tweak( TT_Face face,
- + FT_String* family,
- + int ppem,
- + FT_String* style,
- + FT_UInt glyph_index,
- + SPH_ScaleRule* rule,
- + FT_UInt num_rules )
- + {
- + FT_UInt i;
- +
- +
- + /* rule checks may be able to be optimized further */
- + for ( i = 0; i < num_rules; i++ )
- + {
- + if ( family &&
- + ( strcmp( rule[i].family, "" ) == 0 ||
- + strcmp( rule[i].family, family ) == 0 ) )
- + if ( rule[i].ppem == 0 ||
- + rule[i].ppem == ppem )
- + if ( ( style &&
- + strcmp( rule[i].style, "" ) == 0 ) ||
- + strcmp( rule[i].style, style ) == 0 )
- + if ( rule[i].glyph == 0 ||
- + FT_Get_Char_Index( (FT_Face)face,
- + rule[i].glyph ) == glyph_index )
- + {
- + /* printf( "%s,%d,%s,%c ", family, ppem, style, rule[i].glyph ); */
- + return rule[i].scale;
- + }
- + }
- + return 1.0;
- + }
- +#endif
- /*************************************************************************/
- /* */
- @@ -852,6 +894,54 @@
- FT_Outline* outline;
- FT_Int n_points;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int checked_use_various_tweaks_env = 0;
- + FT_Bool use_various_tweaks = FALSE;
- +
- + TT_Face face = (TT_Face)loader->face;
- + FT_String* family = face->root.family_name;
- + int ppem = loader->size->metrics.x_ppem;
- + FT_String* style = face->root.style_name;
- + float x_scale_factor = 1.0;
- + float y_scale_factor = 1.0;
- +
- + int fitting_strength = 0;
- + FT_UInt checked_fitting_strength = 0;
- +
- + if ( checked_use_various_tweaks_env == 0 )
- + {
- + char *use_various_tweaks_env = getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" );
- + if ( use_various_tweaks_env != NULL )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_various_tweaks_env, "true") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "1") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "on") == 0)
- + use_various_tweaks = TRUE;
- + else if ( strcasecmp(use_various_tweaks_env, "yes") == 0)
- + use_various_tweaks = TRUE;
- + }
- + }
- + checked_use_various_tweaks_env = 1;
- + }
- +
- + if ( checked_fitting_strength == 0)
- + {
- + char *fitting_strength_env = getenv( "INFINALITY_FT_STEM_FITTING_STRENGTH" );
- + if ( fitting_strength_env != NULL )
- + {
- + sscanf ( fitting_strength_env, "%d", &fitting_strength );
- + if (fitting_strength > 100 ) fitting_strength = 100;
- + else if (fitting_strength < 0 ) fitting_strength = 0;
- + }
- + if (fitting_strength > 100 ) fitting_strength = 100;
- + checked_fitting_strength = 1;
- + }
- +
- +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
- outline = &gloader->current.outline;
- n_points = outline->n_points;
- @@ -905,14 +995,36 @@
- FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
- loader->zone.n_points + 4 );
- }
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* scale, but only if enabled and only if TT hinting is being used */
- + if ( fitting_strength > 0 && use_various_tweaks && IS_HINTED( loader->load_flags ) )
- + {
- + x_scale_factor = scale_test_tweak( face, family, ppem, style, loader->glyph_index, X_SCALING_Rules, X_SCALING_RULES_SIZE );
- + /* Enabling this causes problems even though supposedly not being used in rules - need to figure out */
- + /*y_scale_factor = scale_test_tweak( face, family, ppem, style, loader->glyph_index, Y_SCALING_Rules, Y_SCALING_RULES_SIZE );*/
- + }
- /* scale the glyph */
- - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- +#endif
- + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + || x_scale_factor != 1.0 || y_scale_factor != 1.0
- +#endif
- + )
- {
- FT_Vector* vec = outline->points;
- FT_Vector* limit = outline->points + n_points;
- - FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- - FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
- + FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + * x_scale_factor
- +#endif
- + ;
- +
- + FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + * y_scale_factor
- +#endif
- + ;
- for ( ; vec < limit; vec++ )
- @@ -1682,7 +1794,11 @@
- glyph_index );
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- - if ( ( !enhanced_mode || SPH_OPTION_BITMAP_WIDTHS ) && widthp )
- + if ( (
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + ( enhanced_mode && loader->exec->compatible_widths ) ||
- +#endif
- + !enhanced_mode || SPH_OPTION_BITMAP_WIDTHS ) && widthp )
- #else
- if ( widthp )
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/truetype/ttinterp.c.orig src/truetype/ttinterp.c
- --- src/truetype/ttinterp.c.orig 2011-12-23 19:46:15.342075740 -0600
- +++ fsrc/truetype/ttinterp.c 2011-12-23 19:27:09.459546599 -0600
- @@ -6754,7 +6754,14 @@
- if ( ( org_dist ^ cvt_dist ) < 0 )
- cvt_dist = -cvt_dist;
- }
- -
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( CUR.GS.freeVector.y != 0 &&
- + ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
- + {
- + if ( cur_dist < -64 ) cvt_dist -= 16;
- + else if ( cur_dist > 64 && cur_dist < 84) cvt_dist += 32;
- + }
- +#endif
- /* control value cut-in and round */
- if ( ( CUR.opcode & 4 ) != 0 )
- @@ -6811,7 +6818,13 @@
- CUR.GS.minimum_distance, 64 );
- }
- }
- -
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + if ( CUR.GS.freeVector.y != 0
- + && ( CUR.opcode & 16 ) == 0
- + && ( CUR.opcode & 8 ) == 0
- + && ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
- + distance +=48;
- +#endif
- #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.enhanced_mode &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_INLINE_MOVES ) )
- @@ -6834,6 +6847,11 @@
- CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
- }
- }
- +
- + /* else if ( CUR.enhanced_mode && CUR.GS.freeVector.y != 0 &&
- + abs(distance - cur_dist) > 32 && ( CUR.sph_tweak_flags & SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES ) )
- + CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) + FT_PIX_ROUND (distance - cur_dist) ); */
- +
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- Fail:
- @@ -7707,8 +7725,27 @@
- Ins_GETINFO( INS_ARG )
- {
- FT_Long K;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* INFINALITY ENVVAR TO FORCE SUBPIXEL INTERPRETER (useful in debugging) */
- + FT_UInt force_subpixel_interpreter = 0;
- + FT_UInt checked_force_subpixel_interpreter = 0;
- -
- + if ( checked_force_subpixel_interpreter == 0)
- + {
- + char *force_subpixel_interpreter_env = getenv( "INFINALITY_FT_DEBUG_FORCE_SUBPIXEL_INTERPRETER" );
- + if ( force_subpixel_interpreter_env != NULL )
- + {
- + if ( strcasecmp(force_subpixel_interpreter_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(force_subpixel_interpreter_env, "true") == 0) force_subpixel_interpreter = TRUE;
- + else if ( strcasecmp(force_subpixel_interpreter_env, "1") == 0) force_subpixel_interpreter = TRUE;
- + else if ( strcasecmp(force_subpixel_interpreter_env, "on") == 0) force_subpixel_interpreter = TRUE;
- + else if ( strcasecmp(force_subpixel_interpreter_env, "yes") == 0) force_subpixel_interpreter = TRUE;
- + }
- + }
- + checked_force_subpixel_interpreter = 1;
- + }
- +#endif
- K = 0;
- /********************************/
- @@ -7809,7 +7846,14 @@
- }
- }
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- -
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* INFINALITY ENVVAR TO FORCE SUBPIXEL INTERPRETER (useful in debugging) */
- + if ( force_subpixel_interpreter )
- + {
- + K |= 1 << 13;
- + CUR.subpixel_hinting = TRUE;
- + }
- +#endif
- args[0] = K;
- }
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/truetype/ttsubpix.c.orig src/truetype/ttsubpix.c
- --- src/truetype/ttsubpix.c.orig 2011-12-23 19:49:27.948443055 -0600
- +++ src/truetype/ttsubpix.c 2011-12-23 19:49:42.707934810 -0600
- @@ -84,6 +84,49 @@
- int ppem = loader->size->metrics.x_ppem;
- FT_String* style = face->root.style_name;
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + int checked_use_known_settings_on_selected_fonts_env = 0;
- + FT_Bool use_known_settings_on_selected_fonts = FALSE;
- +
- + int fitting_strength = 0;
- + FT_UInt checked_fitting_strength = 0;
- +
- + if ( checked_use_known_settings_on_selected_fonts_env == 0 )
- + {
- + char *use_known_settings_on_selected_fonts_env = getenv( "INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS" );
- + if ( use_known_settings_on_selected_fonts_env != NULL )
- + {
- + if ( strcasecmp(use_known_settings_on_selected_fonts_env, "default" ) != 0 )
- + {
- + if ( strcasecmp(use_known_settings_on_selected_fonts_env, "true") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "1") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "on") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + else if ( strcasecmp(use_known_settings_on_selected_fonts_env, "yes") == 0)
- + use_known_settings_on_selected_fonts = TRUE;
- + }
- + }
- + checked_use_known_settings_on_selected_fonts_env = 1;
- + }
- +
- + if ( checked_fitting_strength == 0)
- + {
- + char *fitting_strength_env = getenv( "INFINALITY_FT_STEM_FITTING_STRENGTH" );
- + if ( fitting_strength_env != NULL )
- + {
- + sscanf ( fitting_strength_env, "%d", &fitting_strength );
- + if (fitting_strength > 100 ) fitting_strength = 100;
- + else if (fitting_strength < 0 ) fitting_strength = 0;
- + }
- + if (fitting_strength > 100 ) fitting_strength = 100;
- + checked_fitting_strength = 1;
- + }
- +
- +
- +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
- +
- /* Don't apply rules if style isn't set */
- if ( !face->root.style_name ) return;
- @@ -161,6 +204,19 @@
- tt_size_ready_bytecode( loader->exec->size, FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
- }
- }
- +
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* These tweaks require the TT interpreter to be on for this glyph */
- + if (IS_HINTED( loader->load_flags ) && use_known_settings_on_selected_fonts )
- + {
- + TWEAK_RULES( TIMES_NEW_ROMAN_HACK );
- + TWEAK_RULES( COURIER_NEW_2_HACK );
- +
- + if (sph_test_tweak( face, family, ppem, style, glyph_index,
- + COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) )
- + loader->exec->compatible_widths |= TRUE;
- + }
- +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
- }
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */
- diff -Nur -x '*~' -x '*.rej' -x '*.orig' -x '*.SUP' src/truetype/ttsubpix.h.orig src/truetype/ttsubpix.h
- --- src/truetype/ttsubpix.h.orig 2011-12-23 19:52:30.830145677 -0600
- +++ src/truetype/ttsubpix.h 2011-12-23 19:50:59.479291216 -0600
- @@ -55,6 +55,10 @@
- #define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0800000
- #define SPH_TWEAK_SKIP_INLINE_DELTAS 0x1000000
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- +#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x4000000
- +#define SPH_TWEAK_COURIER_NEW_2_HACK 0x8000000
- +#endif
- FT_LOCAL( FT_Bool )
- sph_test_tweak( TT_Face face,
- @@ -950,6 +954,149 @@
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_ADDITIONAL_TWEAKS */
- +
- +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
- + /* use compatible widths with these */
- +#define COMPATIBLE_WIDTHS_RULES_SIZE 32
- + SPH_TweakRule COMPATIBLE_WIDTHS_Rules
- + [COMPATIBLE_WIDTHS_RULES_SIZE] =
- + {
- + { "Arial Unicode MS", 12, "Regular", 'm' },
- + { "Arial Unicode MS", 14, "Regular", 'm' },
- + { "Arial", 10, "Regular", L'Ñ' },
- + { "Arial", 11, "Regular", 'm' },
- + { "Arial", 12, "Regular", 'm' },
- + { "Arial", 12, "Regular", L'Ñ' },
- + { "Arial", 13, "Regular", L'Ñ' },
- + { "Arial", 14, "Regular", 'm' },
- + { "Arial", 14, "Regular", L'Ñ' },
- + { "Arial", 15, "Regular", L'Ñ' },
- + { "Arial", 17, "Regular", 'm' },
- + { "DejaVu Sans", 12, "Book", 0 },
- + { "DejaVu Sans", 15, "Book", 0 },
- + { "Georgia", 13, "Regular", 0 },
- + { "Microsoft Sans Serif", 11, "Regular", 0 },
- + { "Microsoft Sans Serif", 12, "Regular", 0 },
- + { "Segoe UI", 11, "Regular", 0 },
- + { "Segoe UI", 12, "Regular", 'm' },
- + { "Segoe UI", 14, "Regular", 'm' },
- + { "Tahoma", 11, "Regular", 0 },
- + { "Times New Roman", 16, "Regular", 'c' },
- + { "Times New Roman", 16, "Regular", 'm' },
- + { "Times New Roman", 16, "Regular", 'o' },
- + { "Times New Roman", 16, "Regular", 'w' },
- + { "Trebuchet MS", 12, "Regular", 0 },
- + { "Trebuchet MS", 14, "Regular", 0 },
- + { "Trebuchet MS", 15, "Regular", 0 },
- + { "Verdana", 10, "Regular", L'Ñ' },
- + { "Verdana", 11, "Regular", L'Ñ' },
- + { "Verdana", 12, "Regular", 0 },
- + { "Verdana", 13, "Regular", 'U' },
- + { "Verdana", 14, "Regular", 'm' },
- + };
- +
- +
- +#if 0
- +
- +#define FAMILY_CLASS_RULES_SIZE 2
- + Font_Class FAMILY_CLASS_Rules
- + [FAMILY_CLASS_RULES_SIZE] =
- + {
- + { "Verdana Class", { "Verdana", "DejaVu Sans", "Bitstream Vera Sans", "", "", "", "", }, },
- + { "Arial Class", { "Arial", "Liberation Sans", "Freesans", "Arimo", "", "", "", }, },
- + };
- +
- +#define STYLE_CLASS_RULES_SIZE 1
- + Font_Class STYLE_CLASS_Rules
- + [STYLE_CLASS_RULES_SIZE] =
- + {
- + { "Regular Class", { "Regular", "Book", "Medium", "", "", "", "", }, },
- + };
- +
- +#endif
- +
- +#define X_SCALING_RULES_SIZE 24
- + SPH_ScaleRule X_SCALING_Rules
- + [X_SCALING_RULES_SIZE] =
- + {
- + { "Bitstream Vera Sans", 10, "Roman", 0, 1.1 },
- + { "Bitstream Vera Sans", 16, "Roman", 0, 1.05 },
- + { "Bitstream Vera Sans", 9, "Roman", 0, 1.05},
- + { "Bitstream Vera Sans", 12, "Roman", 0, 1.05},
- + { "DejaVu Sans", 10, "Book", 0, 1.1 },
- + { "DejaVu Sans", 12, "Book", 0, 1.05 },
- + { "Georgia", 10, "", 0, 1.05},
- + { "Georgia", 11, "", 0, 1.1},
- + { "Georgia", 12, "", 0, 1.025},
- + { "Georgia", 13, "", 0, 1.05},
- + { "Georgia", 16, "", 0, 1.05 },
- + { "Georgia", 17, "", 0, 1.03 },
- + { "Liberation Sans", 12, "Regular", 'm', 1.1 },
- + { "Lucida Grande", 11, "Regular", 'm', 1.1 },
- + { "Segoe UI", 14, "Regular", 'm', 1.05},
- + { "Verdana", 10, "Regular", 0, 1.1 },
- + { "Verdana", 13, "Regular", 'U', .90 },
- + { "Verdana", 16, "Regular", 0, 1.05 },
- + { "Verdana", 9, "Regular", 0, 1.05},
- + { "Verdana", 12, "Regular", 'a', 1.05},
- + { "Verdana", 12, "Regular", 'W', 1.05},
- + { "Arial", 13, "Regular", L'л', .95 },
- + { "Arial", 15, "Regular", L'л', .925 },
- + { "Arial", 14, "Regular", 'm', .95 },
- +
- + };
- +
- +#define Y_SCALING_RULES_SIZE 1
- + SPH_ScaleRule Y_SCALING_Rules
- + [Y_SCALING_RULES_SIZE] =
- + {
- + { "-", 0, "", 0, 1.2 },
- + };
- +
- +
- +#define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12
- + SPH_TweakRule TIMES_NEW_ROMAN_HACK_Rules
- + [TIMES_NEW_ROMAN_HACK_RULES_SIZE] =
- + {
- + { "Times New Roman", 16, "Italic", '2' },
- + { "Times New Roman", 16, "Italic", '5' },
- + { "Times New Roman", 16, "Italic", '7' },
- + { "Times New Roman", 16, "Regular", '2' },
- + { "Times New Roman", 16, "Regular", '5' },
- + { "Times New Roman", 16, "Regular", '7' },
- + { "Times New Roman", 17, "Italic", '2' },
- + { "Times New Roman", 17, "Italic", '5' },
- + { "Times New Roman", 17, "Italic", '7' },
- + { "Times New Roman", 17, "Regular", '2' },
- + { "Times New Roman", 17, "Regular", '5' },
- + { "Times New Roman", 17, "Regular", '7' },
- + };
- +
- +
- +#define COURIER_NEW_2_HACK_RULES_SIZE 15
- + SPH_TweakRule COURIER_NEW_2_HACK_Rules
- + [COURIER_NEW_2_HACK_RULES_SIZE] =
- + {
- + { "Courier New", 10, "Regular", '2' },
- + { "Courier New", 11, "Regular", '2' },
- + { "Courier New", 12, "Regular", '2' },
- + { "Courier New", 13, "Regular", '2' },
- + { "Courier New", 14, "Regular", '2' },
- + { "Courier New", 15, "Regular", '2' },
- + { "Courier New", 16, "Regular", '2' },
- + { "Courier New", 17, "Regular", '2' },
- + { "Courier New", 18, "Regular", '2' },
- + { "Courier New", 19, "Regular", '2' },
- + { "Courier New", 20, "Regular", '2' },
- + { "Courier New", 21, "Regular", '2' },
- + { "Courier New", 22, "Regular", '2' },
- + { "Courier New", 23, "Regular", '2' },
- + { "Courier New", 24, "Regular", '2' },
- + };
- +
- +
- +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
- +
- #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- #endif /* __TTSUBPIX_H__ */
Advertisement
Add Comment
Please, Sign In to add comment