diff options
author | Alexei Podtelezhnikov <apodtele@gmail.com> | 2018-04-28 23:01:44 -0400 |
---|---|---|
committer | Alexei Podtelezhnikov <apodtele@gmail.com> | 2018-04-28 23:01:44 -0400 |
commit | 11ffff2c91e9feca5c90612fec5b2aaa41b4e0e1 (patch) | |
tree | 6b7361f57298b6f32263a696f5fb487ac3a66952 | |
parent | b5a29cce2ff81376ce4d4c77beff1cefeca3e206 (diff) | |
download | freetype2-11ffff2c91e9feca5c90612fec5b2aaa41b4e0e1.tar.gz |
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.
-rw-r--r-- | include/freetype/internal/ftobjs.h | 26 | ||||
-rw-r--r-- | src/base/ftlcdfil.c | 50 | ||||
-rw-r--r-- | src/base/ftobjs.c | 4 | ||||
-rw-r--r-- | src/smooth/ftsmooth.c | 62 |
4 files changed, 94 insertions, 48 deletions
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h index 1c3c6ad45..9ac05e94f 100644 --- a/include/freetype/internal/ftobjs.h +++ b/include/freetype/internal/ftobjs.h @@ -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 diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c index 71e7eca05..aab04d14b 100644 --- a/src/base/ftlcdfil.c +++ b/src/base/ftlcdfil.c @@ -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; + } } } @@ -343,16 +353,28 @@ #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 ); + } } diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 8d07e35ae..642e42f32 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -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: diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c index ef176bdf1..f12e37511 100644 --- a/src/smooth/ftsmooth.c +++ b/src/smooth/ftsmooth.c @@ -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. */ - width /= 3; - bitmap->buffer += width; + /* Render 3 separate monochrome bitmaps, shifting the outline. */ + width /= 3; + FT_Outline_Translate( outline, -sub[0].x, -sub[0].y ); error = render->raster_render( render->raster, ¶ms ); 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, ¶ms ); if ( error ) goto Exit; - FT_Outline_Translate( outline, 42, 0 ); - x_shift += 42; - bitmap->buffer -= 2 * width; - + 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, ¶ms ); if ( error ) goto Exit; + x_shift -= sub[2].x; + y_shift -= sub[2].y; + 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. */ @@ -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, ¶ms ); 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, ¶ms ); if ( error ) goto Exit; - FT_Outline_Translate( outline, 0, -42 ); - y_shift -= 42; - bitmap->buffer -= 2 * pitch; - + 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, ¶ms ); if ( error ) goto Exit; + x_shift -= sub[2].y; + y_shift += sub[2].x; + bitmap->buffer -= 2 * pitch; + bitmap->pitch /= 3; bitmap->rows *= 3; } |