[raster] Rearrange dropout control.
This reduces the code duplication. * src/raster/ftraster.c (Function_Sweep_Span): Change signature. (Vertical_Sweep_Drop, Horizontal_Sweep_Drop): Focus on pixel setting and move duplicated the dropout control logic to... (Draw_Sweep): ... this function and refactor. (Vertical_Sweep_Span, Horizontal_Sweep_Span): Minor.
This commit is contained in:
parent
d7c72ff919
commit
da8e428977
|
@ -401,9 +401,7 @@
|
||||||
typedef void
|
typedef void
|
||||||
Function_Sweep_Span( RAS_ARGS Int y,
|
Function_Sweep_Span( RAS_ARGS Int y,
|
||||||
FT_F26Dot6 x1,
|
FT_F26Dot6 x1,
|
||||||
FT_F26Dot6 x2,
|
FT_F26Dot6 x2 );
|
||||||
PProfile left,
|
|
||||||
PProfile right );
|
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
Function_Sweep_Step( RAS_ARG );
|
Function_Sweep_Step( RAS_ARG );
|
||||||
|
@ -1989,15 +1987,11 @@
|
||||||
static void
|
static void
|
||||||
Vertical_Sweep_Span( RAS_ARGS Int y,
|
Vertical_Sweep_Span( RAS_ARGS Int y,
|
||||||
FT_F26Dot6 x1,
|
FT_F26Dot6 x1,
|
||||||
FT_F26Dot6 x2,
|
FT_F26Dot6 x2 )
|
||||||
PProfile left,
|
|
||||||
PProfile right )
|
|
||||||
{
|
{
|
||||||
Int e1, e2;
|
Int e1, e2;
|
||||||
|
|
||||||
FT_UNUSED( y );
|
FT_UNUSED( y );
|
||||||
FT_UNUSED( left );
|
|
||||||
FT_UNUSED( right );
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE7(( " y=%d x=[% .*f;% .*f]",
|
FT_TRACE7(( " y=%d x=[% .*f;% .*f]",
|
||||||
|
@ -2054,137 +2048,38 @@
|
||||||
static void
|
static void
|
||||||
Vertical_Sweep_Drop( RAS_ARGS Int y,
|
Vertical_Sweep_Drop( RAS_ARGS Int y,
|
||||||
FT_F26Dot6 x1,
|
FT_F26Dot6 x1,
|
||||||
FT_F26Dot6 x2,
|
FT_F26Dot6 x2 )
|
||||||
PProfile left,
|
|
||||||
PProfile right )
|
|
||||||
{
|
{
|
||||||
Long e1, e2, pxl;
|
Int e1 = (Int)TRUNC( x1 );
|
||||||
Int c1, f1;
|
Int e2 = (Int)TRUNC( x2 );
|
||||||
|
Int c1, f1;
|
||||||
|
|
||||||
FT_UNUSED( y );
|
FT_UNUSED( y );
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE7(( " y=%d x=[% .*f;% .*f]",
|
/* undocumented but confirmed: If the drop-out would result in a */
|
||||||
y,
|
/* pixel outside of the bounding box, use the pixel inside of the */
|
||||||
ras.precision_bits, (double)x1 / (double)ras.precision,
|
/* bounding box instead */
|
||||||
ras.precision_bits, (double)x2 / (double)ras.precision ));
|
if ( e1 < 0 || e1 > ras.bRight )
|
||||||
|
e1 = e2;
|
||||||
|
|
||||||
/* Drop-out control */
|
/* otherwise check that the other pixel isn't set */
|
||||||
|
else if ( e2 >=0 && e2 <= ras.bRight )
|
||||||
/* e2 x2 x1 e1 */
|
|
||||||
/* */
|
|
||||||
/* ^ | */
|
|
||||||
/* | | */
|
|
||||||
/* +-------------+---------------------+------------+ */
|
|
||||||
/* | | */
|
|
||||||
/* | v */
|
|
||||||
/* */
|
|
||||||
/* pixel contour contour pixel */
|
|
||||||
/* center center */
|
|
||||||
|
|
||||||
/* drop-out mode scan conversion rules (OpenType specs) */
|
|
||||||
/* ------------------------------------------------------- */
|
|
||||||
/* bit 0 exclude stubs if set */
|
|
||||||
/* bit 1 ignore drop-outs if set */
|
|
||||||
/* bit 2 smart rounding if set */
|
|
||||||
|
|
||||||
e1 = CEILING( x1 );
|
|
||||||
e2 = FLOOR ( x2 );
|
|
||||||
pxl = e1;
|
|
||||||
|
|
||||||
if ( e1 > e2 )
|
|
||||||
{
|
{
|
||||||
Int dropOutControl = left->flags & 7;
|
c1 = (Int)( e2 >> 3 );
|
||||||
|
f1 = (Int)( e2 & 7 );
|
||||||
|
|
||||||
|
if ( ras.bLine[c1] & ( 0x80 >> f1 ) )
|
||||||
if ( e1 == e2 + ras.precision )
|
return;
|
||||||
{
|
|
||||||
/* Drop-out Control Rules #4 and #6 */
|
|
||||||
|
|
||||||
/* The specification neither provides an exact definition */
|
|
||||||
/* of a `stub' nor gives exact rules to exclude them. */
|
|
||||||
/* */
|
|
||||||
/* Here the constraints we use to recognize a stub. */
|
|
||||||
/* */
|
|
||||||
/* 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 */
|
|
||||||
/* - P_Left is the successor of P_Right in that contour */
|
|
||||||
/* - y is the bottom of P_Left */
|
|
||||||
/* */
|
|
||||||
/* We draw a stub if the following constraints are met. */
|
|
||||||
/* */
|
|
||||||
/* - for an upper or lower stub, there is top or bottom */
|
|
||||||
/* overshoot, respectively */
|
|
||||||
/* - the covered interval is greater or equal to a half */
|
|
||||||
/* pixel */
|
|
||||||
|
|
||||||
if ( dropOutControl & 1 )
|
|
||||||
{
|
|
||||||
/* rightmost stub test */
|
|
||||||
if ( left->next == right &&
|
|
||||||
left->height == 1 &&
|
|
||||||
!( left->flags & Overshoot_Top &&
|
|
||||||
x2 - x1 >= ras.precision_half ) )
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
/* leftmost stub test */
|
|
||||||
if ( right->next == left &&
|
|
||||||
left->offset == 0 &&
|
|
||||||
!( left->flags & Overshoot_Bottom &&
|
|
||||||
x2 - x1 >= ras.precision_half ) )
|
|
||||||
goto Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( dropOutControl & 4 )
|
|
||||||
pxl = SMART( x1, x2 );
|
|
||||||
else
|
|
||||||
pxl = e2;
|
|
||||||
|
|
||||||
/* undocumented but confirmed: If the drop-out would result in a */
|
|
||||||
/* pixel outside of the bounding box, use the pixel inside of the */
|
|
||||||
/* bounding box instead */
|
|
||||||
if ( pxl < 0 )
|
|
||||||
pxl = e1;
|
|
||||||
else if ( TRUNC( pxl ) > ras.bRight )
|
|
||||||
pxl = e2;
|
|
||||||
|
|
||||||
/* check that the other pixel isn't set */
|
|
||||||
e1 = ( pxl == e1 ) ? e2 : e1;
|
|
||||||
|
|
||||||
e1 = TRUNC( e1 );
|
|
||||||
|
|
||||||
c1 = (Int)( e1 >> 3 );
|
|
||||||
f1 = (Int)( e1 & 7 );
|
|
||||||
|
|
||||||
if ( e1 >= 0 && e1 <= ras.bRight &&
|
|
||||||
ras.bLine[c1] & ( 0x80 >> f1 ) )
|
|
||||||
goto Exit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto Exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e1 = TRUNC( pxl );
|
|
||||||
|
|
||||||
if ( e1 >= 0 && e1 <= ras.bRight )
|
if ( e1 >= 0 && e1 <= ras.bRight )
|
||||||
{
|
{
|
||||||
FT_TRACE7(( " -> x=%ld", e1 ));
|
|
||||||
|
|
||||||
c1 = (Int)( e1 >> 3 );
|
c1 = (Int)( e1 >> 3 );
|
||||||
f1 = (Int)( e1 & 7 );
|
f1 = (Int)( e1 & 7 );
|
||||||
|
|
||||||
ras.bLine[c1] |= 0x80 >> f1;
|
ras.bLine[c1] |= 0x80 >> f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Exit:
|
|
||||||
FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2218,15 +2113,10 @@
|
||||||
static void
|
static void
|
||||||
Horizontal_Sweep_Span( RAS_ARGS Int y,
|
Horizontal_Sweep_Span( RAS_ARGS Int y,
|
||||||
FT_F26Dot6 x1,
|
FT_F26Dot6 x1,
|
||||||
FT_F26Dot6 x2,
|
FT_F26Dot6 x2 )
|
||||||
PProfile left,
|
|
||||||
PProfile right )
|
|
||||||
{
|
{
|
||||||
Long e1, e2;
|
Long e1, e2;
|
||||||
|
|
||||||
FT_UNUSED( left );
|
|
||||||
FT_UNUSED( right );
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE7(( " x=%d y=[% .*f;% .*f]",
|
FT_TRACE7(( " x=%d y=[% .*f;% .*f]",
|
||||||
y,
|
y,
|
||||||
|
@ -2290,103 +2180,37 @@
|
||||||
static void
|
static void
|
||||||
Horizontal_Sweep_Drop( RAS_ARGS Int y,
|
Horizontal_Sweep_Drop( RAS_ARGS Int y,
|
||||||
FT_F26Dot6 x1,
|
FT_F26Dot6 x1,
|
||||||
FT_F26Dot6 x2,
|
FT_F26Dot6 x2 )
|
||||||
PProfile left,
|
|
||||||
PProfile right )
|
|
||||||
{
|
{
|
||||||
Long e1, e2, pxl;
|
Int e1 = (Int)TRUNC( x1 );
|
||||||
|
Int e2 = (Int)TRUNC( x2 );
|
||||||
PByte bits;
|
PByte bits;
|
||||||
Int f1;
|
Int f1;
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE7(( " x=%d y=[% .*f;% .*f]",
|
/* undocumented but confirmed: If the drop-out would result in a */
|
||||||
y,
|
/* pixel outside of the bounding box, use the pixel inside of the */
|
||||||
ras.precision_bits, (double)x1 / (double)ras.precision,
|
/* bounding box instead */
|
||||||
ras.precision_bits, (double)x2 / (double)ras.precision ));
|
if ( e1 < 0 || e1 > ras.bTop )
|
||||||
|
e1 = e2;
|
||||||
|
|
||||||
/* During the horizontal sweep, we only take care of drop-outs */
|
/* otherwise check that the other pixel isn't set */
|
||||||
|
else if ( e2 >=0 && e2 <= ras.bTop )
|
||||||
/* e1 + <-- pixel center */
|
|
||||||
/* | */
|
|
||||||
/* x1 ---+--> <-- contour */
|
|
||||||
/* | */
|
|
||||||
/* | */
|
|
||||||
/* x2 <--+--- <-- contour */
|
|
||||||
/* | */
|
|
||||||
/* | */
|
|
||||||
/* e2 + <-- pixel center */
|
|
||||||
|
|
||||||
e1 = CEILING( x1 );
|
|
||||||
e2 = FLOOR ( x2 );
|
|
||||||
pxl = e1;
|
|
||||||
|
|
||||||
if ( e1 > e2 )
|
|
||||||
{
|
{
|
||||||
Int dropOutControl = left->flags & 7;
|
bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
|
||||||
|
f1 = 0x80 >> ( y & 7 );
|
||||||
|
|
||||||
|
if ( *bits & f1 )
|
||||||
if ( e1 == e2 + ras.precision )
|
return;
|
||||||
{
|
|
||||||
if ( dropOutControl & 1 )
|
|
||||||
{
|
|
||||||
/* rightmost stub test */
|
|
||||||
if ( left->next == right &&
|
|
||||||
left->height == 1 &&
|
|
||||||
!( left->flags & Overshoot_Top &&
|
|
||||||
x2 - x1 >= ras.precision_half ) )
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
/* leftmost stub test */
|
|
||||||
if ( right->next == left &&
|
|
||||||
left->offset == 0 &&
|
|
||||||
!( left->flags & Overshoot_Bottom &&
|
|
||||||
x2 - x1 >= ras.precision_half ) )
|
|
||||||
goto Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( dropOutControl & 4 )
|
|
||||||
pxl = SMART( x1, x2 );
|
|
||||||
else
|
|
||||||
pxl = e2;
|
|
||||||
|
|
||||||
/* undocumented but confirmed: If the drop-out would result in a */
|
|
||||||
/* pixel outside of the bounding box, use the pixel inside of the */
|
|
||||||
/* bounding box instead */
|
|
||||||
if ( pxl < 0 )
|
|
||||||
pxl = e1;
|
|
||||||
else if ( TRUNC( pxl ) > ras.bTop )
|
|
||||||
pxl = e2;
|
|
||||||
|
|
||||||
/* check that the other pixel isn't set */
|
|
||||||
e1 = ( pxl == e1 ) ? e2 : e1;
|
|
||||||
|
|
||||||
e1 = TRUNC( e1 );
|
|
||||||
|
|
||||||
bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
|
|
||||||
f1 = 0x80 >> ( y & 7 );
|
|
||||||
|
|
||||||
if ( e1 >= 0 && e1 <= ras.bTop &&
|
|
||||||
*bits & f1 )
|
|
||||||
goto Exit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto Exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e1 = TRUNC( pxl );
|
|
||||||
|
|
||||||
if ( e1 >= 0 && e1 <= ras.bTop )
|
if ( e1 >= 0 && e1 <= ras.bTop )
|
||||||
{
|
{
|
||||||
FT_TRACE7(( " -> y=%ld", e1 ));
|
|
||||||
|
|
||||||
bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
|
bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
|
||||||
f1 = 0x80 >> ( y & 7 );
|
f1 = 0x80 >> ( y & 7 );
|
||||||
|
|
||||||
bits[0] |= f1;
|
*bits |= f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Exit:
|
|
||||||
FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2477,37 +2301,120 @@
|
||||||
x2 = xs;
|
x2 = xs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if bottom ceiling exceeds top floor, it is a drop-out */
|
if ( CEILING( x1 ) <= FLOOR( x2 ) )
|
||||||
if ( CEILING( x1 ) > FLOOR( x2 ) )
|
ras.Proc_Sweep_Span( RAS_VARS y, x1, x2 );
|
||||||
|
|
||||||
|
/* otherwise, bottom ceiling > top floor, it is a drop-out */
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Int dropOutControl = P_Left->flags & 7;
|
Int dropOutControl = P_Left->flags & 7;
|
||||||
|
|
||||||
|
|
||||||
|
/* Drop-out control */
|
||||||
|
|
||||||
|
/* e2 x2 x1 e1 */
|
||||||
|
/* */
|
||||||
|
/* ^ | */
|
||||||
|
/* | | */
|
||||||
|
/* +-------------+---------------------+------------+ */
|
||||||
|
/* | | */
|
||||||
|
/* | v */
|
||||||
|
/* */
|
||||||
|
/* pixel contour contour pixel */
|
||||||
|
/* center center */
|
||||||
|
|
||||||
|
/* drop-out mode scan conversion rules (OpenType specs) */
|
||||||
|
/* ------------------------------------------------------- */
|
||||||
|
/* bit 0 exclude stubs if set */
|
||||||
|
/* bit 1 ignore drop-outs if set */
|
||||||
|
/* bit 2 smart rounding if set */
|
||||||
|
|
||||||
if ( dropOutControl & 2 )
|
if ( dropOutControl & 2 )
|
||||||
goto Next_Pair;
|
goto Next_Pair;
|
||||||
|
|
||||||
P_Left ->X = x1;
|
/* The specification neither provides an exact definition */
|
||||||
P_Right->X = x2;
|
/* of a `stub' nor gives exact rules to exclude them. */
|
||||||
|
/* */
|
||||||
|
/* Here the constraints we use to recognize a stub. */
|
||||||
|
/* */
|
||||||
|
/* 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 */
|
||||||
|
/* - P_Left is the successor of P_Right in that contour */
|
||||||
|
/* - y is the bottom of P_Left */
|
||||||
|
/* */
|
||||||
|
/* We draw a stub if the following constraints are met. */
|
||||||
|
/* */
|
||||||
|
/* - for an upper or lower stub, there is top or bottom */
|
||||||
|
/* overshoot, respectively */
|
||||||
|
/* - the covered interval is greater or equal to a half */
|
||||||
|
/* pixel */
|
||||||
|
|
||||||
|
if ( dropOutControl & 1 )
|
||||||
|
{
|
||||||
|
/* rightmost stub test */
|
||||||
|
if ( P_Left->next == P_Right &&
|
||||||
|
P_Left->height == 1 &&
|
||||||
|
!( P_Left->flags & Overshoot_Top &&
|
||||||
|
x2 - x1 >= ras.precision_half ) )
|
||||||
|
goto Next_Pair;
|
||||||
|
|
||||||
|
/* leftmost stub test */
|
||||||
|
if ( P_Right->next == P_Left &&
|
||||||
|
P_Left->offset == 0 &&
|
||||||
|
!( P_Left->flags & Overshoot_Bottom &&
|
||||||
|
x2 - x1 >= ras.precision_half ) )
|
||||||
|
goto Next_Pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* select the pixel to set and the other pixel */
|
||||||
|
if ( dropOutControl & 4 )
|
||||||
|
{
|
||||||
|
x2 = SMART( x1, x2 );
|
||||||
|
x1 = x1 > x2 ? x2 + ras.precision : x2 - ras.precision;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x2 = FLOOR ( x2 );
|
||||||
|
x1 = CEILING( x1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
P_Left ->X = x2;
|
||||||
|
P_Right->X = x1;
|
||||||
|
|
||||||
/* mark profile for drop-out processing */
|
/* mark profile for drop-out processing */
|
||||||
P_Left->flags |= Dropout;
|
P_Left->flags |= Dropout;
|
||||||
dropouts++;
|
dropouts++;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
|
|
||||||
|
|
||||||
Next_Pair:
|
Next_Pair:
|
||||||
P_Left = P_Left->link;
|
P_Left = P_Left->link;
|
||||||
P_Right = P_Right->link;
|
P_Right = P_Right->link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle drop-outs _after_ the span drawing -- */
|
/* handle drop-outs _after_ the span drawing */
|
||||||
/* drop-out processing has been moved out of the loop */
|
P_Left = draw_left;
|
||||||
/* for performance tuning */
|
P_Right = draw_right;
|
||||||
if ( dropouts > 0 )
|
|
||||||
goto Scan_DropOuts;
|
|
||||||
|
|
||||||
Next_Line:
|
while ( dropouts && P_Left && P_Right )
|
||||||
|
{
|
||||||
|
if ( P_Left->flags & Dropout )
|
||||||
|
{
|
||||||
|
ras.Proc_Sweep_Drop( RAS_VARS y, P_Left->X, P_Right->X );
|
||||||
|
|
||||||
|
P_Left->flags &= ~Dropout;
|
||||||
|
dropouts--;
|
||||||
|
}
|
||||||
|
|
||||||
|
P_Left = P_Left->link;
|
||||||
|
P_Right = P_Right->link;
|
||||||
|
}
|
||||||
|
|
||||||
ras.Proc_Sweep_Step( RAS_VAR );
|
ras.Proc_Sweep_Step( RAS_VAR );
|
||||||
|
|
||||||
|
@ -2518,32 +2425,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|
||||||
Scan_DropOuts:
|
|
||||||
|
|
||||||
P_Left = draw_left;
|
|
||||||
P_Right = draw_right;
|
|
||||||
|
|
||||||
while ( P_Left && P_Right )
|
|
||||||
{
|
|
||||||
if ( P_Left->flags & Dropout )
|
|
||||||
{
|
|
||||||
P_Left->flags &= ~Dropout;
|
|
||||||
#if 0
|
|
||||||
dropouts--; /* -- this is useful when debugging only */
|
|
||||||
#endif
|
|
||||||
ras.Proc_Sweep_Drop( RAS_VARS y,
|
|
||||||
P_Left->X,
|
|
||||||
P_Right->X,
|
|
||||||
P_Left,
|
|
||||||
P_Right );
|
|
||||||
}
|
|
||||||
|
|
||||||
P_Left = P_Left->link;
|
|
||||||
P_Right = P_Right->link;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto Next_Line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue