diff --git a/ChangeLog b/ChangeLog index c63c0f7be..c8aef2c09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,28 +1,48 @@ 2006-11-13 David Turner - * src/truetype/ttinterp.c: undefined the FIX_BYTECODE macro, - since the interpreter "enhancements" are still too buggy for - general use + * src/truetype/ttinterp.c (FIX_BYTECODE): Undefine. The interpreter + `enhancements' are still too buggy for general use. - * src/base/ftlcdfil.c: added support for FT_FORCE_LIGHT_LCD_FILTER - and FT_FORCE_LEGACY_LCD_FILTER at compile time. Define these macros - when building the library to change the default LCD filter to be - used. This is only useful for experimentation + * src/base/ftlcdfil.c: Add support for FT_FORCE_LIGHT_LCD_FILTER and + FT_FORCE_LEGACY_LCD_FILTER at compile time. Define these macros + when building the library to change the default LCD filter to be + used. This is only useful for experimentation. - * include/freetype/ftlcdfil.h: updating documentation + * include/freetype/ftlcdfil.h: Update documentation. 2006-11-10 David Turner - * include/freetype/ftlcdfil.h, include/internal/ftobjs.h, - src/base/ftlcdfilt.c, src/smooth/ftsmooth.c: API change for - the LCD filter, the FT_LcdFilter value is a enum describing - which filter to apply, new values FT_LCD_FILTER_LIGHT and - FT_LCD_FILTER_LEGACY (the latter implements the LibXft original - algorithm which produces incredible color fringes for everything - except very-well hinted text) + * src/smooth/ftsmooth.c: API change for the LCD + filter. The FT_LcdFilter value is an enumeration describing which + filter to apply, with new values FT_LCD_FILTER_LIGHT and + FT_LCD_FILTER_LEGACY (the latter implements the LibXft original + algorithm which produces strong color fringes for everything + except very-well hinted text). - * src/autofit/aflatin.c: various tiny improvements that drastically - improve the handling of serif fonts and of LCD/LCD_V hinting modes. + * include/freetype/ftlcdfil.h (FT_Library_SetLcdFilter): Change + second parameter to an enum type. + + * src/base/ftlcdfil.c (USE_LEGACY): Define. + (_ft_lcd_filter): Rename to... + (_ft_lcd_filter_fir): This. + Update parameters. + (_ft_lcd_filter_legacy) [USE_LEGACY]: New filter function. + (FT_Library_Set_LcdFilter): Update parameters. + Handle new filter modes. + + * include/internal/ftobjs.h: Include FT_LCD_FILTER_H. + (FT_Bitmap_LcdFilterFunc): Change third argument to `FT_Library'. + (FT_LibraryRec) [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Add filtering + callback and update other fields. + + * src/smooth/ftsmooth.c (ft_smooth_render_generic) + [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Update. + Other minor improvements. + + * src/autofit/aflatin.c: Various tiny improvements that drastically + improve the handling of serif fonts and of LCD/LCD_V hinting modes. + (af_latin_hints_compute_edges): Fix typo. + (af_latin_compute_stem_width): Take better care of diagonal stems. 2006-11-09 David Turner diff --git a/README b/README index 99750988c..51c56b2e0 100644 --- a/README +++ b/README @@ -51,7 +51,7 @@ ---------------------------------------------------------------------- -Copyright 2001-2006 by +Copyright 2006 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h index c9e9346f8..3a311d413 100644 --- a/include/freetype/ftlcdfil.h +++ b/include/freetype/ftlcdfil.h @@ -27,40 +27,39 @@ FT_BEGIN_HEADER - /**************************************************************************** - * - * @func: - * FT_LcdFilter - * - * @description: - * a list of values used to identify various types of LCD filters - * - * @values: - * FT_LCD_FILTER_NONE :: value 0 means do not perform filtering. when - * used with subpixel rendering, this will result in sometimes severe - * color fringes - * - * FT_LCD_FILTER_DEFAULT :: - * the default filter reduces color fringes considerably, at the cost of - * a slight bluriness in the output - * - * FT_LCD_FILTER_LIGHT :: - * the light filter is a variant that produces less bluriness - * at the cost of slightly more color fringes than the default one. It - * might be better than the default one, depending on your monitor and - * personal vision. - * - * FT_LCD_FILTER_LEGACY :: - * this filter corresponds to the original libXft color filter, this - * provides high contrast output, but can exhibit really bad color fringes - * if your glyphs are not extremely well hinted to the pixel grid. In - * other words, it only works well when enabling the TrueType bytecode - * interpreter *and* using high-quality hinted fonts. It will suck for - * all other cases. - * - * this filter is only provided for comparison purposes, and might be - * disabled/unsupported in the future... - */ + /**************************************************************************** + * + * @func: + * FT_LcdFilter + * + * @description: + * A list of values to identify various types of LCD filters. + * + * @values: + * FT_LCD_FILTER_NONE :: + * Do not perform filtering. When used with subpixel rendering, this + * results in sometimes severe color fringes. + * + * FT_LCD_FILTER_DEFAULT :: + * The default filter reduces color fringes considerably, at the cost + * of a slight blurriness in the output. + * + * FT_LCD_FILTER_LIGHT :: + * The light filter is a variant that produces less blurriness at the + * cost of slightly more color fringes than the default one. It might + * be better than the default one, depending on the monitor, personal + * vision, and taste. + * + * FT_LCD_FILTER_LEGACY :: + * This filter corresponds to the original libXft color filter. It + * provides high contrast output but can exhibit really bad color + * fringes if glyphs are not extremely well hinted to the pixel grid. + * In other words, it only works well if the TrueType bytecode + * interpreter is enabled *and* high-quality hinted fonts are used. + * + * This filter is only provided for comparison purposes, and might be + * disabled or stay unsupported in the future. + */ typedef enum { FT_LCD_FILTER_NONE = 0, @@ -84,9 +83,11 @@ FT_BEGIN_HEADER * @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V. * * @input: - * library :: A handle to the target library instance. + * library :: + * A handle to the target library instance. * - * filter :: filter type. + * filter :: + * The filter type. * * You can use @FT_LCD_FILTER_NONE here to disable this feature, or * @FT_LCD_FILTER_DEFAULT to use a default filter that should work @@ -97,8 +98,8 @@ FT_BEGIN_HEADER * * @note: * This feature is always disabled by default. Clients must make an - * explicit call to this function with a `filter' value other - * than @FT_LCD_FILTER_NONE in order to enable it. + * explicit call to this function with a `filter' value other than + * @FT_LCD_FILTER_NONE in order to enable it. * * Due to *PATENTS* covering subpixel rendering, this function doesn't * do anything except returning @FT_Err_Unimplemented_Feature if the @@ -106,8 +107,8 @@ FT_BEGIN_HEADER * defined in your build of the library, which should correspond to all * default builds of the library. * - * The filter affects glyph bitmaps rendered through FT_Render_Glyph, - * @@FT_Glyph_Get_Bitmap, @FT_Load_Glyph, and FT_Load_Char. + * The filter affects glyph bitmaps rendered through @FT_Render_Glyph, + * @FT_Glyph_Get_Bitmap, @FT_Load_Glyph, and @FT_Load_Char. * * It does _not_ affect the output of @FT_Outline_Render and * @FT_Outline_Get_Bitmap. diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index a8107356a..b6d859fa7 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -1538,6 +1538,7 @@ /* strong hinting process: snap the stem width to integer pixels */ FT_Pos org_dist = dist; + dist = af_latin_snap_width( axis->widths, axis->width_count, dist ); if ( vertical ) @@ -1573,14 +1574,15 @@ else if ( dist < 128 ) { - /* ok, we're only going to round to an integer width if - * the corresponding distorsion is less than 1/4 pixel - * otherwise, this really screws everything, since the - * diagonals, which are not hinted, will appear a lot - * more bolder or thinner than the vertical stems - */ + /* We only round to an integer width if the corresponding */ + /* distortion is less than 1/4 pixel. Otherwise this */ + /* makes everything worse since the diagonals, which are */ + /* not hinted, appear a lot bolder or thinner than the */ + /* vertical stems. */ + FT_Int delta; + dist = ( dist + 22 ) & ~63; delta = dist - org_dist; if ( delta < 0 ) @@ -1590,7 +1592,7 @@ { dist = org_dist; if ( dist < 48 ) - dist = (dist + 64) >> 1; + dist = ( dist + 64 ) >> 1; } } else diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c index 255e5814d..e0e9ccbe3 100644 --- a/src/base/ftlcdfil.c +++ b/src/base/ftlcdfil.c @@ -33,9 +33,9 @@ FT_Render_Mode mode, FT_Library library ) { - FT_Byte* weights = library->lcd_weights; - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; + FT_Byte* weights = library->lcd_weights; + FT_UInt width = (FT_UInt)bitmap->width; + FT_UInt height = (FT_UInt)bitmap->rows; /* horizontal in-place FIR filter */ @@ -160,24 +160,26 @@ #ifdef USE_LEGACY + /* FIR filter used by the default and light filters */ static void _ft_lcd_filter_legacy( FT_Bitmap* bitmap, FT_Render_Mode mode, FT_Library library ) { - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - FT_Int pitch = bitmap->pitch; + FT_UInt width = (FT_UInt)bitmap->width; + FT_UInt height = (FT_UInt)bitmap->rows; + FT_Int pitch = bitmap->pitch; - static const int filters[3][3] = + static const int filters[3][3] = { - { 65538*9/13, 65538*1/6, 65538*1/13 }, - { 65538*3/13, 65538*4/6, 65538*3/13 }, - { 65538*1/13, 65538*1/6, 65538*9/13 } + { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 }, + { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 }, + { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } }; - FT_UNUSED(library); + FT_UNUSED( library ); + /* horizontal in-place FIR filter */ if ( mode == FT_RENDER_MODE_LCD && width >= 3 ) @@ -189,6 +191,7 @@ { FT_UInt xx; + for ( xx = 0; xx < width; xx += 3 ) { FT_UInt r = 0; @@ -196,113 +199,132 @@ FT_UInt b = 0; FT_UInt p; + p = line[xx]; - r += filters[0][0]*p; - g += filters[0][1]*p; - b += filters[0][2]*p; + r += filters[0][0] * p; + g += filters[0][1] * p; + b += filters[0][2] * p; - p = line[xx+1]; - r += filters[1][0]*p; - g += filters[1][1]*p; - b += filters[1][2]*p; + p = line[xx + 1]; + r += filters[1][0] * p; + g += filters[1][1] * p; + b += filters[1][2] * p; - p = line[xx+2]; - r += filters[2][0]*p; - g += filters[2][1]*p; - b += filters[2][2]*p; + p = line[xx + 2]; + r += filters[2][0] * p; + g += filters[2][1] * p; + b += filters[2][2] * p; - line[xx] = (FT_Byte)( r / 65536 ); - line[xx+1] = (FT_Byte)( g / 65536 ); - line[xx+2] = (FT_Byte)( b / 65536 ); + line[xx] = (FT_Byte)( r / 65536 ); + line[xx + 1] = (FT_Byte)( g / 65536 ); + line[xx + 2] = (FT_Byte)( b / 65536 ); } } } else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 ) { - FT_Byte* column = bitmap->buffer; + FT_Byte* column = bitmap->buffer; + for ( ; width > 0; width--, column++ ) { - FT_Byte* col = column; - FT_Byte* col_end = col + height*pitch; + FT_Byte* col = column; + FT_Byte* col_end = col + height * pitch; - for ( ; col < col_end; col += 3*pitch ) + + for ( ; col < col_end; col += 3 * pitch ) { FT_UInt r = 0; FT_UInt g = 0; FT_UInt b = 0; FT_UInt p; + p = col[0]; - r += filters[0][0]*p; - g += filters[0][1]*p; - b += filters[0][2]*p; + r += filters[0][0] * p; + g += filters[0][1] * p; + b += filters[0][2] * p; - p = col[pitch]; - r += filters[1][0]*p; - g += filters[1][1]*p; - b += filters[1][2]*p; + p = col[pitch]; + r += filters[1][0] * p; + g += filters[1][1] * p; + b += filters[1][2] * p; - p = col[pitch*2]; - r += filters[2][0]*p; - g += filters[2][1]*p; - b += filters[2][2]*p; + p = col[pitch * 2]; + r += filters[2][0] * p; + g += filters[2][1] * p; + b += filters[2][2] * p; - col[0] = (FT_Byte)( r / 65536 ); - col[pitch] = (FT_Byte)( g / 65536 ); - col[2*pitch] = (FT_Byte)( b / 65536 ); + col[0] = (FT_Byte)( r / 65536 ); + col[pitch] = (FT_Byte)( g / 65536 ); + col[2 * pitch] = (FT_Byte)( b / 65536 ); } } } } + #endif /* USE_LEGACY */ + FT_EXPORT( FT_Error ) FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ) { - static const FT_Byte light_filter[5] = { 0, 85, 86, 85, 0 }; - static const FT_Byte default_filter[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 }; + static const FT_Byte light_filter[5] = + { 0, 85, 86, 85, 0 }; + static const FT_Byte default_filter[5] = + { 0x10, 0x40, 0x70, 0x40, 0x10 }; + if ( library == NULL ) return FT_Err_Invalid_Argument; switch ( filter ) { - case FT_LCD_FILTER_NONE: - library->lcd_filter_func = NULL; - library->lcd_extra = 0; - break; + case FT_LCD_FILTER_NONE: + library->lcd_filter_func = NULL; + library->lcd_extra = 0; + break; + + case FT_LCD_FILTER_DEFAULT: +#if defined( FT_FORCE_LEGACY_LCD_FILTER ) + + library->lcd_filter_func = _ft_lcd_filter_legacy; + library->lcd_extra = 0; + +#elif defined( FT_FORCE_LIGHT_LCD_FILTER ) + + memcpy( library->lcd_weights, default_filter, 5 ); + library->lcd_filter_func = _ft_lcd_filter_fir; + library->lcd_extra = 2; - case FT_LCD_FILTER_DEFAULT: -#if defined(FT_FORCE_LEGACY_LCD_FILTER) - library->lcd_filter_func = _ft_lcd_filter_legacy; - library->lcd_extra = 0; -#elif defined(FT_FORCE_LIGHT_LCD_FILTER) - memcpy( library->lcd_weights, default_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; #else - memcpy( library->lcd_weights, default_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; -#endif - break; - case FT_LCD_FILTER_LIGHT: - memcpy( library->lcd_weights, light_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; - break; + memcpy( library->lcd_weights, default_filter, 5 ); + library->lcd_filter_func = _ft_lcd_filter_fir; + library->lcd_extra = 2; + +#endif + + break; + + case FT_LCD_FILTER_LIGHT: + memcpy( library->lcd_weights, light_filter, 5 ); + library->lcd_filter_func = _ft_lcd_filter_fir; + library->lcd_extra = 2; + break; #ifdef USE_LEGACY - case FT_LCD_FILTER_LEGACY: - library->lcd_filter_func = _ft_lcd_filter_legacy; - library->lcd_extra = 0; - break; + + case FT_LCD_FILTER_LEGACY: + library->lcd_filter_func = _ft_lcd_filter_legacy; + library->lcd_extra = 0; + break; + #endif - default: - return FT_Err_Invalid_Argument; + + default: + return FT_Err_Invalid_Argument; } library->lcd_filter = filter; diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c index c7e4c7a4b..85d04eb45 100644 --- a/src/smooth/ftsmooth.c +++ b/src/smooth/ftsmooth.c @@ -175,18 +175,20 @@ { FT_Int extra = slot->library->lcd_extra; + if ( hmul ) { - x_shift -= 64*(extra >> 1); - width += 3*extra; + x_shift -= 64 * ( extra >> 1 ); + width += 3 * extra; pitch = FT_PAD_CEIL( width, 4 ); - x_left -= (extra >> 1); + x_left -= extra >> 1; } + if ( vmul ) { - y_shift -= 64*(extra >> 1); - height += 3*extra; - y_top += (extra >> 1); + y_shift -= 64 * ( extra >> 1 ); + height += 3 * extra; + y_top += extra >> 1; } }