Bug 1084370 - Fix handling of vertical-align in lines with vertical writing mode. r=smontagu
authorJonathan Kew <jkew@mozilla.com>
Thu, 13 Nov 2014 12:58:30 +0000
changeset 215502 f77efca402c2b12116350e599a8c029ce78ebfc6
parent 215501 c49c2442f6667ae518c03ed9fb8bcf3c1a8b5578
child 215503 4a65cacf8a371b99bb0dd97fdff24f27ff9ff913
push id27818
push userryanvm@gmail.com
push dateThu, 13 Nov 2014 20:19:09 +0000
treeherdermozilla-central@292ed84594c1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmontagu
bugs1084370
milestone36.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 1084370 - Fix handling of vertical-align in lines with vertical writing mode. r=smontagu
layout/generic/nsLineLayout.cpp
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -1825,52 +1825,75 @@ nsLineLayout::VerticalAlignFrames(PerSpa
     if (verticalAlignEnum != nsIFrame::eInvalidVerticalAlign) {
       printf(", after SVG dominant-baseline conversion == %d",
              verticalAlignEnum);
     }
     printf(")\n");
 #endif
 
     if (verticalAlignEnum != nsIFrame::eInvalidVerticalAlign) {
+      if (lineWM.IsVertical()) {
+        if (verticalAlignEnum == NS_STYLE_VERTICAL_ALIGN_MIDDLE) {
+          // For vertical writing mode where the dominant baseline is centered
+          // (i.e. text-orientation is not sideways-*), we remap 'middle' to
+          // 'middle-with-baseline' so that images align sensibly with the
+          // center-baseline-aligned text.
+          if (!lineWM.IsSideways()) {
+            verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE;
+          }
+        } else if (lineWM.IsLineInverted()) {
+          // Swap the meanings of top and bottom when line is inverted
+          // relative to block direction.
+          switch (verticalAlignEnum) {
+            case NS_STYLE_VERTICAL_ALIGN_TOP:
+              verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_BOTTOM;
+              break;
+            case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
+              verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_TOP;
+              break;
+            case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
+              verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM;
+              break;
+            case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
+              verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_TEXT_TOP;
+              break;
+          }
+        }
+      }
+
+      // baseline coord that may be adjusted for script offset
+      nscoord revisedBaselineBCoord = baselineBCoord;
+
+      // For superscript and subscript, raise or lower the baseline of the box
+      // to the proper offset of the parent's box, then proceed as for BASELINE
+      if (verticalAlignEnum == NS_STYLE_VERTICAL_ALIGN_SUB ||
+          verticalAlignEnum == NS_STYLE_VERTICAL_ALIGN_SUPER) {
+        revisedBaselineBCoord += lineWM.FlowRelativeToLineRelativeFactor() *
+          (verticalAlignEnum == NS_STYLE_VERTICAL_ALIGN_SUB
+            ? fm->SubscriptOffset() : -fm->SuperscriptOffset());
+        verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_BASELINE;
+      }
+
       switch (verticalAlignEnum) {
         default:
         case NS_STYLE_VERTICAL_ALIGN_BASELINE:
-        {
-          // The element's baseline is aligned with the baseline of
-          // the parent.
-          pfd->mBounds.BStart(lineWM) = baselineBCoord - pfd->mAscent;
+          if (lineWM.IsVertical() && !lineWM.IsSideways()) {
+            if (frameSpan) {
+              pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord -
+                                            pfd->mBounds.BSize(lineWM)/2;
+            } else {
+              pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord -
+                                            logicalBSize/2 +
+                                            pfd->mMargin.BStart(lineWM);
+            }
+          } else {
+            pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord - pfd->mAscent;
+          }
           pfd->mBlockDirAlign = VALIGN_OTHER;
           break;
-        }
-
-        case NS_STYLE_VERTICAL_ALIGN_SUB:
-        {
-          // Lower the baseline of the box to the subscript offset
-          // of the parent's box. This is identical to the baseline
-          // alignment except for the addition of the subscript
-          // offset to the baseline BCoord.
-          nscoord parentSubscript = fm->SubscriptOffset();
-          nscoord revisedBaselineBCoord = baselineBCoord + parentSubscript;
-          pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord - pfd->mAscent;
-          pfd->mBlockDirAlign = VALIGN_OTHER;
-          break;
-        }
-
-        case NS_STYLE_VERTICAL_ALIGN_SUPER:
-        {
-          // Raise the baseline of the box to the superscript offset
-          // of the parent's box. This is identical to the baseline
-          // alignment except for the subtraction of the superscript
-          // offset to the baseline BCoord.
-          nscoord parentSuperscript = fm->SuperscriptOffset();
-          nscoord revisedBaselineBCoord = baselineBCoord - parentSuperscript;
-          pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord - pfd->mAscent;
-          pfd->mBlockDirAlign = VALIGN_OTHER;
-          break;
-        }
 
         case NS_STYLE_VERTICAL_ALIGN_TOP:
         {
           pfd->mBlockDirAlign = VALIGN_TOP;
           nscoord subtreeBSize = logicalBSize;
           if (frameSpan) {
             subtreeBSize = frameSpan->mMaxBCoord - frameSpan->mMinBCoord;
             NS_ASSERTION(subtreeBSize >= logicalBSize,
@@ -1896,17 +1919,18 @@ nsLineLayout::VerticalAlignFrames(PerSpa
           }
           break;
         }
 
         case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
         {
           // Align the midpoint of the frame with 1/2 the parents
           // x-height above the baseline.
-          nscoord parentXHeight = fm->XHeight();
+          nscoord parentXHeight =
+            lineWM.FlowRelativeToLineRelativeFactor() * fm->XHeight();
           if (frameSpan) {
             pfd->mBounds.BStart(lineWM) = baselineBCoord -
               (parentXHeight + pfd->mBounds.BSize(lineWM))/2;
           }
           else {
             pfd->mBounds.BStart(lineWM) = baselineBCoord -
               (parentXHeight + logicalBSize)/2 +
               pfd->mMargin.BStart(lineWM);
@@ -1916,34 +1940,36 @@ nsLineLayout::VerticalAlignFrames(PerSpa
         }
 
         case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
         {
           // The top of the logical box is aligned with the top of
           // the parent element's text.
           // XXX For vertical text we will need a new API to get the logical
           //     max-ascent here
-          nscoord parentAscent = fm->MaxAscent();
+          nscoord parentAscent =
+            lineWM.IsLineInverted() ? fm->MaxDescent() : fm->MaxAscent();
           if (frameSpan) {
             pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent -
               pfd->mBorderPadding.BStart(lineWM) + frameSpan->mBStartLeading;
           }
           else {
             pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent +
                                           pfd->mMargin.BStart(lineWM);
           }
           pfd->mBlockDirAlign = VALIGN_OTHER;
           break;
         }
 
         case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
         {
           // The bottom of the logical box is aligned with the
           // bottom of the parent elements text.
-          nscoord parentDescent = fm->MaxDescent();
+          nscoord parentDescent =
+            lineWM.IsLineInverted() ? fm->MaxAscent() : fm->MaxDescent();
           if (frameSpan) {
             pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent -
                                           pfd->mBounds.BSize(lineWM) +
                                           pfd->mBorderPadding.BEnd(lineWM) -
                                           frameSpan->mBEndLeading;
           }
           else {
             pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent -