Compare commits

...

9 Commits

Author SHA1 Message Date
Alexei Podtelezhnikov fcfd6c17ff Thinko. 2018-04-30 00:07:36 -04:00
Alexei Podtelezhnikov d526705f5e API for Harmony LCD rendering.
This introduces `FT_Library_SetLcdGeometry' for setting up arbitrary
LCD subpixel geometry including non-striped patterns.
2018-04-30 00:02:33 -04:00
Alexei Podtelezhnikov 11ffff2c91 Formulate Harmony LCD rendering.
This generalizes magic outline shifts that make Harmony LCD
rendering work in terms of precise two-dimensional RGB subpixel
positions. These coordinates are now set in time of the `smooth'
module initialization and later used to shift a glyph outline for
rendering. FT_RENDER_MODE_LCD and FT_RENDER_MODE_LCD_V use the same
coordinates. The letter, however, rotates them before using.
The LCD bitmap padding is also calculated using these coordinates.
There should be rendering changes resuting from this commit.
2018-04-28 23:01:44 -04:00
Alexei Podtelezhnikov b5a29cce2f Merge branch 'master' into Harmony 2018-04-28 22:58:51 -04:00
Alexei Podtelezhnikov 66006dbfa4 [autofit] Handle LCD lightly.
This commit explicitly disables stem adjustment and metrics changes
for FT_LOAD_TARGET_LCD, redoing the last commit.

* include/freetype/freetype.h (FT_LOAD_TARGET_XXX): Docs updated.
* src/autofit/afcjk.c (af_cjk_hints_init): Updated.
* src/autofit/aflatin.c (af_latin_hints_init): Updated.
* src/autofit/aflatin2.c (af_latin2_hints_init): Updated.
2017-04-02 22:31:07 -04:00
Alexei Podtelezhnikov e47feb03cc [autofit] LCD equals LIGHT, LCD_V equals NORMAL.
* include/freetype/freetype.h (FT_LOAD_TARGET_XXX): Docs updated.
* src/autofit/afcjk.c (af_cjk_hints_init): Updated.
* src/autofit/aflatin.c (af_latin_hints_init): Updated.
* src/autofit/aflatin2.c (af_latin2_hints_init): Updated.
2017-03-30 22:48:18 -04:00
Alexei Podtelezhnikov 51dd542e55 [smooth] Dubious fix for Firefox.
* src/base/ftlcdfil.c (FT_Library_SetLcdFilter{,Weights})
[!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Return FT_Err_Ok instead of
FT_Err_Unimplemented_Feature.
* include/freetype/ftlcdfil.h: Documentation updated.
2017-03-12 22:18:55 -04:00
Alexei Podtelezhnikov 3f663bc648 [smooth] Harmony itself.
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-03-09 00:08:38 -05:00
Alexei Podtelezhnikov 8901ff06d0 [smooth] Groundwork for Harmony.
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Apply consistent
LCD padding regardless of `FT_CONFIG_OPTION_SUBPIXEL_RENDERING'.

* devel/ftoption.h: Comment out `FT_CONFIG_OPTION_SUBPIXEL_RENDERING'.
2017-03-08 22:40:51 -05:00
7 changed files with 176 additions and 56 deletions

View File

@ -3351,7 +3351,7 @@ FT_BEGIN_HEADER
/* 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 */
/* exceed a sum of 0x100, see section @lcd_rendering. Then the */
/* only difference to gray linear blending is that subpixel-rendered */
/* linear blending is done 3~times per pixel: red foreground subpixel */
/* to red background subpixel and so on for green and blue. */

View File

@ -120,7 +120,7 @@
/* gzip */
/* lzw */
/* bzip2 */
/* lcd_filtering */
/* lcd_rendering */
/* */
/***************************************************************************/

View File

@ -36,10 +36,10 @@ FT_BEGIN_HEADER
/***************************************************************************
*
* @section:
* lcd_filtering
* lcd_rendering
*
* @title:
* LCD Filtering
* LCD Rendering
*
* @abstract:
* Reduce color fringes of subpixel-rendered bitmaps.
@ -298,6 +298,54 @@ FT_BEGIN_HEADER
typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
/**************************************************************************
*
* @func:
* FT_Library_SetLcdGeometry
*
* @description:
* This function can be used to modify default positions of color
* subpixels, which controls Harmony LCD rendering.
*
* @input:
* library ::
* A handle to the target library instance.
*
* sub ::
* A pointer to an array of 3 vectors in 26.6 fractional pixel format;
* the function modifies the default values, see the note below.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
* This function does nothing and returns `FT_Err_Unimplemented_Feature'
* in the context of ClearType-style subpixel rendering when
* FT_CONFIG_OPTION_SUBPIXEL_RENDERING is defined in your build of the
* library.
*
* Subpixel geometry examples:
*
* - {{-21, 0}, {0, 0}, {21, 0}} is the default, corresponding 3 color
* stripes shifted by a third of a pixel. This could be an RGB panel.
*
* - {{21, 0}, {0, 0}, {-21, 0}} looks the same as the default but
* offers you possibility to specify that this is a BGR panel instead,
* while keeping the bitmap in the same RGB888 format.
*
* - {{0, 21}, {0, 0}, {0, -21}} is the vertical RGB, but the bitmap
* stays RGB888 as a result.
*
* - {{32, -21}, {-32, -21}, {0, 42}} is a certain PenTile arrangement.
*
* @since:
* 2.9.x
*/
FT_EXPORT( FT_Error )
FT_Library_SetLcdGeometry( FT_Library library,
FT_Vector* sub );
/* */

View File

@ -312,11 +312,11 @@ FT_BEGIN_HEADER
FT_CMap_Done( FT_CMap cmap );
/* adds LCD padding to Min and Max boundaries */
/* add LCD padding to CBox */
FT_BASE( void )
ft_lcd_padding( FT_Pos* Min,
FT_Pos* Max,
FT_GlyphSlot slot );
ft_lcd_padding( FT_BBox* cbox,
FT_GlyphSlot slot,
FT_Render_Mode mode );
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
@ -392,8 +392,8 @@ FT_BEGIN_HEADER
/* */
/* lcd_weights :: */
/* lcd_filter_func :: */
/* If subpixel rendering is activated, the LCD filtering weights */
/* and callback function. */
/* These fields specify the LCD filtering weights and callback */
/* function for ClearType-style subpixel rendering. */
/* */
/* refcount :: */
/* A counter initialized to~1 at the time an @FT_Face structure is */
@ -897,11 +897,15 @@ FT_BEGIN_HEADER
/* interpreter. Currently, only the TrueType */
/* bytecode debugger uses this. */
/* */
/* lcd_weights :: If subpixel rendering is activated, the LCD */
/* filter weights, if any. */
/* lcd_weights :: The LCD filter weights for ClearType-style */
/* subpixel rendering. */
/* */
/* lcd_filter_func :: If subpixel rendering is activated, the LCD */
/* filtering callback function. */
/* lcd_filter_func :: The LCD filtering callback function for */
/* for ClearType-style subpixel rendering. */
/* */
/* lcd_geometry :: This array specifies LCD subpixel geometry */
/* and controls Harmony LCD rendering technique, */
/* alternative to ClearType. */
/* */
/* pic_container :: Contains global structs and tables, instead */
/* of defining them globally. */
@ -933,6 +937,8 @@ FT_BEGIN_HEADER
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
#else
FT_Vector lcd_geometry[3]; /* RGB subpixel positions */
#endif
#ifdef FT_CONFIG_OPTION_PIC

View File

@ -34,9 +34,9 @@
/* add padding according to filter weights */
FT_BASE_DEF (void)
ft_lcd_padding( FT_Pos* Min,
FT_Pos* Max,
FT_GlyphSlot slot )
ft_lcd_padding( FT_BBox* cbox,
FT_GlyphSlot slot,
FT_Render_Mode mode )
{
FT_Byte* lcd_weights;
FT_Bitmap_LcdFilterFunc lcd_filter_func;
@ -56,10 +56,20 @@
if ( lcd_filter_func == ft_lcd_filter_fir )
{
*Min -= lcd_weights[0] ? 43 :
lcd_weights[1] ? 22 : 0;
*Max += lcd_weights[4] ? 43 :
lcd_weights[3] ? 22 : 0;
if ( mode == FT_RENDER_MODE_LCD )
{
cbox->xMin -= lcd_weights[0] ? 43 :
lcd_weights[1] ? 22 : 0;
cbox->xMax += lcd_weights[4] ? 43 :
lcd_weights[3] ? 22 : 0;
}
else if ( mode == FT_RENDER_MODE_LCD_V )
{
cbox->yMin -= lcd_weights[0] ? 43 :
lcd_weights[1] ? 22 : 0;
cbox->yMax += lcd_weights[4] ? 43 :
lcd_weights[3] ? 22 : 0;
}
}
}
@ -341,18 +351,56 @@
return FT_Err_Ok;
}
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdGeometry( FT_Library library,
FT_Vector* sub )
{
FT_UNUSED( library );
FT_UNUSED( sub );
return FT_THROW( Unimplemented_Feature );
}
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* add padding according to accommodate outline shifts */
/* add padding to accommodate outline shifts */
FT_BASE_DEF (void)
ft_lcd_padding( FT_Pos* Min,
FT_Pos* Max,
FT_GlyphSlot slot )
ft_lcd_padding( FT_BBox* cbox,
FT_GlyphSlot slot,
FT_Render_Mode mode )
{
FT_UNUSED( slot );
FT_Vector* sub = slot->library->lcd_geometry;
*Min -= 21;
*Max += 21;
if ( mode == FT_RENDER_MODE_LCD )
{
cbox->xMin -= FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
cbox->xMax -= FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
cbox->yMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
cbox->yMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
}
else if ( mode == FT_RENDER_MODE_LCD_V )
{
cbox->xMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
cbox->xMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
cbox->yMin += FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
cbox->yMax += FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
}
}
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdGeometry( FT_Library library,
FT_Vector* sub )
{
if ( !library )
return FT_THROW( Invalid_Library_Handle );
if ( !sub )
return FT_THROW( Invalid_Argument );
ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) );
return FT_THROW( Unimplemented_Feature );
}

View File

@ -403,12 +403,12 @@
case FT_RENDER_MODE_LCD:
pixel_mode = FT_PIXEL_MODE_LCD;
ft_lcd_padding( &cbox.xMin, &cbox.xMax, slot );
ft_lcd_padding( &cbox, slot, mode );
goto Round;
case FT_RENDER_MODE_LCD_V:
pixel_mode = FT_PIXEL_MODE_LCD_V;
ft_lcd_padding( &cbox.yMin, &cbox.yMax, slot );
ft_lcd_padding( &cbox, slot, mode );
goto Round;
case FT_RENDER_MODE_NORMAL:

View File

@ -31,6 +31,22 @@
static FT_Error
ft_smooth_init( FT_Renderer render )
{
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_Vector* sub = render->root.library->lcd_geometry;
/* set up default subpixel geometry for striped RGB panels. */
sub[0].x = -21;
sub[0].y = 0;
sub[1].x = 0;
sub[1].y = 0;
sub[2].x = 21;
sub[2].y = 0;
#endif
render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
return 0;
@ -235,33 +251,33 @@
unsigned int width = bitmap->width;
int pitch = bitmap->pitch;
FT_Vector* sub = slot->library->lcd_geometry;
/* Render 3 separate monochrome bitmaps, shifting the outline */
/* by 1/3 pixel. */
/* Render 3 separate monochrome bitmaps, shifting the outline. */
width /= 3;
bitmap->buffer += width;
FT_Outline_Translate( outline, -sub[0].x, -sub[0].y );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, -21, 0 );
x_shift -= 21;
bitmap->buffer += width;
FT_Outline_Translate( outline, sub[0].x - sub[1].x, sub[0].y - sub[1].y );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, 42, 0 );
x_shift += 42;
bitmap->buffer += width;
FT_Outline_Translate( outline, sub[1].x - sub[2].x, sub[1].y - sub[2].y );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
x_shift -= sub[2].x;
y_shift -= sub[2].y;
bitmap->buffer -= 2 * width;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
/* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */
/* XXX: It is more efficient to render every third byte above. */
@ -286,34 +302,36 @@
{
int pitch = bitmap->pitch;
FT_Vector* sub = slot->library->lcd_geometry;
/* Render 3 separate monochrome bitmaps, shifting the outline */
/* by 1/3 pixel. Triple the pitch to render on each third row. */
/* Render 3 separate monochrome bitmaps, shifting the outline. */
/* Notice that the subpixel geometry vectors are rotated. */
/* Triple the pitch to render on each third row. */
bitmap->pitch *= 3;
bitmap->rows /= 3;
bitmap->buffer += pitch;
FT_Outline_Translate( outline, -sub[0].y, sub[0].x );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, 0, 21 );
y_shift += 21;
bitmap->buffer += pitch;
FT_Outline_Translate( outline, sub[0].y - sub[1].y, sub[1].x - sub[0].x );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, 0, -42 );
y_shift -= 42;
bitmap->buffer += pitch;
FT_Outline_Translate( outline, sub[1].y - sub[2].y, sub[2].x - sub[1].x );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
x_shift -= sub[2].y;
y_shift += sub[2].x;
bitmap->buffer -= 2 * pitch;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
bitmap->pitch /= 3;
bitmap->rows *= 3;
}