Handle styling updates for anonymous boxes via Stylo for column-span. draft
authorNeerja Pancholi <npancholi@mozilla.com>
Tue, 19 Sep 2017 11:31:55 -0700
changeset 698693 7b38898f1d607158040291a77fec5069fbfee290
parent 698692 305d7a2cefd481bd168cfd598bb47659e0c12121
child 698694 dc34d03c30af8c1e9be4186aefd8c4d1b4e904d1
push id89334
push userbmo:npancholi@mozilla.com
push dateThu, 16 Nov 2017 00:39:30 +0000
milestone59.0a1
Handle styling updates for anonymous boxes via Stylo for column-span. MozReview-Commit-ID: 3PsiDP71bfG
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsColumnSetWrapperFrame.cpp
layout/generic/nsColumnSetWrapperFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsInlineFrame.cpp
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -952,16 +952,52 @@ nsBlockFrame::GetPrefWidthTightBounds(gf
       }
     }
   }
   data.ForceBreak();
 
   return NS_OK;
 }
 
+void
+nsBlockFrame::UpdateStyleOfOwnedAnonBoxesForColumnSpanSplit(
+  mozilla::ServoRestyleState& aRestyleState) {
+  MOZ_ASSERT(StyleContext()->StyleColumn()->mColumnSpan ==
+    NS_STYLE_COLUMN_SPAN_ALL, "Why call this if we are not the column span?");
+
+  nsIFrame* blockFrame = GetProperty(nsIFrame::IBSplitPrevSibling());
+  if (!blockFrame) {
+    // If this column-span is not an IB-split sibling then no need to restyle it?
+    return;
+  }
+
+  // The later blocks need to get original parent's style.
+  ServoStyleContext* originalStyle = blockFrame->StyleContext()->AsServo();
+
+  // The anonymous block's style inherits from the original parent
+  RefPtr<ServoStyleContext> newContext =
+  aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(
+    nsCSSAnonBoxes::mozColumnSpanWrapper, originalStyle);
+
+  MOZ_ASSERT(!GetPrevContinuation(), "Must be first continuation");
+  MOZ_ASSERT(StyleContext()->GetPseudo() == nsCSSAnonBoxes::mozColumnSpanWrapper,
+              "Unexpected kind of style context");
+
+  for (nsIFrame* cont = this; cont; cont = cont->GetNextContinuation()) {
+    cont->SetStyleContext(newContext);
+  }
+
+  nsIFrame* nextSibling = GetProperty(nsIFrame::IBSplitSibling());
+  if (nextSibling) {
+    for (nsIFrame* cont = nextSibling; cont; cont = cont->GetNextContinuation()) {
+      cont->SetStyleContext(originalStyle);
+    }
+  }
+}
+
 /**
  * Return whether aNewAvailableSpace is smaller *on either side*
  * (inline-start or inline-end) than aOldAvailableSpace, so that we know
  * if we need to redo layout on an line, replaced block, or block
  * formatting context, because its height (which we used to compute
  * aNewAvailableSpace) caused it to intersect additional floats.
  */
 static bool
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -289,16 +289,21 @@ public:
   nscoord GetPrefISize(gfxContext *aRenderingContext) override;
 
   nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const override;
 
   nsresult GetPrefWidthTightBounds(gfxContext* aContext,
                                    nscoord* aX,
                                    nscoord* aXMost) override;
 
+  // Restyles the block wrappers around our column spans.
+  // This will only be called when such wrappers in fact exist.
+  void UpdateStyleOfOwnedAnonBoxesForColumnSpanSplit(
+    mozilla::ServoRestyleState& aRestyleState);
+
   /**
    * Compute the final block size of this frame.
    *
    * @param aReflowInput Data structure passed from parent during reflow.
    * @param aReflowStatus A pointer to the reflow status for when we're finished
    *        doing reflow. this will get set appropriately if the block-size
    *        causes us to exceed the current available (page) block-size.
    * @param aContentBSize The block-size of content, precomputed outside of this
--- a/layout/generic/nsColumnSetWrapperFrame.cpp
+++ b/layout/generic/nsColumnSetWrapperFrame.cpp
@@ -66,16 +66,31 @@ nsColumnSetWrapperFrame::BuildDisplayLis
 
   // Our children won't have backgrounds so it doesn't matter where we put them.
   for (nsIFrame* childFrame : mFrames) {
     BuildDisplayListForChild(aBuilder, childFrame, aLists);
   }
 }
 
 void
+nsColumnSetWrapperFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
+{
+  // All it's children are anon boxes
+  for (nsIFrame* childFrame : mFrames) {
+//    nsIAtom* pseudoStyle = childFrame->StyleContext()->GetPseudo();
+// Cannot assert this since column-spans directly inside a wrapper are never
+// wrapped with the mozColumnSpanWrapper pseudo style
+//    MOZ_ASSERT(pseudoStyle == nsCSSAnonBoxes::mozColumnSet ||
+//               pseudoStyle == nsCSSAnonBoxes::mozColumnSpanWrapper,
+//               "What kind of child is this?");
+    aResult.AppendElement(OwnedAnonBox(childFrame));
+  }
+}
+
+void
 nsColumnSetWrapperFrame::Reflow(nsPresContext*     aPresContext,
                                 ReflowOutput&      aDesiredSize,
                                 const ReflowInput& aReflowInput,
                                 nsReflowStatus&    aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsColumnSetWrapperFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
@@ -132,13 +147,10 @@ nsColumnSetWrapperFrame::Reflow(nsPresCo
     aStatus.MergeCompletionStatusFrom(childStatus);
 
     childOrigin.B(childWm) += childDesiredSize.BSize(childWm);
   }
 
   aDesiredSize.ISize(wm) += borderPadding.IStartEnd(wm);
   aDesiredSize.BSize(wm) += borderPadding.BStartEnd(wm);
 
-  //printf("\nAvailable size %d, %d", availableSpace.ISize(wm), availableSpace.BSize(wm));
-  //printf("\nDesired size %d, %d", aDesiredSize.ISize(wm), aDesiredSize.BSize(wm));
-
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize)
 }
--- a/layout/generic/nsColumnSetWrapperFrame.h
+++ b/layout/generic/nsColumnSetWrapperFrame.h
@@ -25,16 +25,18 @@ public:
   NS_DECL_FRAMEARENA_HELPERS(nsColumnSetWrapperFrame)
 
   friend nsContainerFrame* NS_NewColumnSetWrapperFrame(nsIPresShell* aPresShell,
                                                        nsStyleContext* aContext,
                                                        nsFrameState aStateFlags);
   void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                         const nsDisplayListSet& aLists) override;
 
+  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
+
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("ColumnSetWrapper"), aResult);
   }
 #endif
 
   nscoord GetMinISize(gfxContext* aRenderingContext) override;
   nscoord GetPrefISize(gfxContext* aRenderingContext) override;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -11082,17 +11082,24 @@ nsIFrame::DoUpdateStyleOfOwnedAnonBoxes(
   }
 
   AutoTArray<OwnedAnonBox,4> frames;
   AppendDirectlyOwnedAnonBoxes(frames);
   for (OwnedAnonBox& box : frames) {
     if (box.mUpdateStyleFn) {
       box.mUpdateStyleFn(this, box.mAnonBoxFrame, aRestyleState);
     } else {
-      UpdateStyleOfChildAnonBox(box.mAnonBoxFrame, aRestyleState);
+      if (box.mAnonBoxFrame->StyleContext()->StyleColumn()->mColumnSpan ==
+            NS_STYLE_COLUMN_SPAN_ALL) {
+        nsBlockFrame* blockFrame = static_cast<nsBlockFrame*>(box.mAnonBoxFrame);
+        MOZ_ASSERT(blockFrame, "This must be a valid block frame!");
+        blockFrame->UpdateStyleOfOwnedAnonBoxesForColumnSpanSplit(aRestyleState);
+      } else {
+        UpdateStyleOfChildAnonBox(box.mAnonBoxFrame, aRestyleState);
+      }
     }
   }
 }
 
 /* virtual */ void
 nsIFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
 {
   MOZ_ASSERT(!(GetStateBits() & NS_FRAME_OWNS_ANON_BOXES));
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -970,17 +970,19 @@ nsInlineFrame::UpdateStyleOfOwnedAnonBox
   // changehint being in aChangeList is good enough.  So we don't need to touch
   // aChangeList at all here.
 
   while (blockFrame) {
     MOZ_ASSERT(!blockFrame->GetPrevContinuation(),
                "Must be first continuation");
 
     MOZ_ASSERT(blockFrame->StyleContext()->GetPseudo() ==
-               nsCSSAnonBoxes::mozBlockInsideInlineWrapper,
+               nsCSSAnonBoxes::mozBlockInsideInlineWrapper ||
+               blockFrame->StyleContext()->GetPseudo() ==
+               nsCSSAnonBoxes::mozColumnSpanWrapper,
                "Unexpected kind of style context");
 
     // We don't want to just walk through using GetNextContinuationWithSameStyle
     // here, because we want to set updated style contexts on both our
     // ib-sibling blocks and inlines.
     for (nsIFrame* cont = blockFrame; cont; cont = cont->GetNextContinuation()) {
       cont->SetStyleContext(newContext);
     }