Bug 1461046 Part 1: Change EllipseShapeInfo to tolerate empty circles/ellipses and treat them as singular points/lines (possibly expanded by shape-margin).
MozReview-Commit-ID: 69VQiRjhtqA
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -725,17 +725,20 @@ public:
const nscoord aBEnd) const override;
nscoord BStart() const override {
return mCenter.y - mRadii.height - mShapeMargin;
}
nscoord BEnd() const override {
return mCenter.y + mRadii.height + mShapeMargin;
}
bool IsEmpty() const override {
- return mRadii.IsEmpty();
+ // An EllipseShapeInfo is never empty, because an ellipse or circle with
+ // a zero radius acts like a point, and an ellipse with one zero radius
+ // acts like a line.
+ return false;
}
void Translate(nscoord aLineLeft, nscoord aBlockStart) override
{
mCenter.MoveBy(aLineLeft, aBlockStart);
for (nsRect& interval : mIntervals) {
interval.MoveBy(aLineLeft, aBlockStart);
@@ -861,38 +864,46 @@ nsFloatManager::EllipseShapeInfo::Ellips
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 bEnd of the ellipse, the intercept is nscoord_MIN.
- const int32_t iIntercept = (bIsInExpandedRegion ||
- bIsMoreThanEllipseBEnd) ? nscoord_MIN :
+ // We have one other special case to consider: when the ellipse has no
+ // height. In that case we treat the bInAppUnits == 0 case as
+ // intercepting at the width of the ellipse. All other cases solve
+ // the intersection mathematically.
+ const int32_t iIntercept =
+ (bIsInExpandedRegion || bIsMoreThanEllipseBEnd) ? nscoord_MIN :
iExpand + NSAppUnitsToIntPixels(
- XInterceptAtY(bInAppUnits, mRadii.width, mRadii.height),
+ (!!mRadii.height || bInAppUnits) ?
+ XInterceptAtY(bInAppUnits, mRadii.width, mRadii.height) :
+ mRadii.width,
aAppUnitsPerDevPixel);
// Set iMax in preparation for this block row.
int32_t iMax = iIntercept;
for (uint32_t i = 0; i < iSize; ++i) {
const uint32_t index = i + b * iSize;
MOZ_ASSERT(index < (iSize * bSize),
"Our distance field index should be in-bounds.");
// Handle our three cases, in order.
if (i < iExpand ||
bIsInExpandedRegion) {
// Case 1: Expanded reqion pixel.
df[index] = MAX_MARGIN_5X;
} else if ((int32_t)i <= iIntercept) {
- // Case 2: Pixel within the ellipse.
- df[index] = 0;
+ // Case 2: Pixel within the ellipse, or just outside the edge of it.
+ // Having a positive height indicates that there's an area we can
+ // be inside of.
+ df[index] = (!!mRadii.height) ? 0 : 5;
} else {
// Case 3: Other pixel.
// Backward-looking neighborhood distance from target pixel X
// with chamfer 5-7-11 looks like:
//
// +--+--+--+
// | |11| |