From 2b0ac18990e7800aad568cf91dcb510ef9beff62 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 18 Feb 2017 10:42:23 +0100 Subject: [PATCH] Add face property for stem darkening. * include/freetype/ftautoh.h (FT_PARAM_TAG_STEM_DARKENING): New macro. * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): Add `no_stem_darkening' field. * src/autofit/afloader.c (af_loader_load_glyph), src/autofit/afmodule.c (af_property_set): Updated. * src/base/ftobjs.c: Include FT_AUTOHINTER_H. (ft_open_face_internal): Updated. (FT_Face_Properties): Handle FT_PARAM_TAG_STEM_DARKENING. * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Updated. * src/cff/cffdrivr.c (cff_property_set): Updated. --- ChangeLog | 22 ++++++++++++++++ include/freetype/freetype.h | 41 ++++++++++++++++++++++++++++++ include/freetype/ftautoh.h | 23 ++++++++++++++++- include/freetype/ftcffdrv.h | 2 ++ include/freetype/ftlcdfil.h | 3 +++ include/freetype/internal/ftobjs.h | 7 +++++ src/autofit/afloader.c | 8 +++++- src/autofit/afmodule.c | 8 +++--- src/base/ftobjs.c | 21 ++++++++++++++- src/cff/cf2ft.c | 9 ++++++- src/cff/cffdrivr.c | 8 +++--- 11 files changed, 138 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index f2b4dc168..68a914f14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2017-02-16 Nikolaus Waxweiler + Werner Lemberg + + Add face property for stem darkening. + + * include/freetype/ftautoh.h (FT_PARAM_TAG_STEM_DARKENING): New + macro. + + * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): Add + `no_stem_darkening' field. + + * src/autofit/afloader.c (af_loader_load_glyph), + src/autofit/afmodule.c (af_property_set): Updated. + + * src/base/ftobjs.c: Include FT_AUTOHINTER_H. + (ft_open_face_internal): Updated. + (FT_Face_Properties): Handle FT_PARAM_TAG_STEM_DARKENING. + + * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Updated. + + * src/cff/cffdrivr.c (cff_property_set): Updated. + 2017-02-16 Nikolaus Waxweiler Werner Lemberg diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index b902bc599..814e6052c 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -3629,6 +3629,10 @@ FT_BEGIN_HEADER * Note that only a subset of the available properties can be * controlled. * + * * Stem darkening (@FT_PARAM_TAG_STEM_DARKENING, corresponding to the + * property `no-stem-darkening' provided by the `autofit' and `cff' + * modules; see @auto_hinter and @cff_driver). + * * * LCD filter weights (@FT_PARAM_TAG_LCD_FILTER_WEIGHTS, corresponding * to function @FT_Library_SetLcdFilterWeights). * @@ -3648,6 +3652,43 @@ FT_BEGIN_HEADER * @return: * FreeType error code. 0~means success. * + * @note: + * Here an example that sets two properties. You must define + * FT_CONFIG_OPTION_SUBPIXEL_RENDERING to make the LCD filter examples + * work. + * + * { + * FT_Parameter property1; + * FT_Bool darken_stems = 1; + * + * FT_Parameter property2; + * FT_LcdFiveTapFilter custom_weight = + * { 0x10, 0x40, 0x70, 0x40, 0x10 }; + * + * FT_Parameter properties[2] = { property1, property2 }; + * + * + * property1.tag = FT_PARAM_TAG_STEM_DARKENING; + * property1.data = &darken_stems; + * + * property2.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; + * property2.data = custom_weight; + * + * FT_Face_Properties( face, 2, properties ); + * } + * + * The next example resets a single property to its default value. + * + * { + * FT_Parameter property; + * + * + * property.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; + * property.data = NULL; + * + * FT_Face_Option( face, 1, &property ); + * } + * */ FT_EXPORT( FT_Error ) FT_Face_Properties( FT_Face face, diff --git a/include/freetype/ftautoh.h b/include/freetype/ftautoh.h index 69f07cf78..dc00ae1ab 100644 --- a/include/freetype/ftautoh.h +++ b/include/freetype/ftautoh.h @@ -477,11 +477,32 @@ FT_BEGIN_HEADER * of emboldening versus the CFF driver. * * This property can be set via the `FREETYPE_PROPERTIES' environment - * variable similar to the CFF driver. + * variable similar to the CFF driver. It can also be set per face + * using @FT_Face_Properties with @FT_PARAM_TAG_STEM_DARKENING. * */ + /* + * @constant: + * FT_PARAM_TAG_STEM_DARKENING + * + * @description: + * An @FT_Parameter tag to be used with @FT_Face_Properties. The + * corresponding Boolean argument specifies whether to apply stem + * darkening, overriding the global default values or the values set up + * with @FT_Property_Set (see @no-stem-darkening[autofit] and + * @no-stem-darkening[cff]). + * + * This is a passive setting that only takes effect if the font driver + * or autohinter honors it, which the CFF driver always does, but the + * autohinter only in `light' hinting mode (as of version 2.7.0). + * + */ +#define FT_PARAM_TAG_STEM_DARKENING \ + FT_MAKE_TAG( 'd', 'a', 'r', 'k' ) + + /************************************************************************** * * @property: diff --git a/include/freetype/ftcffdrv.h b/include/freetype/ftcffdrv.h index 35758f8fb..a473389b8 100644 --- a/include/freetype/ftcffdrv.h +++ b/include/freetype/ftcffdrv.h @@ -203,6 +203,8 @@ FT_BEGIN_HEADER * * This property can be set via the `FREETYPE_PROPERTIES' environment * variable (using values 1 and 0 for `on' and `off', respectively). + * It can also be set per face using @FT_Face_Properties with + * @FT_PARAM_TAG_STEM_DARKENING. * */ diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h index 181d4db4e..a021c803b 100644 --- a/include/freetype/ftlcdfil.h +++ b/include/freetype/ftlcdfil.h @@ -268,6 +268,9 @@ FT_BEGIN_HEADER * defined in your build of the library, which should correspond to all * default builds of FreeType. * + * LCD filter weights can also be set per face using @FT_Face_Properties + * with @FT_PARAM_TAG_LCD_FILTER_WEIGHTS. + * * @since: * 2.4.0 */ diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h index cd2697ebc..5fa341fca 100644 --- a/include/freetype/internal/ftobjs.h +++ b/include/freetype/internal/ftobjs.h @@ -348,6 +348,11 @@ FT_BEGIN_HEADER /* @FT_Done_Face only destroys a face if the counter is~1, */ /* otherwise it simply decrements it. */ /* */ + /* no_stem_darkening :: */ + /* Overrides the module-level default, see @stem-darkening[cff], */ + /* for example. FALSE and TRUE toggle stem darkening on and off, */ + /* respectively, value~-1 means to use the module/driver default. */ + /* */ /* lcd_weights :: */ /* Overrides the library default with custom weights for the 5-tap */ /* FIR filter. `{0, 0, 0, 0, 0}' means to use the library default. */ @@ -366,6 +371,8 @@ FT_BEGIN_HEADER FT_Int refcount; + FT_Char no_stem_darkening; + #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING FT_LcdFiveTapFilter lcd_weights; /* preset or custom filter weights */ #endif diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c index 1dd9462ae..fb8ea3ce1 100644 --- a/src/autofit/afloader.c +++ b/src/autofit/afloader.c @@ -336,8 +336,14 @@ * `standard_{vertical,horizontal}_width' change. * * Ignore errors and carry on without emboldening. + * */ - if ( !module->no_stem_darkening ) + + /* stem darkening only works well in `light' mode */ + if ( scaler.render_mode == FT_RENDER_MODE_LIGHT && + ( !face->internal->no_stem_darkening || + ( face->internal->no_stem_darkening < 0 && + !module->no_stem_darkening ) ) ) af_loader_embolden_glyph_in_slot( loader, face, style_metrics ); loader->transformed = internal->glyph_transformed; diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c index 1566baf6e..9d7ba224d 100644 --- a/src/autofit/afmodule.c +++ b/src/autofit/afmodule.c @@ -304,12 +304,10 @@ long nsd = ft_strtol( s, NULL, 10 ); - if ( nsd == 0 ) - module->no_stem_darkening = 0; - else if ( nsd == 1 ) - module->no_stem_darkening = 1; + if ( !nsd ) + module->no_stem_darkening = FALSE; else - return FT_THROW( Invalid_Argument ); + module->no_stem_darkening = TRUE; } else #endif diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 5be56a14a..d9ce466f6 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -37,6 +37,8 @@ #include FT_SERVICE_KERNING_H #include FT_SERVICE_TRUETYPE_ENGINE_H +#include FT_AUTOHINTER_H + #ifdef FT_CONFIG_OPTION_MAC_FONTS #include "ftbase.h" #endif @@ -2425,6 +2427,8 @@ internal->refcount = 1; + internal->no_stem_darkening = -1; + #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING ft_memset( internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS ); #endif @@ -3611,7 +3615,22 @@ for ( ; num_properties > 0; num_properties-- ) { - if ( properties->tag == FT_PARAM_TAG_LCD_FILTER_WEIGHTS ) + if ( properties->tag == FT_PARAM_TAG_STEM_DARKENING ) + { + if ( properties->data ) + { + if ( *( (FT_Bool*)properties->data ) == TRUE ) + face->internal->no_stem_darkening = FALSE; + else + face->internal->no_stem_darkening = TRUE; + } + else + { + /* use module default */ + face->internal->no_stem_darkening = -1; + } + } + else if ( properties->tag == FT_PARAM_TAG_LCD_FILTER_WEIGHTS ) { #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING if ( properties->data ) diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c index c0d067e94..3a21a9bcb 100644 --- a/src/cff/cf2ft.c +++ b/src/cff/cf2ft.c @@ -340,6 +340,11 @@ CFF_Builder* builder = &decoder->builder; CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); + FT_Bool no_stem_darkening_driver = + driver->no_stem_darkening; + FT_Char no_stem_darkening_font = + builder->face->root.internal->no_stem_darkening; + /* local error */ FT_Error error2 = FT_Err_Ok; CF2_BufferRec buf; @@ -373,7 +378,9 @@ font->renderingFlags = 0; if ( hinted ) font->renderingFlags |= CF2_FlagsHinted; - if ( scaled && !driver->no_stem_darkening ) + if ( scaled && ( !no_stem_darkening_font || + ( no_stem_darkening_font < 0 && + !no_stem_darkening_driver ) ) ) font->renderingFlags |= CF2_FlagsDarkened; font->darkenParams[0] = driver->darken_params[0]; diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index cbafd7e7e..c0466d0c0 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -854,12 +854,10 @@ long nsd = ft_strtol( s, NULL, 10 ); - if ( nsd == 0 ) - driver->no_stem_darkening = 0; - else if ( nsd == 1 ) - driver->no_stem_darkening = 1; + if ( !nsd ) + driver->no_stem_darkening = FALSE; else - return FT_THROW( Invalid_Argument ); + driver->no_stem_darkening = TRUE; } else #endif