📄 ttraster.c
字号:
fresh = ras.fresh; result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny ); if ( fresh && !ras.fresh ) ras.cProfile->start = -ras.cProfile->start; return result; }/****************************************************************************//* *//* Function: Bezier_Up *//* *//* Description: Computes thes x-coordinates of an ascending bezier arc *//* and stores them in the render pool. *//* *//* Input: None. The arc is taken from the top of the Bezier stack. *//* *//* Returns: SUCCESS on success. *//* FAILURE on Render Pool overflow. *//* *//****************************************************************************/ static Bool Bezier_Up( RAS_ARGS Long miny, Long maxy ) { Long y1, y2, e, e2, e0; Short f1; TPoint* arc; TPoint* start_arc; PStorage top; arc = ras.arc; y1 = arc[2].y; y2 = arc[0].y; top = ras.top; if ( y2 < miny || y1 > maxy ) goto Fin; e2 = FLOOR( y2 ); if ( e2 > maxy ) e2 = maxy; e0 = miny; if ( y1 < miny ) e = miny; else { e = CEILING( y1 ); f1 = FRAC( y1 ); e0 = e; if ( f1 == 0 ) { if ( ras.joint ) { top--; ras.joint = FALSE; } *top++ = arc[2].x; DEBUG_PSET; e += ras.precision; } } if ( ras.fresh ) { ras.cProfile->start = TRUNC( e0 ); ras.fresh = FALSE; } if ( e2 < e ) goto Fin; if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff ) { ras.top = top; ras.error = Raster_Err_Overflow; return FAILURE; } start_arc = arc; while ( arc >= start_arc && e <= e2 ) { ras.joint = FALSE; y2 = arc[0].y; if ( y2 > e ) { y1 = arc[2].y; if ( y2 - y1 >= ras.precision_step ) { Split_Bezier( arc ); arc += 2; } else { *top++ = arc[2].x + FMulDiv( arc[0].x - arc[2].x, e - y1, y2 - y1 ); DEBUG_PSET; arc -= 2; e += ras.precision; } } else { if ( y2 == e ) { ras.joint = TRUE; *top++ = arc[0].x; DEBUG_PSET; e += ras.precision; } arc -= 2; } } Fin: ras.top = top; ras.arc -= 2; return SUCCESS; }/****************************************************************************//* *//* Function: Bezier_Down *//* *//* Description: Computes the x-coordinates of a descending bezier arc *//* and stores them in the render pool. *//* *//* Input: None. Arc is taken from the top of the Bezier stack. *//* *//* Returns: SUCCESS on success. *//* FAILURE on Render Pool overflow. *//* *//****************************************************************************/ static Bool Bezier_Down( RAS_ARGS Long miny, Long maxy ) { TPoint* arc = ras.arc; Bool result, fresh; arc[0].y = -arc[0].y; arc[1].y = -arc[1].y; arc[2].y = -arc[2].y; fresh = ras.fresh; result = Bezier_Up( RAS_VARS -maxy, -miny ); if ( fresh && !ras.fresh ) ras.cProfile->start = -ras.cProfile->start; arc[0].y = -arc[0].y; return result; }/****************************************************************************//* *//* Function: Line_To *//* *//* Description: Injects a new line segment and adjusts Profiles list. *//* *//* Input: x, y : segment endpoint (start point in LastX,LastY) *//* *//* Returns: SUCCESS on success. *//* FAILURE on Render Pool overflow or Incorrect Profile. *//* *//****************************************************************************/ static Bool Line_To( RAS_ARGS Long x, Long y ) { /* First, detect a change of direction */ switch ( ras.state ) { case Unknown: if ( y > ras.lastY ) { if ( New_Profile( RAS_VARS Ascending ) ) return FAILURE; } else { if ( y < ras.lastY ) if ( New_Profile( RAS_VARS Descending ) ) return FAILURE; } break; case Ascending: if ( y < ras.lastY ) { if ( End_Profile( RAS_VAR ) || New_Profile( RAS_VARS Descending ) ) return FAILURE; } break; case Descending: if ( y > ras.lastY ) { if ( End_Profile( RAS_VAR ) || New_Profile( RAS_VARS Ascending ) ) return FAILURE; } break; default: ; } /* Then compute the lines */ switch ( ras.state ) { case Ascending: if ( Line_Up ( RAS_VARS ras.lastX, ras.lastY, x, y, ras.minY, ras.maxY ) ) return FAILURE; break; case Descending: 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: Bezier_To *//* *//* Description: Injects a new bezier arc and adjusts the profile list. *//* *//* Input: x, y : arc endpoint (start point in LastX, LastY) *//* Cx, Cy : control point *//* *//* Returns: SUCCESS on success. *//* FAILURE on Render Pool overflow or Incorrect Profile. *//* *//****************************************************************************/ static Bool Bezier_To( RAS_ARGS Long x, Long y, Long cx, Long cy ) { Long y1, y2, y3, x3; TStates state_bez; Push_Bezier( RAS_VARS ras.lastX, ras.lastY, cx, cy, x, 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 == y2 ) { if ( y2 == y3 ) state_bez = Flat; else if ( y2 > y3 ) state_bez = Descending; else state_bez = Ascending; } else if ( y1 > y2 ) { if ( y2 >= y3 ) state_bez = Descending; else state_bez = Unknown; } else if ( y2 <= y3 ) state_bez = Ascending; else state_bez = Unknown; /* split non-monotonic arcs, ignore flat ones, or */ /* computes the up and down ones */ switch ( state_bez ) { case Flat: ras.arc -= 2; break; case Unknown: Split_Bezier( ras.arc ); ras.arc += 2; break; default: /* detect a change of direction */ if ( ras.state != state_bez ) { if ( ras.state != Unknown ) if ( End_Profile( RAS_VAR ) ) return FAILURE; if ( New_Profile( RAS_VARS state_bez ) ) return FAILURE; } /* compute */ switch ( ras.state ) { case Ascending: if ( Bezier_Up ( RAS_VARS ras.minY, ras.maxY ) ) return FAILURE; break; case Descending: if ( Bezier_Down( RAS_VARS ras.minY, ras.maxY ) ) return FAILURE; break; default: ; } } } while ( ras.arc >= ras.arcs ); ras.lastX = x3; ras.lastY = y3; return SUCCESS; }/****************************************************************************//* *//* Function: Decompose_Curve *//* *//* Description: Scans the outline arays 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, last : indexes of first and last point in *//* contour. *//* *//* Returns: SUCCESS on success. *//* FAILURE on error. *//* *//****************************************************************************/#undef SWAP_#define SWAP_(x,y) { Long swap = x; x = y; y = swap; } static Bool Decompose_Curve( RAS_ARGS UShort first, UShort last, Bool flipped ) { Long x, y; /* current point */ Long cx, cy; /* current Bezier control point */ Long mx, my; /* current middle point */ Long x_first, y_first; /* first point's coordinates */ Long x_last, y_last; /* last point's coordinates */ UShort index; /* current point's index */ Bool on_curve; /* current point's state */ x_first = SCALED( ras.coords[first].x ); y_first = SCALED( ras.coords[first].y ); if ( flipped ) SWAP_( x_first,y_first ); x_last = SCALED( ras.coords[last].x ); y_last = SCALED( ras.coords[last].y ); if ( flipped ) SWAP_( x_last,y_last ); ras.lastX = cx = x_first; ras.lastY = cy = y_first; on_curve = (ras.flags[first] & 1); index = first; /* check first point to determine origin */ if ( !on_curve ) { /* first point is off the curve. Yes, this happens... */ if ( ras.flags[last] & 1 ) { ras.lastX = x_last; /* start at last point if it */ ras.lastY = y_last; /* is on the curve */ } else { /* if both first and last points are off the curve, */ /* start at their middle and record its position */ /* for closure */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -