Bug 1401709 - Do attach base line layout to orthogonal rtc. r?xidorn draft 13-1401709
authorKevin Hsieh <kevin.hsieh@ucla.edu>
Thu, 21 Sep 2017 19:36:12 -0700
branch13-1401709
changeset 668844 ec89d0c758d2c23fad95db2b476dcde64b89cdf1
parent 666213 dd927fbee259fc604f2be4d165c92cb29485f1da
child 732787 f2da475dfccca8c80b61f50f42e4720f4f5f2b0f
push id81135
push userbmo:kevin.hsieh@ucla.edu
push dateFri, 22 Sep 2017 03:19:09 +0000
reviewersxidorn
bugs1401709
milestone57.0a1
Bug 1401709 - Do attach base line layout to orthogonal rtc. r?xidorn MozReview-Commit-ID: JCgaXWD43m5
layout/generic/crashtests/1401709.html
layout/generic/crashtests/crashtests.list
layout/generic/nsLineLayout.cpp
layout/generic/nsRubyBaseContainerFrame.cpp
layout/generic/nsRubyFrame.cpp
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/1401709.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+addEventListener("DOMContentLoaded", () => {
+  a = document.head
+  b = document.createElement("link")
+  a.appendChild(b)
+  b.style.cssFloat = "left"
+  b.style.display = "block"
+  a.style.writingMode = "sideways-rl"
+  a.style.display = "ruby-text-container"
+})
+</script>
+</head>
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -653,8 +653,9 @@ load 1304441.html
 load 1308876-1.html
 load 1316649.html
 load 1349650.html
 asserts-if(browserIsRemote,0-5) load 1349816-1.html # bug 1350352
 load 1364361-1.html
 load 1367413-1.html
 load 1368617-1.html
 load 1373586.html
+load 1401709.html
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -76,19 +76,19 @@ nsLineLayout::nsLineLayout(nsPresContext
     mDirtyNextLine(false),
     mLineAtStart(false),
     mHasRuby(false),
     mSuppressLineWrap(nsSVGUtils::IsInSVGTextSubtree(aOuterReflowInput->mFrame))
 {
   MOZ_ASSERT(aOuterReflowInput, "aOuterReflowInput must not be null");
   NS_ASSERTION(aFloatManager || aOuterReflowInput->mFrame->IsLetterFrame(),
                "float manager should be present");
-  MOZ_ASSERT(aOuterReflowInput->mFrame->IsRubyTextContainerFrame() ||
-             !mBaseLineLayout,
-             "Only ruby text container frames may have "
+  MOZ_ASSERT((!!mBaseLineLayout) ==
+              aOuterReflowInput->mFrame->IsRubyTextContainerFrame(),
+             "Only ruby text container frames have "
              "a different base line layout");
   MOZ_COUNT_CTOR(nsLineLayout);
 
   // Stash away some style data that we need
   nsBlockFrame* blockFrame = do_QueryFrame(aOuterReflowInput->mFrame);
   if (blockFrame)
     mStyleText = blockFrame->StyleTextForLineLayout();
   else
@@ -1209,16 +1209,20 @@ nsLineLayout::SyncAnnotationBounds(PerFr
   MOZ_ASSERT(aRubyFrame->mFrame->IsRubyFrame());
   MOZ_ASSERT(aRubyFrame->mSpan);
 
   PerSpanData* span = aRubyFrame->mSpan;
   WritingMode lineWM = mRootSpan->mWritingMode;
   for (PerFrameData* pfd = span->mFirstFrame; pfd; pfd = pfd->mNext) {
     for (PerFrameData* rtc = pfd->mNextAnnotation;
          rtc; rtc = rtc->mNextAnnotation) {
+      if (lineWM.IsOrthogonalTo(rtc->mFrame->GetWritingMode())) {
+        // Inter-character case: don't attempt to sync annotation bounds.
+        continue;
+      }
       // When the annotation container is reflowed, the width of the
       // ruby container is unknown so we use a dummy container size;
       // in the case of RTL block direction, the final position will be
       // fixed up later.
       const nsSize dummyContainerSize;
       LogicalRect rtcBounds(lineWM, rtc->mFrame->GetRect(),
                             dummyContainerSize);
       rtc->mBounds = rtcBounds;
@@ -3012,16 +3016,20 @@ nsLineLayout::ExpandRubyBoxWithAnnotatio
   if (reservedISize) {
     ExpandRubyBox(aFrame, reservedISize, aContainerSize);
   }
 
   WritingMode lineWM = mRootSpan->mWritingMode;
   bool isLevelContainer = aFrame->mFrame->IsRubyBaseContainerFrame();
   for (PerFrameData* annotation = aFrame->mNextAnnotation;
        annotation; annotation = annotation->mNextAnnotation) {
+    if (lineWM.IsOrthogonalTo(annotation->mFrame->GetWritingMode())) {
+      // Inter-character case: don't attempt to expand ruby annotations.
+      continue;
+    }
     if (isLevelContainer) {
       nsIFrame* rtcFrame = annotation->mFrame;
       MOZ_ASSERT(rtcFrame->IsRubyTextContainerFrame());
       // It is necessary to set the rect again because the container
       // width was unknown, and zero was used instead when we reflow
       // them. The corresponding base containers were repositioned in
       // VerticalAlignFrames and PlaceTopBottomFrames.
       MOZ_ASSERT(
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -337,50 +337,46 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
   reflowInputs.SetCapacity(rtcCount);
   lineLayouts.SetCapacity(rtcCount);
 
   // Begin the line layout for each ruby text container in advance.
   bool hasSpan = false;
   for (uint32_t i = 0; i < rtcCount; i++) {
     nsRubyTextContainerFrame* textContainer = textContainers[i];
     WritingMode rtcWM = textContainer->GetWritingMode();
-    nsLineLayout* baseLineLayout =
-        lineWM.IsOrthogonalTo(rtcWM) ? nullptr : aReflowInput.mLineLayout;
-        // Don't attach a base line layout in the inter-character case.
+    WritingMode reflowWM = lineWM.IsOrthogonalTo(rtcWM) ? rtcWM : lineWM;
     if (textContainer->IsSpanContainer()) {
       hasSpan = true;
     }
 
     ReflowInput* reflowInput = new ReflowInput(
       aPresContext, *aReflowInput.mParentReflowInput, textContainer,
       availSize.ConvertTo(textContainer->GetWritingMode(), lineWM));
     reflowInputs.AppendElement(reflowInput);
     nsLineLayout* lineLayout = new nsLineLayout(aPresContext,
                                                 reflowInput->mFloatManager,
                                                 reflowInput, nullptr,
-                                                baseLineLayout);
+                                                aReflowInput.mLineLayout);
     lineLayout->SetSuppressLineWrap(true);
     lineLayouts.AppendElement(lineLayout);
 
     // Line number is useless for ruby text
     // XXX nullptr here may cause problem, see comments for
     //     nsLineLayout::mBlockRI and nsLineLayout::AddFloat
     lineLayout->Init(nullptr, reflowInput->CalcLineHeight(), -1);
     reflowInput->mLineLayout = lineLayout;
 
     // Border and padding are suppressed on ruby text containers.
     // If the writing mode is vertical-rl, the horizontal position of
     // rt frames will be updated when reflowing this text container,
     // hence leave container size 0 here for now.
     lineLayout->BeginLineReflow(0, 0, reflowInput->ComputedISize(),
-                                NS_UNCONSTRAINEDSIZE, false, false,
-                                baseLineLayout ? lineWM : rtcWM, nsSize(0, 0));
-    if (baseLineLayout) {
-      lineLayout->AttachRootFrameToBaseLineLayout();
-    }
+                                NS_UNCONSTRAINEDSIZE,
+                                false, false, reflowWM, nsSize(0, 0));
+    lineLayout->AttachRootFrameToBaseLineLayout();
   }
 
   aReflowInput.mLineLayout->BeginSpan(this, &aReflowInput,
                                       0, aReflowInput.AvailableISize(),
                                       &mBaseline);
 
   bool allowInitialLineBreak, allowLineBreak;
   GetIsLineBreakAllowed(this, aReflowInput.mLineLayout->LineIsBreakable(),
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -310,16 +310,21 @@ nsRubyFrame::ReflowSegment(nsPresContext
   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
+    //       the text containers. But it should be fine now as we are
+    //       not actually using this line layout to reflow something,
+    //       but just read the writing mode from it.
+    textReflowInput.mLineLayout = aReflowInput.mLineLayout;
     textContainer->Reflow(aPresContext, textMetrics,
                           textReflowInput, textReflowStatus);
     // Ruby text containers always return complete reflow status even when
     // they have continuations, because the breaking has already been
     // handled when reflowing the base containers.
     NS_ASSERTION(textReflowStatus.IsEmpty(),
                  "Ruby text container must not break itself inside");
     // The metrics is initialized with reflow state of this ruby frame,