📄 ftgrays.c
字号:
{
if ( ex < ras.min_ex )
ex = (TCoord)( ras.min_ex - 1 );
ras.area = 0;
ras.cover = 0;
ras.ex = ex - ras.min_ex;
ras.ey = ey - ras.min_ey;
ras.last_ey = SUBPIXELS( ey );
ras.invalid = 0;
gray_set_cell( RAS_VAR_ ex, ey );
}
/*************************************************************************/
/* */
/* Render a scanline as one or more cells. */
/* */
static void
gray_render_scanline( RAS_ARG_ TCoord ey,
TPos x1,
TCoord y1,
TPos x2,
TCoord y2 )
{
TCoord ex1, ex2, fx1, fx2, delta;
long p, first, dx;
int incr, lift, mod, rem;
dx = x2 - x1;
ex1 = TRUNC( x1 );
ex2 = TRUNC( x2 );
fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
/* trivial case. Happens often */
if ( y1 == y2 )
{
gray_set_cell( RAS_VAR_ ex2, ey );
return;
}
/* everything is located in a single cell. That is easy! */
/* */
if ( ex1 == ex2 )
{
delta = y2 - y1;
ras.area += (TArea)( fx1 + fx2 ) * delta;
ras.cover += delta;
return;
}
/* ok, we'll have to render a run of adjacent cells on the same */
/* scanline... */
/* */
p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
first = ONE_PIXEL;
incr = 1;
if ( dx < 0 )
{
p = fx1 * ( y2 - y1 );
first = 0;
incr = -1;
dx = -dx;
}
delta = (TCoord)( p / dx );
mod = (TCoord)( p % dx );
if ( mod < 0 )
{
delta--;
mod += (TCoord)dx;
}
ras.area += (TArea)( fx1 + first ) * delta;
ras.cover += delta;
ex1 += incr;
gray_set_cell( RAS_VAR_ ex1, ey );
y1 += delta;
if ( ex1 != ex2 )
{
p = ONE_PIXEL * ( y2 - y1 + delta );
lift = (TCoord)( p / dx );
rem = (TCoord)( p % dx );
if ( rem < 0 )
{
lift--;
rem += (TCoord)dx;
}
mod -= (int)dx;
while ( ex1 != ex2 )
{
delta = lift;
mod += rem;
if ( mod >= 0 )
{
mod -= (TCoord)dx;
delta++;
}
ras.area += (TArea)ONE_PIXEL * delta;
ras.cover += delta;
y1 += delta;
ex1 += incr;
gray_set_cell( RAS_VAR_ ex1, ey );
}
}
delta = y2 - y1;
ras.area += (TArea)( fx2 + ONE_PIXEL - first ) * delta;
ras.cover += delta;
}
/*************************************************************************/
/* */
/* Render a given line as a series of scanlines. */
/* */
static void
gray_render_line( RAS_ARG_ TPos to_x,
TPos to_y )
{
TCoord ey1, ey2, fy1, fy2;
TPos dx, dy, x, x2;
long p, first;
int delta, rem, mod, lift, incr;
ey1 = TRUNC( ras.last_ey );
ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
fy1 = (TCoord)( ras.y - ras.last_ey );
fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
dx = to_x - ras.x;
dy = to_y - ras.y;
/* XXX: we should do something about the trivial case where dx == 0, */
/* as it happens very often! */
/* perform vertical clipping */
{
TCoord min, max;
min = ey1;
max = ey2;
if ( ey1 > ey2 )
{
min = ey2;
max = ey1;
}
if ( min >= ras.max_ey || max < ras.min_ey )
goto End;
}
/* everything is on a single scanline */
if ( ey1 == ey2 )
{
gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
goto End;
}
/* vertical line - avoid calling gray_render_scanline */
incr = 1;
if ( dx == 0 )
{
TCoord ex = TRUNC( ras.x );
TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
TPos area;
first = ONE_PIXEL;
if ( dy < 0 )
{
first = 0;
incr = -1;
}
delta = (int)( first - fy1 );
ras.area += (TArea)two_fx * delta;
ras.cover += delta;
ey1 += incr;
gray_set_cell( &ras, ex, ey1 );
delta = (int)( first + first - ONE_PIXEL );
area = (TArea)two_fx * delta;
while ( ey1 != ey2 )
{
ras.area += area;
ras.cover += delta;
ey1 += incr;
gray_set_cell( &ras, ex, ey1 );
}
delta = (int)( fy2 - ONE_PIXEL + first );
ras.area += (TArea)two_fx * delta;
ras.cover += delta;
goto End;
}
/* ok, we have to render several scanlines */
p = ( ONE_PIXEL - fy1 ) * dx;
first = ONE_PIXEL;
incr = 1;
if ( dy < 0 )
{
p = fy1 * dx;
first = 0;
incr = -1;
dy = -dy;
}
delta = (int)( p / dy );
mod = (int)( p % dy );
if ( mod < 0 )
{
delta--;
mod += (TCoord)dy;
}
x = ras.x + delta;
gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
ey1 += incr;
gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
if ( ey1 != ey2 )
{
p = ONE_PIXEL * dx;
lift = (int)( p / dy );
rem = (int)( p % dy );
if ( rem < 0 )
{
lift--;
rem += (int)dy;
}
mod -= (int)dy;
while ( ey1 != ey2 )
{
delta = lift;
mod += rem;
if ( mod >= 0 )
{
mod -= (int)dy;
delta++;
}
x2 = x + delta;
gray_render_scanline( RAS_VAR_ ey1, x,
(TCoord)( ONE_PIXEL - first ), x2,
(TCoord)first );
x = x2;
ey1 += incr;
gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
}
}
gray_render_scanline( RAS_VAR_ ey1, x,
(TCoord)( ONE_PIXEL - first ), to_x,
fy2 );
End:
ras.x = to_x;
ras.y = to_y;
ras.last_ey = SUBPIXELS( ey2 );
}
static void
gray_split_conic( FT_Vector* base )
{
TPos a, b;
base[4].x = base[2].x;
b = base[1].x;
a = base[3].x = ( base[2].x + b ) / 2;
b = base[1].x = ( base[0].x + b ) / 2;
base[2].x = ( a + b ) / 2;
base[4].y = base[2].y;
b = base[1].y;
a = base[3].y = ( base[2].y + b ) / 2;
b = base[1].y = ( base[0].y + b ) / 2;
base[2].y = ( a + b ) / 2;
}
static void
gray_render_conic( RAS_ARG_ const FT_Vector* control,
const FT_Vector* to )
{
TPos dx, dy;
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;
level = 1;
dx = dx / ras.conic_level;
while ( dx > 0 )
{
dx >>= 2;
level++;
}
/* a shortcut to speed things up */
if ( level <= 1 )
{
/* we compute the mid-point directly in order to avoid */
/* calling gray_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;
gray_render_line( RAS_VAR_ mid_x, mid_y );
gray_render_line( RAS_VAR_ to_x, to_y );
return;
}
arc = ras.bez_stack;
levels = ras.lev_stack;
top = 0;
levels[0] = level;
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 ) < ras.min_ey )
goto Draw;
gray_split_conic( arc );
arc += 2;
top++;
levels[top] = levels[top - 1] = level - 1;
continue;
}
Draw:
{
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;
gray_render_line( RAS_VAR_ mid_x, mid_y );
gray_render_line( RAS_VAR_ to_x, to_y );
top--;
arc -= 2;
}
}
return;
}
static void
gray_split_cubic( FT_Vector* base )
{
TPos a, b, c, d;
base[6].x = base[3].x;
c = base[1].x;
d = base[2].x;
base[1].x = a = ( base[0].x + c ) / 2;
base[5].x = b = ( base[3].x + d ) / 2;
c = ( c + d ) / 2;
base[2].x = a = ( a + c ) / 2;
base[4].x = b = ( b + c ) / 2;
base[3].x = ( a + b ) / 2;
base[6].y = base[3].y;
c = base[1].y;
d = base[2].y;
base[1].y = a = ( base[0].y + c ) / 2;
base[5].y = b = ( base[3].y + d ) / 2;
c = ( c + d ) / 2;
base[2].y = a = ( a + c ) / 2;
base[4].y = b = ( b + c ) / 2;
base[3].y = ( a + b ) / 2;
}
static void
gray_render_cubic( RAS_ARG_ const FT_Vector* control1,
const FT_Vector* control2,
const FT_Vector* to )
{
TPos dx, dy, da, db;
int top, level;
int* levels;
FT_Vector* arc;
dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
if ( dx < 0 )
dx = -dx;
dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
if ( dy < 0 )
dy = -dy;
if ( dx < dy )
dx = dy;
da = dx;
dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
if ( dx < 0 )
dx = -dx;
dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
if ( dy < 0 )
dy = -dy;
if ( dx < dy )
dx = dy;
db = dx;
level = 1;
da = da / ras.cubic_level;
db = db / ras.conic_level;
while ( da > 0 || db > 0 )
{
da >>= 2;
db >>= 3;
level++;
}
if ( level <= 1 )
{
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -