forked from minhngoc25a/freetype2
Change default LCD filter to be normalized and color-balanced.
Update documentation. * src/base/ftlcdfil.c (FT_Library_SetLcdFilter): Update `default_filter'.
This commit is contained in:
parent
98afe3f5c8
commit
01ce1c6a99
|
@ -1,3 +1,10 @@
|
||||||
|
2015-11-28 Nikolaus Waxweiler <madigens@gmail.com>
|
||||||
|
|
||||||
|
Change default LCD filter to be normalized and color-balanced.
|
||||||
|
|
||||||
|
* src/base/ftlcdfil.c (FT_Library_SetLcdFilter): Update
|
||||||
|
`default_filter'.
|
||||||
|
|
||||||
2015-11-28 Werner Lemberg <wl@gnu.org>
|
2015-11-28 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
[docmaker] Allow references to section names.
|
[docmaker] Allow references to section names.
|
||||||
|
|
|
@ -2828,9 +2828,14 @@ FT_BEGIN_HEADER
|
||||||
* @FT_LOAD_TARGET_MONO instead.
|
* @FT_LOAD_TARGET_MONO instead.
|
||||||
*
|
*
|
||||||
* FT_LOAD_TARGET_LIGHT ::
|
* FT_LOAD_TARGET_LIGHT ::
|
||||||
* A lighter hinting algorithm for non-monochrome modes. Many
|
* A lighter hinting algorithm for gray-level modes. Many generated
|
||||||
* generated glyphs are more fuzzy but better resemble its original
|
* glyphs are fuzzier but better resemble their original shape. This
|
||||||
* shape. A bit like rendering on Mac OS~X.
|
* is achieved by snapping glyphs to the pixel grid only vertically
|
||||||
|
* (Y-axis), as is done by Microsoft's ClearType and Adobe's
|
||||||
|
* proprietary font renderer. This preserves inter-glyph spacing in
|
||||||
|
* horizontal text. The snapping is done either by the native font
|
||||||
|
* driver if the driver itself and the font support it or by the
|
||||||
|
* auto-hinter.
|
||||||
*
|
*
|
||||||
* FT_LOAD_TARGET_MONO ::
|
* FT_LOAD_TARGET_MONO ::
|
||||||
* Strong hinting algorithm that should only be used for monochrome
|
* Strong hinting algorithm that should only be used for monochrome
|
||||||
|
@ -2937,7 +2942,10 @@ FT_BEGIN_HEADER
|
||||||
/* field in the @FT_GlyphSlotRec structure gives the format of the */
|
/* field in the @FT_GlyphSlotRec structure gives the format of the */
|
||||||
/* returned bitmap. */
|
/* returned bitmap. */
|
||||||
/* */
|
/* */
|
||||||
/* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity. */
|
/* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity, */
|
||||||
|
/* indicating pixel coverage. Use linear alpha blending and gamma */
|
||||||
|
/* correction to correctly render non-monochrome glyph bitmaps onto a */
|
||||||
|
/* surface; see @FT_Render_Glyph. */
|
||||||
/* */
|
/* */
|
||||||
/* <Values> */
|
/* <Values> */
|
||||||
/* FT_RENDER_MODE_NORMAL :: */
|
/* FT_RENDER_MODE_NORMAL :: */
|
||||||
|
@ -3007,6 +3015,82 @@ FT_BEGIN_HEADER
|
||||||
/* the glyph image format, finding the relevant renderer, and */
|
/* the glyph image format, finding the relevant renderer, and */
|
||||||
/* invoking it. */
|
/* invoking it. */
|
||||||
/* */
|
/* */
|
||||||
|
/* When FreeType outputs a bitmap of a glyph, it really outputs an */
|
||||||
|
/* alpha coverage map. If a pixel is completely covered by a */
|
||||||
|
/* filled-in outline, the bitmap contains 0xFF at that pixel, meaning */
|
||||||
|
/* that 0xFF/0xFF fraction of that pixel is covered, meaning the */
|
||||||
|
/* pixel is 100% black (or 0% bright). If a pixel is only 50% */
|
||||||
|
/* covered (value 0x80), the pixel is made 50% black (50% bright or a */
|
||||||
|
/* middle shade of grey). 0% covered means 0% black (100% bright or */
|
||||||
|
/* white). */
|
||||||
|
/* */
|
||||||
|
/* On high-DPI screens like on smartphones and tablets, the pixels */
|
||||||
|
/* are so small that their chance of being completely covered and */
|
||||||
|
/* therefore completely black are fairly good. On the low-DPI */
|
||||||
|
/* screens, however, the situation is different. The pixels are too */
|
||||||
|
/* large for most of the details of a glyph and shades of gray are */
|
||||||
|
/* the norm rather than the exception. */
|
||||||
|
/* */
|
||||||
|
/* This is relevant because all our screens have a second problem: */
|
||||||
|
/* they are not linear. 1~+~1 is not~2. Twice the value does not */
|
||||||
|
/* result in twice the brightness. When a pixel is only 50% covered, */
|
||||||
|
/* the coverage map says 50% black, and this translates to a pixel */
|
||||||
|
/* value of 128 when you use 8~bits per channel (0-255). However, */
|
||||||
|
/* this does not translate to 50% brightness for that pixel on our */
|
||||||
|
/* sRGB and gamma~2.2 screens. Due to their non-linearity, they */
|
||||||
|
/* dwell longer in the darks and only a pixel value of about 186 */
|
||||||
|
/* results in 50% brightness – 128 ends up too dark on both bright */
|
||||||
|
/* and dark backgrounds. The net result is that dark text looks */
|
||||||
|
/* burnt-out, pixely and blotchy on bright background, bright text */
|
||||||
|
/* too frail on dark backgrounds, and colored text on colored */
|
||||||
|
/* background (for example, red on green) seems to have dark halos or */
|
||||||
|
/* `dirt' around it. The situation is especially ugly for diagonal */
|
||||||
|
/* stems like in `w' glyph shapes where the quality of FreeType's */
|
||||||
|
/* anti-aliasing depends on the correct display of grays. On */
|
||||||
|
/* high-DPI screens where smaller, fully black pixels reign supreme, */
|
||||||
|
/* this doesn't matter, but on our low-DPI screens with all the gray */
|
||||||
|
/* shades, it does. 0% and 100% brightness are the same things in */
|
||||||
|
/* linear and non-linear space, just all the shades in-between */
|
||||||
|
/* aren't. */
|
||||||
|
/* */
|
||||||
|
/* The blending function for placing text over a background is */
|
||||||
|
/* */
|
||||||
|
/* { */
|
||||||
|
/* dst = alpha * src + (1 - alpha) * dst , */
|
||||||
|
/* } */
|
||||||
|
/* */
|
||||||
|
/* which is known as the OVER operator. */
|
||||||
|
/* */
|
||||||
|
/* To correctly composite an antialiased pixel of a glyph onto a */
|
||||||
|
/* surface, */
|
||||||
|
/* */
|
||||||
|
/* 1. take the foreground and background colors (e.g., in sRGB space) */
|
||||||
|
/* and apply gamma to get them in a linear space, */
|
||||||
|
/* */
|
||||||
|
/* 2. use OVER to blend the two linear colors using the glyph pixel */
|
||||||
|
/* as the alpha value (remember, the glyph bitmap is a coverage */
|
||||||
|
/* bitmap), and */
|
||||||
|
/* */
|
||||||
|
/* 3. apply inverse gamma to the blended pixel and write it back to */
|
||||||
|
/* the image. */
|
||||||
|
/* */
|
||||||
|
/* Internal testing at Adobe found that a target inverse gamma of~1.8 */
|
||||||
|
/* for step~3 gives good results across a wide range of displays with */
|
||||||
|
/* an sRGB gamma curve or a similar one. */
|
||||||
|
/* */
|
||||||
|
/* This process can cost performance. There is an approximation that */
|
||||||
|
/* does not need to know about the background color; see */
|
||||||
|
/* https://bel.fi/alankila/lcd/ and */
|
||||||
|
/* https://bel.fi/alankila/lcd/alpcor.html for details. */
|
||||||
|
/* */
|
||||||
|
/* *ATTENTION*: Linear blending is even more important when dealing */
|
||||||
|
/* with subpixel-rendered glyphs to prevent color-fringing! A */
|
||||||
|
/* subpixel-rendered glyph must first be filtered with a filter that */
|
||||||
|
/* gives equal weight to the three color primaries and does not */
|
||||||
|
/* exceed a sum of 0x100, see section @lcd_filtering. Then the */
|
||||||
|
/* only difference to gray linear blending is that subpixel-rendered */
|
||||||
|
/* linear blending is done 3~times per pixel. */
|
||||||
|
/* */
|
||||||
/* <InOut> */
|
/* <InOut> */
|
||||||
/* slot :: A handle to the glyph slot containing the image to */
|
/* slot :: A handle to the glyph slot containing the image to */
|
||||||
/* convert. */
|
/* convert. */
|
||||||
|
|
|
@ -445,13 +445,26 @@ FT_BEGIN_HEADER
|
||||||
* no-stem-darkening[autofit]
|
* no-stem-darkening[autofit]
|
||||||
*
|
*
|
||||||
* @description:
|
* @description:
|
||||||
* *Experimental* *only*
|
* *Experimental* *only,* *requires* *linear* *alpha* *blending* *and*
|
||||||
|
* *gamma* *correction*
|
||||||
*
|
*
|
||||||
* The main purpose of emboldening glyphs or `stem darkening' is to
|
* Stem darkening emboldens glyphs at smaller sizes to make them more
|
||||||
* enhance readability at smaller sizes. The smaller the size, the more
|
* readable on common low-DPI screens when using linear alpha blending
|
||||||
* emboldening is applied to keep glyphs from `thinning out'. All
|
* and gamma correction, see @FT_Render_Glyph. When not using linear
|
||||||
* glyphs that pass through the autohinter will be emboldened unless
|
* alpha blending and gamma correction, glyphs will appear heavy and
|
||||||
* this property is set to TRUE.
|
* fuzzy!
|
||||||
|
*
|
||||||
|
* Gamma correction essentially lightens fonts since shades of grey are
|
||||||
|
* shifted to higher pixel values (=~higher brightness) to match the
|
||||||
|
* original intention to the reality of our screens. The side-effect is
|
||||||
|
* that glyphs `thin out'. Mac OS~X and Adobe's proprietary font
|
||||||
|
* rendering library implement a counter-measure: stem darkening at
|
||||||
|
* smaller sizes where shades of gray dominate. By emboldening a glyph
|
||||||
|
* slightly in relation to its pixel size, individual pixels get higher
|
||||||
|
* coverage of filled-in outlines and are therefore `blacker'. This
|
||||||
|
* counteracts the `thinning out' of glyphs, making text remain readable
|
||||||
|
* at smaller sizes. All glyphs that pass through the auto-hinter will
|
||||||
|
* be emboldened unless this property is set to TRUE.
|
||||||
*
|
*
|
||||||
* See the description of the CFF driver for algorithmic details. Total
|
* See the description of the CFF driver for algorithmic details. Total
|
||||||
* consistency with the CFF driver is currently not achieved because the
|
* consistency with the CFF driver is currently not achieved because the
|
||||||
|
@ -460,18 +473,6 @@ FT_BEGIN_HEADER
|
||||||
* The smaller the size (especially 9ppem and down), the higher the loss
|
* The smaller the size (especially 9ppem and down), the higher the loss
|
||||||
* of emboldening versus the CFF driver.
|
* of emboldening versus the CFF driver.
|
||||||
*
|
*
|
||||||
* *ATTENTION*: This feature has been developed with linear alpha
|
|
||||||
* blending and gamma correction of glyphs in mind: A rendering library
|
|
||||||
* must apply linear alpha blending while compositing glyph bitmaps onto
|
|
||||||
* a surface and then apply gamma correction to the glyph pixels to get
|
|
||||||
* from linear space to display space (unless the display works in
|
|
||||||
* linear space). Internal testing at Adobe found that a gamma
|
|
||||||
* correction value of 1.8 gives good results across a wide range of
|
|
||||||
* displays with a sRGB gamma curve or a similar one.
|
|
||||||
*
|
|
||||||
* If this is not possible, it might be better to disable stem
|
|
||||||
* darkening. Currently, this can only be done globally.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,56 +41,76 @@ FT_BEGIN_HEADER
|
||||||
* LCD Filtering
|
* LCD Filtering
|
||||||
*
|
*
|
||||||
* @abstract:
|
* @abstract:
|
||||||
* Reduce color fringes of LCD-optimized bitmaps.
|
* Reduce color fringes of subpixel-rendered bitmaps.
|
||||||
*
|
*
|
||||||
* @description:
|
* @description:
|
||||||
* The @FT_Library_SetLcdFilter API can be used to specify a low-pass
|
* Subpixel rendering exploits the color-striped structure of LCD
|
||||||
* filter, which is then applied to LCD-optimized bitmaps generated
|
* pixels, increasing the available resolution in the direction of the
|
||||||
* through @FT_Render_Glyph. This is useful to reduce color fringes
|
* stripe (usually horizontal RGB) by a factor of~3. Since these
|
||||||
* that would occur with unfiltered rendering.
|
* subpixels are color pixels, using them unfiltered creates severe
|
||||||
|
* color fringes. Use the @FT_Library_SetLcdFilter API to specify a
|
||||||
|
* low-pass filter, which is then applied to subpixel-rendered bitmaps
|
||||||
|
* generated through @FT_Render_Glyph.
|
||||||
*
|
*
|
||||||
* Note that no filter is active by default, and that this function is
|
* Note that no filter is active by default, and that this function is
|
||||||
* *not* implemented in default builds of the library. You need to
|
* *not* implemented in default builds of the library. You need to
|
||||||
* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
|
* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
|
||||||
* in order to activate it.
|
* in order to activate it.
|
||||||
*
|
*
|
||||||
* FreeType generates alpha coverage maps, which are linear by nature.
|
* A filter should have two properties:
|
||||||
* For instance, the value 0x80 in bitmap representation means that
|
|
||||||
* (within numerical precision) 0x80/0xFF fraction of that pixel is
|
|
||||||
* covered by the glyph's outline. The blending function for placing
|
|
||||||
* text over a background is
|
|
||||||
*
|
*
|
||||||
* {
|
* 1) It should be normalized, meaning the sum of the 5~components
|
||||||
* dst = alpha * src + (1 - alpha) * dst ,
|
* should be 256 (0x100). It is possible to go above or under this
|
||||||
* }
|
* target sum, however: going under means tossing out contrast, going
|
||||||
|
* over means invoking clamping and thereby non-linearities that
|
||||||
|
* increase contrast somewhat at the expense of greater distortion
|
||||||
|
* and color-fringing. Contrast is better enhanced through stem
|
||||||
|
* darkening.
|
||||||
*
|
*
|
||||||
* which is known as OVER. However, when calculating the output of the
|
* 2) It should be color-balanced, meaning a filter `{~a, b, c, b, a~}'
|
||||||
* OVER operator, the source colors should first be transformed to a
|
* where a~+ b~=~c. It distributes the computed coverage for one
|
||||||
* linear color space, then alpha blended in that space, and transformed
|
* subpixel to all subpixels equally, sacrificing some won resolution
|
||||||
* back to the output color space.
|
* but drastically reducing color-fringing. Positioning improvements
|
||||||
|
* remain! Note that color-fringing can only really be minimized
|
||||||
|
* when using a color-balanced filter and alpha-blending the glyph
|
||||||
|
* onto a surface in linear space; see @FT_Render_Glyph.
|
||||||
*
|
*
|
||||||
* When linear light blending is used, the default FIR5 filtering
|
* Regarding the form, a filter can be a `boxy' filter or a `beveled'
|
||||||
* weights (as given by FT_LCD_FILTER_DEFAULT) are no longer optimal, as
|
* filter. Boxy filters are sharper but are less forgiving of non-ideal
|
||||||
* they have been designed for black on white rendering while lacking
|
* gamma curves of a screen (viewing angles!), beveled filters are
|
||||||
* gamma correction. To preserve color neutrality, weights for a FIR5
|
* fuzzier but more tolerant.
|
||||||
* filter should be chosen according to two free parameters `a' and `c',
|
|
||||||
* and the FIR weights should be
|
|
||||||
*
|
*
|
||||||
* {
|
* Examples:
|
||||||
* [a - c, a + c, 2 * a, a + c, a - c] .
|
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* This formula generates equal weights for all the color primaries
|
* - [0x10 0x40 0x70 0x40 0x10] is beveled and neither balanced nor
|
||||||
* across the filter kernel, which makes it colorless. One suggested
|
* normalized.
|
||||||
* set of weights is
|
|
||||||
*
|
*
|
||||||
* {
|
* - [0x1A 0x33 0x4D 0x33 0x1A] is beveled and balanced but not
|
||||||
* [0x10, 0x50, 0x60, 0x50, 0x10] ,
|
* normalized.
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* where `a' has value 0x30 and `c' value 0x20. The weights in filter
|
* - [0x19 0x33 0x66 0x4c 0x19] is beveled and normalized but not
|
||||||
* may have a sum larger than 0x100, which increases coloration slightly
|
* balanced.
|
||||||
* but also improves contrast.
|
*
|
||||||
|
* - [0x00 0x4c 0x66 0x4c 0x00] is boxily beveled and normalized but not
|
||||||
|
* balanced.
|
||||||
|
*
|
||||||
|
* - [0x00 0x55 0x56 0x55 0x00] is boxy, normalized, and almost
|
||||||
|
* balanced.
|
||||||
|
*
|
||||||
|
* - [0x08 0x4D 0x56 0x4D 0x08] is beveled, normalized and, almost
|
||||||
|
* balanced.
|
||||||
|
*
|
||||||
|
* It is important to understand that linear alpha blending and gamma
|
||||||
|
* correction is critical for correctly rendering glyphs onto surfaces
|
||||||
|
* without artifacts and even more critical when subpixel rendering is
|
||||||
|
* involved.
|
||||||
|
*
|
||||||
|
* Each of the 3~alpha values (subpixels) is independently used to blend
|
||||||
|
* one color channel. That is, red alpha blends the red channel of the
|
||||||
|
* text color with the red channel of the background pixel. The
|
||||||
|
* distribution of density values by the color-balanced filter assumes
|
||||||
|
* alpha blending is done in linear space; only then color artifacts
|
||||||
|
* cancel out.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,10 +131,21 @@ FT_BEGIN_HEADER
|
||||||
* The default filter reduces color fringes considerably, at the cost
|
* The default filter reduces color fringes considerably, at the cost
|
||||||
* of a slight blurriness in the output.
|
* of a slight blurriness in the output.
|
||||||
*
|
*
|
||||||
|
* It is a beveled, normalized, and color-balanced five-tap filter
|
||||||
|
* that is more forgiving to screens with non-ideal gamma curves and
|
||||||
|
* viewing angles. Note that while color-fringing is reduced, it can
|
||||||
|
* only be minimized by using linear alpha blending and gamma
|
||||||
|
* correction to render glyphs onto surfaces.
|
||||||
|
*
|
||||||
* FT_LCD_FILTER_LIGHT ::
|
* FT_LCD_FILTER_LIGHT ::
|
||||||
* The light filter is a variant that produces less blurriness at the
|
* The light filter is a variant that is sharper at the cost of
|
||||||
* cost of slightly more color fringes than the default one. It might
|
* slightly more color fringes than the default one.
|
||||||
* be better, depending on taste, your monitor, or your personal vision.
|
*
|
||||||
|
* It is a boxy, normalized, and color-balanced three-tap filter that
|
||||||
|
* is less forgiving to screens with non-ideal gamma curves and
|
||||||
|
* viewing angles. This filter works best when the rendering system
|
||||||
|
* uses linear alpha blending and gamma correction to render glyphs
|
||||||
|
* onto surfaces.
|
||||||
*
|
*
|
||||||
* FT_LCD_FILTER_LEGACY ::
|
* FT_LCD_FILTER_LEGACY ::
|
||||||
* This filter corresponds to the original libXft color filter. It
|
* This filter corresponds to the original libXft color filter. It
|
||||||
|
|
|
@ -305,12 +305,10 @@
|
||||||
FT_Library_SetLcdFilter( FT_Library library,
|
FT_Library_SetLcdFilter( FT_Library library,
|
||||||
FT_LcdFilter filter )
|
FT_LcdFilter filter )
|
||||||
{
|
{
|
||||||
|
static const FT_Byte default_filter[5] =
|
||||||
|
{ 0x08, 0x4d, 0x56, 0x4d, 0x08 };
|
||||||
static const FT_Byte light_filter[5] =
|
static const FT_Byte light_filter[5] =
|
||||||
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
|
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
|
||||||
/* the values here sum up to a value larger than 256, */
|
|
||||||
/* providing a cheap gamma correction */
|
|
||||||
static const FT_Byte default_filter[5] =
|
|
||||||
{ 0x10, 0x40, 0x70, 0x40, 0x10 };
|
|
||||||
|
|
||||||
|
|
||||||
if ( !library )
|
if ( !library )
|
||||||
|
|
Loading…
Reference in New Issue