📄 ftraster.c
字号:
PLong top; arc = ras.arc; y1 = arc[degree].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[degree].x; 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[degree].y; if ( y2 - y1 >= ras.precision_step ) { splitter( arc ); arc += degree; } else { *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x, e - y1, y2 - y1 ); arc -= degree; e += ras.precision; } } else { if ( y2 == e ) { ras.joint = TRUE; *top++ = arc[0].x; e += ras.precision; } arc -= degree; } } Fin: ras.top = top; ras.arc -= degree; return SUCCESS; } /*************************************************************************/ /* */ /* <Function> */ /* Bezier_Down */ /* */ /* <Description> */ /* Computes the x-coordinates of an descending Bezier arc and stores */ /* them in the render pool. */ /* */ /* <Input> */ /* degree :: The degree of the Bezier arc (either 2 or 3). */ /* */ /* splitter :: The function to split Bezier arcs. */ /* */ /* miny :: A lower vertical clipping bound value. */ /* */ /* maxy :: An upper vertical clipping bound value. */ /* */ /* <Return> */ /* SUCCESS on success, FAILURE on render pool overflow. */ /* */ static Bool Bezier_Down( RAS_ARGS Int degree, TSplitter splitter, 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; if ( degree > 2 ) arc[3].y = -arc[3].y; fresh = ras.fresh; result = Bezier_Up( RAS_VARS degree, splitter, -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 :: The x-coordinate of the segment's end point (its start point */ /* is stored in `LastX'). */ /* */ /* y :: The y-coordinate of the segment's end point (its start point */ /* is stored in `LastY'). */ /* */ /* <Return> */ /* 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> */ /* 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 : Descending; if ( ras.state != state_bez ) { /* finalize current profile if any */ if ( ras.state != Unknown && 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 ) { 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. */ /* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -