📄 ttraster.c
字号:
ras.lastX = (ras.lastX + x_last)/2; ras.lastY = (ras.lastY + y_last)/2; x_last = ras.lastX; y_last = ras.lastY; } } /* now process each contour point individually */ while ( index < last ) { index++; x = SCALED( ras.coords[index].x ); y = SCALED( ras.coords[index].y ); if ( flipped ) SWAP_( x, y ); if ( on_curve ) { /* the previous point was on the curve */ on_curve = ( ras.flags[index] & 1 ); if ( on_curve ) { /* two successive on points => emit segment */ if ( Line_To( RAS_VARS x, y ) ) return FAILURE; } else { /* else, keep current control point for next bezier */ cx = x; cy = y; } } else { /* the previous point was off the curve */ on_curve = ( ras.flags[index] & 1 ); if ( on_curve ) { /* reaching an `on' point */ if ( Bezier_To( RAS_VARS x, y, cx, cy ) ) return FAILURE; } else { /* two successive `off' points => create middle point */ mx = ( cx + x ) / 2; my = ( cy + y ) / 2; if ( Bezier_To( RAS_VARS mx, my, cx, cy ) ) return FAILURE; cx = x; cy = y; } } } /* end of contour, close curve cleanly */ if ( ras.flags[first] & 1 ) { if ( on_curve ) return Line_To( RAS_VARS x_first, y_first ); else return Bezier_To( RAS_VARS x_first, y_first, cx, cy ); } else if ( !on_curve ) return Bezier_To( RAS_VARS x_last, y_last, cx, cy ); return SUCCESS; }/****************************************************************************//* *//* Function: Convert_Glyph *//* *//* Description: Converts a glyph into a series of segments and arcs *//* and makes a Profiles list with them. *//* *//* Input: _xCoord, _yCoord : coordinates tables. *//* *//* Uses the 'Flag' table too. *//* *//* Returns: SUCCESS on success. *//* FAILURE if any error was encountered during rendering. *//* *//****************************************************************************/ static Bool Convert_Glyph( RAS_ARGS int flipped ) { Short i; UShort start; PProfile lastProfile; ras.fProfile = NULL; ras.joint = FALSE; ras.fresh = FALSE; ras.maxBuff = ras.sizeBuff - AlignProfileSize; ras.numTurns = 0; ras.cProfile = (PProfile)ras.top; ras.cProfile->offset = ras.top; ras.num_Profs = 0; start = 0; for ( i = 0; i < ras.nContours; i++ ) { ras.state = Unknown; ras.gProfile = NULL; if ( Decompose_Curve( RAS_VARS start, ras.outs[i], flipped ) ) return FAILURE; start = ras.outs[i] + 1; /* We must now see if the extreme arcs join or not */ if ( ( FRAC( ras.lastY ) == 0 && ras.lastY >= ras.minY && ras.lastY <= ras.maxY ) ) if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow ) ras.top--; /* Note that ras.gProfile can be nil if the contour was too small */ /* to be drawn. */ lastProfile = ras.cProfile; if ( End_Profile( RAS_VAR ) ) return FAILURE; /* close the 'next profile in contour' linked list */ if ( ras.gProfile ) lastProfile->next = ras.gProfile; } if (Finalize_Profile_Table( RAS_VAR )) return FAILURE; return (ras.top < ras.maxBuff ? SUCCESS : FAILURE ); }/************************************************//* *//* Init_Linked *//* *//* Inits an empty linked list. *//* *//************************************************/ static void Init_Linked( TProfileList* l ) { *l = NULL; }/************************************************//* *//* InsNew : *//* *//* Inserts a new Profile in a linked list. *//* *//************************************************/ static void InsNew( PProfileList list, PProfile profile ) { PProfile *old, current; Long x; old = list; current = *old; x = profile->X; while ( current ) { if ( x < current->X ) break; old = ¤t->link; current = *old; } profile->link = current; *old = profile; }/*************************************************//* *//* DelOld : *//* *//* Removes an old Profile from a linked list. *//* *//*************************************************/ static void DelOld( PProfileList list, PProfile profile ) { PProfile *old, current; old = list; current = *old; while ( current ) { if ( current == profile ) { *old = current->link; return; } old = ¤t->link; current = *old; } /* we should never get there, unless the Profile was not part of */ /* the list. */ }/************************************************//* *//* Update : *//* *//* Update all X offsets of a drawing list *//* *//************************************************/ static void Update( PProfile first ) { PProfile current = first; while ( current ) { current->X = *current->offset; current->offset += current->flow; current->height--; current = current->link; } }/************************************************//* *//* Sort : *//* *//* Sorts a trace list. In 95%, the list *//* is already sorted. We need an algorithm *//* which is fast in this case. Bubble sort *//* is enough and simple. *//* *//************************************************/ static void Sort( PProfileList list ) { PProfile *old, current, next; /* First, set the new X coordinate of each profile */ Update( *list ); /* Then sort them */ old = list; current = *old; if ( !current ) return; next = current->link; while ( next ) { if ( current->X <= next->X ) { old = ¤t->link; current = *old; if ( !current ) return; } else { *old = next; current->link = next->link; next->link = current; old = list; current = *old; } next = current->link; } }/***********************************************************************//* *//* Vertical Sweep Procedure Set : *//* *//* These three routines are used during the vertical black/white *//* sweep phase by the generic Draw_Sweep() function. *//* *//***********************************************************************/ static void Vertical_Sweep_Init( RAS_ARGS Short* min, Short* max ) { switch ( ras.target.flow ) { case TT_Flow_Up: ras.traceOfs = *min * ras.target.cols; ras.traceIncr = ras.target.cols; break; default: ras.traceOfs = ( ras.target.rows - 1 - *min ) * ras.target.cols; ras.traceIncr = -ras.target.cols; } ras.gray_min_x = 0; ras.gray_max_x = 0; } static void Vertical_Sweep_Span( RAS_ARGS Short y, TT_F26Dot6 x1, TT_F26Dot6 x2, PProfile left, PProfile right ) { Long e1, e2; Short c1, c2; Short f1, f2; Byte* target; /* Drop-out control */ e1 = TRUNC( CEILING( x1 ) ); if ( x2-x1-ras.precision <= ras.precision_jitter ) e2 = e1; else e2 = TRUNC( FLOOR( x2 ) ); if ( e2 >= 0 && e1 < ras.bWidth ) { if ( e1 < 0 ) e1 = 0; if ( e2 >= ras.bWidth ) e2 = ras.bWidth-1; c1 = (Short)(e1 >> 3); c2 = (Short)(e2 >> 3); f1 = e1 & 7; f2 = e2 & 7; if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2; target = ras.bTarget + ras.traceOfs + c1; if ( c1 != c2 ) { *target |= LMask[f1]; if ( c2 > c1 + 1 ) MEM_Set( target + 1, 0xFF, c2 - c1 - 1 ); target[c2 - c1] |= RMask[f2]; } else *target |= ( LMask[f1] & RMask[f2] ); } } static void Vertical_Sweep_Drop( RAS_ARGS Short y, TT_F26Dot6 x1, TT_F26Dot6 x2, PProfile left, PProfile right ) { Long e1, e2; Short c1, f1; /* Drop-out control */ e1 = CEILING( x1 ); e2 = FLOOR ( x2 ); if ( e1 > e2 ) { if ( e1 == e2 + ras.precision ) { switch ( ras.dropOutControl ) { case 1: e1 = e2; break; case 4: e1 = CEILING( (x1 + x2 + 1) / 2 ); break; case 2: case 5: /* Drop-out Control Rule #4 */ /* The spec is not very clear regarding rule #4. It */ /* presents a method that is way too costly to implement */ /* while the general idea seems to get rid of 'stubs'. */ /* */ /* Here, we only get rid of stubs recognized when: */ /* */ /* upper stub: */ /* */ /* - P_Left and P_Right are in the same contour */ /* - P_Right is the successor of P_Left in that contour */ /* - y is the top of P_Left and P_Right */ /* */ /* lower stub: */ /* */ /* - P_Left and P_Right are in the same contour */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -