[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:
parent
5710ef989d
commit
410f3799b6
19
ChangeLog
19
ChangeLog
|
@ -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>
|
||||
|
||||
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Clean up.
|
||||
|
|
|
@ -107,22 +107,19 @@ FT_BEGIN_HEADER
|
|||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Uncomment the line below if you want to activate sub-pixel rendering */
|
||||
/* (a.k.a. LCD rendering, or ClearType) in this build of the library. */
|
||||
/* Uncomment the line below if you want to activate LCD rendering */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
/* _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
|
||||
/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
|
|
@ -107,20 +107,17 @@ FT_BEGIN_HEADER
|
|||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Uncomment the line below if you want to activate sub-pixel rendering */
|
||||
/* (a.k.a. LCD rendering, or ClearType) in this build of the library. */
|
||||
/* Uncomment the line below if you want to activate LCD rendering */
|
||||
/* 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 */
|
||||
/* and should not be activated in any default build of the library. */
|
||||
/* */
|
||||
/* This macro has no impact on the FreeType API, only on its */
|
||||
/* _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. */
|
||||
/* When this macro is not defined, FreeType offers alternative LCD */
|
||||
/* rendering technology that produces excellent output without LCD */
|
||||
/* filtering. */
|
||||
/* */
|
||||
/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
|
|
|
@ -3131,11 +3131,13 @@ FT_BEGIN_HEADER
|
|||
/* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* The LCD-optimized glyph bitmaps produced by `FT_Render_Glyph' can */
|
||||
/* be filtered to reduce color-fringes by using */
|
||||
/* @FT_Library_SetLcdFilter (not active in the default builds). It */
|
||||
/* is up to the caller to either call `FT_Library_SetLcdFilter' (if */
|
||||
/* available) or do the filtering itself. */
|
||||
/* Should you define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your */
|
||||
/* `ftoption.h', which enables patented ClearType-style rendering, */
|
||||
/* the LCD-optimized glyph bitmaps should be filtered to reduce color */
|
||||
/* fringes inherent to this technology. You can either set up LCD */
|
||||
/* 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. */
|
||||
/* Embedded bitmaps often have a different pixel mode like */
|
||||
|
|
|
@ -44,9 +44,16 @@ FT_BEGIN_HEADER
|
|||
* Reduce color fringes of subpixel-rendered bitmaps.
|
||||
*
|
||||
* @description:
|
||||
* Subpixel 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
|
||||
* Should you #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your
|
||||
* `ftoption.h', which enables patented ClearType-style rendering,
|
||||
* 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
|
||||
* color fringes. Use the @FT_Library_SetLcdFilter API to specify a
|
||||
* 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
|
||||
* 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:
|
||||
*
|
||||
* 1) It should be normalized, meaning the sum of the 5~components
|
||||
|
|
|
@ -190,7 +190,23 @@
|
|||
/* taking into account the origin shift */
|
||||
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 */
|
||||
if ( lcd_filter_func )
|
||||
{
|
||||
|
@ -210,7 +226,8 @@
|
|||
: lcd_weights[1] ? 22 : 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
|
||||
cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
|
||||
|
@ -339,57 +356,97 @@
|
|||
|
||||
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
/* render outline into bitmap */
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
/* expand it horizontally */
|
||||
if ( hmul )
|
||||
if ( hmul ) /* lcd */
|
||||
{
|
||||
FT_Byte* line = bitmap->buffer;
|
||||
FT_UInt hh;
|
||||
FT_Byte* line;
|
||||
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, ¶ms );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
FT_Outline_Translate( outline, -21, 0 );
|
||||
bitmap->buffer += width;
|
||||
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
FT_Outline_Translate( outline, -21, 0 );
|
||||
bitmap->buffer += width;
|
||||
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
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;
|
||||
FT_Byte* end = line + width;
|
||||
|
||||
|
||||
for ( xx = width / 3; xx > 0; xx-- )
|
||||
line = bitmap->buffer + i * pitch;
|
||||
for ( j = 0; j < width; j++ )
|
||||
{
|
||||
FT_UInt pixel = line[xx-1];
|
||||
|
||||
|
||||
end[-3] = (FT_Byte)pixel;
|
||||
end[-2] = (FT_Byte)pixel;
|
||||
end[-1] = (FT_Byte)pixel;
|
||||
end -= 3;
|
||||
temp[3 * j ] = line[j];
|
||||
temp[3 * j + 1] = line[j + width];
|
||||
temp[3 * j + 2] = line[j + width + width];
|
||||
}
|
||||
FT_MEM_COPY( line, temp, pitch );
|
||||
}
|
||||
|
||||
FT_FREE( temp );
|
||||
}
|
||||
|
||||
/* expand it vertically */
|
||||
if ( vmul )
|
||||
else if ( vmul ) /* lcd_v */
|
||||
{
|
||||
FT_Byte* read = bitmap->buffer + ( height - height / 3 ) * pitch;
|
||||
FT_Byte* write = bitmap->buffer;
|
||||
FT_UInt hh;
|
||||
/* Render 3 separate monochrome bitmaps, shifting the outline */
|
||||
/* by 1/3 pixel. Triple the pitch to render on each third row. */
|
||||
bitmap->pitch *= 3;
|
||||
bitmap->rows /= 3;
|
||||
|
||||
FT_Outline_Translate( outline, 0, 21 );
|
||||
bitmap->buffer += 2 * pitch;
|
||||
|
||||
for ( hh = height / 3; hh > 0; hh-- )
|
||||
{
|
||||
ft_memcpy( write, read, pitch );
|
||||
write += pitch;
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
ft_memcpy( write, read, pitch );
|
||||
write += pitch;
|
||||
FT_Outline_Translate( outline, 0, -21 );
|
||||
bitmap->buffer -= pitch;
|
||||
|
||||
ft_memcpy( write, read, pitch );
|
||||
write += pitch;
|
||||
read += pitch;
|
||||
}
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
FT_Outline_Translate( outline, 0, -21 );
|
||||
bitmap->buffer -= pitch;
|
||||
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
FT_Outline_Translate( outline, 0, 21 );
|
||||
|
||||
bitmap->pitch /= 3;
|
||||
bitmap->rows *= 3;
|
||||
}
|
||||
else /* grayscale */
|
||||
{
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
|
Loading…
Reference in New Issue