📄 ttraster.c
字号:
/****************************************************************************//* *//* Function: New_Profile *//* *//* Description: Creates a new Profile in the render pool. *//* *//* Input: aState state/orientation of the new Profile *//* *//* Returns: SUCCESS on success. *//* FAILURE in case of overflow or of incoherent Profile. *//* *//****************************************************************************/ static Bool New_Profile( RAS_ARGS TStates aState ) { if ( !ras.fProfile ) { ras.cProfile = (PProfile)ras.top; ras.fProfile = ras.cProfile; ras.top += AlignProfileSize; } if ( ras.top >= ras.maxBuff ) { ras.error = Raster_Err_Overflow; return FAILURE; } switch ( aState ) { case Ascending: ras.cProfile->flow = TT_Flow_Up; PTRACE7(( "New ascending profile = %lx\n", (long)ras.cProfile )); break; case Descending: ras.cProfile->flow = TT_Flow_Down; PTRACE7(( "New descending profile = %lx\n", (long)ras.cProfile )); break; default: PTRACE0(( "Invalid profile direction in Raster:New_Profile !!\n" )); ras.error = Raster_Err_Invalid; return FAILURE; } ras.cProfile->start = 0; ras.cProfile->height = 0; ras.cProfile->offset = ras.top; ras.cProfile->link = (PProfile)0; ras.cProfile->next = (PProfile)0; if ( !ras.gProfile ) ras.gProfile = ras.cProfile; ras.state = aState; ras.fresh = TRUE; ras.joint = FALSE; return SUCCESS; }/****************************************************************************//* *//* Function: End_Profile *//* *//* Description: Finalizes the current Profile. *//* *//* Input: None *//* *//* Returns: SUCCESS on success. *//* FAILURE in case of overflow or incoherency. *//* *//****************************************************************************/ static Bool End_Profile( RAS_ARG ) { Long h; PProfile oldProfile; h = ras.top - ras.cProfile->offset; if ( h < 0 ) { PTRACE0(( "Negative height encountered in End_Profile!\n" )); ras.error = Raster_Err_Neg_Height; return FAILURE; } if ( h > 0 ) { PTRACE1(( "Ending profile %lx, start = %ld, height = %ld\n", (long)ras.cProfile, ras.cProfile->start, h )); oldProfile = ras.cProfile; ras.cProfile->height = h; ras.cProfile = (PProfile)ras.top; ras.top += AlignProfileSize; ras.cProfile->height = 0; ras.cProfile->offset = ras.top; oldProfile->next = ras.cProfile; ras.num_Profs++; } if ( ras.top >= ras.maxBuff ) { PTRACE1(( "overflow in End_Profile\n" )); ras.error = Raster_Err_Overflow; return FAILURE; } ras.joint = FALSE; return SUCCESS; }/****************************************************************************//* *//* Function: Insert_Y_Turn *//* *//* Description: Insert a salient into the sorted list placed on top *//* of the render pool *//* *//* Input: New y scanline position *//* *//****************************************************************************/ static Bool Insert_Y_Turn( RAS_ARGS Int y ) { PStorage y_turns; Int y2, n; n = ras.numTurns-1; y_turns = ras.sizeBuff - ras.numTurns; /* look for first y value that is <= */ while ( n >= 0 && y < y_turns[n] ) n--; /* if it is <, simply insert it, ignore if == */ if ( n >= 0 && y > y_turns[n] ) while ( n >= 0 ) { y2 = y_turns[n]; y_turns[n] = y; y = y2; n--; } if ( n < 0 ) { if (ras.maxBuff <= ras.top) { ras.error = Raster_Err_Overflow; return FAILURE; } ras.maxBuff--; ras.numTurns++; ras.sizeBuff[-ras.numTurns] = y; } return SUCCESS; }/****************************************************************************//* *//* Function: Finalize_Profile_Table *//* *//* Description: Adjusts all links in the Profiles list. *//* *//* Input: None *//* *//* Returns: None. *//* *//****************************************************************************/ static Bool Finalize_Profile_Table( RAS_ARG ) { Int bottom, top; UShort n; PProfile p; n = ras.num_Profs; if ( n > 1 ) { p = ras.fProfile; while ( n > 0 ) { if ( n > 1 ) p->link = (PProfile)( p->offset + p->height ); else p->link = NULL; switch ( p->flow ) { case TT_Flow_Down: bottom = p->start - p->height+1; top = p->start; p->start = bottom; p->offset += p->height-1; break; case TT_Flow_Up: default: bottom = p->start; top = p->start + p->height-1; } if ( Insert_Y_Turn( RAS_VARS bottom ) || Insert_Y_Turn( RAS_VARS top+1 ) ) return FAILURE; p = p->link; n--; } } else ras.fProfile = NULL; return SUCCESS; }/****************************************************************************//* *//* Function: Split_Bezier *//* *//* Description: Subdivides one Bezier arc into two joint *//* sub-arcs in the Bezier stack. *//* *//* Input: None (subdivided bezier is taken from the top of the *//* stack). *//* *//* Returns: None. *//* *//* *//* Note: This routine is the 'beef' of this component. It is _the_ *//* inner loop that should be optimized to hell to get the *//* best performance. *//* *//****************************************************************************/ static void Split_Bezier( TPoint* base ) { Long a, b; base[4].x = base[2].x; b = base[1].x; a = base[3].x = ( base[2].x + b ) / 2; b = base[1].x = ( base[0].x + b ) / 2; base[2].x = ( a + b ) / 2; base[4].y = base[2].y; b = base[1].y; a = base[3].y = ( base[2].y + b ) / 2; b = base[1].y = ( base[0].y + b ) / 2; base[2].y = ( a + b ) / 2; /* hand optimized. gcc doesn't seem too good at common expression */ /* substitution and instruction scheduling ;-) */ }/****************************************************************************//* *//* Function: Push_Bezier *//* *//* Description: Clears the Bezier stack and pushes a new arc on top of it. *//* *//* Input: x1,y1 x2,y2 x3,y3 new Bezier arc *//* *//* Returns: None. *//* *//****************************************************************************/ static void Push_Bezier( RAS_ARGS Long x1, Long y1, Long x2, Long y2, Long x3, Long y3 ) { ras.arc = ras.arcs; ras.arc[2].x = x1; ras.arc[2].y = y1; ras.arc[1].x = x2; ras.arc[1].y = y2; ras.arc[0].x = x3; ras.arc[0].y = y3; }/****************************************************************************//* *//* Function: Line_Up *//* *//* Description: Computes the x-coordinates of an ascending line segment *//* and stores them in the render pool. *//* *//* Input: x1,y1,x2,y2 Segment start (x1,y1) and end (x2,y2) points *//* *//* Returns: SUCCESS on success. *//* FAILURE on Render Pool overflow. *//* *//****************************************************************************/ static Bool Line_Up( RAS_ARGS Long x1, Long y1, Long x2, Long y2, Long miny, Long maxy ) { Long Dx, Dy; Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */ Long Ix, Rx, Ax; PStorage top; Dx = x2 - x1; Dy = y2 - y1; if ( Dy <= 0 || y2 < miny || y1 > maxy ) return SUCCESS; if ( y1 < miny ) { /* Take care : miny-y1 can be a very large value, we use */ /* a slow MulDiv function to avoid clipping bugs */ x1 += SMulDiv( Dx, miny - y1, Dy ); e1 = TRUNC( miny ); f1 = 0; } else { e1 = TRUNC( y1 ); f1 = FRAC( y1 ); } if ( y2 > maxy ) { /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */ e2 = TRUNC( maxy ); f2 = 0; } else { e2 = TRUNC( y2 ); f2 = FRAC( y2 ); } if ( f1 > 0 ) { if ( e1 == e2 ) return SUCCESS; else { x1 += FMulDiv( Dx, ras.precision - f1, Dy ); e1 += 1; } } else if ( ras.joint ) { ras.top--; ras.joint = FALSE; } ras.joint = ( f2 == 0 ); if ( ras.fresh ) { ras.cProfile->start = e1; ras.fresh = FALSE; } size = e2 - e1 + 1; if ( ras.top + size >= ras.maxBuff ) { ras.error = Raster_Err_Overflow; return FAILURE; } if ( Dx > 0 ) { Ix = (ras.precision*Dx) / Dy; Rx = (ras.precision*Dx) % Dy; Dx = 1; } else { Ix = -( (ras.precision*-Dx) / Dy ); Rx = (ras.precision*-Dx) % Dy; Dx = -1; } Ax = -Dy; top = ras.top; while ( size > 0 ) { *top++ = x1; DEBUG_PSET; x1 += Ix; Ax += Rx; if ( Ax >= 0 ) { Ax -= Dy; x1 += Dx; } size--; } ras.top = top; return SUCCESS; } static Bool Line_Down( RAS_ARGS Long x1, Long y1, Long x2, Long y2, Long miny, Long maxy ) { Bool result, fresh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -