/* */
/* A new `perfect' anti-aliasing renderer (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2000-2003, 2005-2012 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
#define FT_COMPONENT trace_smooth
- /* The maximum distance of a curve from the chord, in 64ths of a pixel; */
- /* used when flattening curves. */
-#define FT_MAX_CURVE_DEVIATION 16
-
-
#ifdef _STANDALONE_
/* as usual, for the speed hungry :-) */
+#undef RAS_ARG
+#undef RAS_ARG_
+#undef RAS_VAR
+#undef RAS_VAR_
+
#ifndef FT_STATIC_RASTER
-#define RAS_ARG PWorker worker
-#define RAS_ARG_ PWorker worker,
+#define RAS_ARG gray_PWorker worker
+#define RAS_ARG_ gray_PWorker worker,
#define RAS_VAR worker
#define RAS_VAR_ worker,
/* must be at least 6 bits! */
#define PIXEL_BITS 8
+#undef FLOOR
+#undef CEILING
+#undef TRUNC
+#undef SCALED
+
#define ONE_PIXEL ( 1L << PIXEL_BITS )
#define PIXEL_MASK ( -1L << PIXEL_BITS )
#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
typedef struct TCell_
{
- TPos x; /* same with TWorker.ex */
- TCoord cover; /* same with TWorker.cover */
- TArea area;
- PCell next;
+ TPos x; /* same with gray_TWorker.ex */
+ TCoord cover; /* same with gray_TWorker.cover */
+ TArea area;
+ PCell next;
} TCell;
- typedef struct TWorker_
+ typedef struct gray_TWorker_
{
TCoord ex, ey;
TPos min_ex, max_ex;
TCoord cover;
int invalid;
- PCell cells;
+ PCell cells;
FT_PtrDist max_cells;
FT_PtrDist num_cells;
PCell* ycells;
TPos ycount;
- } TWorker, *PWorker;
+ } gray_TWorker, *gray_PWorker;
#ifndef FT_STATIC_RASTER
#define ras (*worker)
#else
- static TWorker ras;
+ static gray_TWorker ras;
#endif
- typedef struct TRaster_
+ typedef struct gray_TRaster_
{
- void* buffer;
- long buffer_size;
- int band_size;
- void* memory;
- PWorker worker;
+ void* buffer;
+ long buffer_size;
+ int band_size;
+ void* memory;
+ gray_PWorker worker;
- } TRaster, *PRaster;
+ } gray_TRaster, *gray_PRaster;
const FT_Vector* to )
{
TPos dx, dy;
+ TPos min, max, y;
int top, level;
int* levels;
FT_Vector* arc;
- dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
-
- if ( dx <= FT_MAX_CURVE_DEVIATION )
- {
- gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
- return;
- }
-
- level = 1;
- dx /= FT_MAX_CURVE_DEVIATION;
- while ( dx > 1 )
- {
- dx >>= 2;
- level++;
- }
-
- arc = ras.bez_stack;
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
+ levels = ras.lev_stack;
+ arc = ras.bez_stack;
arc[0].x = UPSCALE( to->x );
arc[0].y = UPSCALE( to->y );
arc[1].x = UPSCALE( control->x );
arc[1].y = UPSCALE( control->y );
arc[2].x = ras.x;
arc[2].y = ras.y;
+ top = 0;
- while ( top >= 0 )
- {
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
+ dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
+ dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
+ if ( dx < dy )
+ dx = dy;
+ if ( dx < ONE_PIXEL / 4 )
+ goto Draw;
- min = max = arc[0].y;
+ /* short-cut the arc that crosses the current band */
+ min = max = arc[0].y;
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
+ y = arc[1].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
+ y = arc[2].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
- goto Draw;
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
+ goto Draw;
+ level = 0;
+ do
+ {
+ dx >>= 2;
+ level++;
+ } while ( dx > ONE_PIXEL / 4 );
+
+ levels[0] = level;
+
+ do
+ {
+ level = levels[top];
+ if ( level > 0 )
+ {
gray_split_conic( arc );
arc += 2;
top++;
gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
top--;
arc -= 2;
- }
- return;
+ } while ( top >= 0 );
}
const FT_Vector* to )
{
FT_Vector* arc;
+ TPos min, max, y;
arc = ras.bez_stack;
arc[3].x = ras.x;
arc[3].y = ras.y;
- for (;;)
- {
- /* Check that the arc crosses the current band. */
- TPos min, max, y;
-
+ /* Short-cut the arc that crosses the current band. */
+ min = max = arc[0].y;
- min = max = arc[0].y;
+ y = arc[1].y;
+ if ( y < min )
+ min = y;
+ if ( y > max )
+ max = y;
- y = arc[1].y;
- if ( y < min )
- min = y;
- if ( y > max )
- max = y;
+ y = arc[2].y;
+ if ( y < min )
+ min = y;
+ if ( y > max )
+ max = y;
- y = arc[2].y;
- if ( y < min )
- min = y;
- if ( y > max )
- max = y;
+ y = arc[3].y;
+ if ( y < min )
+ min = y;
+ if ( y > max )
+ max = y;
- y = arc[3].y;
- if ( y < min )
- min = y;
- if ( y > max )
- max = y;
-
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
- goto Draw;
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
+ goto Draw;
+ for (;;)
+ {
/* Decide whether to split or draw. See `Rapid Termination */
/* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
/* F. Hain, at */
dx_ = FT_ABS( dx );
dy_ = FT_ABS( dy );
- L = ( 236 * FT_MAX( dx_, dy_ ) + 97 * FT_MIN( dx_, dy_ ) ) >> 8;
+
+ /* This is the same as */
+ /* */
+ /* L = ( 236 * FT_MAX( dx_, dy_ ) */
+ /* + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
+ L = ( dx_ > dy_ ? 236 * dx_ + 97 * dy_
+ : 97 * dx_ + 236 * dy_ ) >> 8;
/* Avoid possible arithmetic overflow below by splitting. */
if ( L > 32767 )
goto Split;
/* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
- s_limit = L * (TPos)( FT_MAX_CURVE_DEVIATION / 0.75 );
+ s_limit = L * (TPos)( ONE_PIXEL / 6 );
/* s is L * the perpendicular distance from P1 to the line P0-P3. */
dx1 = arc[1].x - arc[0].x;
static int
gray_move_to( const FT_Vector* to,
- PWorker worker )
+ gray_PWorker worker )
{
TPos x, y;
static int
gray_line_to( const FT_Vector* to,
- PWorker worker )
+ gray_PWorker worker )
{
gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
return 0;
static int
gray_conic_to( const FT_Vector* control,
const FT_Vector* to,
- PWorker worker )
+ gray_PWorker worker )
{
gray_render_conic( RAS_VAR_ control, to );
return 0;
gray_cubic_to( const FT_Vector* control1,
const FT_Vector* control2,
const FT_Vector* to,
- PWorker worker )
+ gray_PWorker worker )
{
gray_render_cubic( RAS_VAR_ control1, control2, to );
return 0;
gray_render_span( int y,
int count,
const FT_Span* spans,
- PWorker worker )
+ gray_PWorker worker )
{
unsigned char* p;
FT_Bitmap* map = &worker->target;
#endif /* _STANDALONE_ */
- typedef struct TBand_
+ typedef struct gray_TBand_
{
TPos min, max;
- } TBand;
+ } gray_TBand;
FT_DEFINE_OUTLINE_FUNCS(func_interface,
(FT_Outline_MoveTo_Func) gray_move_to,
static int
gray_convert_glyph( RAS_ARG )
{
- TBand bands[40];
- TBand* volatile band;
- int volatile n, num_bands;
- TPos volatile min, max, max_y;
- FT_BBox* clip;
+ gray_TBand bands[40];
+ gray_TBand* volatile band;
+ int volatile n, num_bands;
+ TPos volatile min, max, max_y;
+ FT_BBox* clip;
/* Set up state in the raster object */
cell_start += sizeof ( TCell ) - cell_mod;
cell_end = ras.buffer_size;
- cell_end -= cell_end % sizeof( TCell );
+ cell_end -= cell_end % sizeof ( TCell );
cells_max = (PCell)( (char*)ras.buffer + cell_end );
ras.cells = (PCell)( (char*)ras.buffer + cell_start );
static int
- gray_raster_render( PRaster raster,
+ gray_raster_render( gray_PRaster raster,
const FT_Raster_Params* params )
{
const FT_Outline* outline = (const FT_Outline*)params->source;
const FT_Bitmap* target_map = params->target;
- PWorker worker;
+ gray_PWorker worker;
if ( !raster || !raster->buffer || !raster->buffer_size )
gray_raster_new( void* memory,
FT_Raster* araster )
{
- static TRaster the_raster;
+ static gray_TRaster the_raster;
FT_UNUSED( memory );
gray_raster_new( FT_Memory memory,
FT_Raster* araster )
{
- FT_Error error;
- PRaster raster = NULL;
+ FT_Error error;
+ gray_PRaster raster = NULL;
*araster = 0;
- if ( !FT_ALLOC( raster, sizeof ( TRaster ) ) )
+ if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
{
raster->memory = memory;
- *araster = (FT_Raster)raster;
+ *araster = (FT_Raster)raster;
}
return error;
static void
gray_raster_done( FT_Raster raster )
{
- FT_Memory memory = (FT_Memory)((PRaster)raster)->memory;
+ FT_Memory memory = (FT_Memory)((gray_PRaster)raster)->memory;
FT_FREE( raster );
char* pool_base,
long pool_size )
{
- PRaster rast = (PRaster)raster;
+ gray_PRaster rast = (gray_PRaster)raster;
if ( raster )
{
- if ( pool_base && pool_size >= (long)sizeof ( TWorker ) + 2048 )
+ if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 )
{
- PWorker worker = (PWorker)pool_base;
+ gray_PWorker worker = (gray_PWorker)pool_base;
rast->worker = worker;
rast->buffer = pool_base +
- ( ( sizeof ( TWorker ) + sizeof ( TCell ) - 1 ) &
+ ( ( sizeof ( gray_TWorker ) +
+ sizeof ( TCell ) - 1 ) &
~( sizeof ( TCell ) - 1 ) );
rast->buffer_size = (long)( ( pool_base + pool_size ) -
(char*)rast->buffer ) &