[smooth] Harmony LCD rendering.

This is a new technology for LCD-optimized rendering. It capitalizes
on the fact that each color channel grid is shifted by a third of a
pixel.  Therefore it is logical to render 3 separate monochrome
bitmaps shifting the outline by 1/3 pixel, and then combine them.
Importantly, the resulting output does not require additional LCD
filtering.

* src/smooth/ftsmooth.c (ft_smooth_render_generic)
[!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Implement new LCD-optimized
rendering.

* include/freetype/ftlcdfil.h, include/freetype/freetype.h,
include/freetype/config/ftoption.h, devel/ftoption.h: Updated
documentation.
This commit is contained in:
Alexei Podtelezhnikov 2017-03-09 00:08:38 -05:00
parent 5710ef989d
commit 410f3799b6
6 changed files with 150 additions and 77 deletions

View File

@ -1,3 +1,22 @@
2017-08-08 Alexei Podtelezhnikov <apodtele@gmail.com>
[smooth] Harmony LCD rendering.
This is a new technology for LCD-optimized rendering. It capitalizes
on the fact that each color channel grid is shifted by a third of a
pixel. Therefore it is logical to render 3 separate monochrome
bitmaps shifting the outline by 1/3 pixel, and then combine them.
Importantly, the resulting output does not require additional LCD
filtering.
* src/smooth/ftsmooth.c (ft_smooth_render_generic)
[!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Implement new LCD-optimized
rendering.
* include/freetype/ftlcdfil.h, include/freetype/freetype.h,
include/freetype/config/ftoption.h, devel/ftoption.h: Updated
documentation.
2017-08-08 Alexei Podtelezhnikov <apodtele@gmail.com> 2017-08-08 Alexei Podtelezhnikov <apodtele@gmail.com>
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Clean up. * src/smooth/ftsmooth.c (ft_smooth_render_generic): Clean up.

View File

@ -107,22 +107,19 @@ FT_BEGIN_HEADER
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* Uncomment the line below if you want to activate sub-pixel rendering */ /* Uncomment the line below if you want to activate LCD rendering */
/* (a.k.a. LCD rendering, or ClearType) in this build of the library. */ /* 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 */ /* Note that this feature is covered by several Microsoft patents */
/* and should not be activated in any default build of the library. */ /* 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. */
/* */ /* */
/* This macro has no impact on the FreeType API, only on its */ /* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */
/* FT_Render_Glyph still generates a bitmap that is 3 times wider than */
/* the original size in case this macro isn't defined; however, each */
/* triplet of subpixels has R=G=B. */
/* */
/* This is done to allow FreeType clients to run unmodified, forcing */
/* them to display normal gray-level anti-aliased glyphs. */
/* */
#define FT_CONFIG_OPTION_SUBPIXEL_RENDERING
/*************************************************************************/ /*************************************************************************/

View File

@ -107,20 +107,17 @@ FT_BEGIN_HEADER
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* Uncomment the line below if you want to activate sub-pixel rendering */ /* Uncomment the line below if you want to activate LCD rendering */
/* (a.k.a. LCD rendering, or ClearType) in this build of the library. */ /* 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 */ /* Note that this feature is covered by several Microsoft patents */
/* and should not be activated in any default build of the library. */ /* and should not be activated in any default build of the library. */
/* */ /* When this macro is not defined, FreeType offers alternative LCD */
/* This macro has no impact on the FreeType API, only on its */ /* rendering technology that produces excellent output without LCD */
/* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */ /* filtering. */
/* FT_Render_Glyph still generates a bitmap that is 3 times wider than */
/* the original size in case this macro isn't defined; however, each */
/* triplet of subpixels has R=G=B. */
/* */
/* This is done to allow FreeType clients to run unmodified, forcing */
/* them to display normal gray-level anti-aliased glyphs. */
/* */ /* */
/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ /* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */

View File

@ -3131,11 +3131,13 @@ FT_BEGIN_HEADER
/* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */ /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */
/* */ /* */
/* <Note> */ /* <Note> */
/* The LCD-optimized glyph bitmaps produced by `FT_Render_Glyph' can */ /* Should you define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your */
/* be filtered to reduce color-fringes by using */ /* `ftoption.h', which enables patented ClearType-style rendering, */
/* @FT_Library_SetLcdFilter (not active in the default builds). It */ /* the LCD-optimized glyph bitmaps should be filtered to reduce color */
/* is up to the caller to either call `FT_Library_SetLcdFilter' (if */ /* fringes inherent to this technology. You can either set up LCD */
/* available) or do the filtering itself. */ /* filtering with @FT_Library_SetLcdFilter or @FT_Face_Properties, */
/* or do the filtering yourself. The default FreeType LCD rendering */
/* technology does not require filtering. */
/* */ /* */
/* The selected render mode only affects vector glyphs of a font. */ /* The selected render mode only affects vector glyphs of a font. */
/* Embedded bitmaps often have a different pixel mode like */ /* Embedded bitmaps often have a different pixel mode like */

View File

@ -44,9 +44,16 @@ FT_BEGIN_HEADER
* Reduce color fringes of subpixel-rendered bitmaps. * Reduce color fringes of subpixel-rendered bitmaps.
* *
* @description: * @description:
* Subpixel rendering exploits the color-striped structure of LCD * Should you #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your
* pixels, increasing the available resolution in the direction of the * `ftoption.h', which enables patented ClearType-style rendering,
* stripe (usually horizontal RGB) by a factor of~3. Since these * the LCD-optimized glyph bitmaps should be filtered to reduce color
* fringes inherent to this technology. The default FreeType LCD
* rendering uses different technology, and API described below,
* although available, does nothing.
*
* ClearType-style LCD rendering exploits the color-striped structure of
* LCD pixels, increasing the available resolution in the direction of
* the stripe (usually horizontal RGB) by a factor of~3. Since these
* subpixels are color pixels, using them unfiltered creates severe * subpixels are color pixels, using them unfiltered creates severe
* color fringes. Use the @FT_Library_SetLcdFilter API to specify a * color fringes. Use the @FT_Library_SetLcdFilter API to specify a
* low-pass filter, which is then applied to subpixel-rendered bitmaps * low-pass filter, which is then applied to subpixel-rendered bitmaps
@ -54,12 +61,6 @@ FT_BEGIN_HEADER
* the higher resolution to reduce color fringes, making the glyph image * the higher resolution to reduce color fringes, making the glyph image
* slightly blurrier. Positional improvements will remain. * slightly blurrier. Positional improvements will remain.
* *
* Note that no filter is active by default, and that this function is
* *not* implemented in default builds of the library. You need to
* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
* in order to activate it and explicitly call @FT_Library_SetLcdFilter
* to enable it.
*
* A filter should have two properties: * A filter should have two properties:
* *
* 1) It should be normalized, meaning the sum of the 5~components * 1) It should be normalized, meaning the sum of the 5~components

View File

@ -190,7 +190,23 @@
/* taking into account the origin shift */ /* taking into account the origin shift */
FT_Outline_Get_CBox( outline, &cbox ); FT_Outline_Get_CBox( outline, &cbox );
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
/* add minimal padding for LCD rendering */
if ( hmul )
{
cbox.xMax += 21;
cbox.xMin -= 21;
}
if ( vmul )
{
cbox.yMax += 21;
cbox.yMin -= 21;
}
#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* add minimal padding for LCD filter depending on specific weights */ /* add minimal padding for LCD filter depending on specific weights */
if ( lcd_filter_func ) if ( lcd_filter_func )
{ {
@ -210,7 +226,8 @@
: lcd_weights[1] ? 22 : 0; : lcd_weights[1] ? 22 : 0;
} }
} }
#endif
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift ); cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift ); cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
@ -339,57 +356,97 @@
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* render outline into bitmap */ if ( hmul ) /* lcd */
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
/* expand it horizontally */
if ( hmul )
{ {
FT_Byte* line = bitmap->buffer; FT_Byte* line;
FT_UInt hh; FT_Byte* temp;
FT_Int i, j;
/* Render 3 separate monochrome bitmaps, shifting the outline */
/* by 1/3 pixel. */
width /= 3;
for ( hh = height; hh > 0; hh--, line += pitch ) FT_Outline_Translate( outline, 21, 0 );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, -21, 0 );
bitmap->buffer += width;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, -21, 0 );
bitmap->buffer += width;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, 21, 0 );
bitmap->buffer -= 2 * width;
/* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */
/* XXX: It is more efficient to render every third byte above. */
if ( FT_ALLOC( temp, (FT_ULong)pitch ) )
goto Exit;
for ( i = 0; i < height; i++ )
{ {
FT_UInt xx; line = bitmap->buffer + i * pitch;
FT_Byte* end = line + width; for ( j = 0; j < width; j++ )
for ( xx = width / 3; xx > 0; xx-- )
{ {
FT_UInt pixel = line[xx-1]; temp[3 * j ] = line[j];
temp[3 * j + 1] = line[j + width];
temp[3 * j + 2] = line[j + width + width];
end[-3] = (FT_Byte)pixel;
end[-2] = (FT_Byte)pixel;
end[-1] = (FT_Byte)pixel;
end -= 3;
} }
FT_MEM_COPY( line, temp, pitch );
} }
FT_FREE( temp );
} }
else if ( vmul ) /* lcd_v */
/* expand it vertically */
if ( vmul )
{ {
FT_Byte* read = bitmap->buffer + ( height - height / 3 ) * pitch; /* Render 3 separate monochrome bitmaps, shifting the outline */
FT_Byte* write = bitmap->buffer; /* by 1/3 pixel. Triple the pitch to render on each third row. */
FT_UInt hh; bitmap->pitch *= 3;
bitmap->rows /= 3;
FT_Outline_Translate( outline, 0, 21 );
bitmap->buffer += 2 * pitch;
for ( hh = height / 3; hh > 0; hh-- ) error = render->raster_render( render->raster, &params );
{ if ( error )
ft_memcpy( write, read, pitch ); goto Exit;
write += pitch;
ft_memcpy( write, read, pitch ); FT_Outline_Translate( outline, 0, -21 );
write += pitch; bitmap->buffer -= pitch;
ft_memcpy( write, read, pitch ); error = render->raster_render( render->raster, &params );
write += pitch; if ( error )
read += pitch; goto Exit;
}
FT_Outline_Translate( outline, 0, -21 );
bitmap->buffer -= pitch;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, 0, 21 );
bitmap->pitch /= 3;
bitmap->rows *= 3;
}
else /* grayscale */
{
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
} }
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */