Bug 1421105 - Part5:Update the styling of anon boxes created by column-span splitting for Servo. draft
authorNeerja Pancholi <npancholi@mozilla.com>
Mon, 27 Nov 2017 17:50:30 -0800
changeset 762848 5c71eed1f789b77ec25ab64c2f3bc0e8e2abcff0
parent 762847 9cdaed8817493dd64ebfa3c91dddc7eb0fcdaf6d
child 762849 f978264dec9e03a4a83d95e8842d571d5fa8baee
push id101269
push userbmo:npancholi@mozilla.com
push dateSat, 03 Mar 2018 02:23:39 +0000
bugs1421105
milestone60.0a1
Bug 1421105 - Part5:Update the styling of anon boxes created by column-span splitting for Servo. MozReview-Commit-ID: JtoGXkDELsS
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
@@ -941,16 +941,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
@@ -288,16 +288,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 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
@@ -22,16 +22,24 @@ NS_NewColumnSetWrapperFrame(nsIPresShell
 
 NS_IMPL_FRAMEARENA_HELPERS(nsColumnSetWrapperFrame)
 
 nsColumnSetWrapperFrame::nsColumnSetWrapperFrame(nsStyleContext* aContext)
 : nsBlockFrame(aContext, kClassID)
 {
 }
 
+void
+nsColumnSetWrapperFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
+{
+  if (mFrames.NotEmpty()) {
+    aResult.AppendElement(OwnedAnonBox(mFrames.FirstChild()));
+  }
+}
+
 /*
  * Any append, insert or remove operation is disallowed on ColumnSetWrapperFrame
  * because in that case we must recreate the entire frame hierarchy under this
  * wrapper to account for the added/removed element changing the breaking of
  * frames across column-spans. This is handled in nsCSSFrameConstructor's
  * ContentAppended/ContentRemoved/ContentInserted path.
  * See nsCSSFrameConstructor::WipeContainingBlock.
  */
--- a/layout/generic/nsColumnSetWrapperFrame.h
+++ b/layout/generic/nsColumnSetWrapperFrame.h
@@ -22,16 +22,18 @@ class nsColumnSetWrapperFrame final : pu
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS(nsColumnSetWrapperFrame)
 
   friend nsBlockFrame* NS_NewColumnSetWrapperFrame(nsIPresShell* aPresShell,
                                                    nsStyleContext* aContext,
                                                    nsFrameState aStateFlags);
 
+  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
+
   virtual nsContainerFrame* GetContentInsertionFrame() override {
     MOZ_ASSERT_UNREACHABLE("Should not be called because we don't know whether"
                            " we're inserting a column-span or not.");
   }
 
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("ColumnSetWrapper"), aResult);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -11210,17 +11210,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);
     }