--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1180,19 +1180,18 @@ nsIFrame::Extend3DContext() const
return false;
}
if (HasOpacity()) {
return false;
}
const nsStyleEffects* effects = StyleEffects();
- nsRect temp;
return !nsFrame::ShouldApplyOverflowClipping(this, disp) &&
- !GetClipPropClipRect(disp, effects, &temp, GetSize()) &&
+ !GetClipPropClipRect(disp, effects, GetSize()) &&
!nsSVGIntegrationUtils::UsingEffectsForFrame(this);
}
bool
nsIFrame::Combines3DTransformWithAncestors() const
{
if (!GetParent() || !GetParent()->Extend3DContext()) {
return false;
@@ -1930,70 +1929,45 @@ inline static bool IsSVGContentWithCSSCl
// elements regardless of the value of the 'position' property. Here we obey
// the CSS spec for outer-<svg> (since that's what we generally do), but
// obey the SVG spec for other SVG elements to which 'clip' applies.
return (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
aFrame->GetContent()->IsAnyOfSVGElements(nsGkAtoms::svg,
nsGkAtoms::foreignObject);
}
-bool
+Maybe<nsRect>
nsIFrame::GetClipPropClipRect(const nsStyleDisplay* aDisp,
const nsStyleEffects* aEffects,
- nsRect* aRect,
const nsSize& aSize) const
{
- NS_PRECONDITION(aRect, "Must have aRect out parameter");
-
if (!(aEffects->mClipFlags & NS_STYLE_CLIP_RECT) ||
!(aDisp->IsAbsolutelyPositioned(this) || IsSVGContentWithCSSClip(this))) {
- return false;
- }
-
- *aRect = aEffects->mClip;
+ return Nothing();
+ }
+
+ nsRect rect = aEffects->mClip;
if (MOZ_LIKELY(StyleBorder()->mBoxDecorationBreak ==
NS_STYLE_BOX_DECORATION_BREAK_SLICE)) {
// The clip applies to the joined boxes so it's relative the first
// continuation.
nscoord y = 0;
for (nsIFrame* f = GetPrevContinuation(); f; f = f->GetPrevContinuation()) {
y += f->GetRect().height;
}
- aRect->MoveBy(nsPoint(0, -y));
+ rect.MoveBy(nsPoint(0, -y));
}
if (NS_STYLE_CLIP_RIGHT_AUTO & aEffects->mClipFlags) {
- aRect->width = aSize.width - aRect->x;
+ rect.width = aSize.width - rect.x;
}
if (NS_STYLE_CLIP_BOTTOM_AUTO & aEffects->mClipFlags) {
- aRect->height = aSize.height - aRect->y;
- }
- return true;
-}
-
-/**
- * If the CSS 'clip' property applies to this frame, set it up
- * in aBuilder->ClipState() to clip all content descendants. Returns true
- * if the property applies, and if so also returns the clip rect (relative
- * to aFrame) in *aRect.
- */
-static bool
-ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
- const nsIFrame* aFrame,
- const nsStyleDisplay* aDisp,
- const nsStyleEffects* aEffects,
- nsRect* aRect,
- DisplayListClipState::AutoSaveRestore& aClipState)
-{
- if (!aFrame->GetClipPropClipRect(aDisp, aEffects, aRect, aFrame->GetSize()))
- return false;
-
- nsRect clipRect = *aRect + aBuilder->ToReferenceFrame(aFrame);
- aClipState.ClipContentDescendants(clipRect);
- return true;
+ rect.height = aSize.height - rect.y;
+ }
+ return Some(rect);
}
/**
* If the CSS 'overflow' property applies to this frame, and is not
* handled by constructing a dedicated nsHTML/XULScrollFrame, set up clipping
* for that overflow in aBuilder->ClipState() to clip all containing-block
* descendants.
*/
@@ -2339,20 +2313,21 @@ nsIFrame::BuildDisplayListForStackingCon
DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
nsDisplayListBuilder::AutoInTransformSetter
inTransformSetter(aBuilder, inTransform);
nsDisplayListBuilder::AutoSaveRestorePerspectiveIndex
perspectiveIndex(aBuilder, this);
CheckForApzAwareEventHandlers(aBuilder, this);
- nsRect clipPropClip;
- if (ApplyClipPropClipping(aBuilder, this, disp, effects, &clipPropClip,
- nestedClipState)) {
- dirtyRect.IntersectRect(dirtyRect, clipPropClip);
+ Maybe<nsRect> clipPropClip = GetClipPropClipRect(disp, effects, GetSize());
+ if (clipPropClip) {
+ dirtyRect.IntersectRect(dirtyRect, *clipPropClip);
+ nestedClipState.ClipContentDescendants(
+ *clipPropClip + aBuilder->ToReferenceFrame(this));
}
// extend3DContext also guarantees that applyAbsPosClipping and usingSVGEffects are false
// We only modify the preserve-3d rect if we are the top of a preserve-3d heirarchy
if (extend3DContext) {
// Mark these first so MarkAbsoluteFramesForDisplayList knows if we are
// going to be forced to descend into frames.
aBuilder->MarkPreserve3DFramesForDisplayList(this);
@@ -2862,22 +2837,22 @@ nsIFrame::BuildDisplayListForChild(nsDis
aBuilder->SetContainsBlendMode(true);
}
// True stacking context.
// For stacking contexts, BuildDisplayListForStackingContext handles
// clipping and MarkAbsoluteFramesForDisplayList.
child->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
aBuilder->DisplayCaret(child, dirty, &list);
} else {
- nsRect clipRect;
- if (ApplyClipPropClipping(aBuilder, child, disp, effects, &clipRect,
- clipState)) {
- // clipRect is in builder-reference-frame coordinates,
- // dirty/clippedDirtyRect are in child coordinates
- dirty.IntersectRect(dirty, clipRect);
+ Maybe<nsRect> clipPropClip =
+ child->GetClipPropClipRect(disp, effects, child->GetSize());
+ if (clipPropClip) {
+ dirty.IntersectRect(dirty, *clipPropClip);
+ clipState.ClipContentDescendants(
+ *clipPropClip + aBuilder->ToReferenceFrame(child));
}
child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
if (aBuilder->IsBuildingLayerEventRegions()) {
// If this frame has a different animated geometry root than its parent,
// make sure we accumulate event regions for its layer.
if (buildingForChild.IsAnimatedGeometryRoot()) {
@@ -7932,20 +7907,18 @@ UnionBorderBoxes(nsIFrame* aFrame, bool
if (nsFrame::ShouldApplyOverflowClipping(aFrame, disp) ||
fType == nsGkAtoms::scrollFrame ||
fType == nsGkAtoms::listControlFrame ||
fType == nsGkAtoms::svgOuterSVGFrame) {
return u;
}
const nsStyleEffects* effects = aFrame->StyleEffects();
- nsRect clipPropClipRect;
- bool hasClipPropClip =
- aFrame->GetClipPropClipRect(disp, effects, &clipPropClipRect,
- bounds.Size());
+ Maybe<nsRect> clipPropClipRect =
+ aFrame->GetClipPropClipRect(disp, effects, bounds.Size());
// Iterate over all children except pop-ups.
const nsIFrame::ChildListIDs skip(nsIFrame::kPopupList |
nsIFrame::kSelectPopupList);
for (nsIFrame::ChildListIterator childLists(aFrame);
!childLists.IsDone(); childLists.Next()) {
if (skip.Contains(childLists.CurrentID())) {
continue;
@@ -7966,19 +7939,19 @@ UnionBorderBoxes(nsIFrame* aFrame, bool
bool validRect = true;
nsRect childRect = UnionBorderBoxes(child, true, validRect) +
child->GetPosition();
if (!validRect) {
continue;
}
- if (hasClipPropClip) {
+ if (clipPropClipRect) {
// Intersect with the clip before transforming.
- childRect.IntersectRect(childRect, clipPropClipRect);
+ childRect.IntersectRect(childRect, *clipPropClipRect);
}
// Note that we transform each child separately according to
// aFrame's transform, and then union, which gives a different
// (smaller) result from unioning and then transforming the
// union. This doesn't match the way we handle overflow areas
// with 2-D transforms, though it does match the way we handle
// overflow areas in preserve-3d 3-D scenes.
@@ -8188,23 +8161,22 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
ComputeAndIncludeOutlineArea(this, aOverflowAreas, aNewSize);
// Nothing in here should affect scrollable overflow.
aOverflowAreas.VisualOverflow() =
ComputeEffectsRect(this, aOverflowAreas.VisualOverflow(), aNewSize);
// Absolute position clipping
const nsStyleEffects* effects = StyleEffects();
- nsRect clipPropClipRect;
- bool hasClipPropClip =
- GetClipPropClipRect(disp, effects, &clipPropClipRect, aNewSize);
- if (hasClipPropClip) {
+ Maybe<nsRect> clipPropClipRect =
+ GetClipPropClipRect(disp, effects, aNewSize);
+ if (clipPropClipRect) {
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
- o.IntersectRect(o, clipPropClipRect);
+ o.IntersectRect(o, *clipPropClipRect);
}
}
/* If we're transformed, transform the overflow rect by the current transformation. */
bool hasTransform = IsTransformed();
nsSize oldSize = mRect.Size();
bool sizeChanged = ((aOldSize ? *aOldSize : oldSize) != aNewSize);
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2873,30 +2873,28 @@ public:
/**
* Return true if and only if this frame obeys visibility:hidden.
* if it does not, then nsContainerFrame will hide its view even though
* this means children can't be made visible again.
*/
virtual bool SupportsVisibilityHidden() { return true; }
/**
- * Returns true if the frame has a valid clip rect set via the 'clip'
- * property, and the 'clip' property applies to this frame. The 'clip'
- * property applies to HTML frames if they are absolutely positioned. The
- * 'clip' property applies to SVG frames regardless of the value of the
- * 'position' property.
+ * Returns the clip rect set via the 'clip' property, if the 'clip' property
+ * applies to this frame; otherwise returns Nothing(). The 'clip' property
+ * applies to HTML frames if they are absolutely positioned. The 'clip'
+ * property applies to SVG frames regardless of the value of the 'position'
+ * property.
*
- * If this method returns true, then we also set aRect to the computed clip
- * rect, with coordinates relative to this frame's origin. aRect must not be
- * null!
+ * The coordinates of the returned rectangle are relative to this frame's
+ * origin.
*/
- bool GetClipPropClipRect(const nsStyleDisplay* aDisp,
- const nsStyleEffects* aEffects,
- nsRect* aRect,
- const nsSize& aSize) const;
+ Maybe<nsRect> GetClipPropClipRect(const nsStyleDisplay* aDisp,
+ const nsStyleEffects* aEffects,
+ const nsSize& aSize) const;
/**
* Check if this frame is focusable and in the current tab order.
* Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
* For example, only the selected radio button in a group is in the
* tab order, unless the radio group has no selection in which case
* all of the visible, non-disabled radio buttons in the group are
* in the tab order. On the other hand, all of the visible, non-disabled