author | Robert O'Callahan <robert@ocallahan.org> |
Fri, 05 Apr 2013 00:36:45 +1300 | |
changeset 127810 | 3396e302a1e44e964f3dfeea457f26498acbdff4 |
parent 127809 | 5f7f4e26d4a9b1e17772e32caf1aa9502b008a21 |
child 127811 | 1e958f7224a737ac34be464a9e11e445c8d1b0df |
push id | 24512 |
push user | ryanvm@gmail.com |
push date | Fri, 05 Apr 2013 20:13:49 +0000 |
treeherder | mozilla-central@139b6ba547fa [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mattwoodrow |
bugs | 841192 |
milestone | 23.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/base/DisplayListClipState.cpp +++ b/layout/base/DisplayListClipState.cpp @@ -57,25 +57,16 @@ DisplayListClipState::ClipContentDescend aClipOnStack.SetTo(aRect); if (mClipContentDescendants) { aClipOnStack.IntersectWith(*mClipContentDescendants); } mClipContentDescendants = &aClipOnStack; mCurrentCombinedClip = nullptr; } -DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox:: -AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, - uint32_t aFlags) - : AutoSaveRestore(aBuilder->ClipState()) -{ - mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame, mClip, aFlags); -} - void DisplayListClipState::ClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, DisplayItemClip& aClipOnStack, uint32_t aFlags) { nscoord radii[8]; bool hasBorderRadius = aFrame->GetContentBoxBorderRadii(radii); @@ -86,9 +77,16 @@ DisplayListClipState::ClipContainingBloc nsRect clipRect = aFrame->GetContentRectRelativeToSelf() + aBuilder->ToReferenceFrame(aFrame); // If we have a border-radius, we have to clip our content to that // radius. ClipContainingBlockDescendants(clipRect, hasBorderRadius ? radii : nullptr, aClipOnStack); } +DisplayListClipState::AutoSaveRestore::AutoSaveRestore(nsDisplayListBuilder* aBuilder) + : mState(aBuilder->ClipState()) + , mSavedState(aBuilder->ClipState()) + , mClipUsed(false) + , mRestored(false) +{} + }
--- a/layout/base/DisplayListClipState.h +++ b/layout/base/DisplayListClipState.h @@ -3,16 +3,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef DISPLAYLISTCLIPSTATE_H_ #define DISPLAYLISTCLIPSTATE_H_ #include "DisplayItemClip.h" +#include "mozilla/DebugOnly.h" + class nsIFrame; class nsDisplayListBuilder; namespace mozilla { /** * All clip coordinates are in appunits relative to the reference frame * for the display item we're building. @@ -35,26 +37,35 @@ public: { return mClipContainingBlockDescendants; } const DisplayItemClip* GetClipForContentDescendants() const { return mClipContentDescendants; } + class AutoSaveRestore; + friend class AutoSaveRestore; + + class AutoClipContainingBlockDescendantsToContentBox; + friend class AutoClipContainingBlockDescendantsToContentBox; + + class AutoClipMultiple; + friend class AutoClipMultiple; + + enum { + ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT = 0x01 + }; + +private: void SetClipForContainingBlockDescendants(const DisplayItemClip* aClip) { mClipContainingBlockDescendants = aClip; mCurrentCombinedClip = nullptr; } - void SetClipForContentDescendants(const DisplayItemClip* aClip) - { - mClipContentDescendants = aClip; - mCurrentCombinedClip = nullptr; - } void Clear() { mClipContentDescendants = nullptr; mClipContainingBlockDescendants = nullptr; mCurrentCombinedClip = nullptr; } @@ -65,38 +76,29 @@ public: */ void ClipContainingBlockDescendants(const nsRect& aRect, const nscoord* aRadii, DisplayItemClip& aClipOnStack); void ClipContentDescendants(const nsRect& aRect, DisplayItemClip& aClipOnStack); - enum { - ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT = 0x01 - }; /** * Clips containing-block descendants to the frame's content-box, * taking border-radius into account. * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then * we assume display items will not draw outside the content rect, so * clipping is only required if there is a border-radius. This is an * optimization to reduce the amount of clipping required. */ void ClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, DisplayItemClip& aClipOnStack, - uint32_t aFlags = 0); + uint32_t aFlags); - class AutoSaveRestore; - friend class AutoSaveRestore; - - class AutoClipContainingBlockDescendantsToContentBox; - -private: /** * All content descendants (i.e. following placeholder frames to their * out-of-flows if necessary) should be clipped by mClipContentDescendants. * Null if no clipping applies. */ const DisplayItemClip* mClipContentDescendants; /** * All containing-block descendants (i.e. frame descendants), including @@ -110,39 +112,137 @@ private: * mClipContainingBlockDescendants. * Allocated in the nsDisplayListBuilder arena. Null if none has been * allocated or both mClipContentDescendants and mClipContainingBlockDescendants * are null. */ const DisplayItemClip* mCurrentCombinedClip; }; +/** + * A class to automatically save and restore the current clip state. Also + * offers methods for modifying the clip state. Only one modification is allowed + * to be in scope at a time using one of these objects; multiple modifications + * require nested objects. The interface is written this way to prevent + * dangling pointers to DisplayItemClips. + */ class DisplayListClipState::AutoSaveRestore { public: - AutoSaveRestore(DisplayListClipState& aState) - : mState(aState) - , mSavedState(aState) - {} + AutoSaveRestore(nsDisplayListBuilder* aBuilder); void Restore() { mState = mSavedState; + mRestored = true; } ~AutoSaveRestore() { mState = mSavedState; } + + void Clear() + { + NS_ASSERTION(!mRestored, "Already restored!"); + mState.Clear(); + mClipUsed = false; + } + + /** + * Intersects the given clip rect (with optional aRadii) with the current + * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to + * the result, stored in aClipOnStack. + */ + void ClipContainingBlockDescendants(const nsRect& aRect, + const nscoord* aRadii) + { + NS_ASSERTION(!mRestored, "Already restored!"); + NS_ASSERTION(!mClipUsed, "mClip already used"); + mClipUsed = true; + mState.ClipContainingBlockDescendants(aRect, aRadii, mClip); + } + + void ClipContentDescendants(const nsRect& aRect) + { + NS_ASSERTION(!mRestored, "Already restored!"); + NS_ASSERTION(!mClipUsed, "mClip already used"); + mClipUsed = true; + mState.ClipContentDescendants(aRect, mClip); + } + + /** + * Clips containing-block descendants to the frame's content-box, + * taking border-radius into account. + * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then + * we assume display items will not draw outside the content rect, so + * clipping is only required if there is a border-radius. This is an + * optimization to reduce the amount of clipping required. + */ + void ClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + uint32_t aFlags = 0) + { + NS_ASSERTION(!mRestored, "Already restored!"); + NS_ASSERTION(!mClipUsed, "mClip already used"); + mClipUsed = true; + mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame, mClip, aFlags); + } + protected: DisplayListClipState& mState; DisplayListClipState mSavedState; + DisplayItemClip mClip; + DebugOnly<bool> mClipUsed; + DebugOnly<bool> mRestored; }; class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox : public AutoSaveRestore { public: AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - uint32_t aFlags = 0); + uint32_t aFlags = 0) + : AutoSaveRestore(aBuilder) + { + mClipUsed = true; + mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame, mClip, aFlags); + } +}; + +/** + * Do not use this outside of nsFrame::BuildDisplayListForChild, use + * multiple AutoSaveRestores instead. We provide this class just to ensure + * BuildDisplayListForChild is as efficient as possible. + */ +class DisplayListClipState::AutoClipMultiple : public AutoSaveRestore { +public: + AutoClipMultiple(nsDisplayListBuilder* aBuilder) + : AutoSaveRestore(aBuilder) + , mExtraClipUsed(false) + {} + + /** + * *aClip must survive longer than this object. Be careful!!! + */ + void SetClipForContainingBlockDescendants(const DisplayItemClip* aClip) + { + mState.SetClipForContainingBlockDescendants(aClip); + } + + /** + * Intersects the given clip rect (with optional aRadii) with the current + * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to + * the result, stored in aClipOnStack. + */ + void ClipContainingBlockDescendantsExtra(const nsRect& aRect, + const nscoord* aRadii) + { + NS_ASSERTION(!mRestored, "Already restored!"); + NS_ASSERTION(!mExtraClipUsed, "mExtraClip already used"); + mExtraClipUsed = true; + mState.ClipContainingBlockDescendants(aRect, aRadii, mExtraClip); + } + protected: - DisplayItemClip mClip; + DisplayItemClip mExtraClip; + DebugOnly<bool> mExtraClipUsed; }; } #endif /* DISPLAYLISTCLIPSTATE_H_ */
--- a/layout/forms/nsFileControlFrame.cpp +++ b/layout/forms/nsFileControlFrame.cpp @@ -352,19 +352,18 @@ nsFileControlFrame::BuildDisplayList(nsD } // Clip height only nsRect clipRect(aBuilder->ToReferenceFrame(this), GetSize()); clipRect.width = GetVisualOverflowRect().XMost(); nsDisplayListCollection tempList; { - DisplayListClipState::AutoSaveRestore saveClipState(aBuilder->ClipState()); - DisplayItemClip clipOnStack; - aBuilder->ClipState().ClipContainingBlockDescendants(clipRect, nullptr, clipOnStack); + DisplayListClipState::AutoSaveRestore clipState(aBuilder); + clipState.ClipContainingBlockDescendants(clipRect, nullptr); // Our background is inherited to the text input, and we don't really want to // paint it or out padding and borders (which we never have anyway, per // styles in forms.css) -- doing it just makes us look ugly in some cases and // has no effect in others. nsBlockFrame::BuildDisplayList(aBuilder, aDirtyRect, tempList); }
--- a/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/layout/forms/nsHTMLButtonControlFrame.cpp @@ -112,41 +112,34 @@ nsHTMLButtonControlFrame::BuildDisplayLi const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { nsDisplayList onTop; if (IsVisibleForPainting(aBuilder)) { mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop); } - bool overflowClip = - IsInput() || StyleDisplay()->mOverflowX != NS_STYLE_OVERFLOW_VISIBLE; - nsRect rect; - nscoord radii[8]; nsDisplayListCollection set; - { - DisplayListClipState::AutoSaveRestore saveClipState(aBuilder->ClipState()); - DisplayItemClip overflowClipOnStack; + // Do not allow the child subtree to receive events. + if (!aBuilder->IsForEventDelivery()) { + DisplayListClipState::AutoSaveRestore clipState(aBuilder); - if (overflowClip) { + if (IsInput() || StyleDisplay()->mOverflowX != NS_STYLE_OVERFLOW_VISIBLE) { nsMargin border = StyleBorder()->GetComputedBorder(); - rect = nsRect(aBuilder->ToReferenceFrame(this), GetSize()); + nsRect rect(aBuilder->ToReferenceFrame(this), GetSize()); rect.Deflate(border); + nscoord radii[8]; bool hasRadii = GetPaddingBoxBorderRadii(radii); - aBuilder->ClipState().ClipContainingBlockDescendants(rect, - hasRadii ? radii : nullptr, overflowClipOnStack); + clipState.ClipContainingBlockDescendants(rect, hasRadii ? radii : nullptr); } - // Do not allow the child subtree to receive events. - if (!aBuilder->IsForEventDelivery()) { - BuildDisplayListForChild(aBuilder, mFrames.FirstChild(), aDirtyRect, set, - DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT); - // That should put the display items in set.Content() - } + BuildDisplayListForChild(aBuilder, mFrames.FirstChild(), aDirtyRect, set, + DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT); + // That should put the display items in set.Content() } // Put the foreground outline and focus rects on top of the children set.Content()->AppendToTop(&onTop); set.MoveTo(aLists); DisplayOutline(aBuilder, aLists);
--- a/layout/generic/TextOverflow.cpp +++ b/layout/generic/TextOverflow.cpp @@ -97,35 +97,33 @@ IsHorizontalOverflowVisible(nsIFrame* aF while (f && f->StyleContext()->GetPseudo() && f->GetType() != nsGkAtoms::scrollFrame) { f = f->GetParent(); } return !f || f->StyleDisplay()->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE; } static void -ClipMarker(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, - const nsRect& aContentArea, - const nsRect& aMarkerRect, - DisplayItemClip& aClipOnStack) +ClipMarker(const nsRect& aContentArea, + const nsRect& aMarkerRect, + DisplayListClipState::AutoSaveRestore& aClipState) { nscoord rightOverflow = aMarkerRect.XMost() - aContentArea.XMost(); nsRect markerRect = aMarkerRect; if (rightOverflow > 0) { // Marker overflows on the right side (content width < marker width). markerRect.width -= rightOverflow; - aBuilder->ClipState().ClipContentDescendants(markerRect, aClipOnStack); + aClipState.ClipContentDescendants(markerRect); } else { nscoord leftOverflow = aContentArea.x - aMarkerRect.x; if (leftOverflow > 0) { // Marker overflows on the left side markerRect.width -= leftOverflow; markerRect.x += leftOverflow; - aBuilder->ClipState().ClipContentDescendants(markerRect, aClipOnStack); + aClipState.ClipContentDescendants(markerRect); } } } static void InflateLeft(nsRect* aRect, nscoord aDelta) { nscoord xmost = aRect->XMost(); @@ -703,43 +701,39 @@ TextOverflow::CanHaveTextOverflow(nsDisp void TextOverflow::CreateMarkers(const nsLineBox* aLine, bool aCreateLeft, bool aCreateRight, const nsRect& aInsideMarkersArea) { if (aCreateLeft) { - DisplayListClipState::AutoSaveRestore saveClip(mBuilder->ClipState()); + DisplayListClipState::AutoSaveRestore clipState(mBuilder); nsRect markerRect = nsRect(aInsideMarkersArea.x - mLeft.mIntrinsicWidth, aLine->mBounds.y, mLeft.mIntrinsicWidth, aLine->mBounds.height); markerRect += mBuilder->ToReferenceFrame(mBlock); - DisplayItemClip clipOnStack; - ClipMarker(mBuilder, mBlock, - mContentArea + mBuilder->ToReferenceFrame(mBlock), - markerRect, clipOnStack); + ClipMarker(mContentArea + mBuilder->ToReferenceFrame(mBlock), + markerRect, clipState); nsDisplayItem* marker = new (mBuilder) nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect, aLine->GetAscent(), mLeft.mStyle, 0); mMarkerList.AppendNewToTop(marker); } if (aCreateRight) { - DisplayListClipState::AutoSaveRestore saveClip(mBuilder->ClipState()); + DisplayListClipState::AutoSaveRestore clipState(mBuilder); nsRect markerRect = nsRect(aInsideMarkersArea.XMost(), aLine->mBounds.y, mRight.mIntrinsicWidth, aLine->mBounds.height); markerRect += mBuilder->ToReferenceFrame(mBlock); - DisplayItemClip clipOnStack; - ClipMarker(mBuilder, mBlock, - mContentArea + mBuilder->ToReferenceFrame(mBlock), - markerRect, clipOnStack); + ClipMarker(mContentArea + mBuilder->ToReferenceFrame(mBlock), + markerRect, clipState); nsDisplayItem* marker = new (mBuilder) nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect, aLine->GetAscent(), mRight.mStyle, 1); mMarkerList.AppendNewToTop(marker); } } void
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1576,52 +1576,52 @@ nsIFrame::GetClipPropClipRect(const nsSt * 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, - nsRect* aRect, DisplayItemClip& aClipOnStack) + nsRect* aRect, + DisplayListClipState::AutoSaveRestore& aClipState) { if (!aFrame->GetClipPropClipRect(aDisp, aRect, aFrame->GetSize())) return false; nsRect clipRect = *aRect + aBuilder->ToReferenceFrame(aFrame); - aBuilder->ClipState().ClipContentDescendants(clipRect, aClipOnStack); + aClipState.ClipContentDescendants(clipRect); return true; } /** * 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. */ static void ApplyOverflowClipping(nsDisplayListBuilder* aBuilder, const nsIFrame* aFrame, const nsStyleDisplay* aDisp, - DisplayItemClip& aClipOnStack) + DisplayListClipState::AutoClipMultiple& aClipState) { // Only -moz-hidden-unscrollable is handled here (and 'hidden' for table // frames, and any non-visible value for blocks in a paginated context). // We allow -moz-hidden-unscrollable to apply to any kind of frame. This // is required by comboboxes which make their display text (an inline frame) // have clipping. if (!nsFrame::ShouldApplyOverflowClipping(aFrame, aDisp)) { return; } nsRect rect = aFrame->GetPaddingRectRelativeToSelf() + aBuilder->ToReferenceFrame(aFrame); nscoord radii[8]; bool haveRadii = aFrame->GetPaddingBoxBorderRadii(radii); - aBuilder->ClipState().ClipContainingBlockDescendants(rect, - haveRadii ? radii : nullptr, aClipOnStack); + aClipState.ClipContainingBlockDescendantsExtra(rect, haveRadii ? radii : nullptr); } #ifdef DEBUG static void PaintDebugBorder(nsIFrame* aFrame, nsRenderingContext* aCtx, const nsRect& aDirtyRect, nsPoint aPt) { nsRect r(aPt, aFrame->GetSize()); if (aFrame->HasView()) { aCtx->SetColor(NS_RGB(0,0,255)); @@ -1797,43 +1797,42 @@ nsIFrame::BuildDisplayListForStackingCon } } inTransform = true; } bool useOpacity = HasOpacity() && !nsSVGUtils::CanOptimizeOpacity(this); bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this); - DisplayListClipState::AutoSaveRestore saveClipState(aBuilder->ClipState()); + DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (isTransformed || useOpacity || usingSVGEffects) { // We don't need to pass ancestor clipping down to our children; // everything goes inside a display item's child list, and the display // item itself will be clipped. // For transforms we also need to clear ancestor clipping because it's // relative to the wrong display item reference frame anyway. - aBuilder->ClipState().Clear(); + clipState.Clear(); } nsDisplayListCollection set; { nsDisplayListBuilder::AutoBuildingDisplayList rootSetter(aBuilder, true); - DisplayListClipState::AutoSaveRestore clipState(aBuilder->ClipState()); + DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder); nsDisplayListBuilder::AutoInTransformSetter inTransformSetter(aBuilder, inTransform); if (usingSVGEffects) { dirtyRect = nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect); } nsRect clipPropClip; - DisplayItemClip clipPropClipOnStack; if (ApplyClipPropClipping(aBuilder, this, disp, &clipPropClip, - clipPropClipOnStack)) { + nestedClipState)) { dirtyRect.IntersectRect(dirtyRect, clipPropClip); } MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect); // Preserve3DChildren() 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 (Preserves3DChildren()) { @@ -1894,17 +1893,17 @@ nsIFrame::BuildDisplayListForStackingCon #endif resultList.AppendToTop(set.Outlines()); // 8, 9: non-negative z-index children resultList.AppendToTop(set.PositionedDescendants()); if (!isTransformed) { // Restore saved clip state now so that any display items we create below // are clipped properly. - saveClipState.Restore(); + clipState.Restore(); } /* If there are any SVG effects, wrap the list up in an SVG effects item * (which also handles CSS group opacity). Note that we create an SVG effects * item even if resultList is empty, since a filter can produce graphical * output even if the element being filtered wouldn't otherwise do so. */ if (usingSVGEffects) { @@ -1928,17 +1927,17 @@ nsIFrame::BuildDisplayListForStackingCon * a separate nsDisplayTransform instead. When the child is already an nsDisplayTransform, * we can skip this step, as the computed transform will already include our own. * * We also traverse into sublists created by nsDisplayWrapList or nsDisplayOpacity, so that * we find all the correct children. */ if (isTransformed && !resultList.IsEmpty()) { // Restore clip state now so nsDisplayTransform is clipped properly. - saveClipState.Restore(); + clipState.Restore(); if (Preserves3DChildren()) { WrapPreserve3DList(this, aBuilder, &resultList); } else { resultList.AppendNewToTop( new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList)); } } @@ -2109,50 +2108,47 @@ nsIFrame::BuildDisplayListForChild(nsDis // Don't build an nsDisplayFixedPosition if our root scroll frame is not // active, that's pointless and the extra layer(s) created may be wasteful. bool buildFixedPositionItem = disp->mPosition == NS_STYLE_POSITION_FIXED && !child->GetParent()->GetParent() && !aBuilder->IsInFixedPosition() && IsRootScrollFrameActive(PresContext()->PresShell()) && !isSVG; nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(aBuilder, child, pseudoStackingContext, buildFixedPositionItem); - DisplayListClipState::AutoSaveRestore clipState(aBuilder->ClipState()); + DisplayListClipState::AutoClipMultiple clipState(aBuilder); if (savedOutOfFlowData) { clipState.SetClipForContainingBlockDescendants( savedOutOfFlowData->mContainingBlockClip); } // Setup clipping for the parent's overflow:-moz-hidden-unscrollable, // or overflow:hidden on elements that don't support scrolling (and therefore // don't create nsHTML/XULScrollFrame). This clipping needs to not clip // anything directly rendered by the parent, only the rendering of its // children. // Don't use overflowClip to restrict the dirty rect, since some of the // descendants may not be clipped by it. Even if we end up with unnecessary // display items, they'll be pruned during ComputeVisibility. - DisplayItemClip overflowClipOnStack; nsIFrame* parent = child->GetParent(); const nsStyleDisplay* parentDisp = parent == this ? ourDisp : parent->StyleDisplay(); - ApplyOverflowClipping(aBuilder, parent, parentDisp, overflowClipOnStack); + ApplyOverflowClipping(aBuilder, parent, parentDisp, clipState); nsDisplayList list; nsDisplayList extraPositionedDescendants; if (isStackingContext) { // True stacking context. // For stacking contexts, BuildDisplayListForStackingContext handles // clipping and MarkAbsoluteFramesForDisplayList. child->BuildDisplayListForStackingContext(aBuilder, dirty, &list); aBuilder->DisplayCaret(child, dirty, &list); } else { nsRect clipRect; - DisplayItemClip clipPropClipOnStack; - if (ApplyClipPropClipping(aBuilder, child, disp, &clipRect, - clipPropClipOnStack)) { + if (ApplyClipPropClipping(aBuilder, child, disp, &clipRect, clipState)) { // clipRect is in builder-reference-frame coordinates, // dirty/clippedDirtyRect are in child coordinates dirty.IntersectRect(dirty, clipRect); } child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty); if (!pseudoStackingContext) { @@ -2183,17 +2179,17 @@ nsIFrame::BuildDisplayListForChild(nsDis extraPositionedDescendants.AppendToTop(pseudoStack.PositionedDescendants()); #ifdef DEBUG DisplayDebugBorders(aBuilder, child, aLists); #endif } // Clear clip rect for the construction of the items below. Since we're // clipping all their contents, they themselves don't need to be clipped. - aBuilder->ClipState().Clear(); + clipState.Clear(); if (isPositioned || isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) { // Genuine stacking contexts, and positioned pseudo-stacking-contexts, // go in this level. if (!list.IsEmpty()) { // Make sure the root of a fixed position frame sub-tree gets the // correct displaylist item type.
--- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -2123,42 +2123,40 @@ nsGfxScrollFrameInner::BuildDisplayList( nsPoint horzShift = nsPoint(sHorzExpandScrollPort * dirtyRectBefore.width, 0); dirtyRect = dirtyRect.Union(dirtyRectBefore - horzShift); dirtyRect = dirtyRect.Union(dirtyRectBefore + horzShift); } nsDisplayListCollection set; { - DisplayListClipState::AutoSaveRestore saveClipState(aBuilder->ClipState()); - DisplayItemClip clipOnStack; + DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (usingDisplayport) { nsRect clip = displayPort + aBuilder->ToReferenceFrame(mOuter); if (mIsRoot) { - aBuilder->ClipState().ClipContentDescendants(clip, clipOnStack); + clipState.ClipContentDescendants(clip); } else { - aBuilder->ClipState().ClipContainingBlockDescendants(clip, nullptr, clipOnStack); + clipState.ClipContainingBlockDescendants(clip, nullptr); } } else { nsRect clip = mScrollPort + aBuilder->ToReferenceFrame(mOuter); // Our override of GetBorderRadii ensures we never have a radius at // the corners where we have a scrollbar. if (mIsRoot) { #ifdef DEBUG nscoord radii[8]; #endif NS_ASSERTION(!mOuter->GetPaddingBoxBorderRadii(radii), "Roots with radii not supported"); - aBuilder->ClipState().ClipContentDescendants(clip, clipOnStack); + clipState.ClipContentDescendants(clip); } else { nscoord radii[8]; bool haveRadii = mOuter->GetPaddingBoxBorderRadii(radii); - aBuilder->ClipState().ClipContainingBlockDescendants(clip, - haveRadii ? radii : nullptr, clipOnStack); + clipState.ClipContainingBlockDescendants(clip, haveRadii ? radii : nullptr); } } mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, aLists); } // Since making new layers is expensive, only use nsDisplayScrollLayer // if the area is scrollable and we're the content process.
--- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -513,23 +513,22 @@ nsPageFrame::BuildDisplayList(nsDisplayL clipRect.height = expectedPageContentHeight; NS_ASSERTION(clipRect.y < child->GetSize().height, "Should be clipping to region inside the page content bounds"); } clipRect += aBuilder->ToReferenceFrame(child); nsDisplayList content; { - DisplayListClipState::AutoSaveRestore saveClip(aBuilder->ClipState()); + DisplayListClipState::AutoSaveRestore clipState(aBuilder); - DisplayItemClip clipOnStack; // Overwrite current clip, since we're going to wrap in a transform // and the current clip is no longer meaningful. - aBuilder->ClipState().Clear(); - aBuilder->ClipState().ClipContainingBlockDescendants(clipRect, nullptr, clipOnStack); + clipState.Clear(); + clipState.ClipContainingBlockDescendants(clipRect, nullptr); child->BuildDisplayListForStackingContext(aBuilder, child->GetVisualOverflowRectRelativeToSelf(), &content); // We may need to paint out-of-flow frames whose placeholders are // on other pages. Add those pages to our display list. Note that // out-of-flow frames can't be placed after their placeholders so // we don't have to process earlier pages. The display lists for
--- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -378,38 +378,36 @@ nsSubDocumentFrame::BuildDisplayList(nsD dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame); // and convert into the appunits of the subdoc dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD); } aBuilder->EnterPresShell(subdocRootFrame, dirty); } - DisplayListClipState::AutoSaveRestore saveClip(aBuilder->ClipState()); - DisplayItemClip clipOnStack; + DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (ShouldClipSubdocument()) { - aBuilder->ClipState().ClipContainingBlockDescendantsToContentBox(aBuilder, this, - clipOnStack); + clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this); } nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable(); bool constructZoomItem = subdocRootFrame && parentAPD != subdocAPD; bool needsOwnLayer = constructZoomItem || presContext->IsRootContentDocument() || (sf && sf->IsScrollingActive()); nsDisplayList childItems; { - DisplayListClipState::AutoSaveRestore willClearClip(aBuilder->ClipState()); + DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder); if (needsOwnLayer) { // Clear current clip. There's no point in propagating it down, since // the layer we will construct will be clipped by the current clip. // In fact for nsDisplayZoom propagating it down would be incorrect since // nsDisplayZoom changes the meaning of appunits. - aBuilder->ClipState().Clear(); + nestedClipState.Clear(); } if (subdocRootFrame) { subdocRootFrame-> BuildDisplayListForStackingContext(aBuilder, dirty, &childItems); } if (!aBuilder->IsForEventDelivery()) {
--- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -943,22 +943,21 @@ RenderFrameParent::GetRootLayer() const void RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { // We're the subdoc for <browser remote="true"> and it has // painted content. Display its shadow layer tree. - DisplayListClipState::AutoSaveRestore saveClip(aBuilder->ClipState()); + DisplayListClipState::AutoSaveRestore clipState(aBuilder); nsPoint offset = aBuilder->ToReferenceFrame(aFrame); nsRect bounds = aFrame->EnsureInnerView()->GetBounds() + offset; - DisplayItemClip clipOnStack; - aBuilder->ClipState().ClipContentDescendants(bounds, clipOnStack); + clipState.ClipContentDescendants(bounds); ContainerLayer* container = GetRootLayer(); if (aBuilder->IsForEventDelivery() && container) { ViewTransform offset = ViewTransform(GetContentRectLayerOffset(aFrame, aBuilder), 1, 1); BuildListForLayer(container, mFrameLoader, offset, aBuilder, *aLists.Content(), aFrame); } else {