Bug 1069519 part 2 - Make line height calculation be aware of ruby annotations. r=dholbert
authorXidorn Quan <quanxunzhen@gmail.com>
Thu, 08 Jan 2015 16:02:41 +1100
changeset 248419 0491510520344b87bf4d035cc8e9c0bdaf372a71
parent 248418 a3292d545bea6b9957ce0b1e293524fa816adce9
child 248420 87ca345a376736ce695cbc157fdb280e9b4d911b
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1069519
milestone37.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 1069519 part 2 - Make line height calculation be aware of ruby annotations. r=dholbert
layout/generic/nsLineLayout.cpp
layout/generic/nsRubyFrame.cpp
layout/generic/nsRubyFrame.h
layout/reftests/css-ruby/justification-1-ref.html
layout/reftests/css-ruby/justification-1.html
layout/reftests/css-ruby/ruby-reflow-1-noruby.html
layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html
layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -19,16 +19,17 @@
 #include "nsStyleContext.h"
 #include "nsPresContext.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsLayoutUtils.h"
 #include "nsTextFrame.h"
 #include "nsStyleStructInlines.h"
 #include "nsBidiPresUtils.h"
+#include "nsRubyFrame.h"
 #include "RubyUtils.h"
 #include <algorithm>
 
 #ifdef DEBUG
 #undef  NOISY_INLINEDIR_ALIGN
 #undef  NOISY_BLOCKDIR_ALIGN
 #undef  REALLY_NOISY_BLOCKDIR_ALIGN
 #undef  NOISY_REFLOW
@@ -1821,16 +1822,39 @@ nsLineLayout::VerticalAlignFrames(PerSpa
         spanFrame->StyleText()->mLineHeight.GetUnit() == eStyleUnit_Normal) {
       logicalBSize = spanFramePFD->mBounds.BSize(lineWM);
     }
 
     nscoord leading = logicalBSize - contentBSize;
     psd->mBStartLeading = leading / 2;
     psd->mBEndLeading = leading - psd->mBStartLeading;
     psd->mLogicalBSize = logicalBSize;
+    if (spanFrame->GetType() == nsGkAtoms::rubyFrame) {
+      // We may need to extend leadings here for ruby annotations as
+      // required by section Line Spacing in the CSS Ruby spec.
+      // See http://dev.w3.org/csswg/css-ruby/#line-height
+      auto rubyFrame = static_cast<nsRubyFrame*>(spanFrame);
+      nscoord startLeading, endLeading;
+      rubyFrame->GetBlockLeadings(startLeading, endLeading);
+      nscoord deltaLeading = startLeading + endLeading - leading;
+      if (deltaLeading > 0) {
+        // If the total leading is not wide enough for ruby annotations,
+        // extend the side which is not enough. If both sides are not
+        // wide enough, replace the leadings with the requested values.
+        if (startLeading < psd->mBStartLeading) {
+          psd->mBEndLeading += deltaLeading;
+        } else if (endLeading < psd->mBEndLeading) {
+          psd->mBStartLeading += deltaLeading;
+        } else {
+          psd->mBStartLeading = startLeading;
+          psd->mBEndLeading = endLeading;
+        }
+        psd->mLogicalBSize += deltaLeading;
+      }
+    }
 
     if (zeroEffectiveSpanBox) {
       // When the span-box is to be ignored, zero out the initial
       // values so that the span doesn't impact the final line
       // height. The contents of the span can impact the final line
       // height.
 
       // Note that things are readjusted for this span after its children
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -162,16 +162,19 @@ nsRubyFrame::Reflow(nsPresContext* aPres
                  "No line layout provided to RubyFrame reflow method.");
     aStatus = NS_FRAME_COMPLETE;
     return;
   }
 
   // Grab overflow frames from prev-in-flow and its own.
   MoveOverflowToChildList();
 
+  // Clear leadings
+  mBStartLeading = mBEndLeading = 0;
+
   // Begin the span for the ruby frame
   WritingMode frameWM = aReflowState.GetWritingMode();
   WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode();
   LogicalMargin borderPadding = aReflowState.ComputedLogicalBorderPadding();
   nscoord startEdge = borderPadding.IStart(frameWM);
   nscoord endEdge = aReflowState.AvailableISize() - borderPadding.IEnd(frameWM);
   NS_ASSERTION(aReflowState.AvailableISize() != NS_UNCONSTRAINEDSIZE,
                "should no longer use available widths");
@@ -389,16 +392,24 @@ nsRubyFrame::ReflowSegment(nsPresContext
 
   nscoord deltaISize = segmentISize - baseMetrics.ISize(lineWM);
   if (deltaISize <= 0) {
     RubyUtils::ClearReservedISize(aBaseContainer);
   } else {
     RubyUtils::SetReservedISize(aBaseContainer, deltaISize);
     aReflowState.mLineLayout->AdvanceICoord(deltaISize);
   }
+
+  // Set block leadings of the base container
+  LogicalMargin leadings(lineWM, offsetRect - baseRect);
+  NS_ASSERTION(leadings.BStart(lineWM) >= 0 && leadings.BEnd(lineWM) >= 0,
+               "Leadings should be non-negative (because adding "
+               "ruby annotation can only increase the size)");
+  mBStartLeading = std::max(mBStartLeading, leadings.BStart(lineWM));
+  mBEndLeading = std::max(mBEndLeading, leadings.BEnd(lineWM));
 }
 
 nsRubyBaseContainerFrame*
 nsRubyFrame::PullOneSegment(ContinuationTraversingState& aState)
 {
   // Pull a ruby base container
   nsIFrame* baseFrame = PullNextInFlowChild(aState);
   if (!baseFrame) {
--- a/layout/generic/nsRubyFrame.h
+++ b/layout/generic/nsRubyFrame.h
@@ -51,24 +51,36 @@ public:
   virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode)
     const MOZ_OVERRIDE;
   virtual bool CanContinueTextRun() const MOZ_OVERRIDE;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
 #endif
 
+  void GetBlockLeadings(nscoord& aStartLeading, nscoord& aEndLeading)
+  {
+    aStartLeading = mBStartLeading;
+    aEndLeading = mBEndLeading;
+  }
+
 protected:
   friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
                                            nsStyleContext* aContext);
   explicit nsRubyFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
 
   void ReflowSegment(nsPresContext* aPresContext,
                      const nsHTMLReflowState& aReflowState,
                      nsRubyBaseContainerFrame* aBaseContainer,
                      nsReflowStatus& aStatus);
 
   nsRubyBaseContainerFrame* PullOneSegment(ContinuationTraversingState& aState);
 
+  // The three members below are not initialized until the first reflow.
+
   nscoord mBaseline;
+
+  // The leadings required to put the annotations.
+  nscoord mBStartLeading;
+  nscoord mBEndLeading;
 };
 
 #endif /* nsRubyFrame_h___ */
--- a/layout/reftests/css-ruby/justification-1-ref.html
+++ b/layout/reftests/css-ruby/justification-1-ref.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
   <meta charset="UTF-8">
   <title>Bug 1116631 - Justification with ruby span</title>
   <link rel="stylesheet" href="common.css">
   <style>
-    rtc { line-height: 0; }
+    body { line-height: 2; }
   </style>
 </head>
 <body>
   <div style="width: 200px; height: 100px; -moz-text-align-last: justify; overflow: auto;"><ruby>
     <rb>a</rb><rb>b</rb>
   </ruby></div>
 </body>
 </html>
--- a/layout/reftests/css-ruby/justification-1.html
+++ b/layout/reftests/css-ruby/justification-1.html
@@ -1,17 +1,17 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
   <meta charset="UTF-8">
   <title>Bug 1116631 - Justification with ruby span</title>
   <link rel="stylesheet" href="common.css">
   <style>
-    rtc { line-height: 0; }
+    body { line-height: 2; }
   </style>
 </head>
 <body>
   <div style="width: 200px; height: 100px; -moz-text-align-last: justify; overflow: auto;"><ruby>
     <rb>a</rb><rb>b</rb>
-    <rtc><div style="width: 100px; height: 0;"></div></rtc>
+    <rtc><div style="width: 100px;"></div></rtc>
   </ruby></div>
 </body>
 </html>
--- a/layout/reftests/css-ruby/ruby-reflow-1-noruby.html
+++ b/layout/reftests/css-ruby/ruby-reflow-1-noruby.html
@@ -2,13 +2,16 @@
 <html style="overflow:hidden;">
 <head>
 <title>CSS Test: Ruby Base Frames Reflowed</title>
 <link rel="author" title="Susanna Bowen" href="mailto:sgbowen8@gmail.com">
 <link rel="help" href="http://www.w3.org/TR/2014/WD-css-ruby-1-20140805/">
 <meta name="assert" content="Test checks that ruby bases are reflowed.">
 <meta charset="UTF-8">
 <link rel="stylesheet" href="common.css">
+<style>
+body { line-height: 2em; }
+</style>
 </head>
 <body>
 新幹線
 </body>
 </html>
--- a/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html
+++ b/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html
@@ -2,16 +2,19 @@
 <html style="overflow:hidden;">
 <head>
 <title>CSS Test: Ruby Text Frames Visible</title>
 <link rel="author" title="Susanna Bowen" href="mailto:sgbowen8@gmail.com">
 <link rel="help" href="http://www.w3.org/TR/2014/WD-css-ruby-1-20140805/">
 <meta name="assert" content="Test checks that ruby text is rendered.">
 <meta charset="UTF-8">
 <link rel="stylesheet" href="common.css">
+<style>
+body { line-height: 2em; }
+</style>
 </head>
 <body>
 <ruby>
   <rbc><rb>新</rb><rb>幹</rb><rb>線</rb></rbc>
   <rtc><rt>しん</rt><rt>かん</rt><rt>せん</rt></rtc>
 </ruby>
 </body>
 </html>
--- a/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html
+++ b/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html
@@ -3,16 +3,17 @@
 <head>
 <title>CSS Test: Ruby Base Frames Reflowed</title>
 <link rel="author" title="Susanna Bowen" href="mailto:sgbowen8@gmail.com">
 <link rel="help" href="http://www.w3.org/TR/2014/WD-css-ruby-1-20140805/">
 <meta name="assert" content="Test checks that ruby bases are reflowed.">
 <meta charset="UTF-8">
 <link rel="stylesheet" href="common.css">
 <style>
+body { line-height: 2em; }
 rtc { color: transparent; }
 </style>
 </head>
 <body>
 <ruby>
   <rbc><rb>新</rb><rb>幹</rb><rb>線</rb></rbc>
   <rtc><rt>しん</rt><rt>かん</rt><rt>せん</rt></rtc>
 </ruby>