Consider the smooth renderer completed ! It will probably
be moved to "freetype2/src/base" soon and become part of the library. changes include: - fixed a bug which prevented large spans being drawn correctly. - now renders large glyphs that overflow the render pool. - various performance enhancements. the renderer now renders large glyphs with much greater speed :-) - also faster with small glyphs .. future plans: - fix a vertical-dropout bug in the standard raster (b&w) - write a demonstration program to demonstrate direct composition..
This commit is contained in:
parent
82942cc279
commit
ea10fbf91f
|
@ -38,15 +38,19 @@
|
|||
/* - can easily be modified to render to _any_ number of gray levels */
|
||||
/* cheaply.. */
|
||||
/* */
|
||||
/* - faster than the standard renderer for small (< 20) pixel sizes */
|
||||
/* */
|
||||
/* It has the following disadvantages (for now): */
|
||||
/* */
|
||||
/* - need more memory than the standard scan-converter to render */
|
||||
/* a single outline. Note that this may be changed in a near */
|
||||
/* future (we might be able to pack the data in the TCell structure) */
|
||||
/* */
|
||||
/* - apparently, glyphs rendered with this module are a bit more */
|
||||
/* "fuzzy" than those produced with the standard renderer. I hope */
|
||||
/* to fix this using a gamma table somewhere.. */
|
||||
/* - a bit slower than the standard renderer for large glyphs (whose */
|
||||
/* size is typically > 100 pixels), but faster for smaller sizes.. */
|
||||
/* */
|
||||
/* - apparently, glyphs rendered with this module are very slightly */
|
||||
/* more "fuzzy" than those produced with the standard renderer. */
|
||||
/* */
|
||||
/* */
|
||||
|
||||
|
@ -61,8 +65,10 @@
|
|||
#include <freetype.h> /* to link to FT_Outline_Decompose */
|
||||
#endif
|
||||
|
||||
/* define this to dump debugging information */
|
||||
#define xxxDEBUG_GRAYS
|
||||
|
||||
/* as usual, for the speed hungry :-) */
|
||||
#ifndef FT_STATIC_RASTER
|
||||
|
||||
#define RAS_ARG PRaster raster
|
||||
|
@ -84,7 +90,9 @@
|
|||
|
||||
#endif
|
||||
|
||||
/* must be at least 6 bits !! */
|
||||
#define PIXEL_BITS 8
|
||||
|
||||
#define ONE_PIXEL (1L << PIXEL_BITS)
|
||||
#define PIXEL_MASK (-1L << PIXEL_BITS)
|
||||
#define TRUNC(x) ((x) >> PIXEL_BITS)
|
||||
|
@ -96,6 +104,10 @@
|
|||
#define UPSCALE(x) (PIXEL_BITS >= 6 ? (x) << (PIXEL_BITS-6) : (x) >> (6-PIXEL_BITS))
|
||||
#define DOWNSCALE(x) (PIXEL_BITS >= 6 ? (x) >> (PIXEL_BITS-6) : (x) << (6-PIXEL_BITS))
|
||||
|
||||
/* define if you want to use more compact storage, this increases the number */
|
||||
/* of cells available in the render pool but slows down the rendering a bit */
|
||||
/* useful when you have a really tiny render pool */
|
||||
#define xxxGRAYS_COMPACT
|
||||
|
||||
|
||||
|
||||
|
@ -104,21 +116,32 @@
|
|||
/* TYPE DEFINITIONS */
|
||||
/* */
|
||||
|
||||
typedef int TScan;
|
||||
typedef long TPos;
|
||||
typedef float TDist;
|
||||
typedef int TScan; /* integer scanline/pixel coordinate */
|
||||
typedef long TPos; /* sub-pixel coordinate */
|
||||
|
||||
/* maximum number of gray spans in a call to the span callback */
|
||||
#define FT_MAX_GRAY_SPANS 32
|
||||
|
||||
|
||||
#ifdef GRAYS_COMPACT
|
||||
typedef struct TCell_
|
||||
{
|
||||
short x : 14;
|
||||
short y : 14;
|
||||
int cover : PIXEL_BITS+2;
|
||||
int area : PIXEL_BITS*2+2;
|
||||
|
||||
} TCell, *PCell;
|
||||
#else
|
||||
typedef struct TCell_
|
||||
{
|
||||
TScan x;
|
||||
TScan y;
|
||||
int area;
|
||||
int cover;
|
||||
int area;
|
||||
|
||||
} TCell, *PCell;
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct TRaster_
|
||||
|
@ -153,6 +176,11 @@ typedef struct TRaster_
|
|||
void* render_span_data;
|
||||
int span_y;
|
||||
|
||||
int band_size;
|
||||
int band_shoot;
|
||||
int conic_level;
|
||||
int cubic_level;
|
||||
|
||||
void* memory;
|
||||
|
||||
} TRaster, *PRaster;
|
||||
|
@ -231,8 +259,8 @@ int record_cell( RAS_ARG )
|
|||
return 1;
|
||||
|
||||
cell = ras.cells + ras.num_cells++;
|
||||
cell->x = ras.ex - ras.min_ex;
|
||||
cell->y = ras.ey - ras.min_ey;
|
||||
cell->x = (ras.ex - ras.min_ex);
|
||||
cell->y = (ras.ey - ras.min_ey);
|
||||
cell->area = ras.area;
|
||||
cell->cover = ras.cover;
|
||||
}
|
||||
|
@ -441,6 +469,20 @@ int render_line( RAS_ARG_ TPos to_x, TPos to_y )
|
|||
/* we should do something about the trivial case where dx == 0, */
|
||||
/* as it happens very often !! ... XXXXX */
|
||||
|
||||
/* perform vertical clipping */
|
||||
{
|
||||
TScan min, max;
|
||||
min = ey1;
|
||||
max = ey2;
|
||||
if (ey1 > ey2)
|
||||
{
|
||||
min = ey2;
|
||||
max = ey1;
|
||||
}
|
||||
if (min >= ras.max_ey || max < ras.min_ey)
|
||||
goto Fin;
|
||||
}
|
||||
|
||||
/* everything is on a single scanline */
|
||||
if ( ey1 == ey2 )
|
||||
{
|
||||
|
@ -448,9 +490,7 @@ int render_line( RAS_ARG_ TPos to_x, TPos to_y )
|
|||
goto Fin;
|
||||
}
|
||||
|
||||
/* ok, we'll have to render a run of adjacent cells on the same */
|
||||
/* scanline.. */
|
||||
/* */
|
||||
/* ok, we'll have to render several scanlines */
|
||||
p = (ONE_PIXEL-fy1)*dx;
|
||||
first = ONE_PIXEL;
|
||||
incr = 1;
|
||||
|
@ -535,6 +575,7 @@ void split_conic( FT_Vector* base )
|
|||
base[2].y = ( a + b ) / 2;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int render_conic( RAS_ARG_ FT_Vector* control, FT_Vector* to )
|
||||
{
|
||||
|
@ -548,50 +589,80 @@ int render_conic( RAS_ARG_ FT_Vector* control, FT_Vector* to )
|
|||
if (dx < dy) dx = dy;
|
||||
|
||||
level = 1;
|
||||
dx = dx/16;
|
||||
dx = dx/ras.conic_level;
|
||||
while ( dx > 0 )
|
||||
{
|
||||
dx >>= 1;
|
||||
level++;
|
||||
}
|
||||
|
||||
/* a shortcut to speed things up */
|
||||
if (level <= 1)
|
||||
return render_line( RAS_VAR_ UPSCALE(to->x), UPSCALE(to->y) );
|
||||
{
|
||||
/* we compute the mid-point directly in order to avoid */
|
||||
/* calling split_conic().. */
|
||||
TPos to_x, to_y, mid_x, mid_y;
|
||||
|
||||
to_x = UPSCALE(to->x);
|
||||
to_y = UPSCALE(to->y);
|
||||
mid_x = (ras.x + to_x + 2*UPSCALE(control->x))/4;
|
||||
mid_y = (ras.y + to_y + 2*UPSCALE(control->y))/4;
|
||||
|
||||
return render_line( RAS_VAR_ mid_x, mid_y ) ||
|
||||
render_line( RAS_VAR_ to_x, to_y );
|
||||
}
|
||||
|
||||
arc = ras.bez_stack;
|
||||
arc[0] = *to;
|
||||
arc[1] = *control;
|
||||
arc[2].x = ras.x;
|
||||
arc[2].y = ras.y;
|
||||
|
||||
arc[0].x = UPSCALE(arc[0].x);
|
||||
arc[0].y = UPSCALE(arc[0].y);
|
||||
arc[1].x = UPSCALE(arc[1].x);
|
||||
arc[1].y = UPSCALE(arc[1].y);
|
||||
|
||||
levels = ras.lev_stack;
|
||||
top = 0;
|
||||
levels[0] = level;
|
||||
|
||||
for (;;)
|
||||
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;
|
||||
|
||||
while (top >= 0)
|
||||
{
|
||||
level = levels[top];
|
||||
if (level > 1)
|
||||
{
|
||||
/* check that the arc crosses the current band */
|
||||
TPos min, max, y;
|
||||
min = max = arc[0].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;
|
||||
if ( TRUNC(min) >= ras.max_ey || TRUNC(max) < 0 )
|
||||
goto Draw;
|
||||
|
||||
split_conic(arc);
|
||||
arc += 2;
|
||||
top ++;
|
||||
levels[top] = levels[top-1] = level-1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
Draw:
|
||||
{
|
||||
if (render_line( RAS_VAR_ arc[0].x, arc[0].y )) return 1;
|
||||
TPos to_x, to_y, mid_x, mid_y;
|
||||
|
||||
to_x = arc[0].x;
|
||||
to_y = arc[0].y;
|
||||
mid_x = (ras.x + to_x + 2*arc[1].x)/4;
|
||||
mid_y = (ras.y + to_y + 2*arc[1].y)/4;
|
||||
|
||||
if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
|
||||
render_line( RAS_VAR_ to_x, to_y ) ) return 1;
|
||||
top--;
|
||||
arc-=2;
|
||||
if (top < 0)
|
||||
arc -= 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -621,6 +692,7 @@ void split_cubic( FT_Vector* base )
|
|||
base[3].y = ( a + b ) / 2;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int render_cubic( RAS_ARG_ FT_Vector* control1,
|
||||
FT_Vector* control2,
|
||||
|
@ -642,8 +714,8 @@ int render_cubic( RAS_ARG_ FT_Vector* control1,
|
|||
db = dx;
|
||||
|
||||
level = 1;
|
||||
da = da/16;
|
||||
db = db/32;
|
||||
da = da/ras.cubic_level;
|
||||
db = db/ras.conic_level;
|
||||
while ( da > 0 || db > 0 )
|
||||
{
|
||||
da >>= 1;
|
||||
|
@ -652,50 +724,84 @@ int render_cubic( RAS_ARG_ FT_Vector* control1,
|
|||
}
|
||||
|
||||
if (level <= 1)
|
||||
return render_line( RAS_VAR_ UPSCALE(to->x), UPSCALE(to->y) );
|
||||
{
|
||||
TPos to_x, to_y, mid_x, mid_y;
|
||||
|
||||
to_x = UPSCALE(to->x);
|
||||
to_y = UPSCALE(to->y);
|
||||
mid_x = (ras.x + to_x + 3*UPSCALE(control1->x+control2->x))/8;
|
||||
mid_y = (ras.y + to_y + 3*UPSCALE(control1->y+control2->y))/8;
|
||||
|
||||
return render_line( RAS_VAR_ mid_x, mid_y ) ||
|
||||
render_line( RAS_VAR_ to_x, to_y );
|
||||
}
|
||||
|
||||
arc = ras.bez_stack;
|
||||
arc[0] = *to;
|
||||
arc[1] = *control2;
|
||||
arc[2] = *control1;
|
||||
arc[0].x = UPSCALE(to->x);
|
||||
arc[0].y = UPSCALE(to->y);
|
||||
arc[1].x = UPSCALE(control2->x);
|
||||
arc[1].y = UPSCALE(control2->y);
|
||||
arc[2].x = UPSCALE(control1->x);
|
||||
arc[2].y = UPSCALE(control1->y);
|
||||
arc[3].x = ras.x;
|
||||
arc[3].y = ras.y;
|
||||
|
||||
arc[0].x = UPSCALE(arc[0].x);
|
||||
arc[0].y = UPSCALE(arc[0].y);
|
||||
arc[1].x = UPSCALE(arc[1].x);
|
||||
arc[1].y = UPSCALE(arc[1].y);
|
||||
arc[2].x = UPSCALE(arc[2].x);
|
||||
arc[2].y = UPSCALE(arc[2].y);
|
||||
|
||||
levels = ras.lev_stack;
|
||||
top = 0;
|
||||
levels[0] = level;
|
||||
|
||||
for (;;)
|
||||
while (top >= 0)
|
||||
{
|
||||
level = levels[top];
|
||||
if (level > 1)
|
||||
{
|
||||
/* check that the arc crosses the current band */
|
||||
TPos min, max, y;
|
||||
min = max = arc[0].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[3].y;
|
||||
if ( y < min ) min = y;
|
||||
if ( y > max ) max = y;
|
||||
if ( TRUNC(min) >= ras.max_ey || TRUNC(max) < 0 )
|
||||
goto Draw;
|
||||
split_cubic(arc);
|
||||
arc += 3;
|
||||
top ++;
|
||||
levels[top] = levels[top-1] = level-1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
Draw:
|
||||
{
|
||||
if (render_line( RAS_VAR_ arc[0].x, arc[0].y )) return 1;
|
||||
TPos to_x, to_y, mid_x, mid_y;
|
||||
|
||||
to_x = arc[0].x;
|
||||
to_y = arc[0].y;
|
||||
mid_x = (ras.x + to_x + 3*(arc[1].x+arc[2].x))/8;
|
||||
mid_y = (ras.y + to_y + 3*(arc[1].y+arc[2].y))/8;
|
||||
|
||||
if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
|
||||
render_line( RAS_VAR_ to_x, to_y ) ) return 1;
|
||||
top --;
|
||||
arc -= 3;
|
||||
if (top < 0)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* a macro comparing two cell pointers. returns true if a <= b */
|
||||
#if 1
|
||||
#define PACK(a) ( ((long)(a)->y << 16) | (a)->x )
|
||||
#define LESS_THAN(a,b) ( PACK(a) < PACK(b) )
|
||||
#else
|
||||
#define LESS_THAN(a,b) ( (a)->y<(b)->y || ((a)->y==(b)->y && (a)->x < (b)->x) )
|
||||
#endif
|
||||
|
||||
#define SWAP_CELLS(a,b,temp) { temp = *(a); *(a) = *(b); *(b) = temp; }
|
||||
#define DEBUG_SORT
|
||||
#define QUICK_SORT
|
||||
|
@ -740,7 +846,7 @@ void shell_sort ( PCell cells,
|
|||
/* it should be faster than calling the stdlib qsort(), and we can even */
|
||||
/* tailor our insertion threshold... */
|
||||
|
||||
#define QSORT_THRESHOLD 7 /* below this size, a sub-array will be sorted */
|
||||
#define QSORT_THRESHOLD 9 /* below this size, a sub-array will be sorted */
|
||||
/* through a normal insertion sort.. */
|
||||
|
||||
static
|
||||
|
@ -902,7 +1008,7 @@ int check_sort( PCell cells, int count )
|
|||
static
|
||||
void grays_render_span( int y, int count, FT_Span* spans, PRaster raster )
|
||||
{
|
||||
unsigned char *p, *q, *limit;
|
||||
unsigned char *p;
|
||||
FT_Bitmap* map = &raster->target;
|
||||
/* first of all, compute the scanline offset */
|
||||
p = (unsigned char*)map->buffer - y*map->pitch;
|
||||
|
@ -912,12 +1018,16 @@ int check_sort( PCell cells, int count )
|
|||
for ( ; count > 0; count--, spans++ )
|
||||
{
|
||||
if (spans->coverage)
|
||||
#if 1
|
||||
memset( p + spans->x, (spans->coverage+1) >> 1, spans->len );
|
||||
#else
|
||||
{
|
||||
q = p + spans->x;
|
||||
limit = q + spans->len;
|
||||
for ( ; q < limit; q++ )
|
||||
q[0] = (spans->coverage+1) >> 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -983,6 +1093,8 @@ int check_sort( PCell cells, int count )
|
|||
coverage = 255;
|
||||
}
|
||||
|
||||
y += ras.min_ey;
|
||||
|
||||
if (coverage)
|
||||
{
|
||||
/* see if we can add this span to the current list */
|
||||
|
@ -1026,7 +1138,7 @@ int check_sort( PCell cells, int count )
|
|||
|
||||
/* add a gray span to the current list */
|
||||
span->x = (short)x;
|
||||
span->len = (unsigned char)acount;
|
||||
span->len = (unsigned short)acount;
|
||||
span->coverage = (unsigned char)coverage;
|
||||
ras.num_gray_spans++;
|
||||
}
|
||||
|
@ -1036,7 +1148,7 @@ int check_sort( PCell cells, int count )
|
|||
static
|
||||
void grays_sweep( RAS_ARG_ FT_Bitmap* target )
|
||||
{
|
||||
TScan x, y, cover;
|
||||
TScan x, y, cover, area;
|
||||
PCell start, cur, limit;
|
||||
|
||||
cur = ras.cells;
|
||||
|
@ -1052,24 +1164,25 @@ int check_sort( PCell cells, int count )
|
|||
y = start->y;
|
||||
x = start->x;
|
||||
|
||||
area = start->area;
|
||||
cover += start->cover;
|
||||
|
||||
/* accumulate all start cells */
|
||||
for (;;)
|
||||
{
|
||||
++cur;
|
||||
if (cur >= limit || cur->y != start->y || cur->x != start->x)
|
||||
break;
|
||||
start->area += cur->area;
|
||||
start->cover += cur->cover;
|
||||
}
|
||||
|
||||
/* compute next cover */
|
||||
cover += start->cover;
|
||||
area += cur->area;
|
||||
cover += cur->cover;
|
||||
}
|
||||
|
||||
/* if the start cell has a non-null area, we must draw an */
|
||||
/* individual gray pixel there.. */
|
||||
if (start->area && x >= 0)
|
||||
if (area && x >= 0)
|
||||
{
|
||||
grays_hline( RAS_VAR_ x, y, cover*(ONE_PIXEL*2)-start->area, 1 );
|
||||
grays_hline( RAS_VAR_ x, y, cover*(ONE_PIXEL*2)-area, 1 );
|
||||
x++;
|
||||
}
|
||||
|
||||
|
@ -1100,7 +1213,7 @@ int check_sort( PCell cells, int count )
|
|||
#ifdef DEBUG_GRAYS
|
||||
{
|
||||
int n;
|
||||
FT_GraySpan* span;
|
||||
FT_Span* span;
|
||||
|
||||
fprintf( stderr, "y=%3d ", ras.span_y );
|
||||
span = ras.gray_spans;
|
||||
|
@ -1111,8 +1224,14 @@ int check_sort( PCell cells, int count )
|
|||
#endif
|
||||
}
|
||||
|
||||
typedef struct TBand_
|
||||
{
|
||||
FT_Pos min, max;
|
||||
|
||||
} TBand;
|
||||
|
||||
static
|
||||
int Convert_Glyph( RAS_ARG_ FT_Outline* outline )
|
||||
int grays_convert_glyph( RAS_ARG_ FT_Outline* outline )
|
||||
{
|
||||
static
|
||||
FT_Outline_Funcs interface =
|
||||
|
@ -1123,23 +1242,119 @@ int check_sort( PCell cells, int count )
|
|||
(FT_Outline_CubicTo_Func)Cubic_To
|
||||
};
|
||||
|
||||
TBand bands[40], *band;
|
||||
int n, num_bands;
|
||||
TPos min, max, max_y;
|
||||
|
||||
/* Set up state in the raster object */
|
||||
compute_cbox( RAS_VAR_ outline );
|
||||
|
||||
/* clip to target bitmap, exit if nothing to do */
|
||||
if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width ||
|
||||
ras.max_ey <= 0 || ras.min_ey >= ras.target.rows )
|
||||
return 0;
|
||||
|
||||
if (ras.min_ex < 0) ras.min_ex = 0;
|
||||
if (ras.min_ey < 0) ras.min_ey = 0;
|
||||
|
||||
if (ras.max_ex > ras.target.width) ras.max_ex = ras.target.width;
|
||||
if (ras.max_ey > ras.target.rows) ras.max_ey = ras.target.rows;
|
||||
|
||||
/* simple heuristic used to speed-up the bezier decomposition */
|
||||
/* see the code in render_conic and render_cubic for more details */
|
||||
ras.conic_level = 32;
|
||||
ras.cubic_level = 16;
|
||||
{
|
||||
int level = 0;
|
||||
if (ras.max_ex > 24 || ras.max_ey > 24)
|
||||
level++;
|
||||
if (ras.max_ex > 120 || ras.max_ey > 120)
|
||||
level+=2;
|
||||
|
||||
ras.conic_level <<= level;
|
||||
ras.cubic_level <<= level;
|
||||
}
|
||||
|
||||
/* setup vertical bands */
|
||||
num_bands = (ras.max_ey - ras.min_ey)/ras.band_size;
|
||||
if (num_bands == 0) num_bands = 1;
|
||||
if (num_bands >= 39) num_bands = 39;
|
||||
|
||||
ras.band_shoot = 0;
|
||||
|
||||
min = ras.min_ey;
|
||||
max_y = ras.max_ey;
|
||||
for ( n = 0; n < num_bands; n++, min = max )
|
||||
{
|
||||
max = min + ras.band_size;
|
||||
if (n == num_bands-1 || max > max_y)
|
||||
max = max_y;
|
||||
|
||||
bands[0].min = min;
|
||||
bands[0].max = max;
|
||||
band = bands;
|
||||
|
||||
while (band >= bands)
|
||||
{
|
||||
FT_Pos bottom, top, middle;
|
||||
int error;
|
||||
|
||||
ras.num_cells = 0;
|
||||
ras.invalid = 1;
|
||||
ras.min_ey = band->min;
|
||||
ras.max_ey = band->max;
|
||||
|
||||
/* Now decompose curve */
|
||||
if ( FT_Outline_Decompose( outline, &interface, &ras ) )
|
||||
error = FT_Outline_Decompose( outline, &interface, &ras ) ||
|
||||
record_cell( RAS_VAR );
|
||||
|
||||
if (!error)
|
||||
{
|
||||
#ifdef SHELL_SORT
|
||||
shell_sort( ras.cells, ras.num_cells );
|
||||
#else
|
||||
quick_sort( ras.cells, ras.num_cells );
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_GRAYS
|
||||
check_sort( ras.cells, ras.num_cells );
|
||||
dump_cells( RAS_VAR );
|
||||
#endif
|
||||
|
||||
grays_sweep( RAS_VAR_ &ras.target );
|
||||
band--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* render pool overflow, we will reduce the render band by half */
|
||||
bottom = band->min;
|
||||
top = band->max;
|
||||
middle = bottom + ((top-bottom) >> 1);
|
||||
|
||||
/* waoow !! this is too complex for a single scanline, something */
|
||||
/* must be really rotten here !! */
|
||||
if (middle == bottom)
|
||||
{
|
||||
#ifdef DEBUG_GRAYS
|
||||
fprintf( stderr, "Rotten glyph !!\n" );
|
||||
#endif
|
||||
return 1;
|
||||
/* XXX: the error condition is in ras.error */
|
||||
}
|
||||
|
||||
/* record the last cell */
|
||||
return record_cell( RAS_VAR );
|
||||
if (bottom-top >= ras.band_size)
|
||||
ras.band_shoot++;
|
||||
|
||||
band[1].min = bottom;
|
||||
band[1].max = middle;
|
||||
band[0].min = middle;
|
||||
band[0].max = top;
|
||||
band++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ras.band_shoot > 8 && ras.band_size > 16)
|
||||
ras.band_size = ras.band_size/2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1175,20 +1390,6 @@ int check_sort( PCell cells, int count )
|
|||
ras.num_cells = 0;
|
||||
ras.invalid = 1;
|
||||
|
||||
if (Convert_Glyph( (PRaster)raster, outline ))
|
||||
return 1;
|
||||
|
||||
#ifdef SHELL_SORT
|
||||
shell_sort( ras.cells, ras.num_cells );
|
||||
#else
|
||||
quick_sort( ras.cells, ras.num_cells );
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_GRAYS
|
||||
check_sort( ras.cells, ras.num_cells );
|
||||
dump_cells( RAS_VAR );
|
||||
#endif
|
||||
|
||||
ras.render_span = (FT_Raster_Span_Func)grays_render_span;
|
||||
ras.render_span_data = &ras;
|
||||
if ( params->flags & ft_raster_flag_direct )
|
||||
|
@ -1197,8 +1398,7 @@ int check_sort( PCell cells, int count )
|
|||
ras.render_span_data = params->user;
|
||||
}
|
||||
|
||||
grays_sweep( (PRaster)raster, target_map );
|
||||
return 0;
|
||||
return grays_convert_glyph( (PRaster)raster, outline );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1259,8 +1459,12 @@ int check_sort( PCell cells, int count )
|
|||
const char* pool_base,
|
||||
long pool_size )
|
||||
{
|
||||
PRaster rast = (PRaster)raster;
|
||||
|
||||
if (raster && pool_base && pool_size >= 4096)
|
||||
init_cells( (PRaster)raster, (char*)pool_base, pool_size );
|
||||
init_cells( rast, (char*)pool_base, pool_size );
|
||||
|
||||
rast->band_size = (pool_size / sizeof(TCell))/8;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue