📄 ftraster.c
字号:
/* <Input> */ /* x1 :: The start x coordinate. */ /* y1 :: The start y coordinate. */ /* x2 :: The end x coordinate. */ /* y2 :: The end y coordinate. */ /* miny :: The minimum vertical grid coordinate. */ /* maxy :: The maximum vertical grid coordinate. */ /* */ /* <Return> */ /* SUCCESS or FAILURE. */ /* */ static TResult Line_Down( RAS_ARG_ TPos x1, TPos y1, TPos x2, TPos y2, TPos miny, TPos maxy ) { TResult result, fresh; /* simply invert the coordinates and call Line_Up */ fresh = ras.fresh; result = Line_Up( RAS_VAR_ x1, -y1, x2, -y2, -maxy, -miny ); /* if this was a fresh profile, invert the recorded start position */ if ( fresh && !ras.fresh ) ras.cur_prof->start = -ras.cur_prof->start; return result; } /* A function type describing the functions used to split bezier arcs */ typedef void (*TSplitter)( TPoint* base );#ifdef FT_DYNAMIC_BEZIER_STEPS static TPos Dynamic_Bezier_Threshold( RAS_ARG_ int degree, TPoint* arc ) { TPos min_x, max_x, min_y, max_y, A, B; TPos wide_x, wide_y, threshold; TPoint* cur = arc; TPoint* limit = cur + degree; /* first of all, set the threshold to the maximum x or y extent */ min_x = max_x = arc[0].x; min_y = max_y = arc[0].y; cur++; for ( ; cur < limit; cur++ ) { TPos x = cur->x; TPos y = cur->y; if ( x < min_x ) min_x = x; if ( x > max_x ) max_x = x; if ( y < min_y ) min_y = y; if ( y > max_y ) max_y = y; } wide_x = (max_x - min_x) << 4; wide_y = (max_y - min_y) << 4; threshold = wide_x; if (threshold < wide_y) threshold = wide_y; /* now compute the second and third order error values */ wide_x = arc[0].x + arc[1].x - arc[2].x*2; wide_y = arc[0].y + arc[1].y - arc[2].y*2; if (wide_x < 0) wide_x = -wide_x; if (wide_y < 0) wide_y = -wide_y; A = wide_x; if ( A < wide_y ) A = wide_y; if (degree >= 3) { wide_x = arc[3].x - arc[0].x + 3*(arc[2].x - arc[3].x); wide_y = arc[3].y - arc[0].y + 3*(arc[2].y - arc[3].y); if (wide_x < 0) wide_x = -wide_x; if (wide_y < 0) wide_y = -wide_y; B = wide_x; if ( B < wide_y ) B = wide_y; } else B = 0; while ( A > 0 || B > 0 ) { threshold >>= 1; A >>= 2; B >>= 3; } if (threshold < PRECISION_STEP) threshold = PRECISION_STEP; return threshold; }#endif /*************************************************************************/ /* */ /* <Function> */ /* Bezier_Up */ /* */ /* <Description> */ /* Computes the scan-line intersections of an ascending second-order */ /* Bezier arc and stores them in the render pool. The arc is taken */ /* from the top of the stack. */ /* */ /* <Input> */ /* miny :: The minimum vertical grid coordinate. */ /* maxy :: The maximum vertical grid coordinate. */ /* */ /* <Return> */ /* SUCCESS or FAILURE. */ /* */ static TResult Bezier_Up( RAS_ARG_ int degree, TSplitter splitter, TPos miny, TPos maxy ) { TPos y1, y2, e, e2, e0, threshold; int f1; TPoint* arc; TPoint* start_arc; PPos top; arc = ras.arc; y1 = arc[degree].y; y2 = arc[0].y; top = ras.cursor; if ( y2 < miny || y1 > maxy ) goto Fin; e2 = FLOOR( y2 ); /* integer end y */ if ( e2 > maxy ) e2 = FLOOR(maxy); e0 = CEILING(miny); if ( y1 < miny ) { e = e0; /* integer start y == current scanline */ } else { e = CEILING( y1 ); /* integer start y == current scanline */ f1 = FRAC( y1 ); /* fractional shift of start y */ e0 = e; /* first integer scanline to be pushed */ if ( f1 == 0 ) /* do we start on an integer scanline? */ { if ( ras.joint ) { top--; ras.joint = FALSE; } *top++ = arc[degree].x; /* write directly start position */ DEBUG_PSET; e += PRECISION; /* go to next scanline */ } } /* record start position if necessary */ if ( ras.fresh ) { ras.cur_prof->start = TRUNC( e0 ); ras.fresh = FALSE; } /* exit if the current scanline is already above the max scanline */ if ( e2 < e ) goto Fin; /* check for overflow */ if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.pool_limit ) { ras.cursor = top; ras.error = ErrRaster_Overflow; return FAILURE; }#ifdef FT_DYNAMIC_BEZIER_STEPS /* compute dynamic bezier step threshold */ threshold = Dynamic_Bezier_Threshold( RAS_VAR_ degree, arc );#else threshold = PRECISION_STEP;#endif start_arc = arc; /* loop while there is still an arc on the bezier stack */ /* and the current scan line is below y max == e2 */ while ( arc >= start_arc && e <= e2 ) { ras.joint = FALSE; y2 = arc[0].y; /* final y of the top-most arc */ if ( y2 > e ) /* the arc intercepts the current scanline */ { y1 = arc[degree].y; /* start y of top-most arc */ if ( y2 >= e + PRECISION || y2 - y1 >= threshold ) { /* if the arc's height is too great, split it */ splitter( arc ); arc += degree; } else { /* otherwise, approximate it as a segment and compute */ /* its intersection with the current scanline */ *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x, e - y1, y2 - y1 ); DEBUG_PSET; arc -= degree; /* pop the arc */ e += PRECISION; /* go to next scanline */ } } else { if ( y2 == e ) /* if the arc falls on the scanline */ { /* record its _joint_ intersection */ ras.joint = TRUE; *top++ = arc[0].x; DEBUG_PSET; e += PRECISION; /* go to next scanline */ } arc -= degree; /* pop the arc */ } } Fin: ras.cursor = top; ras.arc -= degree; return SUCCESS; } /*************************************************************************/ /* */ /* <Function> */ /* Bezier_Down */ /* */ /* <Description> */ /* Computes the scan-line intersections of a descending second-order */ /* Bezier arc and stores them in the render pool. The arc is taken */ /* from the top of the stack. */ /* */ /* <Input> */ /* miny :: The minimum vertical grid coordinate. */ /* maxy :: The maximum vertical grid coordinate. */ /* */ /* <Return> */ /* SUCCESS or FAILURE. */ /* */ static TResult Bezier_Down( RAS_ARG_ int degree, TSplitter splitter, TPos miny, TPos maxy ) { TPoint* arc = ras.arc; TResult 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_VAR_ degree, splitter, -maxy, -miny ); if ( fresh && !ras.fresh ) ras.cur_prof->start = -ras.cur_prof->start; arc[0].y = -arc[0].y; return result; }#ifdef FT_RASTER_CONIC_BEZIERS /*************************************************************************/ /* */ /* <Function> */ /* Split_Conic */ /* */ /* <Description> */ /* Subdivides one second-order Bezier arc into two joint sub-arcs in */ /* the Bezier stack. */ /* */ /* <Note> */ /* This routine is the `beef' of the component. It is one of _the_ */ /* inner loops that should be optimized like hell to get the best */ /* performance.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -