[base] Finish experimental (disabled) BBox_Cubic_Check implementation.

* src/base/ftbbox.c (BBox_Cubic_Check): Scale arguments to improve
accuracy and avoid overflows.
This commit is contained in:
Alexei Podtelezhnikov 2013-08-15 22:51:42 -04:00
parent 61a65510dc
commit 1a9c3d14fb
2 changed files with 66 additions and 5 deletions

View File

@ -1,9 +1,17 @@
2013-08-15 Alexei Podtelezhnikov <apodtele@gmail.com>
[base] Finish experimental (disabled) BBox_Cubic_Check implementation.
* src/base/ftbbox.c (BBox_Cubic_Check): Scale arguments to improve
accuracy and avoid overflows.
2013-08-13 Alexei Podtelezhnikov <apodtele@gmail.com>
[base] Refactor experimental (disabled) BBox_Cubic_Check.
* src/base/ftbbox.c (BBox_Cubic_Check): Implement the minimum search
as the mirror image of the maximum search.
as the mirror image of the maximum search implemented here...
(update_max): New function.
2013-08-06 John Tytgat <John.Tytgat@esko.com>

View File

@ -275,10 +275,62 @@
FT_Pos* min,
FT_Pos* max )
{
*max = update_max( p1, p2, p3, p4, *max );
FT_Pos nmin, nmax;
FT_Int shift;
/* This implementation relies on iterative bisection of the segment. */
/* The fixed-point arithmentic of bisection is inherently stable but */
/* may loose accuracy in the two lowest bits. To compensate, we */
/* upscale the segment if there is room. Large values may need to be */
/* downscaled to avoid overflows during bisection bisection. This */
/* function is only called when a control off-point is outside the */
/* the bbox and, thus, has the top absolute value among arguments. */
shift = 27 - FT_MSB( FT_ABS( p2 ) | FT_ABS( p3 ) );
if ( shift > 0 )
{
/* upscaling too much just wastes time */
if ( shift > 2 )
shift = 2;
p1 <<= shift;
p2 <<= shift;
p3 <<= shift;
p4 <<= shift;
nmin = *min << shift;
nmax = *max << shift;
}
else
{
p1 >>= -shift;
p2 >>= -shift;
p3 >>= -shift;
p4 >>= -shift;
nmin = *min >> -shift;
nmax = *max >> -shift;
}
nmax = update_max( p1, p2, p3, p4, nmax );
/* now flip the signs to update the minimum */
*min = -update_max( -p1, -p2, -p3, -p4, -*min );
nmin = -update_max( -p1, -p2, -p3, -p4, -nmin );
if ( shift > 0 )
{
nmin >>= shift;
nmax >>= shift;
}
else
{
nmin <<= -shift;
nmax <<= -shift;
}
if ( nmin < *min )
*min = nmin;
if ( nmax > *max )
*max = nmax;
}
#else
@ -482,8 +534,9 @@
FT_Vector* to,
TBBox_Rec* user )
{
/* we don't need to check `to' since it is always an `on' point, thus */
/* within the bbox */
/* We don't need to check `to' since it is always an on-point, */
/* thus within the bbox. Only segments with an off-point outside */
/* the bbox can possibly reach new extreme values. */
if ( CHECK_X( control1, user->bbox ) ||
CHECK_X( control2, user->bbox ) )