Bug 1220438 - Correct baseline offset computation of text decoration for vertical-rl. r=jfkthame draft
authorXidorn Quan <quanxunzhen@gmail.com>
Fri, 01 Apr 2016 16:29:31 +1100
changeset 347835 9814a77550a0d2125f6d3ba7e55594929b65fd8b
parent 347489 27b90cd89c3a632dc88c57da21ff8b1f46f2cd7c
child 517723 94bd0f1bbffb446d9568faa8417a51c1e525fa54
push id14683
push userxquan@mozilla.com
push dateTue, 05 Apr 2016 23:05:52 +0000
reviewersjfkthame
bugs1220438
milestone48.0a1
Bug 1220438 - Correct baseline offset computation of text decoration for vertical-rl. r=jfkthame MozReview-Commit-ID: 5VHapeQ6mBU
layout/generic/nsTextFrame.cpp
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4958,26 +4958,32 @@ nsTextFrame::GetTextDecorations(
                     nsTextFrame::TextDecorationColorResolution aColorResolution,
                     nsTextFrame::TextDecorations& aDecorations)
 {
   const nsCompatibility compatMode = aPresContext->CompatibilityMode();
 
   bool useOverride = false;
   nscolor overrideColor = NS_RGBA(0, 0, 0, 0);
 
-  // frameBStartOffset represents the offset to f's BStart from our baseline in our
-  // coordinate space
+  bool nearestBlockFound = false;
+  WritingMode wm = GetWritingMode();
+  bool vertical = wm.IsVertical();
+
+  // physicalBlockStartOffset represents the offset from our baseline
+  // to f's physical block start, which is top in horizontal writing
+  // mode, and left in vertical writing modes, in our coordinate space.
+  // This physical block start is logical block start in most cases,
+  // but for vertical-rl, it is logical block end, and consequently in
+  // that case, it starts from the descent instead of ascent.
+  nscoord physicalBlockStartOffset =
+    wm.IsVerticalRL() ? GetSize().width - mAscent : mAscent;
   // baselineOffset represents the offset from our baseline to f's baseline or
   // the nearest block's baseline, in our coordinate space, whichever is closest
   // during the particular iteration
-  nscoord frameBStartOffset = mAscent,
-          baselineOffset = 0;
-
-  bool nearestBlockFound = false;
-  bool vertical = GetWritingMode().IsVertical();
+  nscoord baselineOffset = 0;
 
   for (nsIFrame* f = this, *fChild = nullptr;
        f;
        fChild = f,
        f = nsLayoutUtils::GetParentOrPlaceholderFor(f))
   {
     nsStyleContext *const context = f->StyleContext();
     if (!context->HasTextDecorationLines()) {
@@ -5010,29 +5016,32 @@ nsTextFrame::GetTextDecorations(
       if (fChild->VerticalAlignEnum() != NS_STYLE_VERTICAL_ALIGN_BASELINE) {
 
         // Since offset is the offset in the child's coordinate space, we have
         // to undo the accumulation to bring the transform out of the block's
         // coordinate space
         const nscoord lineBaselineOffset = LazyGetLineBaselineOffset(fChild,
                                                                      fBlock);
 
-        baselineOffset = frameBStartOffset - lineBaselineOffset -
+        baselineOffset = physicalBlockStartOffset - lineBaselineOffset -
           (vertical ? fChild->GetNormalPosition().x
                     : fChild->GetNormalPosition().y);
       }
     }
     else if (!nearestBlockFound) {
-      // use a dummy WritingMode, because nsTextFrame::GetLogicalBaseLine
-      // doesn't use it anyway
-      baselineOffset = frameBStartOffset - f->GetLogicalBaseline(WritingMode());
+      // offset here is the offset from f's baseline to f's top/left
+      // boundary. It's descent for vertical-rl, and ascent otherwise.
+      nscoord offset = wm.IsVerticalRL() ?
+        f->GetSize().width - f->GetLogicalBaseline(wm) :
+        f->GetLogicalBaseline(wm);
+      baselineOffset = physicalBlockStartOffset - offset;
     }
 
     nearestBlockFound = nearestBlockFound || firstBlock;
-    frameBStartOffset +=
+    physicalBlockStartOffset +=
       vertical ? f->GetNormalPosition().x : f->GetNormalPosition().y;
 
     const uint8_t style = styleText->GetDecorationStyle();
     if (textDecorations) {
       nscolor color;
       if (useOverride) {
         color = overrideColor;
       } else if (IsSVGText()) {