Bug 1267515 part 2 - Place ruby annotations outside annotations from ruby descendants. r=dholbert
authorXidorn Quan <me@upsuper.org>
Wed, 26 Oct 2016 17:40:58 +1100
changeset 348947 ca6ff07941fcc205d3d0a118d8bdb6e2dcefb00e
parent 348946 10b8471d7d455260dc55469b1936661b9a8d13b0
child 348948 a8e375f76713163cd3f2aa59d0a7e93ec378e2e9
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1267515
milestone52.0a1
Bug 1267515 part 2 - Place ruby annotations outside annotations from ruby descendants. r=dholbert MozReview-Commit-ID: Gbo43pC5jqr
layout/generic/nsRubyBaseContainerFrame.cpp
layout/generic/nsRubyBaseContainerFrame.h
layout/generic/nsRubyFrame.cpp
layout/generic/nsTextFrame.cpp
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -310,16 +310,18 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
 
   if (!aReflowInput.mLineLayout) {
     NS_ASSERTION(
       aReflowInput.mLineLayout,
       "No line layout provided to RubyBaseContainerFrame reflow method.");
     return;
   }
 
+  mDescendantLeadings.Reset();
+
   MoveOverflowToChildList();
   // Ask text containers to drain overflows
   AutoRubyTextContainerArray textContainers(this);
   const uint32_t rtcCount = textContainers.Length();
   for (uint32_t i = 0; i < rtcCount; i++) {
     textContainers[i]->MoveOverflowToChildList();
   }
 
--- a/layout/generic/nsRubyBaseContainerFrame.h
+++ b/layout/generic/nsRubyBaseContainerFrame.h
@@ -5,28 +5,25 @@
  * http://mozilla.org/MPL/2.0/. */
 
 /* rendering object for CSS "display: ruby-base-container" */
 
 #ifndef nsRubyBaseContainerFrame_h___
 #define nsRubyBaseContainerFrame_h___
 
 #include "nsContainerFrame.h"
+#include "RubyUtils.h"
 
 /**
  * Factory function.
  * @return a newly allocated nsRubyBaseContainerFrame (infallible)
  */
 nsContainerFrame* NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
                                                nsStyleContext* aContext);
 
-namespace mozilla {
-struct RubyColumn;
-} // namespace mozilla
-
 class nsRubyBaseContainerFrame final : public nsContainerFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsRubyBaseContainerFrame)
   NS_DECL_QUERYFRAME
 
   // nsIFrame overrides
@@ -53,16 +50,23 @@ public:
 
   virtual nscoord
     GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
+  void UpdateDescendantLeadings(const mozilla::RubyBlockLeadings& aLeadings) {
+    mDescendantLeadings.Update(aLeadings);
+  }
+  mozilla::RubyBlockLeadings GetDescendantLeadings() const {
+    return mDescendantLeadings;
+  }
+
 protected:
   friend nsContainerFrame*
     NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
                                  nsStyleContext* aContext);
   explicit nsRubyBaseContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
 
   struct RubyReflowInput;
   nscoord ReflowColumns(const RubyReflowInput& aReflowInput,
@@ -78,11 +82,14 @@ protected:
   // Pull ruby base and corresponding ruby text frames from
   // continuations after them.
   void PullOneColumn(nsLineLayout* aLineLayout,
                      PullFrameState& aPullFrameState,
                      mozilla::RubyColumn& aColumn,
                      bool& aIsComplete);
 
   nscoord mBaseline;
+
+  // Leading produced by descendant ruby annotations.
+  mozilla::RubyBlockLeadings mDescendantLeadings;
 };
 
 #endif /* nsRubyBaseContainerFrame_h___ */
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -85,16 +85,29 @@ nsRubyFrame::AddInlinePrefISize(nsRender
     for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
          !e.AtEnd(); e.Next()) {
       e.GetBaseContainer()->AddInlinePrefISize(aRenderingContext, aData);
     }
   }
   aData->mLineIsEmpty = false;
 }
 
+static nsRubyBaseContainerFrame*
+FindRubyBaseContainerAncestor(nsIFrame* aFrame)
+{
+  for (nsIFrame* ancestor = aFrame->GetParent();
+       ancestor && ancestor->IsFrameOfType(nsIFrame::eLineParticipant);
+       ancestor = ancestor->GetParent()) {
+    if (ancestor->GetType() == nsGkAtoms::rubyBaseContainerFrame) {
+      return static_cast<nsRubyBaseContainerFrame*>(ancestor);
+    }
+  }
+  return nullptr;
+}
+
 /* virtual */ void
 nsRubyFrame::Reflow(nsPresContext* aPresContext,
                     ReflowOutput& aDesiredSize,
                     const ReflowInput& aReflowInput,
                     nsReflowStatus& aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsRubyFrame");
@@ -157,16 +170,21 @@ nsRubyFrame::Reflow(nsPresContext* aPres
   aDesiredSize.ISize(lineWM) = aReflowInput.mLineLayout->EndSpan(this);
   if (boxDecorationBreakClone || !GetPrevContinuation()) {
     aDesiredSize.ISize(lineWM) += borderPadding.IStart(frameWM);
   }
   if (boxDecorationBreakClone || NS_FRAME_IS_COMPLETE(aStatus)) {
     aDesiredSize.ISize(lineWM) += borderPadding.IEnd(frameWM);
   }
 
+  // Update descendant leadings of ancestor ruby base container.
+  if (nsRubyBaseContainerFrame* rbc = FindRubyBaseContainerAncestor(this)) {
+    rbc->UpdateDescendantLeadings(mLeadings);
+  }
+
   nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize,
                                          borderPadding, lineWM, frameWM);
 }
 
 void
 nsRubyFrame::ReflowSegment(nsPresContext* aPresContext,
                            const ReflowInput& aReflowInput,
                            nsRubyBaseContainerFrame* aBaseContainer,
@@ -263,16 +281,19 @@ nsRubyFrame::ReflowSegment(nsPresContext
   // the ruby frame. Right now, the base container's rect's block-axis
   // position is relative to the block container frame containing the
   // lines, so we use 0 instead. (i.e. we assume that the base container
   // is adjacent to the ruby frame's block-start edge.)
   // XXX We may need to add border/padding here. See bug 1055667.
   baseRect.BStart(lineWM) = 0;
   // The rect for offsets of text containers.
   LogicalRect offsetRect = baseRect;
+  RubyBlockLeadings descLeadings = aBaseContainer->GetDescendantLeadings();
+  offsetRect.BStart(lineWM) -= descLeadings.mStart;
+  offsetRect.BSize(lineWM) += descLeadings.mStart + descLeadings.mEnd;
   for (uint32_t i = 0; i < rtcCount; i++) {
     nsRubyTextContainerFrame* textContainer = textContainers[i];
     WritingMode rtcWM = textContainer->GetWritingMode();
     nsReflowStatus textReflowStatus;
     ReflowOutput textMetrics(aReflowInput);
     ReflowInput textReflowInput(aPresContext, aReflowInput, textContainer,
                                       availSize.ConvertTo(rtcWM, lineWM));
     // FIXME We probably shouldn't be using the same nsLineLayout for
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5328,26 +5328,27 @@ GenerateTextRunForEmphasisMarks(nsTextFr
     flags = gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
   }
   return aFontMetrics->GetThebesFontGroup()->
     MakeTextRun<char16_t>(emphasisString.get(), emphasisString.Length(),
                           dt, appUnitsPerDevUnit, flags, nullptr);
 }
 
 static nsRubyFrame*
-FindRubyAncestor(nsTextFrame* aFrame)
-{
+FindFurthestInlineRubyAncestor(nsTextFrame* aFrame)
+{
+  nsRubyFrame* rubyFrame = nullptr;
   for (nsIFrame* frame = aFrame->GetParent();
        frame && frame->IsFrameOfType(nsIFrame::eLineParticipant);
        frame = frame->GetParent()) {
     if (frame->GetType() == nsGkAtoms::rubyFrame) {
-      return static_cast<nsRubyFrame*>(frame);
-    }
-  }
-  return nullptr;
+      rubyFrame = static_cast<nsRubyFrame*>(frame);
+    }
+  }
+  return rubyFrame;
 }
 
 nsRect
 nsTextFrame::UpdateTextEmphasis(WritingMode aWM, PropertyProvider& aProvider)
 {
   const nsStyleText* styleText = StyleText();
   if (!styleText->HasTextEmphasis()) {
     Properties().Delete(EmphasisMarkProperty());
@@ -5380,17 +5381,17 @@ nsTextFrame::UpdateTextEmphasis(WritingM
     ? nsLayoutUtils::GetInflatedFontMetricsForFrame(GetParent())
     : do_AddRef(aProvider.GetFontMetrics());
   // When the writing mode is vertical-lr the line is inverted, and thus
   // the ascent and descent are swapped.
   nscoord absOffset = (side == eLogicalSideBStart) != aWM.IsLineInverted() ?
     baseFontMetrics->MaxAscent() + fm->MaxDescent() :
     baseFontMetrics->MaxDescent() + fm->MaxAscent();
   RubyBlockLeadings leadings;
-  if (nsRubyFrame* ruby = FindRubyAncestor(this)) {
+  if (nsRubyFrame* ruby = FindFurthestInlineRubyAncestor(this)) {
     leadings = ruby->GetBlockLeadings();
   }
   if (side == eLogicalSideBStart) {
     info->baselineOffset = -absOffset - leadings.mStart;
     overflowRect.BStart(aWM) = -overflowRect.BSize(aWM) - leadings.mStart;
   } else {
     MOZ_ASSERT(side == eLogicalSideBEnd);
     info->baselineOffset = absOffset + leadings.mEnd;