Bug 848973 - Make nsStyleDisplay::IsBlockInside() and friends work only on style structs for the passed in frame and document them. r=roc
authorCameron McCormack <cam@mcc.id.au>
Sun, 07 Apr 2013 09:40:07 +1000
changeset 134917 9cb8ac3f27a2a297248314c46e4d26c7f944c367
parent 134916 56ceb60c5d0b40792a0c79d94c9b75d1d58f5e8c
child 134918 3fd383ca51c812e99a2c8c1fdf692a57d9d336a4
push id3752
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 17:21:10 +0000
treeherdermozilla-aurora@1580544aef0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs848973
milestone23.0a1
Bug 848973 - Make nsStyleDisplay::IsBlockInside() and friends work only on style structs for the passed in frame and document them. r=roc
layout/base/nsCSSFrameConstructor.cpp
layout/generic/nsFrame.cpp
layout/style/nsStyleStruct.h
layout/style/nsStyleStructInlines.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1950,17 +1950,21 @@ nsCSSFrameConstructor::ConstructTable(ns
   nsFrameItems childItems;
 
   // Process children
   nsFrameConstructorSaveState absoluteSaveState;
   const nsStyleDisplay* display = outerStyleContext->StyleDisplay();
 
   // Mark the table frame as an absolute container if needed
   newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
-  if (display->IsPositioned(aParentFrame)) {
+  if ((display->IsRelativelyPositionedStyle() ||
+       display->IsAbsolutelyPositionedStyle() ||
+       (display->HasTransformStyle() &&
+        aParentFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms))) &&
+      !aParentFrame->IsSVGText()) {
     aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
   }
   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
     ConstructFramesFromItemList(aState, aItem.mChildItems,
                                 innerFrame, childItems);
   } else {
     ProcessChildren(aState, content, styleContext, innerFrame,
                     true, childItems, false, aItem.mPendingBinding);
@@ -3562,17 +3566,16 @@ nsCSSFrameConstructor::ConstructFrameFro
     // Use frameToAddToList as the primary frame.  In the non-scrollframe case
     // they're equal, but in the scrollframe case newFrame is the scrolled
     // frame, while frameToAddToList is the scrollframe (and should be the
     // primary frame).
     primaryFrame = frameToAddToList;
 
     // If we need to create a block formatting context to wrap our
     // kids, do it now.
-    const nsStyleDisplay* maybeAbsoluteContainingBlockDisplay = display;
     nsIFrame* maybeAbsoluteContainingBlock = newFrame;
     nsIFrame* possiblyLeafFrame = newFrame;
     if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS) {
       nsRefPtr<nsStyleContext> blockContext;
       blockContext =
         mPresShell->StyleSet()->ResolveAnonymousBoxStyle(*data->mAnonBoxPseudo,
                                                          styleContext);
       nsIFrame* blockFrame =
@@ -3582,17 +3585,16 @@ nsCSSFrameConstructor::ConstructFrameFro
 
       SetInitialSingleChild(newFrame, blockFrame);
 
       // Now figure out whether newFrame or blockFrame should be the
       // absolute container.  It should be the latter if it's
       // positioned, otherwise the former.
       const nsStyleDisplay* blockDisplay = blockContext->StyleDisplay();
       if (blockDisplay->IsPositioned(blockFrame)) {
-        maybeAbsoluteContainingBlockDisplay = blockDisplay;
         maybeAbsoluteContainingBlock = blockFrame;
       }
       
       // Our kids should go into the blockFrame
       newFrame = blockFrame;
     }
 
     aState.AddChild(frameToAddToList, aFrameItems, content, styleContext,
@@ -3615,17 +3617,17 @@ nsCSSFrameConstructor::ConstructFrameFro
     nsFrameItems childItems;
     nsFrameConstructorSaveState absoluteSaveState;
 
     if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) {
       aState.PushAbsoluteContainingBlock(nullptr, absoluteSaveState);
     } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH)) {
       nsIFrame* cb = maybeAbsoluteContainingBlock;
       cb->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
-      if (maybeAbsoluteContainingBlockDisplay->IsPositioned(cb)) {
+      if (cb->IsPositioned()) {
         aState.PushAbsoluteContainingBlock(cb, absoluteSaveState);
       }
     }
 
     if (bits & FCDATA_USE_CHILD_ITEMS) {
       NS_ASSERTION(!ShouldSuppressFloatingOfDescendants(newFrame),
                    "uh oh -- this frame is supposed to _suppress_ floats, but "
                    "we're about to push it as a float containing block...");
@@ -4233,18 +4235,17 @@ nsCSSFrameConstructor::FindDisplayData(c
                !mPresShell->GetPresContext()->IsPaginated(),
                "Shouldn't propagate scroll in paginated contexts");
 
   // If the frame is a block-level frame and is scrollable, then wrap it in a
   // scroll frame.
   // XXX Ignore tables for the time being
   // XXXbz it would be nice to combine this with the other block
   // case... Think about how do do this?
-  if ((aParentFrame ? aDisplay->IsBlockInside(aParentFrame) :
-                      aDisplay->IsBlockInsideStyle()) &&
+  if (aDisplay->IsBlockInsideStyle() &&
       aDisplay->IsScrollableOverflow() &&
       !propagatedScrollToViewport) {
     // Except we don't want to do that for paginated contexts for
     // frames that are block-outside and aren't frames for native
     // anonymous stuff.
     if (mPresShell->GetPresContext()->IsPaginated() &&
         aDisplay->IsBlockOutsideStyle() &&
         !aElement->IsInNativeAnonymousSubtree()) {
@@ -4255,18 +4256,17 @@ nsCSSFrameConstructor::FindDisplayData(c
     }
 
     static const FrameConstructionData sScrollableBlockData =
       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructScrollableBlock);
     return &sScrollableBlockData;
   }
 
   // Handle various non-scrollable blocks
-  if ((aParentFrame ? aDisplay->IsBlockInside(aParentFrame) :
-                      aDisplay->IsBlockInsideStyle())) {
+  if (aDisplay->IsBlockInsideStyle()) {
     static const FrameConstructionData sNonScrollableBlockData =
       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructNonScrollableBlock);
     return &sNonScrollableBlockData;
   }
 
   static const FrameConstructionDataByInt sDisplayData[] = {
     // To keep the hash table small don't add inline frames (they're
     // typically things like FONT and B), because we can quickly
@@ -4322,18 +4322,17 @@ nsCSSFrameConstructor::FindDisplayData(c
                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
                        &nsCSSFrameConstructor::ConstructTableRow) },
     { NS_STYLE_DISPLAY_TABLE_CELL,
       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
                        &nsCSSFrameConstructor::ConstructTableCell) }
   };
 
-  return FindDataByInt((aParentFrame ? aDisplay->GetDisplay(aParentFrame) :
-                                       aDisplay->mDisplay),
+  return FindDataByInt(aDisplay->mDisplay,
                        aElement, aStyleContext, sDisplayData,
                        ArrayLength(sDisplayData));
 }
 
 nsIFrame*
 nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
                                                 FrameConstructionItem&   aItem,
                                                 nsIFrame*                aParentFrame,
@@ -5285,18 +5284,17 @@ nsCSSFrameConstructor::AddFrameConstruct
     bool isInline =
       // Table-internal things are inline-outside if and only if they're kids of
       // inlines, since they'll trigger construction of inline-table
       // pseudos.
       ((bits & FCDATA_IS_TABLE_PART) &&
        (!aParentFrame || // No aParentFrame means inline
         aParentFrame->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE)) ||
       // Things that are inline-outside but aren't inline frames are inline
-      (aParentFrame ? display->IsInlineOutside(aParentFrame) :
-                      display->IsInlineOutsideStyle()) ||
+      display->IsInlineOutsideStyle() ||
       // Popups that are certainly out of flow.
       isPopup;
 
     // Set mIsAllInline conservatively.  It just might be that even an inline
     // that has mIsAllInline false doesn't need an {ib} split.  So this is just
     // an optimization to keep from doing too much work in cases when we can
     // show that mIsAllInline is true..
     item->mIsAllInline = item->mHasInlineEnds = isInline ||
@@ -10446,17 +10444,17 @@ nsCSSFrameConstructor::CreateLetterFrame
                  "Containing block is confused");
     nsFrameConstructorState state(mPresShell,
                                   GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
                                   GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
                                   aBlockContinuation);
 
     // Create the right type of first-letter frame
     const nsStyleDisplay* display = sc->StyleDisplay();
-    if (display->IsFloating(aParentFrame)) {
+    if (display->IsFloatingStyle() && !aParentFrame->IsSVGText()) {
       // Make a floating first-letter frame
       CreateFloatingLetterFrame(state, aBlockFrame, aTextContent, textFrame,
                                 blockContent, aParentFrame, sc, aResult);
     }
     else {
       // Make an inflow first-letter frame
       nsIFrame* letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2087,17 +2087,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
   // Child is composited if it's transformed, partially transparent, or has
   // SVG effects.
   const nsStyleDisplay* disp = child->StyleDisplay();
   const nsStylePosition* pos = child->StylePosition();
   bool isVisuallyAtomic = child->HasOpacity()
     || child->IsTransformed()
     || nsSVGIntegrationUtils::UsingEffectsForFrame(child);
 
-  bool isPositioned = !isSVG && disp->IsPositioned(child);
+  bool isPositioned = disp->IsPositioned(child);
   bool isStackingContext =
     (isPositioned && pos->mZIndex.GetUnit() == eStyleUnit_Integer) ||
      isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
 
   if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating(child)) ||
       ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
        IsSVGContentWithCSSClip(child)) ||
       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1328,20 +1328,25 @@ struct nsStyleText {
   }
 
   bool WordCanWrapStyle() const {
     return WhiteSpaceCanWrapStyle() &&
            mWordWrap == NS_STYLE_WORDWRAP_BREAK_WORD;
   }
 
   // These are defined in nsStyleStructInlines.h.
-  inline bool HasTextShadow(const nsIFrame* aFrame) const;
-  inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aFrame) const;
-  inline bool WhiteSpaceCanWrap(const nsIFrame* aFrame) const;
-  inline bool WordCanWrap(const nsIFrame* aFrame) const;
+
+  // The aContextFrame argument on each of these is the frame this
+  // style struct is for.  If the frame is for SVG text, the return
+  // value will be massaged to be something that makes sense for
+  // SVG text.
+  inline bool HasTextShadow(const nsIFrame* aContextFrame) const;
+  inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aContextFrame) const;
+  inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
+  inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
 };
 
 struct nsStyleVisibility {
   nsStyleVisibility(nsPresContext* aPresContext);
   nsStyleVisibility(const nsStyleVisibility& aVisibility);
   ~nsStyleVisibility() {
     MOZ_COUNT_DTOR(nsStyleVisibility);
   }
@@ -1681,28 +1686,34 @@ struct nsStyleDisplay {
    * or a related property. */
   bool HasTransformStyle() const {
     return mSpecifiedTransform != nullptr || 
            mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
            mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
   }
 
   // These are defined in nsStyleStructInlines.h.
-  inline bool IsBlockInside(const nsIFrame* aFrame) const;
-  inline bool IsBlockOutside(const nsIFrame* aFrame) const;
-  inline bool IsInlineOutside(const nsIFrame* aFrame) const;
-  inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aFrame) const;
-  inline uint8_t GetDisplay(const nsIFrame* aFrame) const;
-  inline bool IsFloating(const nsIFrame* aFrame) const;
-  inline bool IsPositioned(const nsIFrame* aFrame) const;
-  inline bool IsRelativelyPositioned(const nsIFrame* aFrame) const;
-  inline bool IsAbsolutelyPositioned(const nsIFrame* aFrame) const;
+
+  // The aContextFrame argument on each of these is the frame this
+  // style struct is for.  If the frame is for SVG text, the return
+  // value will be massaged to be something that makes sense for
+  // SVG text.
+  inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
+  inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
+  inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
+  inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
+  inline uint8_t GetDisplay(const nsIFrame* aContextFrame) const;
+  inline bool IsFloating(const nsIFrame* aContextFrame) const;
+  inline bool IsPositioned(const nsIFrame* aContextFrame) const;
+  inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
+  inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
+
   /* Returns whether the element has the -moz-transform property
    * or a related property, and supports CSS transforms. */
-  inline bool HasTransform(const nsIFrame* aFrame) const;
+  inline bool HasTransform(const nsIFrame* aContextFrame) const;
 };
 
 struct nsStyleTable {
   nsStyleTable(void);
   nsStyleTable(const nsStyleTable& aOther);
   ~nsStyleTable(void);
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
--- a/layout/style/nsStyleStructInlines.h
+++ b/layout/style/nsStyleStructInlines.h
@@ -51,121 +51,136 @@ nsStyleBorder::GetSubImage(uint8_t aInde
 {
   imgIContainer* subImage = nullptr;
   if (aIndex < mSubImages.Count())
     subImage = mSubImages[aIndex];
   return subImage;
 }
 
 bool
-nsStyleText::HasTextShadow(const nsIFrame* aFrame) const
+nsStyleText::HasTextShadow(const nsIFrame* aContextFrame) const
 {
-  return mTextShadow && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  return mTextShadow && !aContextFrame->IsSVGText();
 }
 
 nsCSSShadowArray*
-nsStyleText::GetTextShadow(const nsIFrame* aFrame) const
+nsStyleText::GetTextShadow(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
     return nullptr;
   }
   return mTextShadow;
 }
 
 bool
-nsStyleText::WhiteSpaceCanWrap(const nsIFrame* aFrame) const
+nsStyleText::WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const
 {
-  return WhiteSpaceCanWrapStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  return WhiteSpaceCanWrapStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleText::WordCanWrap(const nsIFrame* aFrame) const
+nsStyleText::WordCanWrap(const nsIFrame* aContextFrame) const
 {
-  return WordCanWrapStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  return WordCanWrapStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsBlockInside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsBlockInside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() == nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
   }
   return IsBlockInsideStyle();
 }
 
 bool
-nsStyleDisplay::IsBlockOutside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsBlockOutside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() == nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
   }
   return IsBlockOutsideStyle();
 }
 
 bool
-nsStyleDisplay::IsInlineOutside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsInlineOutside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() != nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
   }
   return IsInlineOutsideStyle();
 }
 
 bool
-nsStyleDisplay::IsOriginalDisplayInlineOutside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() != nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
   }
   return IsOriginalDisplayInlineOutsideStyle();
 }
 
 uint8_t
-nsStyleDisplay::GetDisplay(const nsIFrame* aFrame) const
+nsStyleDisplay::GetDisplay(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText() &&
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText() &&
       mDisplay != NS_STYLE_DISPLAY_NONE) {
-    return aFrame->GetType() == nsGkAtoms::blockFrame ?
+    return aContextFrame->GetType() == nsGkAtoms::blockFrame ?
              NS_STYLE_DISPLAY_BLOCK :
              NS_STYLE_DISPLAY_INLINE;
   }
   return mDisplay;
 }
 
 bool
-nsStyleDisplay::IsFloating(const nsIFrame* aFrame) const
+nsStyleDisplay::IsFloating(const nsIFrame* aContextFrame) const
 {
-  return IsFloatingStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return IsFloatingStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::HasTransform(const nsIFrame* aFrame) const
+nsStyleDisplay::HasTransform(const nsIFrame* aContextFrame) const
 {
-  return HasTransformStyle() && aFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return HasTransformStyle() && aContextFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
 }
 
 bool
-nsStyleDisplay::IsPositioned(const nsIFrame* aFrame) const
+nsStyleDisplay::IsPositioned(const nsIFrame* aContextFrame) const
 {
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this,
+               "unexpected aContextFrame");
   return (IsAbsolutelyPositionedStyle() ||
           IsRelativelyPositionedStyle() ||
-          HasTransform(aFrame)) &&
-         !aFrame->IsSVGText();
+          HasTransform(aContextFrame)) &&
+         !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsRelativelyPositioned(const nsIFrame* aFrame) const
+nsStyleDisplay::IsRelativelyPositioned(const nsIFrame* aContextFrame) const
 {
-  return IsRelativelyPositionedStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return IsRelativelyPositionedStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsAbsolutelyPositioned(const nsIFrame* aFrame) const
+nsStyleDisplay::IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const
 {
-  return IsAbsolutelyPositionedStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return IsAbsolutelyPositionedStyle() && !aContextFrame->IsSVGText();
 }
 
 uint8_t
 nsStyleVisibility::GetEffectivePointerEvents(nsIFrame* aFrame) const
 {
   if (aFrame->GetContent() && !aFrame->GetContent()->GetParent()) {
     // The root element has a cluster of frames associated with it
     // (root scroll frame, canvas frame, the actual primary frame). Make