Bug 731959 - Display list support for the 'clip' property in SVG means referring to "AbsPos" clip is misleading. r=bz.
authorJonathan Watt <jwatt@jwatt.org>
Fri, 02 Mar 2012 08:28:56 +0000
changeset 88340 15649efe7dd6f50fb906b87d56bb7c93cbde358e
parent 88337 21ce98516c3a1215af4931521a4a7b52bf2e1261
child 88341 412c948ce10019d15cde747af6db85a91d131d77
push id157
push userMs2ger@gmail.com
push dateWed, 07 Mar 2012 19:27:10 +0000
reviewersbz
bugs731959
milestone13.0a1
Bug 731959 - Display list support for the 'clip' property in SVG means referring to "AbsPos" clip is misleading. r=bz.
layout/generic/nsBlockFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -520,22 +520,22 @@ nsBlockFrame::InvalidateInternal(const n
                                  PRUint32 aFlags)
 {
   // Optimize by suppressing invalidation of areas that are clipped out
   // with CSS 'clip'. Don't suppress invalidation of *this* frame directly,
   // because when 'clip' shrinks we need to invalidate this frame and
   // be able to invalidate areas outside the 'clip'.
   if (aForChild) {
     const nsStyleDisplay* disp = GetStyleDisplay();
-    nsRect absPosClipRect;
-    if (GetAbsPosClipRect(disp, &absPosClipRect, GetSize())) {
+    nsRect clipRect;
+    if (GetClipPropClipRect(disp, &clipRect, GetSize())) {
       // Restrict the invalidated area to abs-pos clip rect
       // abs-pos clipping clips everything in the frame
       nsRect r;
-      if (r.IntersectRect(aDamageRect, absPosClipRect - nsPoint(aX, aY))) {
+      if (r.IntersectRect(aDamageRect, clipRect - nsPoint(aX, aY))) {
         nsBlockFrameSuper::InvalidateInternal(r, aX, aY, this, aFlags);
       }
       return;
     }
   }
 
   nsBlockFrameSuper::InvalidateInternal(aDamageRect, aX, aY, this, aFlags);
 }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -347,17 +347,17 @@ nsIFrame::IsVisibleConsideringAncestors(
   return true;
 }
 
 static bool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
                                     const nsIFrame* aFrame,
                                     const nsStyleDisplay* aDisp, 
                                     nsRect* aRect);
 
-static bool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
+static bool ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
                                   const nsStyleDisplay* aDisp, 
                                   const nsIFrame* aFrame,
                                   nsRect* aRect);
 
 void
 NS_MergeReflowStatusInto(nsReflowStatus* aPrimary, nsReflowStatus aSecondary)
 {
   *aPrimary |= aSecondary &
@@ -957,17 +957,17 @@ nsIFrame::Preserves3DChildren() const
       return false;
 
   // If we're all scroll frame, then all descendants will be clipped, so we can't preserve 3d.
   if (GetType() == nsGkAtoms::scrollFrame)
       return false;
 
   nsRect temp;
   return (!ApplyOverflowClipping(nsnull, this, GetStyleDisplay(), &temp) &&
-      !ApplyAbsPosClipping(nsnull, GetStyleDisplay(), this, &temp) &&
+      !ApplyClipPropClipping(nsnull, GetStyleDisplay(), this, &temp) &&
       !nsSVGIntegrationUtils::UsingEffectsForFrame(this));
 }
 
 bool
 nsIFrame::Preserves3D() const
 {
   if (!GetParent() || !GetParent()->Preserves3DChildren() || !IsTransformed()) {
     return false;
@@ -1443,18 +1443,18 @@ nsFrame::DisplayBorderBackgroundOutline(
         nsDisplayBorder(aBuilder, this));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return DisplayOutlineUnconditional(aBuilder, aLists);
 }
 
 bool
-nsIFrame::GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
-                            const nsSize& aSize) const
+nsIFrame::GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
+                              const nsSize& aSize) const
 {
   NS_PRECONDITION(aRect, "Must have aRect out parameter");
 
   if (!aDisp->IsAbsolutelyPositioned() ||
       !(aDisp->mClipFlags & NS_STYLE_CLIP_RECT))
     return false;
 
   *aRect = aDisp->mClip;
@@ -1462,20 +1462,20 @@ nsIFrame::GetAbsPosClipRect(const nsStyl
     aRect->width = aSize.width - aRect->x;
   }
   if (NS_STYLE_CLIP_BOTTOM_AUTO & aDisp->mClipFlags) {
     aRect->height = aSize.height - aRect->y;
   }
   return true;
 }
 
-static bool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
+static bool ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
                                   const nsStyleDisplay* aDisp, const nsIFrame* aFrame,
                                   nsRect* aRect) {
-  if (!aFrame->GetAbsPosClipRect(aDisp, aRect, aFrame->GetSize()))
+  if (!aFrame->GetClipPropClipRect(aDisp, aRect, aFrame->GetSize()))
     return false;
 
   if (aBuilder) {
     *aRect += aBuilder->ToReferenceFrame(aFrame);
   }
   return true;
 }
 
@@ -1557,20 +1557,20 @@ protected:
   nsIFrame*    mContainer;
   nsRect       mRect;
   nscoord      mRadii[8];
   bool mClipBorderBackground;
   bool mClipAll;
   bool mHaveRadius;
 };
 
-class nsAbsPosClipWrapper : public nsDisplayWrapper
+class nsDisplayClipPropWrapper : public nsDisplayWrapper
 {
 public:
-  nsAbsPosClipWrapper(const nsRect& aRect)
+  nsDisplayClipPropWrapper(const nsRect& aRect)
     : mRect(aRect) {}
   virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
                                   nsIFrame* aFrame, nsDisplayList* aList) {
     // We are not a stacking context root. There is no valid underlying
     // frame for the whole list.
     return new (aBuilder) nsDisplayClip(aBuilder, nsnull, aList, mRect);
   }
   virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
@@ -1729,25 +1729,25 @@ nsIFrame::BuildDisplayListForStackingCon
   if (GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
     return NS_OK;
 
   // Replaced elements have their visibility handled here, because
   // they're visually atomic
   if (IsFrameOfType(eReplaced) && !IsVisibleForPainting(aBuilder))
     return NS_OK;
 
-  nsRect absPosClip;
+  nsRect clipPropClip;
   const nsStyleDisplay* disp = GetStyleDisplay();
   // We can stop right away if this is a zero-opacity stacking context and
   // we're painting.
   if (disp->mOpacity == 0.0 && aBuilder->IsForPainting())
     return NS_OK;
 
-  bool applyAbsPosClipping =
-      ApplyAbsPosClipping(aBuilder, disp, this, &absPosClip);
+  bool applyClipPropClipping =
+      ApplyClipPropClipping(aBuilder, disp, this, &clipPropClip);
   nsRect dirtyRect = aDirtyRect;
 
   bool inTransform = aBuilder->IsInTransform();
   if ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
       disp->HasTransform()) {
     if (nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this) ||
         Preserves3DChildren()) {
       dirtyRect = GetVisualOverflowRectRelativeToSelf();
@@ -1765,19 +1765,19 @@ nsIFrame::BuildDisplayListForStackingCon
       if (!nsDisplayTransform::UntransformRect(dirtyRect, this, nsPoint(0, 0), &dirtyRect)) {
         // we have a singular transform - just grab the entire overflow rect
         dirtyRect = GetVisualOverflowRectRelativeToSelf();
       }
     }
     inTransform = true;
   }
 
-  if (applyAbsPosClipping) {
+  if (applyClipPropClipping) {
     dirtyRect.IntersectRect(dirtyRect,
-                            absPosClip - aBuilder->ToReferenceFrame(this));
+                            clipPropClip - aBuilder->ToReferenceFrame(this));
   }
 
   bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
   if (usingSVGEffects) {
     dirtyRect =
       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
   }
 
@@ -1858,19 +1858,19 @@ nsIFrame::BuildDisplayListForStackingCon
 #endif
   resultList.AppendToTop(set.Outlines());
   // 8, 9: non-negative z-index children
   resultList.AppendToTop(set.PositionedDescendants());
 
   /* If we have absolute position clipping and we have, or will have, items to
    * be clipped, wrap the list in a clip wrapper.
    */
-  if (applyAbsPosClipping &&
+  if (applyClipPropClipping &&
       (!resultList.IsEmpty() || usingSVGEffects)) {
-    nsAbsPosClipWrapper wrapper(absPosClip);
+    nsDisplayClipPropWrapper wrapper(clipPropClip);
     nsDisplayItem* item = wrapper.WrapList(aBuilder, this, &resultList);
     if (!item)
       return NS_ERROR_OUT_OF_MEMORY;
     // resultList was emptied
     resultList.AppendToTop(item);
   }
 
   /* If there are any SVG effects, wrap the list up in an SVG effects item
@@ -2083,25 +2083,25 @@ nsIFrame::BuildDisplayListForChild(nsDis
       isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
     // True stacking context
     rv = child->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
     if (NS_SUCCEEDED(rv)) {
       rv = aBuilder->DisplayCaret(child, dirty, &list);
     }
   } else {
     nsRect clipRect;
-    bool applyAbsPosClipping =
-        ApplyAbsPosClipping(aBuilder, disp, child, &clipRect);
+    bool applyClipPropClipping =
+        ApplyClipPropClipping(aBuilder, disp, child, &clipRect);
     // A pseudo-stacking context (e.g., a positioned element with z-index auto).
     // We allow positioned descendants of the child to escape to our parent
     // stacking context's positioned descendant list, because they might be
     // z-index:non-auto
     nsDisplayListCollection pseudoStack;
     nsRect clippedDirtyRect = dirty;
-    if (applyAbsPosClipping) {
+    if (applyClipPropClipping) {
       // clipRect is in builder-reference-frame coordinates,
       // dirty/clippedDirtyRect are in child coordinates
       clippedDirtyRect.IntersectRect(clippedDirtyRect,
                                      clipRect - aBuilder->ToReferenceFrame(child));
     }
     
     if (applyOverflowClip) {
       rv = BuildDisplayListWithOverflowClip(aBuilder, child, clippedDirtyRect,
@@ -2110,18 +2110,18 @@ nsIFrame::BuildDisplayListForChild(nsDis
     } else {
       rv = child->BuildDisplayList(aBuilder, clippedDirtyRect, pseudoStack);
       if (NS_SUCCEEDED(rv)) {
         rv = aBuilder->DisplayCaret(child, dirty, pseudoStack.Content());
       }
     }
     
     if (NS_SUCCEEDED(rv)) {
-      if (applyAbsPosClipping) {
-        nsAbsPosClipWrapper wrapper(clipRect);
+      if (applyClipPropClipping) {
+        nsDisplayClipPropWrapper wrapper(clipRect);
         rv = wrapper.WrapListsInPlace(aBuilder, child, pseudoStack);
       }
     }
     list.AppendToTop(pseudoStack.BorderBackground());
     list.AppendToTop(pseudoStack.BlockBorderBackgrounds());
     list.AppendToTop(pseudoStack.Floats());
     list.AppendToTop(pseudoStack.Content());
     list.AppendToTop(pseudoStack.Outlines());
@@ -6733,23 +6733,23 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
   // Nothing in here should affect scrollable overflow.
   bool hasOutlineOrEffects;
   aOverflowAreas.VisualOverflow() =
     ComputeOutlineAndEffectsRect(this, &hasOutlineOrEffects,
                                  aOverflowAreas.VisualOverflow(), aNewSize,
                                  true);
 
   // Absolute position clipping
-  bool didHaveAbsPosClip = (GetStateBits() & NS_FRAME_HAS_CLIP) != 0;
-  nsRect absPosClipRect;
-  bool hasAbsPosClip = GetAbsPosClipRect(disp, &absPosClipRect, aNewSize);
-  if (hasAbsPosClip) {
+  bool didHaveClipPropClip = (GetStateBits() & NS_FRAME_HAS_CLIP) != 0;
+  nsRect clipPropClipRect;
+  bool hasClipPropClip = GetClipPropClipRect(disp, &clipPropClipRect, aNewSize);
+  if (hasClipPropClip) {
     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
       nsRect& o = aOverflowAreas.Overflow(otype);
-      o.IntersectRect(o, absPosClipRect);
+      o.IntersectRect(o, clipPropClipRect);
     }
     AddStateBits(NS_FRAME_HAS_CLIP);
   } else {
     RemoveStateBits(NS_FRAME_HAS_CLIP);
   }
 
   bool preTransformVisualOverflowChanged =
     !GetVisualOverflowRectRelativeToSelf().IsEqualInterior(aOverflowAreas.VisualOverflow());
@@ -6794,17 +6794,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
       // to nsChangeHint_RepaintFrame. Since the new overflow area is not
       // known at that time, we have to handle it here.
       // If the overflow area hasn't changed, then we don't have to do
       // anything here since repainting the old overflow area was enough.
       // If there is no outline or other effects now, then we don't have
       // to do anything here since removing those styles can't require
       // repainting of areas that weren't in the old overflow area.
       Invalidate(aOverflowAreas.VisualOverflow());
-    } else if (hasAbsPosClip || didHaveAbsPosClip) {
+    } else if (hasClipPropClip || didHaveClipPropClip) {
       // If we are (or were) clipped by the 'clip' property, and our
       // overflow area changes, it might be because the clipping changed.
       // The nsChangeHint_RepaintFrame for the style change will only
       // repaint the old overflow area, so if the overflow area has
       // changed (in particular, if it grows), we have to repaint the
       // new area here.
       Invalidate(aOverflowAreas.VisualOverflow());
     }
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2533,22 +2533,27 @@ NS_PTR_TO_INT32(frame->Properties().Get(
   /**
    * 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 is absolutely positioned and has a clip
-   * rect set via the 'clip' property. If true, then we also set aRect
-   * to the computed clip rect coordinates relative to this frame's origin.
-   * aRect must not be null!
+   * 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.
+   *
+   * 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!
    */
-  bool GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
+  bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
                            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