New revision. Reverts the no_stem_darkening rename, typedefs FT_Byte lcd_weight[5] and uses memset in a few places to avoid creating an emtpy LCD filter.
So far, I have not received comments from Behdad or Qt people on the API as such, however one person on the Qt development list said that he wouldn't like the automatic toggling of the autohinter for font drivers that can't darken stems by themselves. I think that even without the new API, toolkits can already make an informed decision about whether to enable stem darkening or not: by querying the no-stem-darkening property of a driver or the autohinter. If FT_Property_Get returns an error indicating the property doesn't exist, the driver/autohinter probably doesn't darken stems. So now I'm also thinking about how to implement stem darkening in the TrueType driver. The first problem would be to determine the stem widths, but a first version could use the heuristic Dave Arnold described a while back: using fixed values according to what weight a font advertises itself. Problems begin with hinting, as the concept of stem darkening is somewhat incompatible with the explicit programming of TrueType hints. On v40 in backwards compatibility mode, where hinting on the x-axis is ignored, this is less of a problem, because you can just darken vertical stems only. In v40 native mode, (tricky) fonts can modify points on the x-axis. Dave Arnold mentioned that Adobe's software lessens the darkening in that case because many fonts snap vertical stems to pixel boundaries, thereby darkening them already. Some don't, however, so you'd have to darken them normally. Ideally, you measure stems after the hinting process... Not sure if an acceptable solution can be found here so that stem darkening can just be toggled for the TrueType driver and then forgotten about.
From 9d77a2faac41dd39caeadaa13889d286a3023649 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler <[email protected]> Date: Sun, 20 Nov 2016 18:00:01 +0100 Subject: [PATCH 1/2] Implement FT_Face_Option() [1/2] FT_Face_Option() can override certain library or module-wide options on a face-by-face basis. These options are stored in the 'internal' structure of a FT_Face. They are "unset" by default. First up are custom LCD filter weights. * Implement FT_Face_Option() and declare the option tags. * Implement the code to honors the face-level LCD filter option. * Make the default and light filter weights publicly accessible as FT_LCD_FILTER_DEFAULT_WEIGHTS and FT_LCD_FILTER_LIGHT_WEIGHTS. * Modify the signature of FT_Bitmap_LcdFilterFunc to take FT_Byte* instead of FT_Library as the last argument, change _ft_lcd_filter_fir and _ft_lcd_filter_legacy accordingly. * Rename _ft_lcd_filter_fir to ft_lcd_filter_fir and make it accessible from within the FreeType source. --- include/freetype/freetype.h | 80 ++++++++++++++++++++++++++++++++++++++ include/freetype/ftlcdfil.h | 10 +++++ include/freetype/internal/ftobjs.h | 25 +++++++++++- src/base/ftlcdfil.c | 41 ++++++++++--------- src/base/ftobjs.c | 65 +++++++++++++++++++++++++++++++ src/smooth/ftsmooth.c | 62 +++++++++++++++++++++++------ 6 files changed, 250 insertions(+), 33 deletions(-) diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index f3287b7..0ae2598 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -3578,6 +3578,86 @@ FT_BEGIN_HEADER /*************************************************************************/ + /* + * <Function> + * FT_Face_Option + * + * <Description> + * This function can be used to set or override certain (library or + * module-wide) options on a face-by-face basis. Useful for finer grained + * control and avoiding locks on shared structures (threads can modify + * their own faces as they see fit). + * + * <Input> + * face :: A handle to the source face object. + * num_params :: The number of parameters that follow. + * parameters :: A handle to the num_params FT_Parameters. + * + * <Return> + * FreeType error code. 0~means success. + * + * <Note> + * The accepted parameters are: + * + * 1) FT_FACE_OPTION_ENABLE_STEM_DARKENING: + * Toggles stem darkening. Overrides the module setting. + * + * Currently implies forcing the native CFF engine for OpenType/CFF + * fonts and the (LIGHT) autohinter for all other outline formats, as + * only those engines have full control over how an outline is + * rendered. + * + * 2) FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS: + * Sets the weights for the 5-tap in-place FIR filter used by default + * (the legacy intra-pixel filter is not supported). Overrides the + * library setting. See @lcd_filtering. + * + * Pass NULL as data for a tag to reset the option and use the library or + * module default again. + * + * Example: + * { + * // Define FT_CONFIG_OPTION_SUBPIXEL_RENDERING for the LCD filter + * // examples to work. + * + * FT_Parameter parameter1; + * FT_Bool darken_stems = 1; + * parameter1.tag = FT_FACE_OPTION_ENABLE_STEM_DARKENING; + * parameter1.data = &darken_stems; + * + * FT_Parameter parameter2; + * FT_LcdFiveTapFilter custom_weight = { 0x10, 0x40, 0x70, 0x40, 0x10 }; + * parameter2.tag = FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS; + * parameter2.data = custom_weight; + * + * FT_Parameter parameters[2] = { parameter1, parameter2 }; + * + * FT_Face_Option( face, 2, parameters ); + * + * // Switch options around. + * darken_stems = 0; + * ft_memcpy(parameters[1].data, FT_LCD_FILTER_LIGHT_WEIGHTS, FT_LCD_FILTER_FIVE_TAPS); + * + * FT_Face_Option( face, 2, parameters ); + * + * // Example for a single option. + * FT_Parameter parameter3; + * parameter3.tag = FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS; + * parameter3.data = NULL; // Reset option to driver/module default + * + * FT_Face_Option( face, 1, ¶meter3 ); + * } + */ + FT_EXPORT( FT_Error ) + FT_Face_Option( FT_Face face, + FT_UInt num_params, + FT_Parameter* parameters); + +#define FT_FACE_OPTION_ENABLE_STEM_DARKENING FT_MAKE_TAG( 'd', 'a', 'r', 'k' ) +#define FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS FT_MAKE_TAG( 'l', 'c', 'd', 'f' ) + + + /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Name_Index */ diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h index e06a895..cc3338f 100644 --- a/include/freetype/ftlcdfil.h +++ b/include/freetype/ftlcdfil.h @@ -197,6 +197,16 @@ FT_BEGIN_HEADER } FT_LcdFilter; + #define FT_LCD_FILTER_FIVE_TAPS 5 + + typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS]; + + static const FT_LcdFiveTapFilter FT_LCD_FILTER_DEFAULT_WEIGHTS = + { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; + static const FT_LcdFiveTapFilter FT_LCD_FILTER_LIGHT_WEIGHTS = + { 0x00, 0x55, 0x56, 0x55, 0x00 }; + + /************************************************************************** * diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h index 15936f2..d54e4ec 100644 --- a/include/freetype/internal/ftobjs.h +++ b/include/freetype/internal/ftobjs.h @@ -347,6 +347,16 @@ FT_BEGIN_HEADER /* created. @FT_Reference_Face increments this counter, and */ /* @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 e.g. @stem-darkening[cff]. + * FALSE and TRUE toggle stem darkening on and off, respectively, -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. + */ /* */ typedef struct FT_Face_InternalRec_ { @@ -362,6 +372,11 @@ 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 } FT_Face_InternalRec; @@ -779,7 +794,13 @@ FT_BEGIN_HEADER typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap, FT_Render_Mode render_mode, - FT_Library library ); + 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 ); /*************************************************************************/ @@ -875,7 +896,7 @@ FT_BEGIN_HEADER #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING FT_LcdFilter lcd_filter; FT_Int lcd_extra; /* number of extra pixels */ - FT_Byte lcd_weights[5]; /* filter weights, if any */ + FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */ FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ #endif diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c index 8bcbed7..2c1a72e 100644 --- a/src/base/ftlcdfil.c +++ b/src/base/ftlcdfil.c @@ -30,12 +30,11 @@ #define USE_LEGACY /* FIR filter used by the default and light filters */ - static void - _ft_lcd_filter_fir( FT_Bitmap* bitmap, - FT_Render_Mode mode, - FT_Library library ) + FT_BASE( void ) + ft_lcd_filter_fir( FT_Bitmap* bitmap, + FT_Render_Mode mode, + FT_LcdFiveTapFilter weights ) { - FT_Byte* weights = library->lcd_weights; FT_UInt width = (FT_UInt)bitmap->width; FT_UInt height = (FT_UInt)bitmap->rows; @@ -176,7 +175,7 @@ static void _ft_lcd_filter_legacy( FT_Bitmap* bitmap, FT_Render_Mode mode, - FT_Library library ) + FT_Byte* weights ) { FT_UInt width = (FT_UInt)bitmap->width; FT_UInt height = (FT_UInt)bitmap->rows; @@ -189,7 +188,7 @@ { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } }; - FT_UNUSED( library ); + FT_UNUSED( weights ); /* horizontal in-place intra-pixel filter */ @@ -295,8 +294,8 @@ if ( !weights ) return FT_THROW( Invalid_Argument ); - ft_memcpy( library->lcd_weights, weights, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; + 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; @@ -307,12 +306,6 @@ FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ) { - static const FT_Byte default_filter[5] = - { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; - static const FT_Byte light_filter[5] = - { 0x00, 0x55, 0x56, 0x55, 0x00 }; - - if ( !library ) return FT_THROW( Invalid_Library_Handle ); @@ -324,14 +317,14 @@ break; case FT_LCD_FILTER_DEFAULT: - ft_memcpy( library->lcd_weights, default_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; + ft_memcpy( library->lcd_weights, FT_LCD_FILTER_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: - ft_memcpy( library->lcd_weights, light_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; + ft_memcpy( library->lcd_weights, FT_LCD_FILTER_LIGHT_WEIGHTS, FT_LCD_FILTER_FIVE_TAPS ); + library->lcd_filter_func = ft_lcd_filter_fir; library->lcd_extra = 2; break; @@ -356,6 +349,16 @@ #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + FT_BASE( void ) + ft_lcd_filter_fir( FT_Bitmap* bitmap, + FT_Render_Mode mode, + FT_LcdFiveTapFilter weights ) + { + FT_UNUSED( bitmap ); + FT_UNUSED( mode ); + FT_UNUSED( weights ); + } + FT_EXPORT_DEF( FT_Error ) FT_Library_SetLcdFilterWeights( FT_Library library, unsigned char *weights ) diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index c701ebc..cd78424 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -2352,6 +2352,11 @@ internal->transform_delta.y = 0; 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 } if ( aface ) @@ -3506,6 +3511,66 @@ /* documentation is in freetype.h */ + FT_EXPORT_DEF( FT_Error ) + FT_Face_Option( FT_Face face, + FT_UInt num_params, + FT_Parameter* parameters) + { + FT_Error error = FT_Err_Ok; + + + if ( num_params > 0 && !parameters ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + for ( ; num_params > 0; num_params-- ) + { + if ( parameters->tag == FT_FACE_OPTION_ENABLE_STEM_DARKENING ) + { + if ( parameters->data ) + { + if ( *((FT_Bool*)parameters->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 ( parameters->tag == FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS ) + { +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + if ( parameters->data ) + ft_memcpy( face->internal->lcd_weights, parameters->data, FT_LCD_FILTER_FIVE_TAPS ); + else /* NULL == no custom weights, use library default. Signaled by + filling the weight field with zeros. */ + ft_memset( face->internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS ); +#else + error = FT_THROW( Unimplemented_Feature ); + goto Exit; +#endif + } + else + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( error ) + break; + + parameters++; + } + + Exit: + return error; + } + + + /* documentation is in freetype.h */ + FT_EXPORT_DEF( FT_UInt ) FT_Face_GetCharVariantIndex( FT_Face face, FT_ULong charcode, diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c index 1371792..f9a50d5 100644 --- a/src/smooth/ftsmooth.c +++ b/src/smooth/ftsmooth.c @@ -122,6 +122,47 @@ FT_Bool have_outline_shifted = FALSE; FT_Bool have_buffer = FALSE; +#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 weight_i = 0; + + for ( ; weight_i < FT_LCD_FILTER_FIVE_TAPS; weight_i++ ) + if ( slot->face->internal->lcd_weights[weight_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 will always use the default 5-tap + * in-place FIR filter that needs 2 extra pixels. */ + lcd_filter_func = ft_lcd_filter_fir; + lcd_extra = 2; + ft_memcpy( lcd_weights, slot->face->internal->lcd_weights, FT_LCD_FILTER_FIVE_TAPS ); + } + else + { + /* The face's lcd_weights is {0, 0, 0, 0, 0}, use library default. If the + * library is set to use no LCD filtering (lcd_filter_func == NULL), + * lcd_filter_func here will also be set to NULL and the tests further + * below will pass over the filtering process. */ + lcd_filter_func = slot->library->lcd_filter_func; + lcd_extra = slot->library->lcd_extra; + ft_memcpy( lcd_weights, slot->library->lcd_weights, FT_LCD_FILTER_FIVE_TAPS ); + } +#endif + /* check glyph image format */ if ( slot->format != render->glyph_format ) @@ -178,24 +219,21 @@ #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - if ( slot->library->lcd_filter_func ) + if ( lcd_filter_func ) { - FT_Int extra = slot->library->lcd_extra; - - if ( hmul ) { - x_shift += 64 * ( extra >> 1 ); - x_left -= extra >> 1; - width += 3 * extra; + x_shift += 64 * ( lcd_extra >> 1 ); + x_left -= lcd_extra >> 1; + width += 3 * lcd_extra; pitch = FT_PAD_CEIL( width, 4 ); } if ( vmul ) { - y_shift += 64 * ( extra >> 1 ); - y_top += extra >> 1; - height += 3 * extra; + y_shift += 64 * ( lcd_extra >> 1 ); + y_top += lcd_extra >> 1; + height += 3 * lcd_extra; } } @@ -299,8 +337,8 @@ if ( error ) goto Exit; - if ( slot->library->lcd_filter_func ) - slot->library->lcd_filter_func( bitmap, mode, slot->library ); + if ( lcd_filter_func ) + lcd_filter_func( bitmap, mode, lcd_weights ); #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ -- 2.9.3
From 055afba8dc8427d90b65cf374e06ab720ba31823 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler <[email protected]> Date: Sun, 20 Nov 2016 18:08:08 +0100 Subject: [PATCH 2/2] Implement FT_Face_Option() [2/2] Next up is the stem darkening option. * Honor the face-level option in the CFF driver and autohinter. * Change FT_Load_Glyph() to trigger the autohinter for font drivers that can't darken stems by themselves. This currently means all of them except for the CFF driver. Within the autohinter, enforce LIGHT mode because stem darkening currently only really works there. --- src/autofit/afloader.c | 10 +++++++++- src/autofit/afmodule.c | 8 ++++---- src/base/ftobjs.c | 18 ++++++++++++++++-- src/cff/cf2ft.c | 7 ++++++- src/cff/cffdrivr.c | 8 ++++---- 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c index 26bba06..b214514 100644 --- a/src/autofit/afloader.c +++ b/src/autofit/afloader.c @@ -135,7 +135,9 @@ * must therefore be recomputed for each size and * `standard_{vertical,horizontal}_width' change. */ - if ( !module->no_stem_darkening ) + if ( face->internal->no_stem_darkening == FALSE || + ( face->internal->no_stem_darkening < 0 && + !module->no_stem_darkening ) ) { AF_FaceGlobals globals = loader->globals; AF_WritingSystemClass writing_system_class; @@ -492,6 +494,12 @@ scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags ); scaler.flags = 0; /* XXX: fix this */ + /* Stem darkening only works well in LIGHT mode. */ + if ( face->internal->no_stem_darkening == FALSE || + ( face->internal->no_stem_darkening < 0 && + !module->no_stem_darkening ) ) + scaler.render_mode = FT_RENDER_MODE_LIGHT; + error = af_loader_reset( loader, module, face ); if ( !error ) { diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c index f325ebf..caaf594 100644 --- a/src/autofit/afmodule.c +++ b/src/autofit/afmodule.c @@ -291,10 +291,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 == FALSE ) + module->no_stem_darkening = FALSE; + else if ( nsd == TRUE ) + module->no_stem_darkening = TRUE; else return FT_THROW( Invalid_Argument ); } diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index cd78424..1ec1b0f 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -612,7 +612,9 @@ FT_Bool autohint = FALSE; FT_Module hinter; TT_Face ttface = (TT_Face)face; - + FT_Bool driver_can_darken_stems = FALSE; + FT_Bool stem_darkening = FALSE; + FT_Bool no_stem_darkening_driver = TRUE; if ( !face || !face->size || !face->glyph ) return FT_THROW( Invalid_Face_Handle ); @@ -627,8 +629,19 @@ library = driver->root.library; hinter = library->auto_hinter; - /* resolve load flags dependencies */ + /* Determine if stem darkening is to be applied. */ + error = FT_Property_Get( library, driver->clazz->root.module_name, + "no-stem-darkening", &no_stem_darkening_driver ); + if ( !error ) + driver_can_darken_stems = TRUE; + error = FT_Err_Ok; /* Reset error variable. */ + + stem_darkening = ( face->internal->no_stem_darkening == FALSE || + ( face->internal->no_stem_darkening < 0 && + !no_stem_darkening_driver ) ); + + /* resolve load flags dependencies */ if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM; @@ -691,6 +704,7 @@ /* both `fpgm' and `prep' tables are missing */ if ( ( mode == FT_RENDER_MODE_LIGHT && !FT_DRIVER_HINTS_LIGHTLY( driver ) ) || + ( stem_darkening && !driver_can_darken_stems ) || ( FT_IS_SFNT( face ) && ttface->num_locations && ttface->max_profile.maxSizeOfInstructions == 0 && diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c index edbe6a7..1b349d3 100644 --- a/src/cff/cf2ft.c +++ b/src/cff/cf2ft.c @@ -339,6 +339,9 @@ 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; @@ -369,7 +372,9 @@ font->renderingFlags = 0; if ( hinted ) font->renderingFlags |= CF2_FlagsHinted; - if ( scaled && !driver->no_stem_darkening ) + if ( scaled && ( no_stem_darkening_font == FALSE || + ( 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 cf02477..d1b35cf 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -779,10 +779,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 == FALSE ) + driver->no_stem_darkening = FALSE; + else if ( nsd == TRUE ) + driver->no_stem_darkening = TRUE; else return FT_THROW( Invalid_Argument ); } -- 2.9.3
_______________________________________________ Freetype-devel mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/freetype-devel
