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; }