Bug 1385745 Part 1 - Add BBoxFlags::eIncludeOnlyCurrentFrameForNonSVGElement to determine whether include all continuations while computing bbox of a html frame.
MozReview-Commit-ID: Fx11LjhBcrM
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -460,17 +460,24 @@ nsSVGClipPathFrame::GetClipPathTransform
{
SVGClipPathElement *content = static_cast<SVGClipPathElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(gfxMatrix());
nsSVGEnum* clipPathUnits =
&content->mEnumAttributes[SVGClipPathElement::CLIPPATHUNITS];
- return nsSVGUtils::AdjustMatrixForUnits(tm, clipPathUnits, aClippedFrame);
+ uint32_t flags =
+ nsSVGUtils::eBBoxIncludeFillGeometry |
+ (aClippedFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone
+ ? nsSVGUtils::eIncludeOnlyCurrentFrameForNonSVGElement
+ : 0);
+
+ return nsSVGUtils::AdjustMatrixForUnits(tm, clipPathUnits,
+ aClippedFrame, flags);
}
SVGBBox
nsSVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox &aBBox,
const gfxMatrix &aMatrix)
{
nsIContent* node = GetContent()->GetFirstChild();
SVGBBox unionBBox, tmpBBox;
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -212,38 +212,36 @@ nsSVGIntegrationUtils::GetSVGCoordContex
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(firstFrame, firstFrame);
nsPresContext* presContext = firstFrame->PresContext();
return gfx::Size(presContext->AppUnitsToFloatCSSPixels(r.width),
presContext->AppUnitsToFloatCSSPixels(r.height));
}
gfxRect
-nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
+nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame,
+ bool aUnionContinuations)
{
// Except for nsSVGOuterSVGFrame, we shouldn't be getting here with SVG
// frames at all. This function is for elements that are laid out using the
// CSS box model rules.
NS_ASSERTION(!(aNonSVGFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT),
"Frames with SVG layout should not get here");
MOZ_ASSERT(!aNonSVGFrame->IsFrameOfType(nsIFrame::eSVG) ||
aNonSVGFrame->IsSVGOuterSVGFrame());
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
// 'r' is in "user space":
- nsRect r;
- if (aNonSVGFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone) {
- r = GetPreEffectsVisualOverflow(firstFrame, aNonSVGFrame,
- GetOffsetToBoundingBox(firstFrame));
- } else {
- r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
- GetOffsetToBoundingBox(firstFrame),
- false);
- }
+ nsRect r = (aUnionContinuations)
+ ? GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
+ GetOffsetToBoundingBox(firstFrame),
+ false)
+ : GetPreEffectsVisualOverflow(firstFrame, aNonSVGFrame,
+ GetOffsetToBoundingBox(firstFrame));
return nsLayoutUtils::RectToGfxRect(r,
aNonSVGFrame->PresContext()->AppUnitsPerCSSPixel());
}
// XXX Since we're called during reflow, this method is broken for frames with
// continuations. When we're called for a frame with continuations, we're
// called for each continuation in turn as it's reflowed. However, it isn't
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -73,22 +73,23 @@ public:
static mozilla::gfx::Size
GetSVGCoordContextForNonSVGFrame(nsIFrame* aNonSVGFrame);
/**
* SVG effects such as SVG filters, masking and clipPath may require an SVG
* "bbox" for the element they're being applied to in order to make decisions
* about positioning, and to resolve various lengths against. This method
* provides the "bbox" for non-SVG frames. The bbox returned is in CSS px
- * units, and is the union of all aNonSVGFrame's continuations' overflow
- * areas, relative to the top-left of the union of all aNonSVGFrame's
+ * units, and aUnionContinuations decide whether bbox contains the area of
+ * current frame only or the union of all aNonSVGFrame's continuations'
+ * overflow areas, relative to the top-left of the union of all aNonSVGFrame's
* continuations' border box rects.
*/
static gfxRect
- GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame);
+ GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame, bool aUnionContinuations);
/**
* Used to adjust a frame's pre-effects visual overflow rect to take account
* of SVG effects.
*
* XXX This method will not do the right thing for frames with continuations.
* It really needs all the continuations to have been reflowed before being
* called, but we currently call it on each continuation as its overflow
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -221,11 +221,17 @@ nsSVGMaskFrame::GetCanvasTM()
gfxMatrix
nsSVGMaskFrame::GetMaskTransform(nsIFrame* aMaskedFrame)
{
SVGMaskElement *content = static_cast<SVGMaskElement*>(mContent);
nsSVGEnum* maskContentUnits =
&content->mEnumAttributes[SVGMaskElement::MASKCONTENTUNITS];
+ uint32_t flags =
+ nsSVGUtils::eBBoxIncludeFillGeometry |
+ (aMaskedFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone
+ ? nsSVGUtils::eIncludeOnlyCurrentFrameForNonSVGElement
+ : 0);
+
return nsSVGUtils::AdjustMatrixForUnits(gfxMatrix(), maskContentUnits,
- aMaskedFrame);
+ aMaskedFrame, flags);
}
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1094,17 +1094,20 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, ui
}
const bool isOuterSVG = svg && !hasSVGLayout;
MOZ_ASSERT(!isOuterSVG || aFrame->IsSVGOuterSVGFrame());
if (!svg ||
(isOuterSVG && (aFlags & eUseFrameBoundsForOuterSVG))) {
// An HTML element or an SVG outer frame.
MOZ_ASSERT(!hasSVGLayout);
- return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
+ bool onlyCurrentFrame = aFlags & eIncludeOnlyCurrentFrameForNonSVGElement;
+ return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(
+ aFrame,
+ /* aUnionContinuations = */ !onlyCurrentFrame);
}
MOZ_ASSERT(svg);
nsIContent* content = aFrame->GetContent();
if (content->IsSVGElement() &&
!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
return gfxRect();
@@ -1291,21 +1294,22 @@ nsSVGUtils::CanOptimizeOpacity(nsIFrame
return true;
}
return false;
}
gfxMatrix
nsSVGUtils::AdjustMatrixForUnits(const gfxMatrix &aMatrix,
nsSVGEnum *aUnits,
- nsIFrame *aFrame)
+ nsIFrame *aFrame,
+ uint32_t aFlags)
{
if (aFrame &&
aUnits->GetAnimValue() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
- gfxRect bbox = GetBBox(aFrame);
+ gfxRect bbox = GetBBox(aFrame, aFlags);
gfxMatrix tm = aMatrix;
tm.PreTranslate(gfxPoint(bbox.X(), bbox.Y()));
tm.PreScale(bbox.Width(), bbox.Height());
return tm;
}
return aMatrix;
}
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -374,48 +374,55 @@ public:
/**
* Take the CTM to userspace for an element, and adjust it to a CTM to its
* object bounding box space if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX.
* (I.e. so that [0,0] is at the top left of its bbox, and [1,1] is at the
* bottom right of its bbox).
*
* If the bbox is empty, this will return a singular matrix.
+ *
+ * @param aFlags One or more of the BBoxFlags values defined below.
*/
static gfxMatrix AdjustMatrixForUnits(const gfxMatrix &aMatrix,
nsSVGEnum *aUnits,
- nsIFrame *aFrame);
+ nsIFrame *aFrame,
+ uint32_t aFlags);
enum BBoxFlags {
eBBoxIncludeFill = 1 << 0,
eBBoxIncludeFillGeometry = 1 << 1,
eBBoxIncludeStroke = 1 << 2,
eBBoxIncludeStrokeGeometry = 1 << 3,
eBBoxIncludeMarkers = 1 << 4,
eBBoxIncludeClipped = 1 << 5,
// Normally a getBBox call on outer-<svg> should only return the
- // bounds of the elements children. This flag will cause the
+ // bounds of the elements children. This flag will cause the
// element's bounds to be returned instead.
eUseFrameBoundsForOuterSVG = 1 << 6,
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
eForGetClientRects = 1 << 7,
+ // If the given frame is an HTML element, only include the region of the
+ // given frame, instead of all continuations of it, while computing bbox if
+ // this flag is set.
+ eIncludeOnlyCurrentFrameForNonSVGElement = 1 << 8,
};
/**
* This function in primarily for implementing the SVG DOM function getBBox()
* and the SVG attribute value 'objectBoundingBox'. However, it has been
* extended with various extra parameters in order to become more of a
* general purpose getter of all sorts of bounds that we might need to obtain
* for SVG elements, or even for other elements that have SVG effects applied
* to them.
*
* @param aFrame The frame of the element for which the bounds are to be
* obtained.
* @param aFlags One or more of the BBoxFlags values defined above.
* @param aToBoundsSpace If not specified the returned rect is in aFrame's
- * element's "user space". A matrix can optionally be pass to specify a
+ * element's "user space". A matrix can optionally be pass to specify a
* transform from aFrame's user space to the bounds space of interest
* (typically this will be the ancestor nsSVGOuterSVGFrame, but it could be
* to any other coordinate space).
*/
static gfxRect GetBBox(nsIFrame *aFrame,
// If the default arg changes, update the handling for
// ObjectBoundingBoxProperty() in the implementation.
uint32_t aFlags = eBBoxIncludeFillGeometry,