[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:
Alexei Podtelezhnikov 2023-11-21 00:53:50 -05:00
parent d7c72ff919
commit da8e428977
1 changed files with 128 additions and 247 deletions

View File

@ -401,9 +401,7 @@
typedef void
Function_Sweep_Span( RAS_ARGS Int y,
FT_F26Dot6 x1,
FT_F26Dot6 x2,
PProfile left,
PProfile right );
FT_F26Dot6 x2 );
typedef void
Function_Sweep_Step( RAS_ARG );
@ -1989,15 +1987,11 @@
static void
Vertical_Sweep_Span( RAS_ARGS Int y,
FT_F26Dot6 x1,
FT_F26Dot6 x2,
PProfile left,
PProfile right )
FT_F26Dot6 x2 )
{
Int e1, e2;
FT_UNUSED( y );
FT_UNUSED( left );
FT_UNUSED( right );
FT_TRACE7(( " y=%d x=[% .*f;% .*f]",
@ -2054,137 +2048,38 @@
static void
Vertical_Sweep_Drop( RAS_ARGS Int y,
FT_F26Dot6 x1,
FT_F26Dot6 x2,
PProfile left,
PProfile right )
FT_F26Dot6 x2 )
{
Long e1, e2, pxl;
Int c1, f1;
Int e1 = (Int)TRUNC( x1 );
Int e2 = (Int)TRUNC( x2 );
Int c1, f1;
FT_UNUSED( y );
FT_TRACE7(( " y=%d x=[% .*f;% .*f]",
y,
ras.precision_bits, (double)x1 / (double)ras.precision,
ras.precision_bits, (double)x2 / (double)ras.precision ));
/* 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 ( e1 < 0 || e1 > ras.bRight )
e1 = e2;
/* 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 */
e1 = CEILING( x1 );
e2 = FLOOR ( x2 );
pxl = e1;
if ( e1 > e2 )
/* otherwise check that the other pixel isn't set */
else if ( e2 >=0 && e2 <= ras.bRight )
{
Int dropOutControl = left->flags & 7;
c1 = (Int)( e2 >> 3 );
f1 = (Int)( e2 & 7 );
if ( e1 == e2 + ras.precision )
{
/* 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;
if ( ras.bLine[c1] & ( 0x80 >> f1 ) )
return;
}
e1 = TRUNC( pxl );
if ( e1 >= 0 && e1 <= ras.bRight )
{
FT_TRACE7(( " -> x=%ld", e1 ));
c1 = (Int)( e1 >> 3 );
f1 = (Int)( e1 & 7 );
ras.bLine[c1] |= 0x80 >> f1;
}
Exit:
FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
}
@ -2218,15 +2113,10 @@
static void
Horizontal_Sweep_Span( RAS_ARGS Int y,
FT_F26Dot6 x1,
FT_F26Dot6 x2,
PProfile left,
PProfile right )
FT_F26Dot6 x2 )
{
Long e1, e2;
FT_UNUSED( left );
FT_UNUSED( right );
FT_TRACE7(( " x=%d y=[% .*f;% .*f]",
y,
@ -2290,103 +2180,37 @@
static void
Horizontal_Sweep_Drop( RAS_ARGS Int y,
FT_F26Dot6 x1,
FT_F26Dot6 x2,
PProfile left,
PProfile right )
FT_F26Dot6 x2 )
{
Long e1, e2, pxl;
Int e1 = (Int)TRUNC( x1 );
Int e2 = (Int)TRUNC( x2 );
PByte bits;
Int f1;
FT_TRACE7(( " x=%d y=[% .*f;% .*f]",
y,
ras.precision_bits, (double)x1 / (double)ras.precision,
ras.precision_bits, (double)x2 / (double)ras.precision ));
/* 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 ( e1 < 0 || e1 > ras.bTop )
e1 = e2;
/* During the horizontal sweep, we only take care of drop-outs */
/* e1 + <-- pixel center */
/* | */
/* x1 ---+--> <-- contour */
/* | */
/* | */
/* x2 <--+--- <-- contour */
/* | */
/* | */
/* e2 + <-- pixel center */
e1 = CEILING( x1 );
e2 = FLOOR ( x2 );
pxl = e1;
if ( e1 > e2 )
/* otherwise check that the other pixel isn't set */
else if ( e2 >=0 && e2 <= ras.bTop )
{
Int dropOutControl = left->flags & 7;
bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
f1 = 0x80 >> ( y & 7 );
if ( e1 == e2 + ras.precision )
{
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;
if ( *bits & f1 )
return;
}
e1 = TRUNC( pxl );
if ( e1 >= 0 && e1 <= ras.bTop )
{
FT_TRACE7(( " -> y=%ld", e1 ));
bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
f1 = 0x80 >> ( y & 7 );
bits[0] |= f1;
*bits |= f1;
}
Exit:
FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
}
@ -2477,37 +2301,120 @@
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;
/* 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 )
goto Next_Pair;
P_Left ->X = x1;
P_Right->X = x2;
/* 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 ( 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 */
P_Left->flags |= Dropout;
dropouts++;
}
else
ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
Next_Pair:
P_Left = P_Left->link;
P_Right = P_Right->link;
}
/* handle drop-outs _after_ the span drawing -- */
/* drop-out processing has been moved out of the loop */
/* for performance tuning */
if ( dropouts > 0 )
goto Scan_DropOuts;
/* handle drop-outs _after_ the span drawing */
P_Left = draw_left;
P_Right = draw_right;
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 );
@ -2518,32 +2425,6 @@
}
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;
}