Bug 1459697 Part 1: In EllipseShapeInfo distance field calculation, remove a warning that might trigger due to rounding error, and shorten the iteration of each block pixel row, when possible.
draft
Bug 1459697 Part 1: In EllipseShapeInfo distance field calculation, remove a warning that might trigger due to rounding error, and shorten the iteration of each block pixel row, when possible.
MozReview-Commit-ID: 6itpj3HBSRy
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -817,19 +817,21 @@ nsFloatManager::EllipseShapeInfo::Ellips
// use a chamfer 5-7-11 5x5 matrix to compute minimum distance to an edge
// pixel. This integer math computation is reasonably close to the true
// Euclidean distance. The distances will be approximately 5x the true
// distance, quantized in integer units. The 5x is factored away in the
// comparison which builds the intervals.
dfType usedMargin5X = CalcUsedShapeMargin5X(aShapeMargin,
aAppUnitsPerDevPixel);
+ // Calculate the bounds of one quadrant of the ellipse, in integer device
+ // pixels. These bounds are equal to the rectangle defined by the radii,
+ // plus the shape-margin value in both dimensions.
const LayoutDeviceIntSize bounds =
- LayoutDevicePixel::FromAppUnitsRounded(mRadii,
- aAppUnitsPerDevPixel) +
+ LayoutDevicePixel::FromAppUnitsRounded(mRadii, aAppUnitsPerDevPixel) +
LayoutDeviceIntSize(usedMargin5X / 5, usedMargin5X / 5);
// Since our distance field is computed with a 5x5 neighborhood, but only
// looks in the negative block and negative inline directions, it is
// effectively a 3x3 neighborhood. We need to expand our distance field
// outwards by a further 2 pixels in both axes (on the minimum block edge
// and the minimum inline edge). We call this edge area the expanded region.
@@ -858,17 +860,17 @@ nsFloatManager::EllipseShapeInfo::Ellips
for (uint32_t b = 0; b < bSize; ++b) {
bool bIsInExpandedRegion(b < bExpand);
nscoord bInAppUnits = (b - bExpand) * aAppUnitsPerDevPixel;
bool bIsMoreThanEllipseBEnd(bInAppUnits > mRadii.height);
// Find the i intercept of the ellipse edge for this block row, and
// adjust it to compensate for the expansion of the inline dimension.
// If we're in the expanded region, or if we're using a b that's more
- // than the bStart of the ellipse, the intercept is nscoord_MIN.
+ // than the bEnd of the ellipse, the intercept is nscoord_MIN.
const int32_t iIntercept = (bIsInExpandedRegion ||
bIsMoreThanEllipseBEnd) ? nscoord_MIN :
iExpand + NSAppUnitsToIntPixels(
XInterceptAtY(bInAppUnits, mRadii.width, mRadii.height),
aAppUnitsPerDevPixel);
// Set iMax in preparation for this block row.
int32_t iMax = iIntercept;
@@ -913,25 +915,33 @@ nsFloatManager::EllipseShapeInfo::Ellips
std::min<dfType>(df[index - iSize - 2] + 11,
df[index - (iSize * 2) - 1] + 11))));
// Check the df value and see if it's less than or equal to the
// usedMargin5X value.
if (df[index] <= usedMargin5X) {
MOZ_ASSERT(iMax < (int32_t)i);
iMax = i;
+ } else {
+ // Since we're computing the bottom-right quadrant, there's no way
+ // for a later i value in this row to be within the usedMargin5X
+ // value. Likewise, every row beyond us will encounter this
+ // condition with an i value less than or equal to our i value now.
+ // Since our chamfer only looks upward and leftward, we can stop
+ // calculating for the rest of the row, because the distance field
+ // values there will never be looked at in a later row's chamfer
+ // calculation.
+ break;
}
}
}
- NS_WARNING_ASSERTION(bIsInExpandedRegion || iMax > nscoord_MIN,
- "Once past the expanded region, we should always "
- "find a pixel within the shape-margin distance for "
- "each block row.");
-
+ // It's very likely, though not guaranteed that we will find an pixel
+ // within the shape-margin distance for each block row. This may not
+ // always be true due to rounding errors.
if (iMax > nscoord_MIN) {
// Origin for this interval is at the center of the ellipse, adjusted
// in the positive block direction by bInAppUnits.
nsPoint origin(aCenter.x, aCenter.y + bInAppUnits);
// Size is an inline iMax plus 1 (to account for the whole pixel) dev
// pixels, by 1 block dev pixel. We convert this to app units.
nsSize size((iMax - iExpand + 1) * aAppUnitsPerDevPixel,
aAppUnitsPerDevPixel);