Bug 1081770 - Move ruby annotation frames when text-align: justify is applied to ruby bases. r=dbaron
authorXidorn Quan <quanxunzhen@gmail.com>
Tue, 09 Dec 2014 17:43:24 +1100
changeset 219833 cffd89b920e3f4b3ec1bab7600d31ab688e5b994
parent 219832 d1510bd5657793434031489c5c342a2980c0808c
child 219834 bcc6081af27599d708da62d3f0c56978977b901c
push id52942
push userxquan@mozilla.com
push dateTue, 16 Dec 2014 09:43:26 +0000
treeherdermozilla-inbound@cffd89b920e3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1081770
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 1081770 - Move ruby annotation frames when text-align: justify is applied to ruby bases. r=dbaron
layout/generic/nsLineLayout.cpp
layout/generic/nsLineLayout.h
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -2527,16 +2527,71 @@ nsLineLayout::ComputeFrameJustification(
 
       aState.mLastParticipant = pfd;
     }
   }
 
   return result;
 }
 
+void
+nsLineLayout::AdvanceAnnotationInlineBounds(PerFrameData* aPFD,
+                                            nscoord aContainerWidth,
+                                            nscoord aDeltaICoord,
+                                            nscoord aDeltaISize)
+{
+  MOZ_ASSERT(aPFD->mFrame->GetType() == nsGkAtoms::rubyTextFrame ||
+             aPFD->mFrame->GetType() == nsGkAtoms::rubyTextContainerFrame);
+  MOZ_ASSERT(aPFD->mSpan, "rt and rtc should have span.");
+
+  WritingMode lineWM = mRootSpan->mWritingMode;
+  WritingMode frameWM = aPFD->mSpan->mWritingMode;
+  LogicalRect bounds = aPFD->mFrame->GetLogicalRect(aContainerWidth);
+  bounds = bounds.ConvertTo(lineWM, frameWM, aContainerWidth);
+  bounds.IStart(lineWM) += aDeltaICoord;
+  bounds.ISize(lineWM) += aDeltaISize;
+  aPFD->mBounds = bounds.ConvertTo(frameWM, lineWM, aContainerWidth);
+  aPFD->mFrame->SetRect(frameWM, aPFD->mBounds, aContainerWidth);
+}
+
+/**
+ * This function applies the changes of icoord and isize caused by
+ * justification to annotations of the given frame.
+ * aPFD must be one of the frames in aContainingSpan.
+ */
+void
+nsLineLayout::ApplyLineJustificationToAnnotations(PerFrameData* aPFD,
+                                                  PerSpanData* aContainingSpan,
+                                                  nscoord aDeltaICoord,
+                                                  nscoord aDeltaISize)
+{
+  PerFrameData* pfd = aPFD->mNextAnnotation;
+  nscoord containerWidth = ContainerWidthForSpan(aContainingSpan);
+  while (pfd) {
+    AdvanceAnnotationInlineBounds(pfd, containerWidth,
+                                  aDeltaICoord, aDeltaISize);
+
+    // There are two cases where an annotation frame has siblings which
+    // do not attached to a ruby base-level frame:
+    // 1. there's an intra-annotation whitespace which has no intra-base
+    //    white-space to pair with;
+    // 2. there are not enough ruby bases to be paired with annotations.
+    // In these cases, their size should not be affected, but we still
+    // need to move them so that they won't overlap other frames.
+    PerFrameData* sibling = pfd->mNext;
+    while (sibling && !sibling->GetFlag(PFD_ISLINKEDTOBASE)) {
+      AdvanceAnnotationInlineBounds(sibling, containerWidth,
+                                    aDeltaICoord + aDeltaISize, 0);
+      sibling = sibling->mNext;
+    }
+
+    pfd = pfd->mNextAnnotation;
+  }
+}
+
 nscoord 
 nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD,
                                       JustificationApplicationState& aState)
 {
   NS_ASSERTION(aPSD, "null arg");
 
   nscoord deltaICoord = 0;
   for (PerFrameData* pfd = aPSD->mFirstFrame; pfd != nullptr; pfd = pfd->mNext) {
@@ -2565,16 +2620,17 @@ nsLineLayout::ApplyFrameJustification(Pe
       else {
         if (nullptr != pfd->mSpan) {
           dw = ApplyFrameJustification(pfd->mSpan, aState);
         }
       }
 
       pfd->mBounds.ISize(lineWM) += dw;
 
+      ApplyLineJustificationToAnnotations(pfd, aPSD, deltaICoord, dw);
       deltaICoord += dw;
       pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerWidthForSpan(aPSD));
     }
   }
   return deltaICoord;
 }
 
 // Align inline frames within the line according to the CSS text-align
--- a/layout/generic/nsLineLayout.h
+++ b/layout/generic/nsLineLayout.h
@@ -665,16 +665,26 @@ protected:
   void RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflowAreas);
 
   bool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaISize);
 
   struct JustificationComputationState;
   int32_t ComputeFrameJustification(PerSpanData* psd,
                                     JustificationComputationState& aState);
 
+  void AdvanceAnnotationInlineBounds(PerFrameData* aPFD,
+                                     nscoord aContainerWidth,
+                                     nscoord aDeltaICoord,
+                                     nscoord aDeltaISize);
+
+  void ApplyLineJustificationToAnnotations(PerFrameData* aPFD,
+                                           PerSpanData* aContainingSpan,
+                                           nscoord aDeltaICoord,
+                                           nscoord aDeltaISize);
+
   // Apply justification.  The return value is the amount by which the width of
   // the span corresponding to aPSD got increased due to justification.
   nscoord ApplyFrameJustification(
       PerSpanData* aPSD, mozilla::JustificationApplicationState& aState);
 
   void AttachFrameToBaseLineLayout(PerFrameData* aFrame);
 
 #ifdef DEBUG