📄 ftraster.c
字号:
/* and set a link from the old one to it */ old = ras.cur_prof; old->height = h; ras.cur_prof = new = (PProfile)ras.cursor; ras.cursor += AlignProfileSize; new->height = 0; new->offset = ras.cursor; old->next = new; ras.num_profs++; } /* check for overflow */ if ( ras.cursor >= ras.pool_limit ) { ras.error = ErrRaster_Overflow; return FAILURE; } ras.joint = FALSE; return SUCCESS; } /*************************************************************************/ /* */ /* <Function> */ /* Insert_Extrema */ /* */ /* <Description> */ /* Records that a given scanline contains at least one local */ /* extremum. The table of extrema is placed at the end of the render */ /* pool and grows downwards. It is used during the sweep phase. */ /* */ /* <Input> */ /* y :: The coordinate of the scanline containing an extremum. */ /* */ static TResult Insert_Extrema( RAS_ARG_ TScan y ) { PPos extrema; TScan y2; int n; PTRACE2(( "EXTREMA += %d", y )); n = ras.n_extrema - 1; extrema = ras.pool_size - ras.n_extrema; /* look for first y extremum that is <= */ while ( n >= 0 && y < extrema[n] ) n--; /* if it is <, simply insert it, ignore if == */ if ( n >= 0 && y > extrema[n] ) while ( n >= 0 ) { y2 = extrema[n]; extrema[n] = y; y = y2; n--; } if ( n < 0 ) { ras.pool_limit--; ras.n_extrema++; ras.pool_size[-ras.n_extrema] = y; if ( ras.pool_limit <= ras.cursor ) { ras.error = ErrRaster_Overflow; return FAILURE; } } return SUCCESS; } /*************************************************************************/ /* */ /* <Function> */ /* Finalize_Profile_Table */ /* */ /* <Description> */ /* Adjusts all links in the profiles list. Called when the outline */ /* parsing is done. */ /* */ /* <Return> */ /* SUCCESS or FAILURE. */ /* */ static TResult Finalize_Profile_Table( RAS_ARG ) { int n, bottom, top; PProfile p; n = ras.num_profs; if ( n > 1 ) { p = ras.start_prof; while ( n > 0 ) { if ( n > 1 ) p->link = (PProfile)( p->offset + p->height ); else p->link = NULL; switch ( p->flow ) { case Flow_Down: PTRACE2(( "FLOW DOWN (start = %d, height = %d)", p->start, p->height )); bottom = p->start - p->height+1; top = p->start; p->start = bottom; p->offset += p->height-1; break; case Flow_Up: default: PTRACE2(( "FLOW UP (start = %d, height = %d)", p->start, p->height )); bottom = p->start; top = p->start + p->height-1; } if ( Insert_Extrema( RAS_VAR_ bottom ) || Insert_Extrema( RAS_VAR_ top+1 ) ) return FAILURE; p = p->link; n--; } } else ras.start_prof = NULL; return SUCCESS; } /*************************************************************************/ /* */ /* <Function> */ /* Line_Up */ /* */ /* <Description> */ /* Computes the scan-line intersections of an ascending line segment */ /* and stores them in the render pool. */ /* */ /* <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_Up( RAS_ARG_ TPos x1, TPos y1, TPos x2, TPos y2, TPos miny, TPos maxy ) { TPos Dx, Dy; int e1, e2, f1, f2, size; TPos Ix, Rx, Ax; PPos top; Dx = x2 - x1; Dy = y2 - y1; if ( Dy <= 0 || y2 < miny || y1 > maxy ) return SUCCESS; /* clip to higher scanline when necessary */ if ( y2 > maxy ) { /* x2 += FMulDiv( Dx, maxy-y2, Dy ); UNNECESSARY */ e2 = TRUNC( maxy ); f2 = 0; } else { e2 = TRUNC( y2 ); f2 = FRAC( y2 ); } /* clip to lower scanline when necessary */ if ( y1 < miny ) { TPos x, y; /* we use a binary search to compute the lower // clipping intersection. That's because we don't // want to use an external function like FT_MulDiv // to compute it directly. */ if ( y2 == miny ) goto Exit; do { x = (x1 + x2) >> 1; y = (y1 + y2) >> 1; if (y <= miny) { x1 = x; y1 = y; } else { x2 = x; y2 = y; } } while ( y1 < miny ); e1 = TRUNC( miny ); f1 = 0; } else { e1 = TRUNC( y1 ); f1 = FRAC( y1 ); } /* adjust start point so that we begin on an integer scanline position */ if ( f1 > 0 ) { if ( e1 == e2 ) goto Exit; else { x1 += FMulDiv( Dx, PRECISION - f1, Dy ); e1 += 1; } } else if ( ras.joint ) { ras.cursor--; ras.joint = FALSE; } ras.joint = ( f2 == 0 ); /* if this is a `fresh' profile, record its starting scanline */ if ( ras.fresh ) { ras.cur_prof->start = e1; ras.fresh = FALSE; } /* check for overflow */ size = e2 - e1 + 1; if ( ras.cursor + size >= ras.pool_limit ) { ras.error = ErrRaster_Overflow; return FAILURE; } /* compute decision variables and push the intersections on top */ /* of the render pool */ Dx <<= PRECISION_BITS; Ix = Dx / Dy; Rx = Dx % Dy; if (Rx < 0) { Ix --; Rx += Dy; } Ax = -Dy; Rx <<= 1; Dy <<= 1; top = ras.cursor; while ( size > 0 ) { *top++ = x1; DEBUG_PSET; x1 += Ix; Ax += Rx; if ( Ax >= 0 ) { Ax -= Dy; x1 ++; } size--; } ras.cursor = top; Exit: return SUCCESS; } /*************************************************************************/ /* */ /* <Function> */ /* Line_Down */ /* */ /* <Description> */ /* Computes the scan-line intersections of a descending line segment */ /* and stores them in the render pool. */ /* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -