[raster] Fix linked profiles in contour loops.
This fixes a subtle bug when the last profile in a contour was not properly short-circuited if it was still empty at `End_Profile`. We finalize all linking in `Finalize_Profile_List` now and do nothing else there. The turns are added in `End_Profile`. * src/raster/ftraster.c (Insert_Y_Turn): Moved up unchanged. (End_Profile): Take care of turns but set only preliminary linking. (Finalize_Profile_Table): Take care of linking and null-termination. (Convert_Glyph): Adjusted accordingly.
This commit is contained in:
parent
749b8f9d34
commit
3fa5c84565
@ -591,6 +591,62 @@
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
* Insert_Y_Turn
|
||||
*
|
||||
* @Description:
|
||||
* Insert a salient into the sorted list placed on top of the render
|
||||
* pool.
|
||||
*
|
||||
* @Input:
|
||||
* New y scanline position.
|
||||
*
|
||||
* @Return:
|
||||
* SUCCESS on success. FAILURE in case of overflow.
|
||||
*/
|
||||
static Bool
|
||||
Insert_Y_Turn( RAS_ARGS Int y )
|
||||
{
|
||||
PLong y_turns;
|
||||
Int 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] )
|
||||
do
|
||||
{
|
||||
Int y2 = (Int)y_turns[n];
|
||||
|
||||
|
||||
y_turns[n] = y;
|
||||
y = y2;
|
||||
} while ( --n >= 0 );
|
||||
|
||||
if ( n < 0 )
|
||||
{
|
||||
ras.maxBuff--;
|
||||
if ( ras.maxBuff <= ras.top )
|
||||
{
|
||||
ras.error = FT_THROW( Raster_Overflow );
|
||||
return FAILURE;
|
||||
}
|
||||
ras.numTurns++;
|
||||
ras.sizeBuff[-ras.numTurns] = y;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
@ -687,11 +743,11 @@
|
||||
static Bool
|
||||
End_Profile( RAS_ARGS Bool overshoot )
|
||||
{
|
||||
Long h;
|
||||
PProfile p = ras.cProfile;
|
||||
Long h = (Long)( ras.top - p->offset );
|
||||
Int bottom, top;
|
||||
|
||||
|
||||
h = (Long)( ras.top - ras.cProfile->offset );
|
||||
|
||||
if ( h < 0 )
|
||||
{
|
||||
FT_ERROR(( "End_Profile: negative height encountered\n" ));
|
||||
@ -701,20 +757,39 @@
|
||||
|
||||
if ( h > 0 )
|
||||
{
|
||||
FT_TRACE7(( " ending profile %p, start = %ld, height = %ld\n",
|
||||
(void *)ras.cProfile, ras.cProfile->start, h ));
|
||||
FT_TRACE7(( " ending profile %p, start = %2ld, height = %+3ld\n",
|
||||
(void *)p, p->start, p->flags & Flow_Up ? h : -h ));
|
||||
|
||||
ras.cProfile->height = h;
|
||||
if ( overshoot )
|
||||
{
|
||||
if ( ras.cProfile->flags & Flow_Up )
|
||||
ras.cProfile->flags |= Overshoot_Top;
|
||||
if ( p->flags & Flow_Up )
|
||||
p->flags |= Overshoot_Top;
|
||||
else
|
||||
ras.cProfile->flags |= Overshoot_Bottom;
|
||||
p->flags |= Overshoot_Bottom;
|
||||
}
|
||||
|
||||
/* premature, the last profile in the contour must loop */
|
||||
ras.cProfile->next = (PProfile)ras.top;
|
||||
p->height = h;
|
||||
|
||||
if ( p->flags & Flow_Up )
|
||||
{
|
||||
bottom = (Int)p->start;
|
||||
top = (Int)( p->start + h - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom = (Int)( p->start - h + 1 );
|
||||
top = (Int)p->start;
|
||||
p->start = bottom;
|
||||
p->offset += h - 1;
|
||||
}
|
||||
|
||||
if ( Insert_Y_Turn( RAS_VARS bottom ) ||
|
||||
Insert_Y_Turn( RAS_VARS top + 1 ) )
|
||||
return FAILURE;
|
||||
|
||||
/* preliminary values to be finalized */
|
||||
p->link = (PProfile)ras.top;
|
||||
p->next = ras.gProfile;
|
||||
|
||||
ras.num_Profs++;
|
||||
}
|
||||
@ -725,62 +800,6 @@
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
* Insert_Y_Turn
|
||||
*
|
||||
* @Description:
|
||||
* Insert a salient into the sorted list placed on top of the render
|
||||
* pool.
|
||||
*
|
||||
* @Input:
|
||||
* New y scanline position.
|
||||
*
|
||||
* @Return:
|
||||
* SUCCESS on success. FAILURE in case of overflow.
|
||||
*/
|
||||
static Bool
|
||||
Insert_Y_Turn( RAS_ARGS Int y )
|
||||
{
|
||||
PLong y_turns;
|
||||
Int 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] )
|
||||
do
|
||||
{
|
||||
Int y2 = (Int)y_turns[n];
|
||||
|
||||
|
||||
y_turns[n] = y;
|
||||
y = y2;
|
||||
} while ( --n >= 0 );
|
||||
|
||||
if ( n < 0 )
|
||||
{
|
||||
ras.maxBuff--;
|
||||
if ( ras.maxBuff <= ras.top )
|
||||
{
|
||||
ras.error = FT_THROW( Raster_Overflow );
|
||||
return FAILURE;
|
||||
}
|
||||
ras.numTurns++;
|
||||
ras.sizeBuff[-ras.numTurns] = y;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
@ -788,56 +807,28 @@
|
||||
*
|
||||
* @Description:
|
||||
* Adjust all links in the profiles list.
|
||||
*
|
||||
* @Return:
|
||||
* SUCCESS on success. FAILURE in case of overflow.
|
||||
*/
|
||||
static Bool
|
||||
static void
|
||||
Finalize_Profile_Table( RAS_ARG )
|
||||
{
|
||||
UShort n;
|
||||
PProfile p;
|
||||
UShort n = ras.num_Profs;
|
||||
PProfile p = ras.fProfile;
|
||||
PProfile q;
|
||||
|
||||
|
||||
n = ras.num_Profs;
|
||||
p = ras.fProfile;
|
||||
|
||||
if ( n > 1 && p )
|
||||
while ( --n )
|
||||
{
|
||||
do
|
||||
{
|
||||
Int bottom, top;
|
||||
q = p->link;
|
||||
|
||||
/* fix the contour loop */
|
||||
if ( q->next == p->next )
|
||||
p->next = q;
|
||||
|
||||
if ( n > 1 )
|
||||
p->link = (PProfile)( p->offset + p->height );
|
||||
else
|
||||
p->link = NULL;
|
||||
|
||||
if ( p->flags & Flow_Up )
|
||||
{
|
||||
bottom = (Int)p->start;
|
||||
top = (Int)( p->start + p->height - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom = (Int)( p->start - p->height + 1 );
|
||||
top = (Int)p->start;
|
||||
p->start = bottom;
|
||||
p->offset += p->height - 1;
|
||||
}
|
||||
|
||||
if ( Insert_Y_Turn( RAS_VARS bottom ) ||
|
||||
Insert_Y_Turn( RAS_VARS top + 1 ) )
|
||||
return FAILURE;
|
||||
|
||||
p = p->link;
|
||||
} while ( --n );
|
||||
p = q;
|
||||
}
|
||||
else
|
||||
ras.fProfile = NULL;
|
||||
|
||||
return SUCCESS;
|
||||
/* null-terminate */
|
||||
p->link = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -2001,17 +1992,14 @@
|
||||
if ( End_Profile( RAS_VARS o ) )
|
||||
return FAILURE;
|
||||
|
||||
/* loop the last profile in the contour */
|
||||
ras.cProfile->next = ras.gProfile;
|
||||
|
||||
if ( !ras.fProfile )
|
||||
if ( !ras.fProfile && ras.num_Profs )
|
||||
ras.fProfile = ras.gProfile;
|
||||
}
|
||||
|
||||
if ( Finalize_Profile_Table( RAS_VAR ) )
|
||||
return FAILURE;
|
||||
if ( ras.num_Profs )
|
||||
Finalize_Profile_Table( RAS_VAR );
|
||||
|
||||
return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user