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 322370 ca6ff07941fcc205d3d0a118d8bdb6e2dcefb00e
parent 322369 10b8471d7d455260dc55469b1936661b9a8d13b0
child 322371 a8e375f76713163cd3f2aa59d0a7e93ec378e2e9
push id83844
push usercbook@mozilla.com
push dateMon, 14 Nov 2016 09:35:48 +0000
treeherdermozilla-inbound@c29cedd0d3f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1267515
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;