📄 ftraster.c
字号:
;
}
/* Then compute the lines */
switch ( ras.state )
{
case Ascending_State:
if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
x, y, ras.minY, ras.maxY ) )
return FAILURE;
break;
case Descending_State:
if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
x, y, ras.minY, ras.maxY ) )
return FAILURE;
break;
default:
;
}
ras.lastX = x;
ras.lastY = y;
return SUCCESS;
}
/*************************************************************************/
/* */
/* <Function> */
/* Conic_To */
/* */
/* <Description> */
/* Injects a new conic arc and adjusts the profile list. */
/* */
/* <Input> */
/* cx :: The x-coordinate of the arc's new control point. */
/* */
/* cy :: The y-coordinate of the arc's new control point. */
/* */
/* x :: The x-coordinate of the arc's end point (its start point is */
/* stored in `lastX'). */
/* */
/* y :: The y-coordinate of the arc's end point (its start point is */
/* stored in `lastY'). */
/* */
/* <Return> */
/* SUCCESS on success, FAILURE on render pool overflow or incorrect */
/* profile. */
/* */
static Bool
Conic_To( RAS_ARGS Long cx,
Long cy,
Long x,
Long y )
{
Long y1, y2, y3, x3, ymin, ymax;
TStates state_bez;
ras.arc = ras.arcs;
ras.arc[2].x = ras.lastX;
ras.arc[2].y = ras.lastY;
ras.arc[1].x = cx; ras.arc[1].y = cy;
ras.arc[0].x = x; ras.arc[0].y = y;
do
{
y1 = ras.arc[2].y;
y2 = ras.arc[1].y;
y3 = ras.arc[0].y;
x3 = ras.arc[0].x;
/* first, categorize the Bezier arc */
if ( y1 <= y3 )
{
ymin = y1;
ymax = y3;
}
else
{
ymin = y3;
ymax = y1;
}
if ( y2 < ymin || y2 > ymax )
{
/* this arc has no given direction, split it! */
Split_Conic( ras.arc );
ras.arc += 2;
}
else if ( y1 == y3 )
{
/* this arc is flat, ignore it and pop it from the Bezier stack */
ras.arc -= 2;
}
else
{
/* the arc is y-monotonous, either ascending or descending */
/* detect a change of direction */
state_bez = y1 < y3 ? Ascending_State : Descending_State;
if ( ras.state != state_bez )
{
/* finalize current profile if any */
if ( ras.state != Unknown_State &&
End_Profile( RAS_VAR ) )
goto Fail;
/* create a new profile */
if ( New_Profile( RAS_VARS state_bez ) )
goto Fail;
}
/* now call the appropriate routine */
if ( state_bez == Ascending_State )
{
if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
goto Fail;
}
else
if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
goto Fail;
}
} while ( ras.arc >= ras.arcs );
ras.lastX = x3;
ras.lastY = y3;
return SUCCESS;
Fail:
return FAILURE;
}
/*************************************************************************/
/* */
/* <Function> */
/* Cubic_To */
/* */
/* <Description> */
/* Injects a new cubic arc and adjusts the profile list. */
/* */
/* <Input> */
/* cx1 :: The x-coordinate of the arc's first new control point. */
/* */
/* cy1 :: The y-coordinate of the arc's first new control point. */
/* */
/* cx2 :: The x-coordinate of the arc's second new control point. */
/* */
/* cy2 :: The y-coordinate of the arc's second new control point. */
/* */
/* x :: The x-coordinate of the arc's end point (its start point is */
/* stored in `lastX'). */
/* */
/* y :: The y-coordinate of the arc's end point (its start point is */
/* stored in `lastY'). */
/* */
/* <Return> */
/* SUCCESS on success, FAILURE on render pool overflow or incorrect */
/* profile. */
/* */
static Bool
Cubic_To( RAS_ARGS Long cx1,
Long cy1,
Long cx2,
Long cy2,
Long x,
Long y )
{
Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
TStates state_bez;
ras.arc = ras.arcs;
ras.arc[3].x = ras.lastX;
ras.arc[3].y = ras.lastY;
ras.arc[2].x = cx1; ras.arc[2].y = cy1;
ras.arc[1].x = cx2; ras.arc[1].y = cy2;
ras.arc[0].x = x; ras.arc[0].y = y;
do
{
y1 = ras.arc[3].y;
y2 = ras.arc[2].y;
y3 = ras.arc[1].y;
y4 = ras.arc[0].y;
x4 = ras.arc[0].x;
/* first, categorize the Bezier arc */
if ( y1 <= y4 )
{
ymin1 = y1;
ymax1 = y4;
}
else
{
ymin1 = y4;
ymax1 = y1;
}
if ( y2 <= y3 )
{
ymin2 = y2;
ymax2 = y3;
}
else
{
ymin2 = y3;
ymax2 = y2;
}
if ( ymin2 < ymin1 || ymax2 > ymax1 )
{
/* this arc has no given direction, split it! */
Split_Cubic( ras.arc );
ras.arc += 3;
}
else if ( y1 == y4 )
{
/* this arc is flat, ignore it and pop it from the Bezier stack */
ras.arc -= 3;
}
else
{
state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
/* detect a change of direction */
if ( ras.state != state_bez )
{
if ( ras.state != Unknown_State &&
End_Profile( RAS_VAR ) )
goto Fail;
if ( New_Profile( RAS_VARS state_bez ) )
goto Fail;
}
/* compute intersections */
if ( state_bez == Ascending_State )
{
if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
goto Fail;
}
else
if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
goto Fail;
}
} while ( ras.arc >= ras.arcs );
ras.lastX = x4;
ras.lastY = y4;
return SUCCESS;
Fail:
return FAILURE;
}
#undef SWAP_
#define SWAP_( x, y ) do \
{ \
Long swap = x; \
\
\
x = y; \
y = swap; \
} while ( 0 )
/*************************************************************************/
/* */
/* <Function> */
/* Decompose_Curve */
/* */
/* <Description> */
/* Scans the outline arrays in order to emit individual segments and */
/* Beziers by calling Line_To() and Bezier_To(). It handles all */
/* weird cases, like when the first point is off the curve, or when */
/* there are simply no `on' points in the contour! */
/* */
/* <Input> */
/* first :: The index of the first point in the contour. */
/* */
/* last :: The index of the last point in the contour. */
/* */
/* flipped :: If set, flip the direction of the curve. */
/* */
/* <Return> */
/* SUCCESS on success, FAILURE on error. */
/* */
static Bool
Decompose_Curve( RAS_ARGS UShort first,
UShort last,
int flipped )
{
FT_Vector v_last;
FT_Vector v_control;
FT_Vector v_start;
FT_Vector* points;
FT_Vector* point;
FT_Vector* limit;
char* tags;
unsigned tag; /* current point's state */
points = ras.outline.points;
limit = points + last;
v_start.x = SCALED( points[first].x );
v_start.y = SCALED( points[first].y );
v_last.x = SCALED( points[last].x );
v_last.y = SCALED( points[last].y );
if ( flipped )
{
SWAP_( v_start.x, v_start.y );
SWAP_( v_last.x, v_last.y );
}
v_control = v_start;
point = points + first;
tags = ras.outline.tags + first;
tag = FT_CURVE_TAG( tags[0] );
/* A contour cannot start with a cubic control point! *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -