[raster] Remove 5-level gray AA mode from monochrome rasterizer.

It was off by default and couldn't be turned on at runtime.  And the
smooth rasterizer superceded it over ten years ago.  No point in
keeping.  Comments suggested that it was there for compatibility
with FreeType 1.

550 lines down.

* src/raster/ftraster.c (FT_RASTER_OPTION_ANTI_ALIASING,
RASTER_GRAY_LINES): Remove macros and all associated code.

(black_TWorker): Remove `gray_min_x' and `gray_max_x'.
(black_TRaster): Remove `grays' and `gray_width'.

(Vertical_Sweep_Init, Vertical_Sweep_Span, Vertical_Sweep_Drop,
ft_black_render): Updated.

* src/raster/ftrend1.c (ft_raster1_render): Simplify code.
(ft_raster5_renderer_class): Removed.
This commit is contained in:
Behdad Esfahbod 2015-01-14 18:06:22 +01:00 committed by Werner Lemberg
parent 747ae2c8aa
commit 8dc8635874
4 changed files with 28 additions and 554 deletions

View File

@ -1,3 +1,26 @@
2015-01-14 Behdad Esfahbod <behdad@behdad.org>
[raster] Remove 5-level gray AA mode from monochrome rasterizer.
It was off by default and couldn't be turned on at runtime. And the
smooth rasterizer superceded it over ten years ago. No point in
keeping. Comments suggested that it was there for compatibility
with FreeType 1.
550 lines down.
* src/raster/ftraster.c (FT_RASTER_OPTION_ANTI_ALIASING,
RASTER_GRAY_LINES): Remove macros and all associated code.
(black_TWorker): Remove `gray_min_x' and `gray_max_x'.
(black_TRaster): Remove `grays' and `gray_width'.
(Vertical_Sweep_Init, Vertical_Sweep_Span, Vertical_Sweep_Drop,
ft_black_render): Updated.
* src/raster/ftrend1.c (ft_raster1_render): Simplify code.
(ft_raster5_renderer_class): Removed.
2015-01-14 Behdad Esfahbod <behdad@behdad.org>
[smooth] Allocate render pool for smooth rasterizer on the stack.

View File

@ -212,13 +212,8 @@ FT_BEGIN_HEADER
/* */
/* This doesn't change the current renderer for other formats. */
/* */
/* Currently, only the B/W renderer, if compiled with */
/* FT_RASTER_OPTION_ANTI_ALIASING (providing a 5-levels */
/* anti-aliasing mode; this option must be set directly in */
/* `ftraster.c' and is undefined by default) accepts a single tag */
/* `pal5' to set its gray palette as a character string with */
/* 5~elements. Consequently, the third and fourth argument are zero */
/* normally. */
/* Currently, no FreeType renderer module uses `parameters'; you */
/* should thus always pass NULL as the value. */
/* */
FT_EXPORT( FT_Error )
FT_Set_Renderer( FT_Library library,

View File

@ -150,14 +150,6 @@
/* define DEBUG_RASTER if you want to compile a debugging version */
/* #define DEBUG_RASTER */
/* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
/* 5-levels anti-aliasing */
/* #define FT_RASTER_OPTION_ANTI_ALIASING */
/* The size of the two-lines intermediate bitmap used */
/* for anti-aliasing, in bytes. */
#define RASTER_GRAY_LINES 2048
/*************************************************************************/
/*************************************************************************/
@ -514,9 +506,6 @@
Short traceIncr; /* sweep's increment in target bitmap */
Short gray_min_x; /* current min x during gray rendering */
Short gray_max_x; /* current max x during gray rendering */
/* dispatch variables */
Function_Sweep_Init* Proc_Sweep_Init;
@ -529,34 +518,13 @@
Bool second_pass; /* indicates whether a horizontal pass */
/* should be performed to control */
/* drop-out accurately when calling */
/* Render_Glyph. Note that there is */
/* no horizontal pass during gray */
/* rendering. */
/* Render_Glyph. */
TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
black_TBand band_stack[16]; /* band stack used for sub-banding */
Int band_top; /* band stack top */
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
Byte* grays;
Byte gray_lines[RASTER_GRAY_LINES];
/* Intermediate table used to render the */
/* graylevels pixmaps. */
/* gray_lines is a buffer holding two */
/* monochrome scanlines */
Short gray_width; /* width in bytes of one monochrome */
/* intermediate scanline of gray_lines. */
/* Each gray pixel takes 2 bits long there */
/* The gray_lines must hold 2 lines, thus with size */
/* in bytes of at least `gray_width*2'. */
#endif /* FT_RASTER_ANTI_ALIASING */
};
@ -566,8 +534,6 @@
long buffer_size;
void* memory;
black_PWorker worker;
Byte grays[5];
Short gray_width;
} black_TRaster, *black_PRaster;
@ -583,70 +549,6 @@
#endif /* !FT_STATIC_RASTER */
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
/* A lookup table used to quickly count set bits in four gray 2x2 */
/* cells. The values of the table have been produced with the */
/* following code: */
/* */
/* for ( i = 0; i < 256; i++ ) */
/* { */
/* l = 0; */
/* j = i; */
/* */
/* for ( c = 0; c < 4; c++ ) */
/* { */
/* l <<= 4; */
/* */
/* if ( j & 0x80 ) l++; */
/* if ( j & 0x40 ) l++; */
/* */
/* j = ( j << 2 ) & 0xFF; */
/* } */
/* printf( "0x%04X", l ); */
/* } */
/* */
static const short count_table[256] =
{
0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
};
#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
/*************************************************************************/
/*************************************************************************/
/** **/
@ -2268,9 +2170,6 @@
ras.traceOfs = -*min * pitch;
if ( pitch > 0 )
ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
ras.gray_min_x = 0;
ras.gray_max_x = 0;
}
@ -2318,11 +2217,6 @@
f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );
f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
if ( ras.gray_min_x > c1 )
ras.gray_min_x = (short)c1;
if ( ras.gray_max_x < c2 )
ras.gray_max_x = (short)c2;
target = ras.bTarget + ras.traceOfs + c1;
c2 -= c1;
@ -2486,11 +2380,6 @@
c1 = (Short)( e1 >> 3 );
f1 = (Short)( e1 & 7 );
if ( ras.gray_min_x > c1 )
ras.gray_min_x = c1;
if ( ras.gray_max_x < c1 )
ras.gray_max_x = c1;
ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
}
}
@ -2695,249 +2584,6 @@
}
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
/*************************************************************************/
/* */
/* Vertical Gray Sweep Procedure Set */
/* */
/* These two routines are used during the vertical gray-levels sweep */
/* phase by the generic Draw_Sweep() function. */
/* */
/* NOTES */
/* */
/* - The target pixmap's width *must* be a multiple of 4. */
/* */
/* - You have to use the function Vertical_Sweep_Span() for the gray */
/* span call. */
/* */
/*************************************************************************/
static void
Vertical_Gray_Sweep_Init( RAS_ARGS Short* min,
Short* max )
{
Long pitch, byte_len;
*min = *min & -2;
*max = ( *max + 3 ) & -2;
ras.traceOfs = 0;
pitch = ras.target.pitch;
byte_len = -pitch;
ras.traceIncr = (Short)byte_len;
ras.traceG = ( *min / 2 ) * byte_len;
if ( pitch > 0 )
{
ras.traceG += ( ras.target.rows - 1 ) * pitch;
byte_len = -byte_len;
}
ras.gray_min_x = (Short)byte_len;
ras.gray_max_x = -(Short)byte_len;
}
static void
Vertical_Gray_Sweep_Step( RAS_ARG )
{
short* count = (short*)count_table;
Byte* grays;
ras.traceOfs += ras.gray_width;
if ( ras.traceOfs > ras.gray_width )
{
PByte pix;
pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
grays = ras.grays;
if ( ras.gray_max_x >= 0 )
{
Long last_pixel = ras.target.width - 1;
Int last_cell = last_pixel >> 2;
Int last_bit = last_pixel & 3;
Bool over = 0;
Int c1, c2;
PByte bit, bit2;
if ( ras.gray_max_x >= last_cell && last_bit != 3 )
{
ras.gray_max_x = last_cell - 1;
over = 1;
}
if ( ras.gray_min_x < 0 )
ras.gray_min_x = 0;
bit = ras.bTarget + ras.gray_min_x;
bit2 = bit + ras.gray_width;
c1 = ras.gray_max_x - ras.gray_min_x;
while ( c1 >= 0 )
{
c2 = count[*bit] + count[*bit2];
if ( c2 )
{
pix[0] = grays[(c2 >> 12) & 0x000F];
pix[1] = grays[(c2 >> 8 ) & 0x000F];
pix[2] = grays[(c2 >> 4 ) & 0x000F];
pix[3] = grays[ c2 & 0x000F];
*bit = 0;
*bit2 = 0;
}
bit++;
bit2++;
pix += 4;
c1--;
}
if ( over )
{
c2 = count[*bit] + count[*bit2];
if ( c2 )
{
switch ( last_bit )
{
case 2:
pix[2] = grays[(c2 >> 4 ) & 0x000F];
case 1:
pix[1] = grays[(c2 >> 8 ) & 0x000F];
default:
pix[0] = grays[(c2 >> 12) & 0x000F];
}
*bit = 0;
*bit2 = 0;
}
}
}
ras.traceOfs = 0;
ras.traceG += ras.traceIncr;
ras.gray_min_x = 32000;
ras.gray_max_x = -32000;
}
}
static void
Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
FT_F26Dot6 x1,
FT_F26Dot6 x2,
PProfile left,
PProfile right )
{
/* nothing, really */
FT_UNUSED_RASTER;
FT_UNUSED( y );
FT_UNUSED( x1 );
FT_UNUSED( x2 );
FT_UNUSED( left );
FT_UNUSED( right );
}
static void
Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
FT_F26Dot6 x1,
FT_F26Dot6 x2,
PProfile left,
PProfile right )
{
Long e1, e2;
PByte pixel;
/* During the horizontal sweep, we only take care of drop-outs */
e1 = CEILING( x1 );
e2 = FLOOR ( x2 );
if ( e1 > e2 )
{
Int dropOutControl = left->flags & 7;
if ( e1 == e2 + ras.precision )
{
switch ( dropOutControl )
{
case 0: /* simple drop-outs including stubs */
e1 = e2;
break;
case 4: /* smart drop-outs including stubs */
e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
break;
case 1: /* simple drop-outs excluding stubs */
case 5: /* smart drop-outs excluding stubs */
/* see Vertical_Sweep_Drop for details */
/* rightmost stub test */
if ( left->next == right && left->height <= 0 )
return;
/* leftmost stub test */
if ( right->next == left && left->start == y )
return;
if ( dropOutControl == 1 )
e1 = e2;
else
e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
break;
default: /* modes 2, 3, 6, 7 */
return; /* no drop-out control */
}
}
else
return;
}
if ( e1 >= 0 )
{
Byte color;
if ( x2 - x1 >= ras.precision_half )
color = ras.grays[2];
else
color = ras.grays[1];
e1 = TRUNC( e1 ) / 2;
if ( e1 < ras.target.rows )
{
pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
if ( ras.target.pitch > 0 )
pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
if ( pixel[0] == ras.grays[0] )
pixel[0] = color;
}
}
}
#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
/*************************************************************************/
/* */
/* Generic Sweep Drawing routine */
@ -3332,118 +2978,10 @@
}
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
/*************************************************************************/
/* */
/* <Function> */
/* Render_Gray_Glyph */
/* */
/* <Description> */
/* Render a glyph with grayscaling. Sub-banding if needed. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
Render_Gray_Glyph( RAS_ARG )
{
Long pixel_width;
FT_Error error;
Set_High_Precision( RAS_VARS ras.outline.flags &
FT_OUTLINE_HIGH_PRECISION );
ras.scale_shift = ras.precision_shift + 1;
if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
ras.dropOutControl = 2;
else
{
if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
ras.dropOutControl = 4;
else
ras.dropOutControl = 0;
if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
ras.dropOutControl += 1;
}
ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
/* Vertical Sweep */
ras.band_top = 0;
ras.band_stack[0].y_min = 0;
ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
ras.bWidth = ras.gray_width;
pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
if ( ras.bWidth > pixel_width )
ras.bWidth = pixel_width;
ras.bWidth = ras.bWidth * 8;
ras.bTarget = (Byte*)ras.gray_lines;
ras.gTarget = (Byte*)ras.target.buffer;
ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
ras.Proc_Sweep_Span = Vertical_Sweep_Span;
ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
error = Render_Single_Pass( RAS_VARS 0 );
if ( error )
return error;
/* Horizontal Sweep */
if ( ras.second_pass && ras.dropOutControl != 2 )
{
ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
ras.band_top = 0;
ras.band_stack[0].y_min = 0;
ras.band_stack[0].y_max = ras.target.width * 2 - 1;
error = Render_Single_Pass( RAS_VARS 1 );
if ( error )
return error;
}
return Raster_Err_None;
}
#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
FT_LOCAL_DEF( FT_Error )
Render_Gray_Glyph( RAS_ARG )
{
FT_UNUSED_RASTER;
return FT_THROW( Unsupported );
}
#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
static void
ft_black_init( black_PRaster raster )
{
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
FT_UInt n;
/* set default 5-levels gray palette */
for ( n = 0; n < 5; n++ )
raster->grays[n] = n * 255 / 4;
raster->gray_width = RASTER_GRAY_LINES / 2;
#else
FT_UNUSED( raster );
#endif
}
@ -3547,26 +3085,10 @@
unsigned long mode,
const char* palette )
{
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
{
/* set 5-levels gray palette */
raster->grays[0] = palette[0];
raster->grays[1] = palette[1];
raster->grays[2] = palette[2];
raster->grays[3] = palette[3];
raster->grays[4] = palette[4];
}
#else
FT_UNUSED( raster );
FT_UNUSED( mode );
FT_UNUSED( palette );
#endif
return 0;
}
@ -3619,16 +3141,8 @@
worker->buff = (PLong) raster->buffer;
worker->sizeBuff = worker->buff +
raster->buffer_size / sizeof ( Long );
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
worker->grays = raster->grays;
worker->gray_width = raster->gray_width;
FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );
#endif
return ( params->flags & FT_RASTER_FLAG_AA )
? Render_Gray_Glyph( RAS_VAR )
: Render_Glyph( RAS_VAR );
return Render_Glyph( RAS_VAR );
}

View File

@ -120,38 +120,11 @@
}
/* check rendering mode */
#ifndef FT_CONFIG_OPTION_PIC
if ( mode != FT_RENDER_MODE_MONO )
{
/* raster1 is only capable of producing monochrome bitmaps */
if ( render->clazz == &ft_raster1_renderer_class )
return FT_THROW( Cannot_Render_Glyph );
return FT_THROW( Cannot_Render_Glyph );
}
else
{
/* raster5 is only capable of producing 5-gray-levels bitmaps */
if ( render->clazz == &ft_raster5_renderer_class )
return FT_THROW( Cannot_Render_Glyph );
}
#else /* FT_CONFIG_OPTION_PIC */
/* When PIC is enabled, we cannot get to the class object */
/* so instead we check the final character in the class name */
/* ("raster5" or "raster1"). Yes this is a hack. */
/* The "correct" thing to do is have different render function */
/* for each of the classes. */
if ( mode != FT_RENDER_MODE_MONO )
{
/* raster1 is only capable of producing monochrome bitmaps */
if ( render->clazz->root.module_name[6] == '1' )
return FT_THROW( Cannot_Render_Glyph );
}
else
{
/* raster5 is only capable of producing 5-gray-levels bitmaps */
if ( render->clazz->root.module_name[6] == '5' )
return FT_THROW( Cannot_Render_Glyph );
}
#endif /* FT_CONFIG_OPTION_PIC */
outline = &slot->outline;
@ -272,35 +245,4 @@
)
/* This renderer is _NOT_ part of the default modules; you will need */
/* to register it by hand in your application. It should only be */
/* used for backwards-compatibility with FT 1.x anyway. */
/* */
FT_DEFINE_RENDERER( ft_raster5_renderer_class,
FT_MODULE_RENDERER,
sizeof ( FT_RendererRec ),
"raster5",
0x10000L,
0x20000L,
0, /* module specific interface */
(FT_Module_Constructor)ft_raster1_init,
(FT_Module_Destructor) 0,
(FT_Module_Requester) 0
,
FT_GLYPH_FORMAT_OUTLINE,
(FT_Renderer_RenderFunc) ft_raster1_render,
(FT_Renderer_TransformFunc)ft_raster1_transform,
(FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,
(FT_Renderer_SetModeFunc) ft_raster1_set_mode,
(FT_Raster_Funcs*) &FT_STANDARD_RASTER_GET
)
/* END */