diff options
-rw-r--r-- | .SRCINFO | 40 | ||||
-rw-r--r-- | .gitignore | 17 | ||||
-rw-r--r-- | 0001-Enable-table-validation-modules.patch | 45 | ||||
-rw-r--r-- | 0002-infinality-2.11.1-2021.12.10.patch | 6395 | ||||
-rw-r--r-- | 0004-Enable-long-PCF-family-names.patch | 27 | ||||
-rw-r--r-- | PKGBUILD | 69 | ||||
-rw-r--r-- | freetype2.install | 14 | ||||
-rwxr-xr-x | freetype2.sh | 12 | ||||
-rwxr-xr-x | infinality-settings.sh | 65 | ||||
-rwxr-xr-x | xft-settings.sh | 15 |
10 files changed, 43 insertions, 6656 deletions
@@ -1,43 +1,13 @@ pkgbase = freetype2-infinality-remix - pkgdesc = TrueType font rendering library with Infinality Remix patches - pkgver = 2.13.0 + pkgdesc = [Meta-PKG] EOL; please delete. Use freetype2 from [extra] repository + pkgver = 2.13.1 pkgrel = 1 - url = http://www.freetype.org/ + url = https://gitlab.archlinux.org/archlinux/packaging/packages/freetype2/-/commit/5b4370f7 install = freetype2.install - arch = i686 - arch = x86_64 + arch = any license = GPL - makedepends = libx11 - makedepends = libpng - makedepends = harfbuzz - source = https://download-mirror.savannah.gnu.org/releases/freetype/freetype-2.13.0.tar.xz - source = https://download-mirror.savannah.gnu.org/releases/freetype/freetype-2.13.0.tar.xz.sig - source = 0001-Enable-table-validation-modules.patch - source = 0002-infinality-2.11.1-2021.12.10.patch - source = 0004-Enable-long-PCF-family-names.patch - source = freetype2.sh - source = infinality-settings.sh - source = xft-settings.sh - validpgpkeys = E30674707856409FF1948010BE6C3AAC63AD8E3F - sha256sums = 5ee23abd047636c24b2d43c6625dcafc66661d1aca64dec9e0d05df29592624c - sha256sums = SKIP - sha256sums = ac11a24b62a6c044cc245ea9fa2a0cbd9e2e62f2371873dd33084c28a76e7176 - sha256sums = 6d563b1f9f9ef52379818ff3ede26b44e0b4cb6e3cf46ea44ca5d36b6d29ae9d - sha256sums = 54800d4da18611cf9232aad8b63d74a83153a51bb56dd39191678c738ffc8b53 - sha256sums = f7f8e09c44f7552c883846e9a6a1efc50377c4932234e74adc4a8ff750606467 - sha256sums = 1a5c12aa96e2ee66f7316b8ccb7012520b231a2d8ee21cfe4064aa28db35a57c - sha256sums = 4842d1461c240cd0f60a7247ee038271fdb1067107bea9024be6bdbb218d1bd4 pkgname = freetype2-infinality-remix - groups = infinality-remix - depends = zlib - depends = bzip2 - depends = sh - depends = libpng - depends = harfbuzz - provides = freetype2=2.13.0 - provides = freetype2-infinality - provides = libfreetype.so - conflicts = freetype2 + depends = freetype2>=2.13.1 conflicts = freetype2-infinality conflicts = freetype2-infinality-ultimate diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..e1cc0116832e --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# based on https://github.com/github/gitignore/blob/master/ArchLinuxPackages.gitignore +*.tar +*.tar.* +*.rpm +*.jar +*.exe +*.msi +*.zip +*.tgz +*.log +*.log.* + +*/ +*.orig +*.bak +*.backup +*.kate-swp diff --git a/0001-Enable-table-validation-modules.patch b/0001-Enable-table-validation-modules.patch deleted file mode 100644 index 6b78bcd7985c..000000000000 --- a/0001-Enable-table-validation-modules.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b609203df7333beea20dbfd604262a9486f01497 Mon Sep 17 00:00:00 2001 -Message-Id: <b609203df7333beea20dbfd604262a9486f01497.1552648361.git.jan.steffens@gmail.com> -From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com> -Date: Tue, 23 Jun 2015 08:40:29 +0200 -Subject: [PATCH 1/4] Enable table validation modules - ---- - modules.cfg | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/modules.cfg b/modules.cfg -index dc6c8d42d..2ab145016 100644 ---- a/modules.cfg -+++ b/modules.cfg -@@ -111,26 +111,26 @@ AUX_MODULES += cache - - # TrueType GX/AAT table validation. Needs `ftgxval.c' below. - # --# AUX_MODULES += gxvalid -+AUX_MODULES += gxvalid - - # Support for streams compressed with gzip (files with suffix .gz). - # - # See include/freetype/ftgzip.h for the API. - AUX_MODULES += gzip - - # Support for streams compressed with LZW (files with suffix .Z). - # - # See include/freetype/ftlzw.h for the API. - AUX_MODULES += lzw - - # Support for streams compressed with bzip2 (files with suffix .bz2). - # - # See include/freetype/ftbzip2.h for the API. - AUX_MODULES += bzip2 - - # OpenType table validation. Needs `ftotval.c' below. - # --# AUX_MODULES += otvalid -+AUX_MODULES += otvalid - - # Auxiliary PostScript driver component to share common code. - # --- -2.21.0 diff --git a/0002-infinality-2.11.1-2021.12.10.patch b/0002-infinality-2.11.1-2021.12.10.patch deleted file mode 100644 index 91c48dc01103..000000000000 --- a/0002-infinality-2.11.1-2021.12.10.patch +++ /dev/null @@ -1,6395 +0,0 @@ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/config.mk a/config.mk ---- b/config.mk 1970-01-01 03:00:00.000000000 +0300 -+++ a/config.mk 2021-09-16 09:19:40.891396586 +0300 -@@ -0,0 +1,62 @@ -+# -+# FreeType 2 configuration rules for UNIX platforms -+# -+ -+ -+# Copyright (C) 1996-2021 by -+# David Turner, Robert Wilhelm, and Werner Lemberg. -+# -+# This file is part of the FreeType project, and may only be used, modified, -+# and distributed under the terms of the FreeType project license, -+# LICENSE.TXT. By continuing to use, modify, or distribute this file you -+# indicate that you have read the license and understand and accept it -+# fully. -+ -+# We need these declarations here since unix-def.mk is a generated file. -+PLATFORM_DIR := $(TOP_DIR)/builds/unix -+PLATFORM := unix -+ -+have_mk := $(wildcard $(OBJ_DIR)/unix-def.mk) -+ifneq ($(have_mk),) -+ # We are building FreeType 2 not in the src tree. -+ include $(OBJ_DIR)/unix-def.mk -+ include $(OBJ_DIR)/unix-cc.mk -+else -+ include $(PLATFORM_DIR)/unix-def.mk -+ include $(PLATFORM_DIR)/unix-cc.mk -+endif -+ -+ifdef BUILD_PROJECT -+ -+ .PHONY: clean_project distclean_project -+ -+ # Now include the main sub-makefile. It contains all the rules used to -+ # build the library with the previous variables defined. -+ # -+ include $(TOP_DIR)/builds/$(PROJECT).mk -+ -+ -+ # The cleanup targets. -+ # -+ clean_project: clean_project_unix -+ distclean_project: distclean_project_unix -+ -+ -+ # This final rule is used to link all object files into a single library. -+ # It is part of the system-specific sub-Makefile because not all -+ # librarians accept a simple syntax like -+ # -+ # librarian library_file {list of object files} -+ # -+ $(PROJECT_LIBRARY): $(OBJECTS_LIST) -+ ifdef CLEAN_LIBRARY -+ -$(CLEAN_LIBRARY) $(NO_OUTPUT) -+ endif -+ $(LINK_LIBRARY) -+ -+ include $(TOP_DIR)/builds/unix/install.mk -+ -+endif -+ -+ -+# EOF -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/configure a/configure ---- b/configure 2021-02-13 10:16:54.000000000 +0200 -+++ a/configure 2021-09-16 09:15:05.050379727 +0300 -@@ -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 - - # respect GNUMAKE environment variable for backward compatibility -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/devel/ftoption.h a/devel/ftoption.h ---- b/devel/ftoption.h 2021-07-15 13:09:04.000000000 +0300 -+++ a/devel/ftoption.h 2021-09-16 09:15:05.050379727 +0300 -@@ -629,6 +629,16 @@ - */ - #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER - -+ /*************************************************************************/ -+ /* */ -+ /* 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 to */ -+ /* defined. */ -+ /* */ -+#define FT_CONFIG_OPTION_INFINALITY_PATCHSET - - /************************************************************************** - * -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/include/freetype/config/ftoption.h a/include/freetype/config/ftoption.h ---- b/include/freetype/config/ftoption.h 2021-07-15 13:09:04.000000000 +0300 -+++ a/include/freetype/config/ftoption.h 2021-09-16 09:15:05.051379735 +0300 -@@ -112,18 +112,21 @@ - #define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES - - -- /************************************************************************** -- * -- * Uncomment the line below if you want to activate LCD rendering -- * technology similar to ClearType in this build of the library. This -- * technology triples the resolution in the direction color subpixels. To -- * mitigate color fringes inherent to this technology, you also need to -- * explicitly set up LCD filtering. -- * -- * When this macro is not defined, FreeType offers alternative LCD -- * rendering technology that produces excellent output. -- */ --/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ -+ /*************************************************************************/ -+ /* */ -+ /* Uncomment the line below if you want to activate LCD rendering */ -+ /* technology similar to ClearType in this build of the library. This */ -+ /* technology triples the resolution in the direction color subpixels. */ -+ /* To mitigate color fringes inherent to this technology, you also need */ -+ /* to explicitly set up LCD filtering. */ -+ /* */ -+ /* Note that this feature is covered by several Microsoft patents */ -+ /* and should not be activated in any default build of the library. */ -+ /* When this macro is not defined, FreeType offers alternative LCD */ -+ /* rendering technology that produces excellent output without LCD */ -+ /* filtering. */ -+ /* */ -+#define FT_CONFIG_OPTION_SUBPIXEL_RENDERING - - - /************************************************************************** -@@ -631,6 +634,17 @@ - */ - #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER - -+ /*************************************************************************/ -+ /* */ -+ /* 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 to */ -+ /* defined. */ -+ /* */ -+#define FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ - - /************************************************************************** - * -@@ -688,8 +702,8 @@ - * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx - */ - /* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ --#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 --/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ -+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ -+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) - - - /************************************************************************** -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/include/freetype/internal/ftobjs.h a/include/freetype/internal/ftobjs.h ---- b/include/freetype/internal/ftobjs.h 2021-02-13 10:16:54.000000000 +0200 -+++ a/include/freetype/internal/ftobjs.h 2021-09-16 09:15:05.051379735 +0300 -@@ -278,12 +278,14 @@ - #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - - typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap, -+ FT_Render_Mode render_mode, - FT_Byte* weights ); - - - /* This is the default LCD filter, an in-place, 5-tap FIR filter. */ - FT_BASE( void ) - ft_lcd_filter_fir( FT_Bitmap* bitmap, -+ FT_Render_Mode mode, - FT_LcdFiveTapFilter weights ); - - #endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ -@@ -908,6 +910,7 @@ - FT_DebugHook_Func debug_hooks[4]; - - #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING -+ FT_Int lcd_extra; /* number of extra pixels */ - FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */ - FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ - #else -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/autofit/aflatin.c a/src/autofit/aflatin.c ---- b/src/autofit/aflatin.c 2021-07-12 15:07:00.000000000 +0300 -+++ a/src/autofit/aflatin.c 2021-09-16 09:15:05.051379735 +0300 -@@ -22,7 +22,10 @@ - #include "afglobal.h" - #include "aflatin.h" - #include "aferrors.h" -- -+#include "strings.h" -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "../base/ftinf.h" -+#endif - - /************************************************************************** - * -@@ -33,6 +36,10 @@ - #undef FT_COMPONENT - #define FT_COMPONENT aflatin - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+FT_Pos infinality_cur_width = 0; -+#endif -+ - - /* needed for computation of round vs. flat segments */ - #define FLAT_THRESHOLD( x ) ( x / 14 ) -@@ -1174,7 +1181,10 @@ - FT_Pos delta; - AF_LatinAxis axis; - FT_UInt nn; -- -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ FT_Bool adjust_heights = FALSE; -+ if(ftinf) adjust_heights=ftinf->autohint_increase_glyph_heights; -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - - if ( dim == AF_DIMENSION_HORZ ) - { -@@ -1202,7 +1212,7 @@ - { - AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT]; - AF_LatinBlue blue = NULL; -- -+ int threshold = 40; - - for ( nn = 0; nn < Axis->blue_count; nn++ ) - { -@@ -1212,7 +1222,12 @@ - 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 /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - if ( blue ) - { - FT_Pos scaled; -@@ -1369,7 +1384,13 @@ - - /* 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 at low ppems ( ~< 200 ), in order to prevent fringes */ -+ if ( dist <= 256 && dist >= -256 ) -+#else - if ( dist <= 48 && dist >= -48 ) -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - { - #if 0 - FT_Pos delta1; -@@ -1420,7 +1441,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 /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - - #endif - -@@ -2583,7 +2609,10 @@ - dist = edge->fpos - blue->shoot.org; - if ( dist < 0 ) - dist = -dist; -- -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ /* round down to pixels */ -+ /*dist = FT_MulFix( dist, scale ) & ~63;*/ -+#endif - dist = FT_MulFix( dist, scale ); - if ( dist < best_dist ) - { -@@ -2748,8 +2777,17 @@ - FT_Pos dist = width; - FT_Int sign = 0; - FT_Int vertical = ( dim == AF_DIMENSION_VERT ); -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ FT_Int infinality_dist = 0; -+ FT_UInt autohint_snap_stem_height = 0; -+ if( ftinf ) autohint_snap_stem_height=ftinf->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; - -- -+ if ( autohint_snap_stem_height == 0 ) -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || - axis->extra_light ) - return width; -@@ -2759,9 +2797,76 @@ - dist = -width; - sign = 1; - } -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ /* Calculate snap value differently than standard freetype */ -+ if ( 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 ) -+ { -+ const char *style_name=metrics->root.scaler.face->style_name; -+ if ( style_name!=NULL && -+ ( strstr( style_name, "Regular" ) || -+ strstr( style_name, "Book" ) || -+ strstr( style_name, "Medium" ) || -+ strcmp( style_name, "Italic" ) == 0 || -+ strcmp( 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 ( 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 /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - { - /* smooth hinting process: very lightly quantize the stem width */ - -@@ -2853,6 +2958,9 @@ - } - } - else -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if ( autohint_snap_stem_height < 100 ) -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - { - /* strong hinting process: snap the stem width to integer pixels */ - -@@ -2860,7 +2968,10 @@ - - - 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 /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - if ( vertical ) - { - /* in the case of vertical hinting, always round */ -@@ -2923,6 +3034,32 @@ - } - - 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 /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - if ( sign ) - dist = -dist; - -@@ -2941,6 +3078,8 @@ - FT_Pos dist, base_delta; - FT_Pos fitted_width; - -+/* 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 */ - - dist = stem_edge->opos - base_edge->opos; - base_delta = base_edge->pos - base_edge->opos; -@@ -3548,8 +3687,11 @@ - int dim; - - AF_LatinAxis axis; -- -- -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ FT_Int emboldening_strength = 0; -+ FT_Bool use_various_tweaks = FALSE; -+ if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks; -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - error = af_glyph_hints_reload( hints, outline ); - if ( error ) - goto Exit; -@@ -3595,7 +3737,11 @@ - } - - af_glyph_hints_save( hints, outline ); -- -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ { -+ infinality_cur_width = metrics->axis->widths[0].cur; -+ } -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - Exit: - return error; - } -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/autofit/aflatin.h a/src/autofit/aflatin.h ---- b/src/autofit/aflatin.h 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/autofit/aflatin.h 2021-09-16 09:15:05.051379735 +0300 -@@ -64,6 +64,9 @@ - - #define AF_LATIN_MAX_WIDTHS 16 - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ extern FT_Pos infinality_cur_width; -+#endif - - #define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */ - #define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/autofit/afmodule.c a/src/autofit/afmodule.c ---- b/src/autofit/afmodule.c 2021-07-12 15:07:00.000000000 +0300 -+++ a/src/autofit/afmodule.c 2021-09-16 09:15:05.051379735 +0300 -@@ -21,6 +21,10 @@ - #include "afloader.h" - #include "aferrors.h" - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "../base/ftinf.h" -+#endif -+ - #ifdef FT_DEBUG_AUTOFIT - - #ifndef FT_MAKE_OPTION_SINGLE_OBJECT -@@ -405,6 +409,9 @@ - module->fallback_style = AF_STYLE_FALLBACK; - module->default_script = AF_SCRIPT_DEFAULT; - module->no_stem_darkening = TRUE; -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if(ftinf) module->no_stem_darkening = !ftinf->stem_darkening_autofit; -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - - module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; - module->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftbase.c a/src/base/ftbase.c ---- b/src/base/ftbase.c 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/base/ftbase.c 2021-09-16 09:15:05.051379735 +0300 -@@ -36,6 +36,9 @@ - #include "ftstream.c" - #include "fttrigon.c" - #include "ftutil.c" -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "ftinf.c" -+#endif - - - /* END */ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf.c a/src/base/ftinf.c ---- b/src/base/ftinf.c 1970-01-01 03:00:00.000000000 +0300 -+++ a/src/base/ftinf.c 2021-09-16 09:15:05.052379743 +0300 -@@ -0,0 +1,363 @@ -+#include <stdlib.h> -+#include "ftinf.h" -+#define true 1 -+#define false 0 -+ -+#define on 1 -+#define off 0 -+#define end (-128) -+ -+#define sw2pv 18 /* STEM_WIDTH_2_PPEM */ -+#define maxp 100 /* MAX_PPEM */ -+ -+typedef signed char pv; /* ppm and values type */ -+/* the arrays start with existence flag + values */ -+typedef struct sa_rules_s { -+ const char *name; -+ pv always_use_100[1+4+1]; -+ pv brightness[1+2+1]; -+ pv contrast[1+2+1]; -+ pv edge_detection[1+4+1]; -+ pv m[1+4+1]; -+ pv bearing_correction[1+2+1]; -+ pv spacing[1+5+1]; -+ pv start[1+5+1]; -+ pv stem_scaling[1+6+1]; -+ pv stem_translating[1+2+1]; -+ pv stem_translating_only[1+10+1]; -+ pv stem_widths[1+4]; /* these end with maxp */ -+ pv synthesize_stems[1+2+1]; -+} sa_rules_t; -+ -+#pragma GCC diagnostic ignored "-Wpedantic" /* C99 struct initializer tags are needed */ -+#pragma GCC diagnostic ignored "-Wunused-function" -+ -+const ftinf_t *ftinf; -+/* final settings, updated from environment */ -+ftinf_t _env; -+ -+/* rules and hashing function */ -+#include "ftinf_rh.c" -+ -+/* rules selection */ -+void ftinf_fill_stem_values( Stem_Data *stem_values, -+ const char *family, int ppem, int use_known ){ -+ /* set the defaults */ -+ stem_values->bearing_correction = TRUE; -+ stem_values->brightness = 0.0; -+ stem_values->contrast = 0.0; -+ stem_values->edge_detection = FALSE; -+ stem_values->m = -1; -+ stem_values->stem_scaling = -1; -+ stem_values->stem_spacing = -1; -+ stem_values->stem_start = -1; -+ stem_values->stem_translating = 0; -+ stem_values->stem_translating_only = -1024; -+ stem_values->stem_width = -1; -+ stem_values->synth_stems = FALSE; -+ stem_values->use_100 = FALSE; -+ /* pick from known rules if requested and they exist for current family */ -+ if( !use_known ) -+ return; -+ else { -+ const sa_rules_t *r=ftinf_rules( family ); -+ int i; -+ if( r==NULL ) return; -+ if( r->stem_widths[0]==on ) -+ for( i=1; r->stem_widths[i]!=maxp; ++i ) -+ if( ppem < r->stem_widths[i] ){ -+ stem_values->stem_width = i-1; -+ break; -+ } -+ -+ if( r->stem_scaling[0]==on ) -+ for( i=1; r->stem_scaling[i]!=end; i+=2 ) -+ if( ppem==r->stem_scaling[i] ){ -+ stem_values->stem_scaling = r->stem_scaling[i+1]; -+ break; -+ } -+ -+ if( r->m[0]==on ) -+ for( i=1; r->m[i]!=end; i+=2 ) -+ if( ppem==r->m[i] ){ -+ stem_values->m = r->m[i+1]; -+ break; -+ } -+ -+ if( r->stem_translating_only[0]==on ) -+ for( i=1; r->stem_translating_only[i]!=end; i+=2 ) -+ if( ppem==r->stem_translating_only[i] || r->stem_translating_only[i]==0 ){ -+ stem_values->stem_translating_only = r->stem_translating_only[i+1]; -+ break; -+ } -+ -+ if( r->stem_translating[0]==on ) -+ for( i=1; r->stem_translating[i]!=end; i+=2 ) -+ if( ppem==r->stem_translating[i] || r->stem_translating[i]==0 ){ -+ stem_values->stem_translating = r->stem_translating[i+1]; -+ break; -+ } -+ -+ if( r->always_use_100[0]==on ) -+ for( i=1; r->always_use_100[i]!=end; i+=2 ) -+ if( ppem>=r->always_use_100[i] && ppem<=r->always_use_100[i+1] ){ -+ stem_values->use_100 = TRUE; -+ break; -+ } -+ -+ if( r->synthesize_stems[0]==on ) -+ for( i=1; r->synthesize_stems[i]!=end; i+=2 ) -+ if( ppem>=r->synthesize_stems[i] && ppem<=r->synthesize_stems[i+1] ){ -+ stem_values->synth_stems = TRUE; -+ break; -+ } -+ -+ if( r->edge_detection[0]==on ) -+ for( i=1; r->edge_detection[i]!=end; i+=2 ) -+ if( ppem>=r->edge_detection[i] && ppem<=r->edge_detection[i+1] ){ -+ stem_values->edge_detection = TRUE; -+ break; -+ } -+ -+ if( r->bearing_correction[0]==on ) -+ for( i=1; r->bearing_correction[i]!=end; i+=2 ) -+ if( ppem>=r->bearing_correction[i] && ppem<=r->bearing_correction[i+1] ){ -+ stem_values->bearing_correction = FALSE; -+ break; -+ } -+ -+#if(0) -+ if( r->brightness[0]==on ) -+ for( i=1; r->brightness[i]!=end; i+=2 ) -+ if( ppem==r->brightness[i]||r->brightness[i]==0 ){ -+ stem_values->brightness=r->brightness[i+1]*(1.0f/300.0f); -+ break; -+ } -+ -+ if( r->contrast[0]==on ) -+ for( i=1; r->contrast[i]!=end; i+=2 ) -+ if( ppem==r->contrast[i]||r->contrast[i]==0 ){ -+ stem_values->contrast=r->contrast[i+1]*(1.0f/300.0f); -+ break; -+ } -+ if( r->spacing[0]==on ){ -+ /* not used by original code */ -+ } -+ if( r->start[0]==on ){ -+ /* not used by original code */ -+ } -+#endif -+ } -+ return; -+} -+ -+void ftinf_get_bc( const char *family, int ppem, float *brightness, float *contrast ){ -+ const sa_rules_t *r=ftinf_rules( family ); -+ *brightness=0; -+ *contrast=0; -+ if( r ){ -+ int i; -+ if( r->brightness[0]==on ) -+ for( i=1; r->brightness[i]!=end; i+=2 ) -+ if( ppem==r->brightness[i]||r->brightness[i]==0 ){ -+ *brightness=r->brightness[i+1]*(1.0f/300.0f); -+ break; -+ } -+ -+ if( r->contrast[0]==on ) -+ for( i=1; r->contrast[i]!=end; i+=2 ) -+ if( ppem==r->contrast[i]||r->contrast[i]==0 ){ -+ *contrast=r->contrast[i+1]*(1.0f/300.0f); -+ break; -+ } -+ } -+ return; -+} -+ -+static int -+bool_val( const char *s ){ -+ if ( s != NULL ) -+ return strcasecmp(s, "true") == 0 -+ || strcasecmp(s, "1") == 0 -+ || strcasecmp(s, "on") == 0 -+ || strcasecmp(s, "yes") ==0; -+ else -+ return 0; -+} -+ -+static int -+int_val( const char *s, int min, int max ){ -+ int val; -+ sscanf ( s, "%d", &val ); -+ if ( val > max ) -+ val = max; -+ else if ( val < min ) -+ val = min; -+ return val; -+} -+ -+/* settings and hashing function */ -+#include "ftinf_sh.c" -+ -+/* -+ Get active Infinality settings -+ */ -+void ftinf_env(){ -+ const char *s; -+ ftinf=ftinf_settings( getenv( "INFINALITY_FT" ) ); -+ -+ if( ftinf==NULL ){ -+ ftinf=ftinf_settings( "ultimate3" ); -+ /* this should always succeed */ -+#if(0) -+ if( ftinf==NULL ){ -+ /* put an error here */ -+ exit(-1); -+ } -+#endif -+ } -+ _env=ftinf[0]; /* copy as defaults */ -+ -+ /* check if custom environment values are set and update with them */ -+ s=getenv( "INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS" ); -+ if( s ) _env.autohint_increase_glyph_heights=bool_val( s ); -+ s=getenv( "INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT" ); -+ if( s ) _env.autohint_snap_stem_height=int_val( s, 0, 100 ); -+ s=getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" ); -+ if( s ) _env.use_various_tweaks=bool_val( s ); -+ s=getenv( "INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS" ); -+ if( s ) _env.use_known_settings_on_selected_fonts=bool_val(s); -+#if(0) /* not used (naming error also) */ -+ s=getenv( "INFINALITY_FT_AUTOHINT_MINIMUM_STEM_WIDTH" ); -+ if( s ) _env.autohint_minimum_stem_height=int_val( s, 0, 100 ); -+#endif -+ s=getenv( "INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE" ); -+ if( s ) sscanf( s, "%d", &_env.stem_snapping_sliding_scale ); -+ s=getenv( "INFINALITY_FT_STEM_ALIGNMENT_STRENGTH" ); -+ if( s ) sscanf( s, "%d", &_env.stem_alignment_strength ); -+ s=getenv( "INFINALITY_FT_STEM_DARKENING_AUTOFIT" ); -+ if( s ) _env.stem_darkening_autofit=bool_val( s ); -+ s=getenv( "INFINALITY_FT_STEM_DARKENING_CFF" ); -+ if( s ) _env.stem_darkening_cff=bool_val( s ); -+ s=getenv( "INFINALITY_FT_STEM_FITTING_STRENGTH" ); -+ if( s ) sscanf( s, "%d", &_env.stem_fitting_strength ); -+ s=getenv( "INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH" ); -+ if( s ) _env.chromeos_style_sharpening_strength=int_val( s, 0, 100 ); -+ s=getenv( "INFINALITY_FT_BRIGHTNESS" ); -+ if( s ) sscanf( s, "%d", &_env.brightness ); -+ s=getenv( "INFINALITY_FT_CONTRAST" ); -+ if( s ) sscanf( s, "%d", &_env.contrast ); -+ s=getenv( "INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH" ); -+ if( s ) _env.windows_style_sharpening_strength=int_val( s, 0, 100 ); -+ s=getenv( "INFINALITY_FT_GAMMA_CORRECTION" ); -+ if( s ){ -+ float *f=_env.gamma_correction; -+ sscanf ( s, "%f %f", &f[0], &f[1] ); -+ if( f[1] < 1.0f ) f[1]=1.0f; -+ } -+ s=getenv( "INFINALITY_FT_FRINGE_FILTER_STRENGTH" ); -+ if( s ) sscanf( s, "%d", &_env.fringe_filter_strength ); -+ s=getenv( "INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH" ); -+ if( s ) sscanf( s, "%d", &_env.grayscale_filter_strength ); -+ s=getenv( "INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH" ); -+ if( s ) sscanf( s, "%d", &_env.autohint_horizontal_stem_darken_strength ); -+ s=getenv( "INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH" ); -+ if( s ) sscanf( s, "%d", &_env.autohint_vertical_stem_darken_strength ); -+ s=getenv( "INFINALITY_FT_GLOBAL_EMBOLDEN_X_VALUE" ); -+ if( s ) sscanf( s, "%d", &_env.global_embolden_x_value ); -+ s=getenv( "INFINALITY_FT_GLOBAL_EMBOLDEN_Y_VALUE" ); -+ if( s ) sscanf( s, "%d", &_env.global_embolden_y_value ); -+ s=getenv( "INFINALITY_FT_BOLD_EMBOLDEN_X_VALUE" ); -+ if( s ) sscanf( s, "%d", &_env.bold_embolden_x_value ); -+ s=getenv( "INFINALITY_FT_BOLD_EMBOLDEN_Y_VALUE" ); -+ if( s ) sscanf( s, "%d", &_env.bold_embolden_y_value ); -+ s=getenv( "INFINALITY_FT_FILTER_PARAMS" ); -+ if( s ) { -+ int *f=_env.filter_params; -+ if( sscanf( s, "%d %d %d %d %d", f+1, f+2, f+3, f+4, f+5 )==5 ) -+ f[0]=on; -+ else -+ f[0]=off; /* FIXME: put a warning? */ -+ } -+ /* do the range verifications as in original code */ -+ if ( _env.stem_snapping_sliding_scale > maxp ) -+ _env.stem_snapping_sliding_scale = 0; -+ else if ( _env.stem_snapping_sliding_scale < 0 ) -+ _env.stem_snapping_sliding_scale = 0; -+ if (_env.stem_snapping_sliding_scale < 11 && -+ _env.stem_snapping_sliding_scale > 0 ) -+ _env.stem_snapping_sliding_scale = 11; -+ -+ if ( _env.stem_alignment_strength > 100 ) -+ _env.stem_alignment_strength = 100; -+ else if ( _env.stem_alignment_strength < 0 ) -+ _env.stem_alignment_strength = 0; -+ -+ if ( _env.stem_fitting_strength > 100 ) -+ _env.stem_fitting_strength = 100; -+ else if ( _env.stem_fitting_strength < 0 ) -+ _env.stem_fitting_strength = 0; -+ -+ if ( _env.chromeos_style_sharpening_strength > 100 ) -+ _env.chromeos_style_sharpening_strength = 100; -+ else if ( _env.chromeos_style_sharpening_strength < 0 ) -+ _env.chromeos_style_sharpening_strength = 0; -+ -+ if ( _env.brightness > 100 ) -+ _env.brightness = 100; -+ else if ( _env.brightness < -100 ) -+ _env.brightness = 0; -+ -+ if ( _env.contrast > 100 ) -+ _env.contrast = 100; -+ else if ( _env.contrast < -100 ) -+ _env.contrast = 0; -+ -+ if ( _env.windows_style_sharpening_strength > 100 ) -+ _env.windows_style_sharpening_strength = 100; -+ else if ( _env.windows_style_sharpening_strength < 0 ) -+ _env.windows_style_sharpening_strength = 0; -+ -+ if ( _env.fringe_filter_strength > 100 ) -+ _env.fringe_filter_strength = 100; -+ else if ( _env.fringe_filter_strength < 0 ) -+ _env.fringe_filter_strength = 0; -+ -+ if ( _env.grayscale_filter_strength > 100 ) -+ _env.grayscale_filter_strength = 100; -+ else if ( _env.grayscale_filter_strength < 0 ) -+ _env.grayscale_filter_strength = 0; -+ -+ if ( _env.autohint_horizontal_stem_darken_strength > 100 ) -+ _env.autohint_horizontal_stem_darken_strength = 100; -+ else if ( _env.autohint_horizontal_stem_darken_strength < 0 ) -+ _env.autohint_horizontal_stem_darken_strength = 0; -+ -+ if ( _env.autohint_vertical_stem_darken_strength > 100 ) -+ _env.autohint_vertical_stem_darken_strength = 100; -+ else if ( _env.autohint_horizontal_stem_darken_strength < 0 ) -+ _env.autohint_vertical_stem_darken_strength = 0; -+ -+ if ( _env.global_embolden_x_value > 128 ) -+ _env.global_embolden_x_value = 128; -+ else if ( _env.global_embolden_x_value < -128 ) -+ _env.global_embolden_x_value = -128; -+ -+ if ( _env.global_embolden_y_value > 128 ) -+ _env.global_embolden_y_value = 128; -+ else if ( _env.global_embolden_y_value < -128 ) -+ _env.global_embolden_y_value = -128; -+ -+ if ( _env.bold_embolden_x_value > 128 ) -+ _env.bold_embolden_x_value = 128; -+ else if (_env.bold_embolden_x_value < -128 ) -+ _env.bold_embolden_x_value = -128; -+ -+ if ( _env.bold_embolden_y_value > 128 ) -+ _env.bold_embolden_y_value = 128; -+ else if ( _env.bold_embolden_y_value < -128 ) -+ _env.bold_embolden_y_value = -128; -+ -+ /* point to the combined and checked settings */ -+ ftinf=&_env; -+} -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf.h a/src/base/ftinf.h ---- b/src/base/ftinf.h 1970-01-01 03:00:00.000000000 +0300 -+++ a/src/base/ftinf.h 2021-09-16 09:15:05.052379743 +0300 -@@ -0,0 +1,66 @@ -+#ifndef _FTINF_H_ -+#define _FTINF_H_ -+/* -+ Stem snapping rules -+ (base freetype typedefs assumed already included) -+ */ -+typedef struct -+{ -+ 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; -+ float brightness; -+ float contrast; -+ FT_Bool use_100; -+ FT_Bool synth_stems; -+ FT_Bool edge_detection; -+ FT_Bool bearing_correction; -+ FT_Int m; -+} Stem_Data; -+ -+/* -+ Infinality settings -+ */ -+typedef struct ftinf_s { -+ const char *name; -+ int autohint_horizontal_stem_darken_strength; -+ int autohint_snap_stem_height; -+ int autohint_increase_glyph_heights; -+ int autohint_vertical_stem_darken_strength; -+ int bold_embolden_x_value; -+ int bold_embolden_y_value; -+ int brightness; -+ int chromeos_style_sharpening_strength; -+ int contrast; -+ int filter_params[6]; /* 1st one used as existence flag */ -+ int fringe_filter_strength; -+ float gamma_correction[2]; -+ int global_embolden_x_value; -+ int global_embolden_y_value; -+ int grayscale_filter_strength; -+ int stem_alignment_strength; -+ int stem_darkening_autofit; -+ int stem_darkening_cff; -+ int stem_fitting_strength; -+ int stem_snapping_sliding_scale; -+ int use_known_settings_on_selected_fonts; -+ int use_various_tweaks; -+ int windows_style_sharpening_strength; -+} ftinf_t; -+ -+extern FT_Pos infinality_cur_width; /* defined in aflatin.c */ -+ -+extern const ftinf_t *ftinf; /* active settings */ -+ -+extern void ftinf_fill_stem_values( Stem_Data *stem_values, -+ const char *family, int ppem, int use_known ); -+extern void ftinf_get_bc( const char *family, int ppem, -+ float *brightness, float *contrast ); -+ -+/* get values from environment (FIXME: maybe update with using user files) */ -+extern void ftinf_env(); -+ -+#endif -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_rh.c a/src/base/ftinf_rh.c ---- b/src/base/ftinf_rh.c 1970-01-01 03:00:00.000000000 +0300 -+++ a/src/base/ftinf_rh.c 2021-09-16 09:15:05.052379743 +0300 -@@ -0,0 +1,626 @@ -+/* ANSI-C code produced by gperf version 3.1 */ -+/* Command-line: gperf --output-file=ftinf_rh.c ftinf_rh.gperf */ -+/* Computed positions: -k'1,$' */ -+ -+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ -+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ -+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ -+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ -+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ -+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ -+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ -+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ -+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ -+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ -+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ -+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ -+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ -+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ -+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ -+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ -+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ -+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ -+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ -+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ -+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ -+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ -+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) -+/* The character set is not based on ISO-646. */ -+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." -+#endif -+ -+#line 9 "ftinf_rh.gperf" -+ -+#include <ctype.h> -+static const struct sa_rules_s* _rules_get( const char*str, unsigned len ); -+/* maximum key range = 82, duplicates = 0 */ -+ -+#ifdef __GNUC__ -+__inline -+#else -+#ifdef __cplusplus -+inline -+#endif -+#endif -+static unsigned int -+_rules_hash (register const char *str, register unsigned int len) -+{ -+ static const unsigned char asso_values[] = -+ { -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 0, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 5, 45, 5, -+ 35, 25, 35, 35, 50, 45, 85, 85, 0, 25, -+ 40, 5, 0, 85, 50, 20, 20, 0, 10, 10, -+ 85, 10, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -+ 85, 85, 85, 85, 85, 85 -+ }; -+ return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; -+} -+ -+#ifdef __GNUC__ -+__inline -+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ -+__attribute__ ((__gnu_inline__)) -+#endif -+#endif -+const struct sa_rules_s * -+_rules_get (register const char *str, register unsigned int len) -+{ -+ enum -+ { -+ TOTAL_KEYWORDS = 58, -+ MIN_WORD_LENGTH = 3, -+ MAX_WORD_LENGTH = 24, -+ MIN_HASH_VALUE = 3, -+ MAX_HASH_VALUE = 84 -+ }; -+ -+ static const struct sa_rules_s wordlist[] = -+ { -+#line 15 "ftinf_rh.gperf" -+{ .name="---", -+ .synthesize_stems={on, 13, 13, end} -+}, -+#line 253 "ftinf_rh.gperf" -+{ .name="ubuntu", -+ .always_use_100={on, 12, 13, 15, 15, end} -+}, -+#line 31 "ftinf_rh.gperf" -+{ .name="arial", -+ .always_use_100={on, 0, maxp, end}, -+ .edge_detection={on, 11, 11, 13, 13, end}, -+ .spacing={on, 10, 11, 23, 25, 30, end}, -+ .start={on, 11, 18, 23, 30, 30, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 16, 8, 32, 9, 32, 16, -24, end} -+}, -+#line 87 "ftinf_rh.gperf" -+{ .name="corbel", -+ .stem_translating_only={on, 10, 16, end}, -+ .stem_widths={on, 10, 21, maxp} -+}, -+#line 71 "ftinf_rh.gperf" -+{ .name="canwell", -+ .stem_scaling={on, 13, 0, end} -+}, -+#line 216 "ftinf_rh.gperf" -+{ .name="pragmata", -+ .always_use_100={on, 0, maxp, end} -+}, -+#line 67 "ftinf_rh.gperf" -+{ .name="cantarell", -+ .stem_translating_only={on, 11, 0, 12, 0, end}, -+ .stem_widths={on, 10, 22, maxp,} -+}, -+#line 39 "ftinf_rh.gperf" -+{ .name="arimo", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end} -+}, -+#line 207 "ftinf_rh.gperf" -+{ .name="optima", -+ .brightness={on, 0, -20, end}, -+ .contrast={on, 0, 25, end}, -+ .stem_scaling={on, 17, 1, end}, -+ .stem_translating_only={on, 10, 0, 11, 0, 12, 0, end} -+}, -+#line 63 "ftinf_rh.gperf" -+{ .name="candara", -+ .stem_scaling={on, 14, 1, 17, 1, end}, -+ .stem_translating_only={on, 10, 16, end} -+}, -+#line 77 "ftinf_rh.gperf" -+{ .name="comfortaa", -+ .stem_widths={on, 10, 19, 22, maxp}, -+ .stem_scaling={on, 11, 0, end} -+}, -+#line 161 "ftinf_rh.gperf" -+{ .name="liberation mono", -+ .always_use_100={on, 0, maxp, end} -+}, -+#line 18 "ftinf_rh.gperf" -+{ .name="andale mono", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_scaling={on, 11, 1, end}, -+ .stem_widths={on, 10, 21, maxp,} -+}, -+#line 256 "ftinf_rh.gperf" -+{ .name="verdana", -+ .always_use_100={on, 0, 14, 16, maxp, end}, -+ .stem_scaling={on, 12, 1, 15, 1, end}, -+ .stem_translating_only={on, 8, 16, 15, 16, 14, 32, 18, 32, 19, 24, end} -+}, -+#line 74 "ftinf_rh.gperf" -+{ .name="century gothic", -+ .stem_widths={on, 10, 22, maxp,} -+}, -+#line 91 "ftinf_rh.gperf" -+{ .name="courier new", -+ .always_use_100={on, 12, 12, end}, -+ .edge_detection={on, 10, 12, end}, -+ .m={on, 13, 1, 14, 1, end} -+}, -+#line 23 "ftinf_rh.gperf" -+{ .name="arial narrow", -+ .stem_widths={on, 10, 21, maxp,} -+}, -+#line 185 "ftinf_rh.gperf" -+{ .name="luxi sans", -+ .always_use_100={on, 13, 13, end}, -+ .stem_widths={on, 10, 17, sw2pv, maxp,} -+}, -+#line 225 "ftinf_rh.gperf" -+{ .name="samba", -+ .stem_scaling={on, 11, 0, end} -+}, -+#line 233 "ftinf_rh.gperf" -+{ .name="tahoma", -+ .always_use_100={on, 11, 11, 14, maxp, end}, -+ .edge_detection={on, 11, 11, end}, -+ .spacing={on, 10, 12, 18, 18, 30, end}, -+ .start={on, 14, 17, 30, 100, 100, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 7, 32, 8, 32, 9, 32, end}, -+}, -+#line 164 "ftinf_rh.gperf" -+{ .name="liberation sans narrow", -+ .stem_widths={on,10, 22, maxp,} -+}, -+#line 81 "ftinf_rh.gperf" -+{ .name="consolas", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating_only={on, 8, 32, 9, 32, end}, -+ .stem_widths={on, 10, 20, maxp,}, -+ .stem_scaling={on, 11, 1, end} -+}, -+#line 203 "ftinf_rh.gperf" -+{ .name="open sans", -+ .stem_translating_only={on, 10, 16, 9, 16, end}, -+ .stem_widths={on, 10, 20, maxp,} -+}, -+#line 167 "ftinf_rh.gperf" -+{ .name="liberation sans", -+ .edge_detection={on, 11, 11, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end}, -+ .stem_widths={on,10, 19, maxp,} -+}, -+#line 193 "ftinf_rh.gperf" -+{ .name="monaco", -+ .always_use_100={on, 0, maxp, end} -+}, -+#line 101 "ftinf_rh.gperf" -+{ .name="cousine", -+ .always_use_100={on, 0, maxp, end} -+}, -+#line 176 "ftinf_rh.gperf" -+{ .name="lucida grande", -+ .stem_scaling={on, 13, 1, end}, -+ .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end}, -+ .stem_widths={on, 10, 16, sw2pv, maxp}, -+}, -+#line 173 "ftinf_rh.gperf" -+{ .name="lucida console", -+ .always_use_100={on, 0, maxp, end} -+}, -+#line 196 "ftinf_rh.gperf" -+{ .name="myriad pro", -+ .stem_scaling={on, 14, 1, 17, 1, end}, -+ .stem_translating_only={on, 10, 16, 11, 0, 9, 16, end} -+}, -+#line 26 "ftinf_rh.gperf" -+{ .name="arial unicode ms", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end} -+}, -+#line 213 "ftinf_rh.gperf" -+{ .name="palatino linotype", -+ .edge_detection={on, 0, 100, end} -+}, -+#line 181 "ftinf_rh.gperf" -+{ .name="lucida sans unicode", -+ .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end}, -+ .stem_widths={on,10, 16, sw2pv, maxp,} -+}, -+#line 140 "ftinf_rh.gperf" -+{ .name="futura", -+ .stem_widths={on, 10, 14, sw2pv, maxp,} -+}, -+#line 147 "ftinf_rh.gperf" -+{ .name="georgia", -+ .stem_translating_only={on, 13, 16, 14, 16, 15, 0, end} -+}, -+#line 125 "ftinf_rh.gperf" -+{ .name="freemono", -+ .always_use_100={on, 0, maxp, end} -+}, -+#line 200 "ftinf_rh.gperf" -+{ .name="nina", -+ .stem_scaling={on, 11, 0, 12, 0, 13, 0, end} -+}, -+#line 121 "ftinf_rh.gperf" -+{ .name="essential pragmatapro", -+ .always_use_100={on, 0, maxp, end}, -+ .m={on, 13, 0, 14, 0, end} -+}, -+#line 247 "ftinf_rh.gperf" -+{ .name="trebuchet ms", -+ .always_use_100={on, 13, 13, end}, -+ .stem_scaling={on, 13, 0, 17, 0, 20, 1, end}, -+ .stem_translating_only={on, 10, 16, 11, 0, 8, 32, 9, 32, end}, -+ .stem_widths={on, 10, 17, sw2pv, maxp,} -+}, -+#line 114 "ftinf_rh.gperf" -+{ .name="droid sans mono", -+ .m={on, 12, 0, end} -+}, -+#line 104 "ftinf_rh.gperf" -+{ .name="dejavu sans mono", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating_only={on, 7, 16, 8, 32, 9, 16, end} -+}, -+#line 57 "ftinf_rh.gperf" -+{ .name="calibri", -+ .always_use_100={on, 23, maxp, end}, -+ .stem_scaling={on, 15, 1, 17, 1, 18, 1, end}, -+ .stem_translating_only={on, 10, 16, 15, 0, end}, -+ .stem_widths={on, 1, 10, 19, maxp,} -+}, -+#line 156 "ftinf_rh.gperf" -+{ .name="inconsolata", -+ .stem_scaling={on, 12, 1, 15, 1, end}, -+ .stem_translating_only={on, 10, 24, 9, 32, end}, -+ .stem_widths={on, 10, 23, maxp,}, -+}, -+#line 96 "ftinf_rh.gperf" -+{ .name="courier", -+ .always_use_100={on, 0, maxp, end}, -+ .m={on, 13, 1, 14, 1, end}, -+ .stem_translating_only={on, 13, 16, 15, 0, end} -+}, -+#line 128 "ftinf_rh.gperf" -+{ .name="freesans", -+ .always_use_100={on, 0, maxp, end}, -+ .edge_detection={on, 11, 11, 13, 13, end}, -+ .spacing={on, 10, 12, 18, 18, 30, end}, -+ .start={on, 10, 18, 18, 25, 30, end}, -+ .stem_scaling={on, 16, 0, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 16, 9, 8, end} -+}, -+#line 150 "ftinf_rh.gperf" -+{ .name="gill sans", -+ .stem_widths={on, 10, 17, sw2pv, maxp,} -+}, -+#line 117 "ftinf_rh.gperf" -+{ .name="droid sans", -+ .always_use_100={on, 12, 12, 15, 15, end}, -+ .stem_translating_only={on, 8, 16, 9, 16, end} -+}, -+#line 108 "ftinf_rh.gperf" -+{ .name="dejavu sans", -+ .always_use_100={on, 10, 14, 16, 17, end}, -+ .m={on, 12, 0, end}, -+ .stem_scaling={on, 12, 1, end}, -+ .stem_translating_only={on, 8, 16, 15, -20, end} -+}, -+#line 219 "ftinf_rh.gperf" -+{ .name="raleway", -+ .stem_scaling={on, 15, 0, end} -+}, -+#line 153 "ftinf_rh.gperf" -+{ .name="helvetica cy", -+ .stem_widths={on, 10, 23, maxp,} -+}, -+#line 228 "ftinf_rh.gperf" -+{ .name="segoe ui", -+ .always_use_100={on, 11, 12, 14, 14, end}, -+ .stem_translating_only={on, 10, 0, 7, 32, 8, 16, 9, 24, end}, -+ .stem_widths={on, 10, 23, maxp,} -+}, -+#line 48 "ftinf_rh.gperf" -+{ .name="bitstream vera sans mono", -+ .always_use_100={on, 0, maxp, end} -+}, -+#line 241 "ftinf_rh.gperf" -+{ .name="times new roman", -+ .always_use_100={on, 14, 14, 16, 16, end}, -+ .bearing_correction={0, 100, end}, -+ .stem_scaling={on, 17, 1, end}, -+ .stem_translating_only={on, 17, 8, end} -+}, -+#line 222 "ftinf_rh.gperf" -+{ .name="rokkitt", -+ .stem_widths={on, 10, 21, maxp,} -+}, -+#line 143 "ftinf_rh.gperf" -+{ .name="garamond", -+ .brightness={on, 0, -20, end}, -+ .contrast={on, 0, 25, end} -+}, -+#line 137 "ftinf_rh.gperf" -+{ .name="freeserif", -+ .stem_scaling={on, 13, 1, 17, 1, end} -+}, -+#line 189 "ftinf_rh.gperf" -+{ .name="microsoft sans serif", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end} -+}, -+#line 44 "ftinf_rh.gperf" -+{ .name="baskerville", -+ .brightness={on, 0, -20, end}, -+ .contrast={on, 0, 25, end} -+}, -+#line 51 "ftinf_rh.gperf" -+{ .name="bitstream vera sans", -+ .always_use_100={on, 10, 14, 16, 17, end}, -+ .m={on, 12, 0, end}, -+ .stem_scaling={on ,12, 1, end}, -+ .stem_translating_only={on, 8, 16, end} -+} -+ }; -+ -+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) -+ { -+ register int key = _rules_hash (str, len); -+ -+ if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE) -+ { -+ register const struct sa_rules_s *resword; -+ -+ switch (key - 3) -+ { -+ case 0: -+ resword = &wordlist[0]; -+ goto compare; -+ case 3: -+ resword = &wordlist[1]; -+ goto compare; -+ case 7: -+ resword = &wordlist[2]; -+ goto compare; -+ case 8: -+ resword = &wordlist[3]; -+ goto compare; -+ case 9: -+ resword = &wordlist[4]; -+ goto compare; -+ case 10: -+ resword = &wordlist[5]; -+ goto compare; -+ case 11: -+ resword = &wordlist[6]; -+ goto compare; -+ case 12: -+ resword = &wordlist[7]; -+ goto compare; -+ case 13: -+ resword = &wordlist[8]; -+ goto compare; -+ case 14: -+ resword = &wordlist[9]; -+ goto compare; -+ case 16: -+ resword = &wordlist[10]; -+ goto compare; -+ case 17: -+ resword = &wordlist[11]; -+ goto compare; -+ case 18: -+ resword = &wordlist[12]; -+ goto compare; -+ case 19: -+ resword = &wordlist[13]; -+ goto compare; -+ case 21: -+ resword = &wordlist[14]; -+ goto compare; -+ case 23: -+ resword = &wordlist[15]; -+ goto compare; -+ case 24: -+ resword = &wordlist[16]; -+ goto compare; -+ case 26: -+ resword = &wordlist[17]; -+ goto compare; -+ case 27: -+ resword = &wordlist[18]; -+ goto compare; -+ case 28: -+ resword = &wordlist[19]; -+ goto compare; -+ case 29: -+ resword = &wordlist[20]; -+ goto compare; -+ case 30: -+ resword = &wordlist[21]; -+ goto compare; -+ case 31: -+ resword = &wordlist[22]; -+ goto compare; -+ case 32: -+ resword = &wordlist[23]; -+ goto compare; -+ case 33: -+ resword = &wordlist[24]; -+ goto compare; -+ case 34: -+ resword = &wordlist[25]; -+ goto compare; -+ case 35: -+ resword = &wordlist[26]; -+ goto compare; -+ case 36: -+ resword = &wordlist[27]; -+ goto compare; -+ case 37: -+ resword = &wordlist[28]; -+ goto compare; -+ case 38: -+ resword = &wordlist[29]; -+ goto compare; -+ case 39: -+ resword = &wordlist[30]; -+ goto compare; -+ case 41: -+ resword = &wordlist[31]; -+ goto compare; -+ case 43: -+ resword = &wordlist[32]; -+ goto compare; -+ case 44: -+ resword = &wordlist[33]; -+ goto compare; -+ case 45: -+ resword = &wordlist[34]; -+ goto compare; -+ case 46: -+ resword = &wordlist[35]; -+ goto compare; -+ case 48: -+ resword = &wordlist[36]; -+ goto compare; -+ case 49: -+ resword = &wordlist[37]; -+ goto compare; -+ case 52: -+ resword = &wordlist[38]; -+ goto compare; -+ case 53: -+ resword = &wordlist[39]; -+ goto compare; -+ case 54: -+ resword = &wordlist[40]; -+ goto compare; -+ case 58: -+ resword = &wordlist[41]; -+ goto compare; -+ case 59: -+ resword = &wordlist[42]; -+ goto compare; -+ case 60: -+ resword = &wordlist[43]; -+ goto compare; -+ case 61: -+ resword = &wordlist[44]; -+ goto compare; -+ case 62: -+ resword = &wordlist[45]; -+ goto compare; -+ case 63: -+ resword = &wordlist[46]; -+ goto compare; -+ case 64: -+ resword = &wordlist[47]; -+ goto compare; -+ case 69: -+ resword = &wordlist[48]; -+ goto compare; -+ case 70: -+ resword = &wordlist[49]; -+ goto compare; -+ case 71: -+ resword = &wordlist[50]; -+ goto compare; -+ case 72: -+ resword = &wordlist[51]; -+ goto compare; -+ case 74: -+ resword = &wordlist[52]; -+ goto compare; -+ case 75: -+ resword = &wordlist[53]; -+ goto compare; -+ case 76: -+ resword = &wordlist[54]; -+ goto compare; -+ case 77: -+ resword = &wordlist[55]; -+ goto compare; -+ case 78: -+ resword = &wordlist[56]; -+ goto compare; -+ case 81: -+ resword = &wordlist[57]; -+ goto compare; -+ } -+ return 0; -+ compare: -+ { -+ register const char *s = resword->name; -+ -+ if (*str == *s && !strcmp (str + 1, s + 1)) -+ return resword; -+ } -+ } -+ } -+ return 0; -+} -+#line 261 "ftinf_rh.gperf" -+ -+ -+static const sa_rules_t* -+ftinf_rules( const char *name ){ -+ if( name ){ -+ enum { -+ max_wlen=31 -+ }; -+ char buf[max_wlen+1]; -+ int len=strlen( name ); -+ if( len <= max_wlen ){ -+ int i; -+ for( i=0; i<len; ++i ) -+ buf[i]=tolower( name[i] ); -+ buf[len]='\0'; -+ return _rules_get( buf, len ); -+ } -+ } -+ return NULL; -+} -+/* -+ gperf --output-file=ftinf_rh.c ftinf_rh.gperf -+*/ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_rh.gperf a/src/base/ftinf_rh.gperf ---- b/src/base/ftinf_rh.gperf 1970-01-01 03:00:00.000000000 +0300 -+++ a/src/base/ftinf_rh.gperf 2021-09-16 09:15:05.052379743 +0300 -@@ -0,0 +1,283 @@ -+%struct-type -+%define slot-name name -+%enum -+%switch=1 -+%readonly-tables -+%omit-struct-type -+%define lookup-function-name _rules_get -+%define hash-function-name _rules_hash -+%{ -+#include <ctype.h> -+static const struct sa_rules_s* _rules_get( const char*str, unsigned len ); -+%} -+struct sa_rules_s; -+%% -+{ .name="---", -+ .synthesize_stems={on, 13, 13, end} -+}, -+{ .name="andale mono", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_scaling={on, 11, 1, end}, -+ .stem_widths={on, 10, 21, maxp,} -+}, -+{ .name="arial narrow", -+ .stem_widths={on, 10, 21, maxp,} -+}, -+{ .name="arial unicode ms", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end} -+}, -+{ .name="arial", -+ .always_use_100={on, 0, maxp, end}, -+ .edge_detection={on, 11, 11, 13, 13, end}, -+ .spacing={on, 10, 11, 23, 25, 30, end}, -+ .start={on, 11, 18, 23, 30, 30, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 16, 8, 32, 9, 32, 16, -24, end} -+}, -+{ .name="arimo", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end} -+}, -+{ .name="baskerville", -+ .brightness={on, 0, -20, end}, -+ .contrast={on, 0, 25, end} -+}, -+{ .name="bitstream vera sans mono", -+ .always_use_100={on, 0, maxp, end} -+}, -+{ .name="bitstream vera sans", -+ .always_use_100={on, 10, 14, 16, 17, end}, -+ .m={on, 12, 0, end}, -+ .stem_scaling={on ,12, 1, end}, -+ .stem_translating_only={on, 8, 16, end} -+}, -+{ .name="calibri", -+ .always_use_100={on, 23, maxp, end}, -+ .stem_scaling={on, 15, 1, 17, 1, 18, 1, end}, -+ .stem_translating_only={on, 10, 16, 15, 0, end}, -+ .stem_widths={on, 1, 10, 19, maxp,} -+}, -+{ .name="candara", -+ .stem_scaling={on, 14, 1, 17, 1, end}, -+ .stem_translating_only={on, 10, 16, end} -+}, -+{ .name="cantarell", -+ .stem_translating_only={on, 11, 0, 12, 0, end}, -+ .stem_widths={on, 10, 22, maxp,} -+}, -+{ .name="canwell", -+ .stem_scaling={on, 13, 0, end} -+}, -+{ .name="century gothic", -+ .stem_widths={on, 10, 22, maxp,} -+}, -+{ .name="comfortaa", -+ .stem_widths={on, 10, 19, 22, maxp}, -+ .stem_scaling={on, 11, 0, end} -+}, -+{ .name="consolas", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating_only={on, 8, 32, 9, 32, end}, -+ .stem_widths={on, 10, 20, maxp,}, -+ .stem_scaling={on, 11, 1, end} -+}, -+{ .name="corbel", -+ .stem_translating_only={on, 10, 16, end}, -+ .stem_widths={on, 10, 21, maxp} -+}, -+{ .name="courier new", -+ .always_use_100={on, 12, 12, end}, -+ .edge_detection={on, 10, 12, end}, -+ .m={on, 13, 1, 14, 1, end} -+}, -+{ .name="courier", -+ .always_use_100={on, 0, maxp, end}, -+ .m={on, 13, 1, 14, 1, end}, -+ .stem_translating_only={on, 13, 16, 15, 0, end} -+}, -+{ .name="cousine", -+ .always_use_100={on, 0, maxp, end} -+}, -+{ .name="dejavu sans mono", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating_only={on, 7, 16, 8, 32, 9, 16, end} -+}, -+{ .name="dejavu sans", -+ .always_use_100={on, 10, 14, 16, 17, end}, -+ .m={on, 12, 0, end}, -+ .stem_scaling={on, 12, 1, end}, -+ .stem_translating_only={on, 8, 16, 15, -20, end} -+}, -+{ .name="droid sans mono", -+ .m={on, 12, 0, end} -+}, -+{ .name="droid sans", -+ .always_use_100={on, 12, 12, 15, 15, end}, -+ .stem_translating_only={on, 8, 16, 9, 16, end} -+}, -+{ .name="essential pragmatapro", -+ .always_use_100={on, 0, maxp, end}, -+ .m={on, 13, 0, 14, 0, end} -+}, -+{ .name="freemono", -+ .always_use_100={on, 0, maxp, end} -+}, -+{ .name="freesans", -+ .always_use_100={on, 0, maxp, end}, -+ .edge_detection={on, 11, 11, 13, 13, end}, -+ .spacing={on, 10, 12, 18, 18, 30, end}, -+ .start={on, 10, 18, 18, 25, 30, end}, -+ .stem_scaling={on, 16, 0, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 16, 9, 8, end} -+}, -+{ .name="freeserif", -+ .stem_scaling={on, 13, 1, 17, 1, end} -+}, -+{ .name="futura", -+ .stem_widths={on, 10, 14, sw2pv, maxp,} -+}, -+{ .name="garamond", -+ .brightness={on, 0, -20, end}, -+ .contrast={on, 0, 25, end} -+}, -+{ .name="georgia", -+ .stem_translating_only={on, 13, 16, 14, 16, 15, 0, end} -+}, -+{ .name="gill sans", -+ .stem_widths={on, 10, 17, sw2pv, maxp,} -+}, -+{ .name="helvetica cy", -+ .stem_widths={on, 10, 23, maxp,} -+}, -+{ .name="inconsolata", -+ .stem_scaling={on, 12, 1, 15, 1, end}, -+ .stem_translating_only={on, 10, 24, 9, 32, end}, -+ .stem_widths={on, 10, 23, maxp,}, -+}, -+{ .name="liberation mono", -+ .always_use_100={on, 0, maxp, end} -+}, -+{ .name="liberation sans narrow", -+ .stem_widths={on,10, 22, maxp,} -+}, -+{ .name="liberation sans", -+ .edge_detection={on, 11, 11, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end}, -+ .stem_widths={on,10, 19, maxp,} -+}, -+{ .name="lucida console", -+ .always_use_100={on, 0, maxp, end} -+}, -+{ .name="lucida grande", -+ .stem_scaling={on, 13, 1, end}, -+ .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end}, -+ .stem_widths={on, 10, 16, sw2pv, maxp}, -+}, -+{ .name="lucida sans unicode", -+ .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end}, -+ .stem_widths={on,10, 16, sw2pv, maxp,} -+}, -+{ .name="luxi sans", -+ .always_use_100={on, 13, 13, end}, -+ .stem_widths={on, 10, 17, sw2pv, maxp,} -+}, -+{ .name="microsoft sans serif", -+ .always_use_100={on, 0, maxp, end}, -+ .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end} -+}, -+{ .name="monaco", -+ .always_use_100={on, 0, maxp, end} -+}, -+{ .name="myriad pro", -+ .stem_scaling={on, 14, 1, 17, 1, end}, -+ .stem_translating_only={on, 10, 16, 11, 0, 9, 16, end} -+}, -+{ .name="nina", -+ .stem_scaling={on, 11, 0, 12, 0, 13, 0, end} -+}, -+{ .name="open sans", -+ .stem_translating_only={on, 10, 16, 9, 16, end}, -+ .stem_widths={on, 10, 20, maxp,} -+}, -+{ .name="optima", -+ .brightness={on, 0, -20, end}, -+ .contrast={on, 0, 25, end}, -+ .stem_scaling={on, 17, 1, end}, -+ .stem_translating_only={on, 10, 0, 11, 0, 12, 0, end} -+}, -+{ .name="palatino linotype", -+ .edge_detection={on, 0, 100, end} -+}, -+{ .name="pragmata", -+ .always_use_100={on, 0, maxp, end} -+}, -+{ .name="raleway", -+ .stem_scaling={on, 15, 0, end} -+}, -+{ .name="rokkitt", -+ .stem_widths={on, 10, 21, maxp,} -+}, -+{ .name="samba", -+ .stem_scaling={on, 11, 0, end} -+}, -+{ .name="segoe ui", -+ .always_use_100={on, 11, 12, 14, 14, end}, -+ .stem_translating_only={on, 10, 0, 7, 32, 8, 16, 9, 24, end}, -+ .stem_widths={on, 10, 23, maxp,} -+}, -+{ .name="tahoma", -+ .always_use_100={on, 11, 11, 14, maxp, end}, -+ .edge_detection={on, 11, 11, end}, -+ .spacing={on, 10, 12, 18, 18, 30, end}, -+ .start={on, 14, 17, 30, 100, 100, end}, -+ .stem_translating={on, 11, 32, end}, -+ .stem_translating_only={on, 7, 32, 8, 32, 9, 32, end}, -+}, -+{ .name="times new roman", -+ .always_use_100={on, 14, 14, 16, 16, end}, -+ .bearing_correction={0, 100, end}, -+ .stem_scaling={on, 17, 1, end}, -+ .stem_translating_only={on, 17, 8, end} -+}, -+{ .name="trebuchet ms", -+ .always_use_100={on, 13, 13, end}, -+ .stem_scaling={on, 13, 0, 17, 0, 20, 1, end}, -+ .stem_translating_only={on, 10, 16, 11, 0, 8, 32, 9, 32, end}, -+ .stem_widths={on, 10, 17, sw2pv, maxp,} -+}, -+{ .name="ubuntu", -+ .always_use_100={on, 12, 13, 15, 15, end} -+}, -+{ .name="verdana", -+ .always_use_100={on, 0, 14, 16, maxp, end}, -+ .stem_scaling={on, 12, 1, 15, 1, end}, -+ .stem_translating_only={on, 8, 16, 15, 16, 14, 32, 18, 32, 19, 24, end} -+}, -+%% -+ -+static const sa_rules_t* -+ftinf_rules( const char *name ){ -+ if( name ){ -+ enum { -+ max_wlen=31 -+ }; -+ char buf[max_wlen+1]; -+ int len=strlen( name ); -+ if( len <= max_wlen ){ -+ int i; -+ for( i=0; i<len; ++i ) -+ buf[i]=tolower( name[i] ); -+ buf[len]='\0'; -+ return _rules_get( buf, len ); -+ } -+ } -+ return NULL; -+} -+/* -+ gperf --output-file=ftinf_rh.c ftinf_rh.gperf -+*/ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_sh.c a/src/base/ftinf_sh.c ---- b/src/base/ftinf_sh.c 1970-01-01 03:00:00.000000000 +0300 -+++ a/src/base/ftinf_sh.c 2021-09-16 09:15:05.052379743 +0300 -@@ -0,0 +1,463 @@ -+/* ANSI-C code produced by gperf version 3.1 */ -+/* Command-line: gperf --output-file=ftinf_sh.c ftinf_sh.gperf */ -+/* Computed positions: -k'1,$' */ -+ -+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ -+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ -+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ -+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ -+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ -+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ -+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ -+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ -+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ -+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ -+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ -+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ -+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ -+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ -+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ -+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ -+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ -+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ -+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ -+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ -+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ -+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ -+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) -+/* The character set is not based on ISO-646. */ -+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." -+#endif -+ -+#line 9 "ftinf_sh.gperf" -+ -+#include <ctype.h> -+static const struct ftinf_s* _settings_get( const char*str, unsigned len); -+/* maximum key range = 37, duplicates = 0 */ -+ -+#ifdef __GNUC__ -+__inline -+#else -+#ifdef __cplusplus -+inline -+#endif -+#endif -+static unsigned int -+_settings_hash (register const char *str, register unsigned int len) -+{ -+ static const unsigned char asso_values[] = -+ { -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 13, -+ 8, 30, 25, 20, 40, 10, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 5, 40, 0, -+ 0, 0, 40, 40, 10, 0, 40, 40, 15, 5, -+ 10, 0, 10, 40, 40, 0, 0, 0, 0, 0, -+ 0, 0, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, -+ 40, 40, 40, 40, 40, 40 -+ }; -+ return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; -+} -+ -+#ifdef __GNUC__ -+__inline -+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ -+__attribute__ ((__gnu_inline__)) -+#endif -+#endif -+const struct ftinf_s * -+_settings_get (register const char *str, register unsigned int len) -+{ -+ enum -+ { -+ TOTAL_KEYWORDS = 22, -+ MIN_WORD_LENGTH = 3, -+ MAX_WORD_LENGTH = 14, -+ MIN_HASH_VALUE = 3, -+ MAX_HASH_VALUE = 39 -+ }; -+ -+ static const struct ftinf_s wordlist[] = -+ { -+#line 76 "ftinf_sh.gperf" -+{ .name="osx", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_vertical_stem_darken_strength=25, -+ .bold_embolden_x_value=16, -+ .brightness=10, -+ .contrast=20, -+ .filter_params={on, 3, 32, 38, 32, 3}, -+ .gamma_correction={1000, 80}, -+ .global_embolden_y_value=8, -+ .grayscale_filter_strength=25, -+}, -+#line 37 "ftinf_sh.gperf" -+{ .name="ipad", -+ .filter_params={on, 0, 0, 100, 0, 0}, -+ .gamma_correction={1000, 80}, -+ .grayscale_filter_strength=100 -+}, -+#line 114 "ftinf_sh.gperf" -+{ .name="shove", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=100, -+ .stem_fitting_strength=100, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true -+}, -+#line 126 "ftinf_sh.gperf" -+{ .name="ubuntu", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_vertical_stem_darken_strength=25, -+ .brightness=-10, -+ .contrast=15, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={1000, 80}, -+ .use_various_tweaks=true -+}, -+#line 27 "ftinf_sh.gperf" -+{ .name="classic", -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .filter_params={on, 6, 25, 38, 25, 6}, -+ .gamma_correction={0, 100}, -+ .use_various_tweaks=true -+}, -+#line 34 "ftinf_sh.gperf" -+{ .name="disabled", -+ .gamma_correction={0, 100}, -+}, -+#line 100 "ftinf_sh.gperf" -+{ .name="sharpened", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=25, -+ .stem_fitting_strength=25, -+ .stem_snapping_sliding_scale=40, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=65 -+}, -+#line 42 "ftinf_sh.gperf" -+{ .name="infinality", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=25, -+ .stem_fitting_strength=25, -+ .stem_snapping_sliding_scale=40, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=5 -+}, -+#line 15 "ftinf_sh.gperf" -+{ .name="custom", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 8, 24, 48, 24, 8}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=75, -+ .stem_fitting_strength=50, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true -+}, -+#line 180 "ftinf_sh.gperf" -+{ .name="vanilla", -+ .filter_params={on, 6, 25, 38, 25, 6}, -+ .gamma_correction={0, 100}, -+}, -+#line 184 "ftinf_sh.gperf" -+{ .name="windows7light", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .contrast=20, -+ .filter_params={on, 20, 25, 38, 25, 05}, -+ .fringe_filter_strength=100, -+ .gamma_correction={1000, 160}, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=100 -+}, -+#line 226 "ftinf_sh.gperf" -+{ .name="windowsxplight", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .brightness=20, -+ .contrast=30, -+ .filter_params={on, 6, 25, 44, 25, 6}, -+ .fringe_filter_strength=100, -+ .gamma_correction={1000, 120}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=65 -+}, -+#line 64 "ftinf_sh.gperf" -+{ .name="nudge", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=25, -+ .stem_fitting_strength=15, -+ .stem_snapping_sliding_scale=30, -+ .use_various_tweaks=true, -+}, -+#line 144 "ftinf_sh.gperf" -+{ .name="ultimate2", -+ .filter_params={on, 6, 22, 36, 22, 6}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+#line 197 "ftinf_sh.gperf" -+{ .name="windows7", -+ .filter_params={on, 20, 25, 42, 25, 06}, -+ .fringe_filter_strength=100, -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_vertical_stem_darken_strength=25, -+ .windows_style_sharpening_strength=65, -+ .gamma_correction={1000, 120}, -+ .brightness=10, -+ .contrast=20, -+ .use_various_tweaks=true, -+ .autohint_snap_stem_height=100, -+ .use_known_settings_on_selected_fonts=true, -+}, -+#line 210 "ftinf_sh.gperf" -+{ .name="windowsxp", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .brightness=10, -+ .contrast=20, -+ .filter_params={on, 6, 25, 44, 25, 6}, -+ .fringe_filter_strength=100, -+ .gamma_correction={1000, 120}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=65 -+}, -+#line 56 "ftinf_sh.gperf" -+{ .name="linux", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 6, 25, 44, 25, 6}, -+ .gamma_correction={0, 100}, -+ .use_various_tweaks=true -+}, -+#line 135 "ftinf_sh.gperf" -+{ .name="ultimate1", -+ .filter_params={on, 4, 22, 38, 22, 4}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+#line 87 "ftinf_sh.gperf" -+{ .name="push", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=75, -+ .stem_fitting_strength=50, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true -+}, -+#line 171 "ftinf_sh.gperf" -+{ .name="ultimate5", -+ .filter_params={on, 12, 28, 42, 28, 12}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+#line 162 "ftinf_sh.gperf" -+{ .name="ultimate4", -+ .filter_params={on, 10, 25, 37, 25, 10}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+#line 153 "ftinf_sh.gperf" -+{ .name="ultimate3", -+ .filter_params={on, 8, 24, 36, 24, 8}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+} -+ }; -+ -+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) -+ { -+ register int key = _settings_hash (str, len); -+ -+ if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE) -+ { -+ register const struct ftinf_s *resword; -+ -+ switch (key - 3) -+ { -+ case 0: -+ resword = &wordlist[0]; -+ goto compare; -+ case 1: -+ resword = &wordlist[1]; -+ goto compare; -+ case 2: -+ resword = &wordlist[2]; -+ goto compare; -+ case 3: -+ resword = &wordlist[3]; -+ goto compare; -+ case 4: -+ resword = &wordlist[4]; -+ goto compare; -+ case 5: -+ resword = &wordlist[5]; -+ goto compare; -+ case 6: -+ resword = &wordlist[6]; -+ goto compare; -+ case 7: -+ resword = &wordlist[7]; -+ goto compare; -+ case 8: -+ resword = &wordlist[8]; -+ goto compare; -+ case 9: -+ resword = &wordlist[9]; -+ goto compare; -+ case 10: -+ resword = &wordlist[10]; -+ goto compare; -+ case 11: -+ resword = &wordlist[11]; -+ goto compare; -+ case 12: -+ resword = &wordlist[12]; -+ goto compare; -+ case 14: -+ resword = &wordlist[13]; -+ goto compare; -+ case 15: -+ resword = &wordlist[14]; -+ goto compare; -+ case 16: -+ resword = &wordlist[15]; -+ goto compare; -+ case 17: -+ resword = &wordlist[16]; -+ goto compare; -+ case 19: -+ resword = &wordlist[17]; -+ goto compare; -+ case 21: -+ resword = &wordlist[18]; -+ goto compare; -+ case 26: -+ resword = &wordlist[19]; -+ goto compare; -+ case 31: -+ resword = &wordlist[20]; -+ goto compare; -+ case 36: -+ resword = &wordlist[21]; -+ goto compare; -+ } -+ return 0; -+ compare: -+ { -+ register const char *s = resword->name; -+ -+ if (*str == *s && !strcmp (str + 1, s + 1)) -+ return resword; -+ } -+ } -+ } -+ return 0; -+} -+#line 242 "ftinf_sh.gperf" -+ -+ -+static const ftinf_t* -+ftinf_settings( const char *name ){ -+ if( name ){ -+ enum { -+ max_wlen=31 -+ }; -+ char buf[max_wlen+1]; -+ int len=strlen( name ); -+ if( len <= max_wlen ){ -+ int i; -+ for( i=0; i<len; ++i ) -+ buf[i]=tolower( name[i] ); -+ buf[len]='\0'; -+ return _settings_get( buf, len ); -+ } -+ } -+ return NULL; -+} -+/* -+ gperf --output-file=ftinf_sh.c ftinf_sh.gperf -+*/ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_sh.gperf a/src/base/ftinf_sh.gperf ---- b/src/base/ftinf_sh.gperf 1970-01-01 03:00:00.000000000 +0300 -+++ a/src/base/ftinf_sh.gperf 2021-09-16 09:15:05.052379743 +0300 -@@ -0,0 +1,264 @@ -+%struct-type -+%define slot-name name -+%enum -+%switch=1 -+%readonly-tables -+%omit-struct-type -+%define lookup-function-name _settings_get -+%define hash-function-name _settings_hash -+%{ -+#include <ctype.h> -+static const struct ftinf_s* _settings_get( const char*str, unsigned len); -+%} -+struct ftinf_s; -+%% -+{ .name="custom", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 8, 24, 48, 24, 8}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=75, -+ .stem_fitting_strength=50, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true -+}, -+{ .name="classic", -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .filter_params={on, 6, 25, 38, 25, 6}, -+ .gamma_correction={0, 100}, -+ .use_various_tweaks=true -+}, -+{ .name="disabled", -+ .gamma_correction={0, 100}, -+}, -+{ .name="ipad", -+ .filter_params={on, 0, 0, 100, 0, 0}, -+ .gamma_correction={1000, 80}, -+ .grayscale_filter_strength=100 -+}, -+{ .name="infinality", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=25, -+ .stem_fitting_strength=25, -+ .stem_snapping_sliding_scale=40, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=5 -+}, -+{ .name="linux", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 6, 25, 44, 25, 6}, -+ .gamma_correction={0, 100}, -+ .use_various_tweaks=true -+}, -+{ .name="nudge", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=25, -+ .stem_fitting_strength=15, -+ .stem_snapping_sliding_scale=30, -+ .use_various_tweaks=true, -+}, -+{ .name="osx", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_vertical_stem_darken_strength=25, -+ .bold_embolden_x_value=16, -+ .brightness=10, -+ .contrast=20, -+ .filter_params={on, 3, 32, 38, 32, 3}, -+ .gamma_correction={1000, 80}, -+ .global_embolden_y_value=8, -+ .grayscale_filter_strength=25, -+}, -+{ .name="push", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=75, -+ .stem_fitting_strength=50, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true -+}, -+{ .name="sharpened", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=25, -+ .stem_fitting_strength=25, -+ .stem_snapping_sliding_scale=40, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=65 -+}, -+{ .name="shove", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_increase_glyph_heights=true, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=100, -+ .stem_fitting_strength=100, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true -+}, -+{ .name="ubuntu", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_vertical_stem_darken_strength=25, -+ .brightness=-10, -+ .contrast=15, -+ .filter_params={on, 11, 22, 38, 22, 11}, -+ .gamma_correction={1000, 80}, -+ .use_various_tweaks=true -+}, -+{ .name="ultimate1", -+ .filter_params={on, 4, 22, 38, 22, 4}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+{ .name="ultimate2", -+ .filter_params={on, 6, 22, 36, 22, 6}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+{ .name="ultimate3", -+ .filter_params={on, 8, 24, 36, 24, 8}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+{ .name="ultimate4", -+ .filter_params={on, 10, 25, 37, 25, 10}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+{ .name="ultimate5", -+ .filter_params={on, 12, 28, 42, 28, 12}, -+ .fringe_filter_strength=25, -+ .gamma_correction={0, 100}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=25 -+}, -+{ .name="vanilla", -+ .filter_params={on, 6, 25, 38, 25, 6}, -+ .gamma_correction={0, 100}, -+}, -+{ .name="windows7light", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .contrast=20, -+ .filter_params={on, 20, 25, 38, 25, 05}, -+ .fringe_filter_strength=100, -+ .gamma_correction={1000, 160}, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=100 -+}, -+{ .name="windows7", -+ .filter_params={on, 20, 25, 42, 25, 06}, -+ .fringe_filter_strength=100, -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_vertical_stem_darken_strength=25, -+ .windows_style_sharpening_strength=65, -+ .gamma_correction={1000, 120}, -+ .brightness=10, -+ .contrast=20, -+ .use_various_tweaks=true, -+ .autohint_snap_stem_height=100, -+ .use_known_settings_on_selected_fonts=true, -+}, -+{ .name="windowsxp", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .brightness=10, -+ .contrast=20, -+ .filter_params={on, 6, 25, 44, 25, 6}, -+ .fringe_filter_strength=100, -+ .gamma_correction={1000, 120}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=65 -+}, -+{ .name="windowsxplight", -+ .autohint_horizontal_stem_darken_strength=10, -+ .autohint_snap_stem_height=100, -+ .autohint_vertical_stem_darken_strength=25, -+ .brightness=20, -+ .contrast=30, -+ .filter_params={on, 6, 25, 44, 25, 6}, -+ .fringe_filter_strength=100, -+ .gamma_correction={1000, 120}, -+ .stem_alignment_strength=15, -+ .stem_fitting_strength=15, -+ .stem_snapping_sliding_scale=30, -+ .use_known_settings_on_selected_fonts=true, -+ .use_various_tweaks=true, -+ .windows_style_sharpening_strength=65 -+}, -+%% -+ -+static const ftinf_t* -+ftinf_settings( const char *name ){ -+ if( name ){ -+ enum { -+ max_wlen=31 -+ }; -+ char buf[max_wlen+1]; -+ int len=strlen( name ); -+ if( len <= max_wlen ){ -+ int i; -+ for( i=0; i<len; ++i ) -+ buf[i]=tolower( name[i] ); -+ buf[len]='\0'; -+ return _settings_get( buf, len ); -+ } -+ } -+ return NULL; -+} -+/* -+ gperf --output-file=ftinf_sh.c ftinf_sh.gperf -+*/ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinit.c a/src/base/ftinit.c ---- b/src/base/ftinit.c 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/base/ftinit.c 2021-09-16 09:15:05.052379743 +0300 -@@ -43,6 +43,10 @@ - #include <freetype/internal/ftdebug.h> - #include <freetype/ftmodapi.h> - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "ftinf.h" -+#endif -+ - - /************************************************************************** - * -@@ -224,10 +228,14 @@ - error = FT_New_Library( memory, alibrary ); - if ( error ) - FT_Done_Memory( memory ); -- else -+ else { - FT_Add_Default_Modules( *alibrary ); -- - FT_Set_Default_Properties( *alibrary ); -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ /* get Infinality settings */ -+ ftinf_env(); -+#endif -+ } - - return error; - } -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftlcdfil.c a/src/base/ftlcdfil.c ---- b/src/base/ftlcdfil.c 2021-07-05 06:41:53.000000000 +0300 -+++ a/src/base/ftlcdfil.c 2021-09-16 09:15:05.052379743 +0300 -@@ -17,11 +17,15 @@ - - - #include <freetype/internal/ftdebug.h> -- - #include <freetype/ftlcdfil.h> - #include <freetype/ftimage.h> - #include <freetype/internal/ftobjs.h> - -+#include <math.h> -+#include <string.h> -+#include <strings.h> -+#include "ftinf.h" -+ - - #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - -@@ -76,13 +80,13 @@ - /* FIR filter used by the default and light filters */ - FT_BASE_DEF( void ) - ft_lcd_filter_fir( FT_Bitmap* bitmap, -+ FT_Render_Mode mode, - FT_LcdFiveTapFilter weights ) - { - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - FT_Int pitch = bitmap->pitch; - FT_Byte* origin = bitmap->buffer; -- FT_Byte mode = bitmap->pixel_mode; - - - /* take care of bitmap flow */ -@@ -90,7 +94,7 @@ - origin += pitch * (FT_Int)( height - 1 ); - - /* horizontal in-place FIR filter */ -- if ( mode == FT_PIXEL_MODE_LCD && width >= 2 ) -+ if ( mode == FT_RENDER_MODE_LCD && width >= 2 ) - { - FT_Byte* line = origin; - -@@ -133,7 +137,7 @@ - } - - /* vertical in-place FIR filter */ -- else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 2 ) -+ else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 ) - { - FT_Byte* column = origin; - -@@ -182,13 +186,13 @@ - /* intra-pixel filter used by the legacy filter */ - static void - _ft_lcd_filter_legacy( FT_Bitmap* bitmap, -+ FT_Render_Mode mode, - FT_Byte* weights ) - { - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - FT_Int pitch = bitmap->pitch; - FT_Byte* origin = bitmap->buffer; -- FT_Byte mode = bitmap->pixel_mode; - - static const unsigned int filters[3][3] = - { -@@ -205,7 +209,7 @@ - origin += pitch * (FT_Int)( height - 1 ); - - /* horizontal in-place intra-pixel filter */ -- if ( mode == FT_PIXEL_MODE_LCD && width >= 3 ) -+ if ( mode == FT_RENDER_MODE_LCD && width >= 3 ) - { - FT_Byte* line = origin; - -@@ -242,7 +246,7 @@ - } - } - } -- else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 3 ) -+ else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 ) - { - FT_Byte* column = origin; - -@@ -298,6 +302,7 @@ - - ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS ); - library->lcd_filter_func = ft_lcd_filter_fir; -+ library->lcd_extra = 2; - - return FT_Err_Ok; - } -@@ -309,11 +314,37 @@ - FT_Library_SetLcdFilter( FT_Library library, - FT_LcdFilter filter ) - { -- static const FT_LcdFiveTapFilter default_weights = -- { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; - static const FT_LcdFiveTapFilter light_weights = - { 0x00, 0x55, 0x56, 0x55, 0x00 }; - -+#ifndef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ static const FT_LcdFiveTapFilter default_weights = -+ { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; -+#else -+ FT_LcdFiveTapFilter default_weights; -+ if( ftinf && ftinf->filter_params[0] ) -+ { -+ const int *f=ftinf->filter_params; -+ /* Assume we were given integers [0-100] get them to [0-255] */ -+ int val; /* 2611=2.55*1024 */ -+ val=(f[1]*2611+512)>>10; if( val > 255 ) val=255; -+ default_weights[0] = (FT_Byte) val; -+ val=(f[2]*2611+512)>>10; if( val > 255 ) val=255; -+ default_weights[1] = (FT_Byte) val; -+ val=(f[3]*2611+512)>>10; if( val > 255 ) val=255; -+ default_weights[2] = (FT_Byte) val; -+ val=(f[4]*2611+512)>>10; if( val > 255 ) val=255; -+ default_weights[3] = (FT_Byte) val; -+ val=(f[5]*2611+512)>>10; if( val > 255 ) val=255; -+ default_weights[4] = (FT_Byte) val; -+ } else { -+ default_weights[0]=0x08; -+ default_weights[1]=0x4d; -+ default_weights[2]=0x56; -+ default_weights[3]=0x4d; -+ default_weights[4]=0x08; -+ } -+#endif - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); -@@ -322,6 +353,7 @@ - { - case FT_LCD_FILTER_NONE: - library->lcd_filter_func = NULL; -+ library->lcd_extra = 0; - break; - - case FT_LCD_FILTER_DEFAULT: -@@ -329,6 +361,7 @@ - default_weights, - FT_LCD_FILTER_FIVE_TAPS ); - library->lcd_filter_func = ft_lcd_filter_fir; -+ library->lcd_extra = 2; - break; - - case FT_LCD_FILTER_LIGHT: -@@ -336,6 +369,7 @@ - light_weights, - FT_LCD_FILTER_FIVE_TAPS ); - library->lcd_filter_func = ft_lcd_filter_fir; -+ library->lcd_extra = 2; - break; - - #ifdef USE_LEGACY -@@ -343,6 +377,7 @@ - case FT_LCD_FILTER_LEGACY: - case FT_LCD_FILTER_LEGACY1: - library->lcd_filter_func = _ft_lcd_filter_legacy; -+ library->lcd_extra = 0; - break; - - #endif -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftobjs.c a/src/base/ftobjs.c ---- b/src/base/ftobjs.c 2021-07-15 13:09:04.000000000 +0300 -+++ a/src/base/ftobjs.c 2021-09-16 09:15:05.053379751 +0300 -@@ -45,7 +45,9 @@ - #ifdef FT_CONFIG_OPTION_MAC_FONTS - #include "ftbase.h" - #endif -- -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "ftinf.h" -+#endif - - #ifdef FT_DEBUG_LEVEL_TRACE - -@@ -99,6 +101,11 @@ - - #define GRID_FIT_METRICS - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include <strings.h> -+#include <stdlib.h> -+#include "../autofit/aflatin.h" -+#endif - - /* forward declaration */ - static FT_Error -@@ -777,6 +784,25 @@ - ft_lookup_glyph_renderer( FT_GlyphSlot slot ); - - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ static void -+ ft_glyphslot_enlarge_metrics( FT_GlyphSlot slot, -+ FT_Render_Mode mode ) -+ { -+ FT_Glyph_Metrics* metrics = &slot->metrics; -+ FT_Pos enlarge_cbox = 0; -+ -+ -+ /* enlarge for grayscale rendering */ -+ if ( mode == FT_RENDER_MODE_NORMAL ) -+ enlarge_cbox = 64; -+ -+ metrics->horiBearingX -= enlarge_cbox; -+ metrics->width += 2 * enlarge_cbox; -+ } -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ -+ -+ - #ifdef GRID_FIT_METRICS - static void - ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot, -@@ -843,8 +869,18 @@ - FT_Bool autohint = FALSE; - FT_Module hinter; - TT_Face ttface = (TT_Face)face; -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET - -+ FT_Bool use_various_tweaks = FALSE; -+ if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks; - -+ /* Force autohint if no tt instructions */ -+ /* NOTE: NEEDS TO BE RUN LATER IN CODE???? */ -+ /*if ( use_various_tweaks && -+ ttface->num_locations && -+ ttface->max_profile.maxSizeOfInstructions == 0 ) -+ load_flags |= FT_LOAD_FORCE_AUTOHINT;*/ -+#endif - if ( !face || !face->size || !face->glyph ) - return FT_THROW( Invalid_Face_Handle ); - -@@ -946,6 +982,18 @@ - { - FT_AutoHinter_Interface hinting; - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if ( use_various_tweaks ) -+ { -+ /* Force slight hinting over full hinting always */ -+ load_flags &= ~FT_LOAD_TARGET_LCD; -+ load_flags &= ~FT_LOAD_TARGET_LCD_V; -+ load_flags &= ~FT_LOAD_TARGET_MONO; -+ load_flags &= ~FT_LOAD_TARGET_NORMAL; -+ load_flags |= FT_LOAD_TARGET_LIGHT; -+ /*printf("%d ", load_flags);*/ -+ } -+#endif - - /* try to load embedded bitmaps first if available */ - /* */ -@@ -991,6 +1039,18 @@ - if ( error ) - goto Exit; - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ infinality_cur_width = 0; -+ -+ { -+ /* fix for sdl_ttf */ -+ FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); -+ -+ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) -+ ft_glyphslot_enlarge_metrics( slot, mode ); -+ } -+#endif -+ - if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - { - /* check that the loaded outline is correct */ -@@ -5353,6 +5413,11 @@ - /* That's ok now */ - *alibrary = library; - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ /* get Infinality settings */ -+ ftinf_env(); -+#endif -+ - return FT_Err_Ok; - } - -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftoutln.c a/src/base/ftoutln.c ---- b/src/base/ftoutln.c 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/base/ftoutln.c 2021-09-16 09:15:05.053379751 +0300 -@@ -22,6 +22,9 @@ - #include <freetype/internal/ftdebug.h> - #include <freetype/fttrigon.h> - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "ftinf.h" -+#endif - - /************************************************************************** - * -@@ -907,8 +910,14 @@ - { - FT_Vector* points; - FT_Int c, first, last; -- FT_Orientation orientation; -- -+ FT_Int orientation; -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ FT_Bool use_various_tweaks = FALSE; -+ if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks; -+ -+ if ( use_various_tweaks ) -+ ystrength = FT_PIX_FLOOR ( ystrength ); -+#endif - - if ( !outline ) - return FT_THROW( Invalid_Outline ); -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftsynth.c a/src/base/ftsynth.c ---- b/src/base/ftsynth.c 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/base/ftsynth.c 2021-09-16 09:15:05.053379751 +0300 -@@ -22,6 +22,9 @@ - #include <freetype/ftoutln.h> - #include <freetype/ftbitmap.h> - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "ftinf.h" -+#endif - - /************************************************************************** - * -@@ -92,7 +95,10 @@ - FT_Face face; - FT_Error error; - FT_Pos xstr, ystr; -- -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ FT_Bool use_various_tweaks = FALSE; -+ if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks; -+#endif - - if ( !slot ) - return; -@@ -110,8 +116,16 @@ - ystr = xstr; - - if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) -+ { -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if ( use_various_tweaks ) -+ (void)FT_Outline_EmboldenXY( &slot->outline, -+ xstr, -+ FT_PIX_FLOOR( ystr ) ); -+ else -+#endif - FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); -- -+ } - else /* slot->format == FT_GLYPH_FORMAT_BITMAP */ - { - /* round to full pixels */ -@@ -149,6 +163,9 @@ - - slot->metrics.width += xstr; - slot->metrics.height += ystr; -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if ( !use_various_tweaks ) -+#endif - slot->metrics.horiAdvance += xstr; - slot->metrics.vertAdvance += ystr; - slot->metrics.horiBearingY += ystr; -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/rules.mk a/src/base/rules.mk ---- b/src/base/rules.mk 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/base/rules.mk 2021-09-16 09:15:05.053379751 +0300 -@@ -44,6 +44,7 @@ - $(BASE_DIR)/ftfntfmt.c \ - $(BASE_DIR)/ftgloadr.c \ - $(BASE_DIR)/fthash.c \ -+ $(BASE_DIR)/ftinf.c \ - $(BASE_DIR)/ftlcdfil.c \ - $(BASE_DIR)/ftobjs.c \ - $(BASE_DIR)/ftoutln.c \ -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/cff/cffobjs.c a/src/cff/cffobjs.c ---- b/src/cff/cffobjs.c 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/cff/cffobjs.c 2021-09-16 09:15:05.053379751 +0300 -@@ -42,6 +42,9 @@ - #include <freetype/internal/psaux.h> - #include <freetype/internal/services/svcfftl.h> - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include "../base/ftinf.h" -+#endif - - /************************************************************************** - * -@@ -1177,6 +1180,9 @@ - driver->hinting_engine = FT_HINTING_ADOBE; - - driver->no_stem_darkening = TRUE; -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if(ftinf) driver->no_stem_darkening = !ftinf->stem_darkening_cff; -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - - driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; - driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; -diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/smooth/ftsmooth.c a/src/smooth/ftsmooth.c ---- b/src/smooth/ftsmooth.c 2021-02-13 10:16:54.000000000 +0200 -+++ a/src/smooth/ftsmooth.c 2021-09-16 09:19:36.749340217 +0300 -@@ -24,6 +24,28 @@ - - #include "ftsmerrs.h" - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+#include <math.h> -+#include FT_BITMAP_H -+#include <string.h> -+#include <strings.h> -+#include FT_OUTLINE_H -+#include "../base/ftinf.h" -+ -+#define verbose FALSE -+#define STVALUES if (verbose) \ -+ printf ( "scale:%f translate:%ld ", *scale_value, *translate_value ); -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ -+ -+ /* initialize renderer -- init its raster */ -+ static FT_Error -+ ft_smooth_init( FT_Renderer render ) -+ { -+ render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); -+ -+ return 0; -+ } -+ - - /* sets render-specific mode */ - static FT_Error -@@ -76,367 +98,2440 @@ - FT_Outline_Get_CBox( &slot->outline, cbox ); - } - -- typedef struct TOrigin_ -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ static FT_Fixed FT_FixedFromFloat(float f) - { -- unsigned char* origin; /* pixmap origin at the bottom-left */ -- int pitch; /* pitch to go down one row */ -+ short value = f; -+ unsigned short fract = (f - value) * 0xFFFF; - -- } TOrigin; - --#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING -+ return (FT_Fixed)((long)value << 16 | (unsigned long)fract ); -+ } - -- /* initialize renderer -- init its raster */ -- static FT_Error -- ft_smooth_init( FT_Renderer render ) -+ -+ /* 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_Vector* sub = render->root.library->lcd_geometry; -+ FT_Byte* line = bitmap->buffer; - - -- /* set up default subpixel geometry for striped RGB panels. */ -- sub[0].x = -21; -- sub[0].y = 0; -- sub[1].x = 0; -- sub[1].y = 0; -- sub[2].x = 21; -- sub[2].y = 0; -+ for ( ; height > 0; height--, line += bitmap->pitch ) -+ { -+ FT_UInt xx; - -- render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); - -- return 0; -+ 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; - } - - -- /* This function writes every third byte in direct rendering mode */ -+ /* Filter to mimic Windows-style sharpening */ -+ /* Determined via 100% experimentation. */ - static void -- ft_smooth_lcd_spans( int y, -- int count, -- const FT_Span* spans, -- TOrigin* target ) -+ _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_Init( &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 ) - { -- unsigned char* dst_line = target->origin - y * target->pitch; -- unsigned char* dst; -- unsigned short w; -+ /* 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; -+ } - -- for ( ; count--; spans++ ) -- for ( dst = dst_line + spans->x * 3, w = spans->len; w--; dst += 3 ) -- *dst = spans->coverage; -+ 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; - -- static FT_Error -- ft_smooth_raster_lcd( FT_Renderer render, -- FT_Outline* outline, -- FT_Bitmap* bitmap ) -+ 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 ) - { -- FT_Error error = FT_Err_Ok; -- FT_Vector* sub = render->root.library->lcd_geometry; -- FT_Pos x, y; -+ /* 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 ; - -- FT_Raster_Params params; -- TOrigin target; -+ 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; - -- /* Render 3 separate coverage bitmaps, shifting the outline. */ -- /* Set up direct rendering to record them on each third byte. */ -- params.source = outline; -- params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; -- params.gray_spans = (FT_SpanFunc)ft_smooth_lcd_spans; -- params.user = ⌖ -- -- params.clip_box.xMin = 0; -- params.clip_box.yMin = 0; -- params.clip_box.xMax = bitmap->width; -- params.clip_box.yMax = bitmap->rows; -- -- if ( bitmap->pitch < 0 ) -- target.origin = bitmap->buffer; -- else -- target.origin = bitmap->buffer -- + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch; -- -- target.pitch = bitmap->pitch; -- -- FT_Outline_Translate( outline, -- -sub[0].x, -- -sub[0].y ); -- error = render->raster_render( render->raster, ¶ms ); -- x = sub[0].x; -- y = sub[0].y; -- if ( error ) -- goto Exit; -+ } -+ 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; - -- target.origin++; -- FT_Outline_Translate( outline, -- sub[0].x - sub[1].x, -- sub[0].y - sub[1].y ); -- error = render->raster_render( render->raster, ¶ms ); -- x = sub[1].x; -- y = sub[1].y; -- if ( error ) -- goto Exit; -+ new_line[xx] -= ( new_line[xx] * strength ) / 100; - -- target.origin++; -- FT_Outline_Translate( outline, -- sub[1].x - sub[2].x, -- sub[1].y - sub[2].y ); -- error = render->raster_render( render->raster, ¶ms ); -- x = sub[2].x; -- y = sub[2].y; -+ if ( height != 1 ) -+ if ( new_nextline[xx] > 155 + ( 100 - strength ) ) -+ new_nextline[xx] = 255; - -- Exit: -- FT_Outline_Translate( outline, x, y ); -+ } -+ } -+ 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; - -- return error; -+ 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 FT_Error -- ft_smooth_raster_lcdv( FT_Renderer render, -- FT_Outline* outline, -- FT_Bitmap* bitmap ) -+ -+ static void -+ _ft_lcd_darken_x ( FT_Bitmap* bitmap, -+ FT_Render_Mode mode, -+ FT_UInt strength, -+ FT_Library library ) - { -- FT_Error error = FT_Err_Ok; -- int pitch = bitmap->pitch; -- FT_Vector* sub = render->root.library->lcd_geometry; -- FT_Pos x, y; - -- FT_Raster_Params params; -+ 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_Init( &new_bitmap ); - -- params.target = bitmap; -- params.source = outline; -- params.flags = FT_RASTER_FLAG_AA; -+ FT_Bitmap_Copy( library, bitmap, &new_bitmap ); -+ new_line = (&new_bitmap)->buffer; - -- /* Render 3 separate coverage bitmaps, shifting the outline. */ -- /* Notice that the subpixel geometry vectors are rotated. */ -- /* Triple the pitch to render on each third row. */ -- bitmap->pitch *= 3; -- bitmap->rows /= 3; -- -- FT_Outline_Translate( outline, -- -sub[0].y, -- sub[0].x ); -- error = render->raster_render( render->raster, ¶ms ); -- x = sub[0].y; -- y = -sub[0].x; -- if ( error ) -- goto Exit; -+ 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; - -- bitmap->buffer += pitch; -- FT_Outline_Translate( outline, -- sub[0].y - sub[1].y, -- sub[1].x - sub[0].x ); -- error = render->raster_render( render->raster, ¶ms ); -- x = sub[1].y; -- y = -sub[1].x; -- bitmap->buffer -= pitch; -- if ( error ) -- goto Exit; -+ for ( xx = 1; xx < width - 1; xx += 1 ) -+ { -+ /* subpixel grid sp11 sp21 sp31 */ -+ /* where sp22 is sp12 sp22 sp32 */ -+ /* current subpixel. sp13 sp23 sp33 */ - -- bitmap->buffer += 2 * pitch; -- FT_Outline_Translate( outline, -- sub[1].y - sub[2].y, -- sub[2].x - sub[1].x ); -- error = render->raster_render( render->raster, ¶ms ); -- x = sub[2].y; -- y = -sub[2].x; -- bitmap->buffer -= 2 * pitch; -+ FT_Int sp21, sp12, sp22, sp32, sp23; - -- Exit: -- FT_Outline_Translate( outline, x, y ); -+ sp12 = line [xx-1]; -+ sp22 = line [xx]; -+ sp32 = line [xx+1]; - -- bitmap->pitch /= 3; -- bitmap->rows *= 3; -+ 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; - -- return error; -+ } -+ } -+ FT_Bitmap_Copy( library, &new_bitmap, bitmap ); -+ FT_Bitmap_Done( library, &new_bitmap ); - } - --#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - -- /* initialize renderer -- init its raster */ -- static FT_Error -- ft_smooth_init( FT_Renderer render ) -+ static void -+ _ft_lcd_darken_y ( FT_Bitmap* bitmap, -+ FT_Render_Mode mode, -+ FT_UInt strength, -+ FT_Library library ) - { -- /* set up default LCD filtering */ -- FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT ); - -- render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); -+ 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; - -- return 0; -+ -+ FT_Bitmap_Init( &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 FT_Error -- ft_smooth_raster_lcd( FT_Renderer render, -- FT_Outline* outline, -- FT_Bitmap* bitmap ) -+ static void -+ _ft_bitmap_cap ( FT_Bitmap* bitmap, -+ FT_UInt strength, -+ FT_Library library ) - { -- FT_Error error = FT_Err_Ok; -- FT_Vector* points = outline->points; -- FT_Vector* points_end = FT_OFFSET( points, outline->n_points ); -- FT_Vector* vec; - -- FT_Raster_Params params; -+ 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; - - -- params.target = bitmap; -- params.source = outline; -- params.flags = FT_RASTER_FLAG_AA; -+ FT_Bitmap_Init( &new_bitmap ); -+ FT_Bitmap_Copy( library, bitmap, &new_bitmap ); -+ new_line = (&new_bitmap)->buffer; - -- /* implode outline */ -- for ( vec = points; vec < points_end; vec++ ) -- vec->x *= 3; -+ if ( strength > 0 ) -+ for ( height = (FT_UInt)bitmap->rows; -+ height > 0; -+ height--, line += bitmap->pitch, new_line += bitmap->pitch ) -+ { -+ FT_UInt xx; - -- /* render outline into the bitmap */ -- error = render->raster_render( render->raster, ¶ms ); - -- /* deflate outline */ -- for ( vec = points; vec < points_end; vec++ ) -- vec->x /= 3; -+ 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 ); -+ } - -- return error; -+ static int -+ pseudo_gamma ( int val, float value ) -+ { -+ return 256 * ( 1.0f - powf( ( 1.0f - val * (1.0f/256.0f) ), 1.0f / value ) ); - } - -+#if(0) -+ static void -+ _ft_bitmap_embolden ( FT_Bitmap* bitmap, -+ FT_UInt strength, -+ FT_Library library ) -+ { - -- static FT_Error -- ft_smooth_raster_lcdv( FT_Renderer render, -- FT_Outline* outline, -- FT_Bitmap* bitmap ) -+ 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_Init(&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_Error error = FT_Err_Ok; -- FT_Vector* points = outline->points; -- FT_Vector* points_end = FT_OFFSET( points, outline->n_points ); -- FT_Vector* vec; -+ for ( xx = 1; xx < width - 1; xx += 1 ) -+ { -+ FT_Int new_value = 0; - -- FT_Raster_Params params; - -+ new_value = ( strength * line [xx-1] ) / 100 -+ + pseudo_gamma( line [xx], .75 ) -+ + (strength * line [xx+1] ) / 100; -+ if ( new_value > 255 ) -+ new_value = 255; - -- params.target = bitmap; -- params.source = outline; -- params.flags = FT_RASTER_FLAG_AA; -+ new_line[xx] = new_value; -+ } -+ } -+ FT_Bitmap_Copy( library, &new_bitmap, bitmap ); -+ FT_Bitmap_Done( library, &new_bitmap ); -+ } - -- /* implode outline */ -- for ( vec = points; vec < points_end; vec++ ) -- vec->y *= 3; - -- /* render outline into the bitmap */ -- error = render->raster_render( render->raster, ¶ms ); - -- /* deflate outline */ -- for ( vec = points; vec < points_end; vec++ ) -- vec->y /= 3; -+ static void -+ _ft_bitmap_gamma ( FT_Bitmap* bitmap, -+ float strength ) -+ { - -- return error; -+ 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] = pseudo_gamma( line [xx], strength ) ; -+ } -+ } -+ } -+#endif -+ -+ /* 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_Init(&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 ) -+ /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */ -+ new_line[xx-1] -= ( new_line[xx-1] * strength ) / 200; -+ -+ if ( rightdiff < 10 ) -+ /* OPPORTUNITY FOR IMPROVEMENT */ -+ new_line[xx+1] -= ( new_line[xx+1] * strength ) / 200; -+ } -+ 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 ) -+ /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */ -+ new_line[xx-1] -= ( new_line[xx-1] * strength ) / 200; -+ -+ if ( rightdiff < 10 ) -+ /* OPPORTUNITY FOR IMPROVEMENT */ -+ new_line[xx+1] -= ( new_line[xx+1] * strength ) / 200; -+ } -+ } -+ /* 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; - --#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - --/* Oversampling scale to be used in rendering overlaps */ --#define SCALE ( 1 << 2 ) -+ 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; -+ } -+ } -+ } -+ -+/* -+ These need to be in sync with params inside ftinf.c -+ (not ideal but perhaps better than making these public) -+ */ -+#define STEM_WIDTH_2_PPEM 18 -+#define MAX_PPEM 100 -+ -+ 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; - -- /* This function averages inflated spans in direct rendering mode */ - static void -- ft_smooth_overlap_spans( int y, -- int count, -- const FT_Span* spans, -- TOrigin* target ) -+ swap_stem ( Stem* s1, Stem* s2 ) - { -- unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch; -- unsigned short x; -- unsigned int cover, sum; -+ 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; -+ } -+ -+ /* 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; -+ 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; -+ 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;*/ -+ -+ const FT_Int MIN_PPEM = 7; -+ /*const FT_Int MAX_PPEM = 100;*/ -+ const FT_Int MAX_STEMS = 3; -+ FT_Int ppem = 0; -+ -+ Stem_Data stem_data; -+ -+ /* reset to default */ -+ *scale_value = 1.0; -+ -+ /* 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 ( slot->face->size->metrics.x_ppem < MIN_PPEM ) -+ return; -+ -+ if ( !FT_IS_SCALABLE( slot->face ) ) -+ return; -+ -+ ppem = slot->face->size->metrics.x_ppem; -+ -+ if ( ppem < 9 ) -+ return; -+ if ( ppem > 20 ) -+ strategy_use_m_control = TRUE; -+ -+ /* 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 ( 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; -+ if ( ftinf && ftinf->use_known_settings_on_selected_fonts ) -+ { -+ ftinf_fill_stem_values( known_stem_values, slot->face->family_name, ppem, TRUE ); -+ /* translate value may be set for < 10 */ -+ if (known_stem_values->stem_translating_only > -1024 ) -+ { -+ *translate_value = known_stem_values->stem_translating_only; -+ return; -+ } -+ if( known_stem_values->bearing_correction == FALSE ) -+ strategy_bearing_correction = FALSE; -+ } else -+ ftinf_fill_stem_values( known_stem_values, slot->face->family_name, ppem, 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; -+ -+ /* Allocate */ -+ segments = NULL; -+ leftmost_segment = (Stem_Segment*) malloc( 4*sizeof ( Stem_Segment ) ); -+ leftmost_segment_not_extrema = leftmost_segment+1; -+ rightmost_segment = leftmost_segment+2; -+ rightmost_segment_not_extrema = leftmost_segment+3; -+ -+ stems = (Stem*) malloc ( (2*MAX_STEMS+2) * sizeof ( Stem ) ); -+ possible_stems = stems+MAX_STEMS; -+ leftmost_stem = possible_stems+MAX_STEMS; -+ rightmost_stem = leftmost_stem + 1; -+ centers = NULL; -+ -+ if ( verbose ) -+ printf("\n"); -+ -+ /* Initialize */ -+ stem_centers=(FT_Long*)calloc( width * 256, sizeof(stem_centers[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 (in blocks of 64) */ -+ if( num_segments % 64 == 0 ) -+ segments = (Stem_Segment*) realloc -+ ( segments, ( num_segments + 64 ) * 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; -+ 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; -+ -+ /* Reallocate (in blocks of 32) */ -+ if( num_centers % 32 == 0 ) -+ centers = (Stem_Center*) realloc -+ ( centers, ( num_centers + 32 ) * 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; */ -+ -+ /* 10 to 20 with 4 matches seems good, */ -+ /* but 1 or 2 with 3 stems needs to somehow get included */ -+ FT_Int deviation1 = 5; -+ FT_Int deviation2=-1, requirement1 = 4, stem_match_requirement = 3; -+ FT_Int 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 no_gap_found = FALSE; -+ FT_Bool no_gap_found_ledge = FALSE; -+ FT_Bool 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; -+ -+ valid_center_average = 0; -+ -+ 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 ) -+ -+ /* 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 ) -+ -+ /* 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 ) -+ -+ /* 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; -+ -+ 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; -+ set_center_to = centers[center].x; -+ } -+ -+ /* see if edges found anything */ -+ if ( strategy_also_use_edge_detection_for_stems && !stem_detected ) -+ { -+ /* Require no gap for edges */ -+ /* stem width less than 1/3 bitmap width, or bitmap_width is small */ -+ /* The stem occurs on the left side of glyph only */ -+ if ( ( stem_matches_ledge >= stem_match_requirement && -+ no_gap_found_ledge ) && -+ ( centers[center].x2 - centers[center].x1 -+ < ( m_horiAdvance * 12 ) / 2 || -+ m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) && -+ centers[center].x < ( m_horiAdvance * 12 ) / 2 ) -+ { -+ stem_detected = TRUE; -+ set_width_to = smallest_width_ledge; -+ set_center_to = centers[center].x1 + set_width_to / 2; -+ stem_matches = stem_matches_ledge; -+ } -+ /* Require no gap for edges */ -+ /* stem width is less than 1/3 bitmap width, or bitmap_width is small */ -+ /* The stem occurs on the right side of glyph only */ -+ else if ( ( stem_matches_redge >= stem_match_requirement && -+ no_gap_found_redge ) && -+ ( centers[center].x2 - centers[center].x1 -+ < ( m_horiAdvance * 12 ) / 2 || -+ m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) && -+ centers[center].x > (m_horiAdvance * 12) / 2 ) -+ { -+ stem_detected = TRUE; -+ set_width_to = smallest_width_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 && (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 stem is within 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 ) -+ { - -- /* When accumulating the oversampled spans we need to assure that */ -- /* fully covered pixels are equal to 255 and do not overflow. */ -- /* It is important that the SCALE is a power of 2, each subpixel */ -- /* cover can also reach a power of 2 after rounding, and the total */ -- /* is clamped to 255 when it adds up to 256. */ -- for ( ; count--; spans++ ) -+ /* make sure it doesn't match the first stem */ -+ if ( abs ( set_center_to - possible_stems[0].center ) >= one_pixel * 2 ) - { -- cover = ( spans->coverage + SCALE * SCALE / 2 ) / ( SCALE * SCALE ); -- for ( x = 0; x < spans->len; x++ ) -+ -+ /* 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 ) - { -- sum = dst[( spans->x + x ) / SCALE] + cover; -- dst[( spans->x + x ) / SCALE] = (unsigned char)( sum - ( sum >> 8 ) ); -+ 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; - -- static FT_Error -- ft_smooth_raster_overlap( FT_Renderer render, -- FT_Outline* outline, -- FT_Bitmap* bitmap ) -+ 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 ) - { -- FT_Error error = FT_Err_Ok; -- FT_Vector* points = outline->points; -- FT_Vector* points_end = FT_OFFSET( points, outline->n_points ); -- FT_Vector* vec; -+ 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++; -+ } - -- FT_Raster_Params params; -- TOrigin target; -+ 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++; -+ } - -- /* Reject outlines that are too wide for 16-bit FT_Span. */ -- /* Other limits are applied upstream with the same error code. */ -- if ( bitmap->width * SCALE > 0x7FFF ) -- return FT_THROW( Raster_Overflow ); -+ /* sort stems in x direction */ -+ if ( valid_stems == 3 ) -+ { -+ if ( stems[0].center > stems[1].center ) -+ swap_stem ( &stems[0], &stems[1] ); - -- /* Set up direct rendering to average oversampled spans. */ -- params.source = outline; -- params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; -- params.gray_spans = (FT_SpanFunc)ft_smooth_overlap_spans; -- params.user = ⌖ -+ 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] ); -+ } -+ -+ /* 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 - -- params.clip_box.xMin = 0; -- params.clip_box.yMin = 0; -- params.clip_box.xMax = bitmap->width * SCALE; -- params.clip_box.yMax = bitmap->rows * SCALE; -+ center_offset = one_pixel / 2; /* half pixel */ -+ modulus = one_pixel; /* whole pixel */ - -- if ( bitmap->pitch < 0 ) -- target.origin = bitmap->buffer; -+ /* 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 -- target.origin = bitmap->buffer -- + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch; -+ 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 ) -+ /* snap left */ -+ *translate_value = -delta / ( columns_per_pixel * 4 ); -+ else -+ /* snap right */ -+ *translate_value = ( modulus - delta ) / ( columns_per_pixel * 4 ); -+ } - -- target.pitch = bitmap->pitch; -+ 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 ); -+ } - -- /* inflate outline */ -- for ( vec = points; vec < points_end; vec++ ) -+ if ( strategy_use_strengths ) - { -- vec->x *= SCALE; -- vec->y *= SCALE; -+ /* 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; - } - -- /* render outline into the bitmap */ -- error = render->raster_render( render->raster, ¶ms ); -+ /* 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 ); - -- /* deflate outline */ -- for ( vec = points; vec < points_end; vec++ ) -+ 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 && -+ ( width - 2 * columns_per_pixel ) > 6 * columns_per_pixel && -+ ppem > 8 && -+ ( advance_stem_location - advance_leftmost_location ) -+ < stems[main_stem].width * 2 ) -+ { -+ /* Possibly use 2 only when compatible widths is on? */ -+ FT_Int mod_factor = 2; -+ -+ 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 ) - { -- vec->x /= SCALE; -- vec->y /= SCALE; -+ if ( known_stem_values->m == 0 ) -+ new_distance = distance_floor; -+ else -+ new_distance = distance_ceiling; - } - -- return error; -+ 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 ) -+ { -+ /* Possibly use 2 only when compatible widths is on? */ -+ FT_Int mod_factor = 2; -+ -+ 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 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 ) -+ /* snap left */ -+ translate_value2 = -delta2 / ( columns_per_pixel * 4 ); -+ else -+ /* snap right */ -+ translate_value2 = ( modulus - delta2 ) -+ / ( columns_per_pixel * 4 ); -+ -+ 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 ) -+ /* stretch left */ -+ new_distance = delta + stem_distance; -+ else -+ /* stretch right */ -+ new_distance = delta - modulus + stem_distance; -+ -+ 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 ) / (float)( stem_distance ); -+ *translate_value = *translate_value -+ - ( (float)( stems[main_stem].center * (float)new_distance ) -+ / (float)stem_distance - stems[main_stem].center ) / 12; -+ -+ 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 ); -+ -+ 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 ); -+ -+ 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 " ); -+ } -+ } -+ goto Exit; -+ } -+ -+ Exit: -+ -+#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 ( centers ); -+ free ( segments ); -+ free ( stem_centers ); -+ free ( stems ); -+ free ( leftmost_segment ); - } - --#undef SCALE - -+ /* Gamma correction */ -+ static void -+ _ft_lcd_gamma_correction_correction ( FT_Bitmap* bitmap, -+ FT_Render_Mode mode, -+ FT_GlyphSlot slot, -+ float gamma_correction_lt, -+ float gamma_correction_value ) -+ { -+ 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->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] = pseudo_gamma ( line[xx], gamma_correction_value );*/ -+ -+ /* sloped */ -+ /*line[xx] = pseudo_gamma ( 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] = pseudo_gamma ( 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 -- ft_smooth_render( FT_Renderer render, -+ ft_smooth_render_generic( FT_Renderer render, - FT_GlyphSlot slot, - FT_Render_Mode mode, -- const FT_Vector* origin ) -+ const FT_Vector* origin, -+ FT_Render_Mode required_mode ) - { -- FT_Error error = FT_Err_Ok; -- FT_Outline* outline = &slot->outline; -+ FT_Error error; -+ FT_Outline* outline = NULL; -+ FT_Outline* outline_orig = NULL; -+ FT_BBox cbox; -+ FT_Pos width, height, pitch, ppem; -+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING -+ FT_Pos height_org, width_org; -+#endif - FT_Bitmap* bitmap = &slot->bitmap; - FT_Memory memory = render->root.memory; -+ FT_Int hmul = ( mode == FT_RENDER_MODE_LCD ); -+ FT_Int vmul = ( mode == FT_RENDER_MODE_LCD_V ); - FT_Pos x_shift = 0; - FT_Pos y_shift = 0; -+ FT_Pos x_left, y_top; -+ -+ FT_Raster_Params params; -+ -+ FT_Bool have_translated_origin = FALSE; -+ FT_Bool have_outline_shifted = FALSE; -+ FT_Bool have_buffer = FALSE; -+ -+#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 alignment_strength = 0; -+ int fitting_strength = 0; -+ int fringe_filter_strength = 0; -+ int grayscale_filter_strength = 0; -+ -+ int autohint_horizontal_stem_darken_strength = 0; -+ int autohint_vertical_stem_darken_strength = 0; -+ -+ int windows_style_sharpening_strength = 0; -+ float gamma_correction_value = 1; -+ float gamma_correction_lt = 0; -+ -+ FT_Int brightness_value = 0.0; -+ FT_Int contrast_value = 0.0; -+ -+ FT_Int snapping_sliding_scale_value = 0; -+ -+ FT_Int global_embolden_x_value = 0; -+ FT_Int global_embolden_y_value = 0; -+ -+ FT_Int bold_embolden_x_value = 0; -+ FT_Int bold_embolden_y_value = 0; -+ -+ FT_Byte chromeos_cutoff; -+ double chromeos_gamma_value; -+ -+ float embolden_value = 0.0; -+ FT_Bool autohinted = FALSE; -+ FT_Bool use_various_tweaks = FALSE; -+ FT_Pos cur_width = infinality_cur_width; -+ -+ const FT_Int MIN_PPEM = 1; -+ /*const FT_Int MAX_PPEM = 100; */ -+ -+ FT_Bool use_known_settings_on_selected_fonts; -+ -+ 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 ) -+ { -+ autohinted = TRUE; -+ } -+ if( ftinf ){ -+ const float *f=ftinf->gamma_correction; -+ -+ use_known_settings_on_selected_fonts=ftinf->use_known_settings_on_selected_fonts; -+ use_various_tweaks=ftinf->use_various_tweaks; -+ snapping_sliding_scale_value=ftinf->stem_snapping_sliding_scale; -+ -+ alignment_strength=ftinf->stem_alignment_strength; -+ if ( snapping_sliding_scale_value != 0 ) -+ alignment_strength = sliding_scale(10, snapping_sliding_scale_value, alignment_strength, 100, ppem); -+ -+ fitting_strength=ftinf->stem_fitting_strength; -+ if ( snapping_sliding_scale_value != 0 ) -+ fitting_strength = sliding_scale(10, snapping_sliding_scale_value, fitting_strength, 100, ppem); -+ -+ chromeos_style_sharpening_strength=ftinf->chromeos_style_sharpening_strength; -+ -+ if ( ppem > 10 ) -+ chromeos_style_sharpening_strength = -+ ( chromeos_style_sharpening_strength * ppem ) / 10; -+ -+ if ( chromeos_style_sharpening_strength > 100 ) -+ chromeos_style_sharpening_strength = 100; -+ -+ brightness_value=ftinf->brightness; -+ contrast_value=ftinf->contrast; -+ -+ windows_style_sharpening_strength=ftinf->windows_style_sharpening_strength; -+ -+ /* Decrease effect slightly 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; - -+ gamma_correction_lt = f[0]; -+ gamma_correction_value = f[1] / 100.0f; -+ -+ fringe_filter_strength=ftinf->fringe_filter_strength; -+ grayscale_filter_strength=ftinf->grayscale_filter_strength; -+ -+ autohint_horizontal_stem_darken_strength=ftinf->autohint_horizontal_stem_darken_strength; -+ autohint_vertical_stem_darken_strength=ftinf->autohint_vertical_stem_darken_strength; -+ -+ global_embolden_x_value=ftinf->global_embolden_x_value; -+ global_embolden_y_value=ftinf->global_embolden_y_value; -+ -+ bold_embolden_x_value=ftinf->bold_embolden_x_value; -+ bold_embolden_y_value=ftinf->bold_embolden_y_value; -+ } else { -+ use_known_settings_on_selected_fonts=FALSE; -+ } -+ -+ /* 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( 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 -+ -+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING -+ -+ FT_Int lcd_extra = 0; -+ FT_LcdFiveTapFilter lcd_weights = { 0 }; -+ FT_Bool have_custom_weight = FALSE; -+ FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL; -+ -+ -+ if ( slot->face ) -+ { -+ FT_Char i; -+ -+ -+ for ( i = 0; i < FT_LCD_FILTER_FIVE_TAPS; i++ ) -+ if ( slot->face->internal->lcd_weights[i] != 0 ) -+ { -+ have_custom_weight = TRUE; -+ break; -+ } -+ } -+ -+ /* -+ * The LCD filter can be set library-wide and per-face. Face overrides -+ * library. If the face filter weights are all zero (the default), it -+ * means that the library default should be used. -+ */ -+ if ( have_custom_weight ) -+ { -+ /* -+ * A per-font filter is set. It always uses the default 5-tap -+ * in-place FIR filter that needs 2 extra pixels. -+ */ -+ ft_memcpy( lcd_weights, -+ slot->face->internal->lcd_weights, -+ FT_LCD_FILTER_FIVE_TAPS ); -+ lcd_filter_func = ft_lcd_filter_fir; -+ lcd_extra = 2; -+ } -+ else -+ { -+ /* -+ * The face's lcd_weights is {0, 0, 0, 0, 0}, meaning `use library -+ * default'. If the library is set to use no LCD filtering -+ * (lcd_filter_func == NULL), `lcd_filter_func' here is also set to -+ * NULL and the tests further below pass over the filtering process. -+ */ -+ ft_memcpy( lcd_weights, -+ slot->library->lcd_weights, -+ FT_LCD_FILTER_FIVE_TAPS ); -+ lcd_filter_func = slot->library->lcd_filter_func; -+ lcd_extra = slot->library->lcd_extra; -+ } -+ -+#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - - /* check glyph image format */ - if ( slot->format != render->glyph_format ) -@@ -446,15 +2541,134 @@ - } - - /* check mode */ -- if ( mode != FT_RENDER_MODE_NORMAL && -- mode != FT_RENDER_MODE_LIGHT && -- mode != FT_RENDER_MODE_LCD && -- mode != FT_RENDER_MODE_LCD_V ) -+ if ( mode != required_mode ) - { - error = FT_THROW( Cannot_Render_Glyph ); - goto Exit; - } - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+RERENDER: -+ if ( align_called == 1 ) -+ { -+ scaleMat.xx = FT_FixedFromFloat(scale_value); -+ scaleMat.xy = 0; -+ scaleMat.yx = 0; -+ scaleMat.yy = ( 1 << 16 ); -+ -+ FT_Outline_Copy(outline_orig, outline); -+ -+ if ( scale_value != 1.0 ) -+ FT_Outline_Transform( outline, &scaleMat ); -+ -+ FT_Outline_Translate( outline, translate_value, 0 ); -+ -+ FT_Outline_EmboldenXY( outline, embolden_value, 0 ); -+ } -+ else -+ { -+#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 ( slot->face ) -+ { -+ 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_EmboldenXY( outline, 12, 0 ); -+ -+ 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_EmboldenXY( outline, 8, 0 ); -+ -+ if ( global_embolden_x_value != 0 || global_embolden_y_value != 0 ) -+ FT_Outline_EmboldenXY( 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_EmboldenXY( outline, -+ bold_embolden_x_value, -+ bold_embolden_y_value ); -+ } -+ -+ FT_Outline_Copy( outline, outline_orig ); -+ } -+ -+ /* translate the outline to the new origin if needed */ -+ if ( align_called == 0 ) -+ { -+ FT_Pos enlarge_cbox = 0; -+ -+ /* enlarge for grayscale rendering */ -+ if ( mode == FT_RENDER_MODE_NORMAL ) -+ enlarge_cbox = 64; -+ -+ if ( origin ) -+ { -+ FT_Outline_Translate( outline, origin->x, origin->y ); -+ have_translated_origin = TRUE; -+ } -+ -+ /* 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 ); -+ have_translated_origin = TRUE; -+ } -+ -+ /* 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 -+ -+ width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6; -+ height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6; -+ -+#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 ) - { -@@ -462,109 +2676,427 @@ - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - -- if ( ft_glyphslot_preset_bitmap( slot, mode, origin ) ) -+ /* allocate new one */ -+ pitch = width; -+ if ( hmul ) - { -- error = FT_THROW( Raster_Overflow ); -- goto Exit; -+ width = width * 3; -+ pitch = FT_PAD_CEIL( width, 4 ); - } - -- if ( !bitmap->rows || !bitmap->pitch ) -- goto Exit; -+ if ( vmul ) -+ height *= 3; - -- /* allocate new one */ -- if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) ) -- goto Exit; -+ x_shift = cbox.xMin; -+ y_shift = cbox.yMin; -+ x_left = cbox.xMin >> 6; -+ y_top = cbox.yMax >> 6; - -- slot->internal->flags |= FT_GLYPH_OWN_BITMAP; -+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING -+ if ( lcd_filter_func ) -+ { -+ if ( hmul ) -+ { -+ x_shift -= 64 * ( lcd_extra >> 1 ); -+ x_left -= lcd_extra >> 1; -+ width += 3 * lcd_extra; -+ pitch = FT_PAD_CEIL( width, 4 ); -+ } - -- x_shift = 64 * -slot->bitmap_left; -- y_shift = 64 * -slot->bitmap_top; -- if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) -- y_shift += 64 * (FT_Int)bitmap->rows / 3; -- else -- y_shift += 64 * (FT_Int)bitmap->rows; -+ if ( vmul ) -+ { -+ y_shift -= 64 * ( lcd_extra >> 1 ); -+ y_top += lcd_extra >> 1; -+ height += 3 * lcd_extra; -+ } -+ } -+#endif -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ } -+#endif - -- if ( origin ) -+ -+ /* Required check is (pitch * height < FT_ULONG_MAX), */ -+ /* but we care realistic cases only. Always pitch <= width. */ -+ if ( width > 0x7FFF || height > 0x7FFF ) - { -- x_shift += origin->x; -- y_shift += origin->y; -+ FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n", -+ width, height )); -+ error = FT_THROW( Raster_Overflow ); -+ goto Exit; - } - -- /* translate outline to render it into the bitmap */ -- if ( x_shift || y_shift ) -- FT_Outline_Translate( outline, x_shift, y_shift ); -+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; -+ bitmap->num_grays = 256; -+ bitmap->width = (unsigned int)width; -+ bitmap->rows = (unsigned int)height; -+ bitmap->pitch = pitch; - -- if ( mode == FT_RENDER_MODE_NORMAL || -- mode == FT_RENDER_MODE_LIGHT ) -+ /* translate outline to render it into the bitmap */ -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if ( align_called == 0 ) - { -- if ( outline->flags & FT_OUTLINE_OVERLAP ) -- error = ft_smooth_raster_overlap( render, outline, bitmap ); -- else -+#endif -+ FT_Outline_Translate( outline, -x_shift, -y_shift ); -+ have_outline_shifted = TRUE; -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ } -+#endif -+ /* release old bitmap buffer */ -+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - { -- FT_Raster_Params params; -+ FT_FREE( bitmap->buffer ); -+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; -+ } - -+ if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) ) -+ goto Exit; -+ else -+ have_buffer = TRUE; - -+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP; -+ -+ /* set up parameters */ - params.target = bitmap; - params.source = outline; - params.flags = FT_RASTER_FLAG_AA; - -- error = render->raster_render( render->raster, ¶ms ); -- } -- } -- else -+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING -+ -+ /* implode outline if needed */ - { -- if ( mode == FT_RENDER_MODE_LCD ) -- error = ft_smooth_raster_lcd ( render, outline, bitmap ); -- else if ( mode == FT_RENDER_MODE_LCD_V ) -- error = ft_smooth_raster_lcdv( render, outline, bitmap ); -+ FT_Vector* points = outline->points; -+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points ); -+ FT_Vector* vec; - --#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - -- /* finally apply filtering */ -+ if ( hmul ) -+ for ( vec = points; vec < points_end; vec++ ) -+ vec->x *= 3; -+ -+ if ( vmul ) -+ for ( vec = points; vec < points_end; vec++ ) -+ vec->y *= 3; -+ } -+ -+ /* render outline into the bitmap */ -+ error = render->raster_render( render->raster, ¶ms ); -+ -+ /* deflate outline if needed */ - { -- FT_Byte* lcd_weights; -- FT_Bitmap_LcdFilterFunc lcd_filter_func; -+ FT_Vector* points = outline->points; -+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points ); -+ FT_Vector* vec; -+ -+ -+ if ( hmul ) -+ for ( vec = points; vec < points_end; vec++ ) -+ vec->x /= 3; -+ -+ if ( vmul ) -+ for ( vec = points; vec < points_end; vec++ ) -+ vec->y /= 3; -+ } -+ -+ if ( error ) -+ goto Exit; - -+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET -+ if ( ppem <= MAX_PPEM && ppem >= MIN_PPEM ) -+ { -+ if ( align_called == 0 && cur_width / ppem < 10 && -+ ( alignment_strength > 0 || fitting_strength > 0 ) ) -+ _lcd_stem_align ( bitmap, -+ mode, -+ slot, -+ &translate_value, -+ &scale_value, -+ alignment_strength, -+ fitting_strength, -+ &embolden_value ); - -- /* Per-face LCD filtering takes priority if set up. */ -- if ( slot->face && slot->face->internal->lcd_filter_func ) -+ if ( align_called == 0 && -+ ( translate_value != 0 || scale_value != 1.0 ) ) - { -- lcd_weights = slot->face->internal->lcd_weights; -- lcd_filter_func = slot->face->internal->lcd_filter_func; -+ align_called = 1; -+ goto RERENDER; - } -- else -+ -+ if ( mode == FT_RENDER_MODE_LCD ) - { -- lcd_weights = slot->library->lcd_weights; -- lcd_filter_func = slot->library->lcd_filter_func; -+ -+ if ( fringe_filter_strength > 0 /*&& autohinted*/ ) -+ _ft_lcd_fringe_filter( bitmap, -+ mode, -+ fringe_filter_strength, -+ slot->library ); -+ -+ /*if ( autohinted) -+ _ft_lcd_stem_end_filter( bitmap, mode, 100, 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 */ -+ float contrast, brightness; -+ ftinf_get_bc( slot->face->family_name, ppem, &brightness, &contrast); -+ if ( slot->face && !_ft_bitmap_bc ( bitmap, brightness, contrast ) ) -+ { -+ 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 / 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 ( lcd_filter_func ) -- lcd_filter_func( bitmap, lcd_weights ); -+ lcd_filter_func( bitmap, mode, lcd_weights ); -+ -+ if ( grayscale_filter_strength > 0 ) -+ _ft_lcd_grayscale_filter( bitmap, -+ mode, -+ grayscale_filter_strength, -+ slot->library ); -+ - } - --#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ -+ /* 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 && -+ lcd_filter_func ) -+ lcd_filter_func( bitmap, mode, lcd_weights ); -+#else -+ if ( lcd_filter_func ) -+ lcd_filter_func( bitmap, mode, lcd_weights ); -+#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */ - -- Exit: -- if ( !error ) -+#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ -+ -+ /* render outline into bitmap */ -+ error = render->raster_render( render->raster, ¶ms ); -+ if ( error ) -+ goto Exit; -+ -+ /* expand it horizontally */ -+ if ( hmul ) - { -- /* everything is fine; the glyph is now officially a bitmap */ -- slot->format = FT_GLYPH_FORMAT_BITMAP; -+ FT_Byte* line = bitmap->buffer; -+ FT_UInt hh; -+ -+ -+ for ( hh = height_org; hh > 0; hh--, line += pitch ) -+ { -+ FT_UInt xx; -+ FT_Byte* end = line + width; -+ -+ -+ for ( xx = width_org; xx > 0; xx-- ) -+ { -+ FT_UInt pixel = line[xx-1]; -+ -+ -+ end[-3] = (FT_Byte)pixel; -+ end[-2] = (FT_Byte)pixel; -+ end[-1] = (FT_Byte)pixel; -+ end -= 3; -+ } -+ } -+ } -+ -+ /* expand it vertically */ -+ if ( vmul ) -+ { -+ FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch; -+ FT_Byte* write = bitmap->buffer; -+ FT_UInt hh; -+ -+ -+ for ( hh = height_org; hh > 0; hh-- ) -+ { -+ ft_memcpy( write, read, pitch ); -+ write += pitch; -+ -+ ft_memcpy( write, read, pitch ); -+ write += pitch; -+ -+ ft_memcpy( write, read, pitch ); -+ write += pitch; -+ read += pitch; -+ } - } -- else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) -+ -+#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ -+ -+ /* -+ * XXX: on 16bit system, we return an error for huge bitmap -+ * to prevent an overflow. -+ */ -+ if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ) -+ { -+ error = FT_THROW( Invalid_Pixel_Size ); -+ goto Exit; -+ } -+ -+ slot->format = FT_GLYPH_FORMAT_BITMAP; -+ slot->bitmap_left = (FT_Int)x_left; -+ slot->bitmap_top = (FT_Int)y_top; -+ -+ /* everything is fine; don't deallocate buffer */ -+ have_buffer = FALSE; -+ -+ error = FT_Err_Ok; -+ -+ Exit: -+ if ( have_outline_shifted ) -+ FT_Outline_Translate( outline, x_shift, y_shift ); -+ if ( have_translated_origin ) -+ FT_Outline_Translate( outline, -origin->x, -origin->y ); -+ if ( have_buffer ) - { - FT_FREE( bitmap->buffer ); - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - -- if ( x_shift || y_shift ) -- FT_Outline_Translate( outline, -x_shift, -y_shift ); -+ return error; -+ } -+ -+ -+ -+ /* convert a slot's glyph image into a horizontal LCD bitmap */ -+ static FT_Error -+ ft_smooth_render_lcd( FT_Renderer render, -+ FT_GlyphSlot slot, -+ FT_Render_Mode mode, -+ const FT_Vector* origin ) -+ { -+ FT_Error error; -+ -+ error = ft_smooth_render_generic( render, slot, mode, origin, -+ FT_RENDER_MODE_LCD ); -+ if ( !error ) -+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD; - - return error; - } - - -+ /* convert a slot's glyph image into a vertical LCD bitmap */ -+ static FT_Error -+ ft_smooth_render_lcd_v( FT_Renderer render, -+ FT_GlyphSlot slot, -+ FT_Render_Mode mode, -+ const FT_Vector* origin ) -+ { -+ FT_Error error; -+ -+ error = ft_smooth_render_generic( render, slot, mode, origin, -+ FT_RENDER_MODE_LCD_V ); -+ if ( !error ) -+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V; -+ -+ return error; -+ } -+ -+ -+ -+ /* convert a slot's glyph image into a bitmap */ -+ static FT_Error -+ ft_smooth_render( FT_Renderer render, -+ FT_GlyphSlot slot, -+ FT_Render_Mode mode, -+ const FT_Vector* origin ) -+ { -+ switch (mode) { -+ case FT_RENDER_MODE_LIGHT: -+ case FT_RENDER_MODE_NORMAL: -+ return ft_smooth_render_generic( render, slot, mode, origin, -+ FT_RENDER_MODE_NORMAL ); -+ case FT_RENDER_MODE_LCD: -+ return ft_smooth_render_lcd( render, slot, mode, origin); -+ case FT_RENDER_MODE_LCD_V: -+ return ft_smooth_render_lcd_v( render, slot, mode, origin); -+ } -+ } -+ -+ - FT_DEFINE_RENDERER( - ft_smooth_renderer_class, - diff --git a/0004-Enable-long-PCF-family-names.patch b/0004-Enable-long-PCF-family-names.patch deleted file mode 100644 index 5e812300cc7e..000000000000 --- a/0004-Enable-long-PCF-family-names.patch +++ /dev/null @@ -1,27 +0,0 @@ -From a7c04e60d28a0ad0420bb7a1943479a08a923d07 Mon Sep 17 00:00:00 2001 -Message-Id: <a7c04e60d28a0ad0420bb7a1943479a08a923d07.1552648361.git.jan.steffens@gmail.com> -In-Reply-To: <b609203df7333beea20dbfd604262a9486f01497.1552648361.git.jan.steffens@gmail.com> -References: <b609203df7333beea20dbfd604262a9486f01497.1552648361.git.jan.steffens@gmail.com> -From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com> -Date: Sun, 14 May 2017 18:09:31 +0200 -Subject: [PATCH 3/4] Enable long PCF family names - ---- - include/freetype/config/ftoption.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h -index 1d4469a99..4ff4e7821 100644 ---- a/include/freetype/config/ftoption.h -+++ b/include/freetype/config/ftoption.h -@@ -847,7 +847,7 @@ FT_BEGIN_HEADER - * If this option is activated, it can be controlled with the - * `no-long-family-names` property of the 'pcf' driver module. - */ --/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ -+#define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES - - - /*************************************************************************/ --- -2.21.0 @@ -1,72 +1,17 @@ -# Maintainer: Liviu Solcovenco <solcovenco dot liviu at gmail dot com> +# Contributor: Liviu Solcovenco <solcovenco dot liviu at gmail dot com> # Contributor: Philip Deljanov <philip dot deljanov at gmail dot com> # Contributor: bohoomil <bohoomil at zoho dot com> pkgname=freetype2-infinality-remix -pkgver=2.13.0 +pkgver=2.13.1 pkgrel=1 -pkgdesc="TrueType font rendering library with Infinality Remix patches" -arch=(i686 x86_64) +pkgdesc="[Meta-PKG] EOL; please delete. Use freetype2 from [extra] repository" +arch=(any) license=('GPL') -url="http://www.freetype.org/" - -# Adding harfbuzz for improved OpenType features auto-hinting -# introduces a cycle dep to harfbuzz depending on freetype wanted by upstream -makedepends=('libx11' 'libpng' 'harfbuzz') - +url='https://gitlab.archlinux.org/archlinux/packaging/packages/freetype2/-/commit/5b4370f7' install=freetype2.install -source=(https://download-mirror.savannah.gnu.org/releases/freetype/freetype-${pkgver}.tar.xz{,.sig} - 0001-Enable-table-validation-modules.patch - 0002-infinality-2.11.1-2021.12.10.patch - 0004-Enable-long-PCF-family-names.patch - freetype2.sh - infinality-settings.sh - xft-settings.sh) - -sha256sums=('5ee23abd047636c24b2d43c6625dcafc66661d1aca64dec9e0d05df29592624c' - 'SKIP' - 'ac11a24b62a6c044cc245ea9fa2a0cbd9e2e62f2371873dd33084c28a76e7176' - '6d563b1f9f9ef52379818ff3ede26b44e0b4cb6e3cf46ea44ca5d36b6d29ae9d' - '54800d4da18611cf9232aad8b63d74a83153a51bb56dd39191678c738ffc8b53' - 'f7f8e09c44f7552c883846e9a6a1efc50377c4932234e74adc4a8ff750606467' - '1a5c12aa96e2ee66f7316b8ccb7012520b231a2d8ee21cfe4064aa28db35a57c' - '4842d1461c240cd0f60a7247ee038271fdb1067107bea9024be6bdbb218d1bd4') - -validpgpkeys=('E30674707856409FF1948010BE6C3AAC63AD8E3F') - -prepare() { - mv freetype-${pkgver} freetype2 - # Patching FreeType - cd freetype2 - patch -Np1 -i ../0001-Enable-table-validation-modules.patch - patch -Np1 -i ../0002-infinality-2.11.1-2021.12.10.patch - patch -Np1 -i ../0004-Enable-long-PCF-family-names.patch -} - -build() { - cd freetype2 - ./configure --prefix=/usr --disable-static --with-harfbuzz --with-png - make -} - -check() { - cd freetype2 - make -k check -} - package() { - groups=('infinality-remix') - depends=('zlib' 'bzip2' 'sh' 'libpng' 'harfbuzz') - provides=("freetype2=$pkgver" 'freetype2-infinality' 'libfreetype.so') - conflicts=('freetype2' 'freetype2-infinality' 'freetype2-infinality-ultimate') - - cd freetype2 - make DESTDIR="${pkgdir}" install - # Disables changes to FREETYPE_PROPERTIES globally. - install -Dm644 ../freetype2.sh "${pkgdir}/etc/profile.d/freetype2.sh" - # Configures generic Xft hinting globally. - install -Dm755 ../xft-settings.sh "${pkgdir}/etc/X11/xinit/xinitrc.d/xft-settings.sh" - # Configures global default Infinality settings. - install -Dm755 ../infinality-settings.sh "${pkgdir}/etc/X11/xinit/xinitrc.d/infinality-settings.sh" + depends=("freetype2>=${pkgver}") + conflicts=('freetype2-infinality' 'freetype2-infinality-ultimate') } diff --git a/freetype2.install b/freetype2.install index e69de29bb2d1..a2e1241f13a8 100644 --- a/freetype2.install +++ b/freetype2.install @@ -0,0 +1,14 @@ +pre_install() { + echo "WARNING: 'freetype2-infinality-remix' is EOL and is to be removed from AUR." + echo "Please install 'freetype2' instead, to ensure proper system functionality." + echo "Additional warning pertaining to extra/freetype2:" + cat <<MSG + The "Infinality" TrueType interpreter version has been removed. + If you've previously configured "truetype:interpreter-version=38", + please update your choice in /etc/profile.d/freetype2.sh . +MSG +} + +pre_upgrade() { + pre_install +} diff --git a/freetype2.sh b/freetype2.sh deleted file mode 100755 index 93165d30fe7f..000000000000 --- a/freetype2.sh +++ /dev/null @@ -1,12 +0,0 @@ -# Subpixel hinting mode can be chosen by setting the right TrueType interpreter -# version. The available settings are: -# -# truetype:interpreter-version=35 # Classic mode (default in 2.6) -# truetype:interpreter-version=38 # Infinality mode -# truetype:interpreter-version=40 # Minimal mode (default in 2.7) -# -# There are more properties that can be set, separated by whitespace. Please -# refer to the FreeType documentation for details. - -# Uncomment and configure below -#export FREETYPE_PROPERTIES="truetype:interpreter-version=40" diff --git a/infinality-settings.sh b/infinality-settings.sh deleted file mode 100755 index 2eb7937f1901..000000000000 --- a/infinality-settings.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -### freetype2-infinality-ultimate settings ### -### rev. 0.5, for freetype2 v.2.6.3 ### -### ### -### Copyright (c) 2015 bohoomil ### -### The MIT License (MIT) http://opensource.org/licenses/MIT ### -### part of infinality-bundle http://bohoomil.com ### - - -### As of version 2.6.2-1, freetype2-infinality-ultimate comes with -### the "ultimate3" rendering style enabled internally by default. -### It is still possible to use the optional "infinality-settings.sh" -### script to switch between additional built-in rendering schemes and -### create custom ones if necessary. Once modified, "infinality-settings.sh" -### needs to be copied to "/etc/X11/xinit/xinitrc.d/". -### -### There are two levels of customization available to a user: -### -### 1. A set of 7 preconfigured styles selectable by name. - -### Available styles: -### ultimate1 <> extra sharp -### ultimate2 <> sharper & lighter ultimate -### ultimate3 <> ultimate: well balanced (default) -### ultimate4 <> darker & smoother -### ultimate5 <> darkest & heaviest ("MacIsh") -### osx <> Apple OS X -### windowsxp <> MS Windows XP - -### If you want to use a style from the list, uncomment the variable below -### and set its name as the value. - - -export INFINALITY_FT="ultimate3" - - -### 2. If you want to create a custom style, uncomment the variables below -### and enter the values of your choice. - - -#export INFINALITY_FT_FILTER_PARAMS="08 24 36 24 08" -#export INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH="0" -#export INFINALITY_FT_FRINGE_FILTER_STRENGTH="25" -#export INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH="0" -#export INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH="25" -#export INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH="25" -#export INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH="0" -#export INFINALITY_FT_STEM_ALIGNMENT_STRENGTH="15" -#export INFINALITY_FT_STEM_FITTING_STRENGTH="15" -#export INFINALITY_FT_STEM_DARKENING_AUTOFIT="false" -#export INFINALITY_FT_STEM_DARKENING_CFF="false" -#export INFINALITY_FT_GAMMA_CORRECTION="0 100" -#export INFINALITY_FT_BRIGHTNESS="0" -#export INFINALITY_FT_CONTRAST="0" -#export INFINALITY_FT_USE_VARIOUS_TWEAKS="true" -#export INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS="false" -#export INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT="0" -#export INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE="0" -#export INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS="false" - -### Please refer to "infinality-settings-generic" file for detailed explanation -### of customization options and provided examples. - -# vim:ft=sh: diff --git a/xft-settings.sh b/xft-settings.sh deleted file mode 100755 index 913a8bd76182..000000000000 --- a/xft-settings.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -XFT_SETTINGS=" -Xft.antialias: 1 -Xft.autohint: 0 -Xft.dpi: 96 -Xft.hinting: 1 -Xft.hintstyle: hintslight -Xft.lcdfilter: lcddefault -Xft.rgba: rgb -" - -echo "$XFT_SETTINGS" | xrdb -merge > /dev/null 2>&1 - -# vim:ft=sh: |