Bug 1324618 part 9. Implement FrameForPseudoElement for ::first-letter. r?emilio draft
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 26 Jun 2017 23:35:09 -0700
changeset 600506 8c38971cfbdcb6d0c0fea8b56da16e62ad4cbfbb
parent 600505 410f00b19f805bcbe83101252311b7e16986a56d
child 600507 2a9d98c0de2905a6fb2c21badfcc256b00f58634
push id65783
push userbzbarsky@mozilla.com
push dateTue, 27 Jun 2017 06:35:27 +0000
reviewersemilio
bugs1324618
milestone56.0a1
Bug 1324618 part 9. Implement FrameForPseudoElement for ::first-letter. r?emilio This also makes us stop reframing on lack of frame for pseudo-elements for which such a lack is expected in various situations and means the pseudo-element's styles do not matter. MozReview-Commit-ID: K1qzeow2Z6H
layout/base/ServoRestyleManager.cpp
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -245,16 +245,40 @@ private:
   nsStyleContext& mParentContext;
   ServoRestyleState& mParentRestyleState;
   RefPtr<nsStyleContext> mStyle;
   bool mShouldPostHints;
   bool mShouldComputeHints;
   nsChangeHint mComputedHint;
 };
 
+// Find the first-letter frame for the given element, if any.  Returns null to
+// indicate there isn't one.
+static nsIFrame*
+FindFirstLetterFrameForElement(const Element* aElement)
+{
+  nsIFrame* frame = aElement->GetPrimaryFrame();
+  if (!frame) {
+    return nullptr;
+  }
+  // The first-letter frame will always be inside the content insertion frame,
+  // which will always be a block if we have a first-letter frame at all.
+  frame = frame->GetContentInsertionFrame();
+  if (!frame) {
+    // We're a leaf; certainly no first-letter frame.
+    return nullptr;
+  }
+
+  if (!frame->IsFrameOfType(nsIFrame::eBlockFrame)) {
+    return nullptr;
+  }
+
+  return static_cast<nsBlockFrame*>(frame)->GetFirstLetter();
+}
+
 static void
 UpdateBackdropIfNeeded(nsIFrame* aFrame, ServoRestyleState& aRestyleState)
 {
   const nsStyleDisplay* display = aFrame->StyleContext()->StyleDisplay();
   if (display->mTopLayer != NS_STYLE_TOP_LAYER_TOP) {
     return;
   }
 
@@ -562,18 +586,21 @@ ServoRestyleManager::FrameForPseudoEleme
     return pseudoElement ? nsLayoutUtils::GetStyleFrame(pseudoElement) : nullptr;
   }
 
   if (aPseudoTagOrNull == nsCSSPseudoElements::after) {
     Element* pseudoElement = nsLayoutUtils::GetAfterPseudo(aElement);
     return pseudoElement ? nsLayoutUtils::GetStyleFrame(pseudoElement) : nullptr;
   }
 
-  if (aPseudoTagOrNull == nsCSSPseudoElements::firstLine ||
-      aPseudoTagOrNull == nsCSSPseudoElements::firstLetter) {
+  if (aPseudoTagOrNull == nsCSSPseudoElements::firstLetter) {
+    return FindFirstLetterFrameForElement(aElement);
+  }
+
+  if (aPseudoTagOrNull == nsCSSPseudoElements::firstLine) {
     // TODO(emilio, bz): Figure out the best way to diff these styles.
     return nullptr;
   }
 
   MOZ_CRASH("Unkown pseudo-element given to "
             "ServoRestyleManager::FrameForPseudoElement");
   return nullptr;
 }