Bug 1257446 part.3 nsTextFrame::GetCharacterRectsInRange() shouldn't call gfxSkipCharsIterator::AdvanceOriginal() before checking if the current offset has already been reached to the end for avoiding assertions r=jfkthame draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 14 Jul 2016 22:02:15 +0900
changeset 399828 407c47897cad8c2e4929ed1226073302faaecee2
parent 399827 0343e2eecf5e25043d260157cf4d8b0874e0ceb6
child 399829 f528daa31337c80b08fc1b3283859c9d8385983e
push id26006
push usermasayuki@d-toybox.com
push dateFri, 12 Aug 2016 06:28:16 +0000
reviewersjfkthame
bugs1257446
milestone51.0a1
Bug 1257446 part.3 nsTextFrame::GetCharacterRectsInRange() shouldn't call gfxSkipCharsIterator::AdvanceOriginal() before checking if the current offset has already been reached to the end for avoiding assertions r=jfkthame New eQueryTextRectArray causes a lot of assertions in various automated tests. The cause is that nsTextFrame::GetCharacterRectsInRange() calls gfxSkipCharsIterator::AdvanceOriginal(1) at the end of the |for| loop *without* checking if the iterator has already reached to the end. MozReview-Commit-ID: 3KFxA11uOUc
layout/generic/nsTextFrame.cpp
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -7448,41 +7448,39 @@ nsTextFrame::GetCharacterRectsInRange(in
   gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
   PropertyProvider properties(this, iter, nsTextFrame::eInflated);
   // Don't trim trailing whitespace, we want the caret to appear in the right
   // place if it's positioned there
   properties.InitializeForDisplay(false);
 
   UpdateIteratorFromOffset(properties, aInOffset, iter);
 
-  for (int32_t i = 0; i < aLength; i++) {
-    if (aInOffset > GetContentEnd()) {
-      break;
-    }
-
+  const int32_t kContentEnd = GetContentEnd();
+  const int32_t kEndOffset = std::min(aInOffset + aLength, kContentEnd + 1);
+  while (aInOffset < kEndOffset) {
     if (!iter.IsOriginalCharSkipped() &&
         !mTextRun->IsClusterStart(iter.GetSkippedOffset())) {
       FindClusterStart(mTextRun,
                        properties.GetStart().GetOriginalOffset() +
                          properties.GetOriginalLength(),
                        &iter);
     }
 
     nsPoint point = GetPointFromIterator(iter, properties);
     nsRect rect;
     rect.x = point.x;
     rect.y = point.y;
 
     nscoord iSize = 0;
-    gfxSkipCharsIterator nextIter(iter);
-    if (aInOffset < GetContentEnd()) {
+    if (aInOffset < kContentEnd) {
+      gfxSkipCharsIterator nextIter(iter);
       nextIter.AdvanceOriginal(1);
       if (!nextIter.IsOriginalCharSkipped() &&
           !mTextRun->IsClusterStart(nextIter.GetSkippedOffset())) {
-        FindClusterEnd(mTextRun, GetContentEnd(), &nextIter);
+        FindClusterEnd(mTextRun, kContentEnd, &nextIter);
       }
 
       gfxFloat advance =
         mTextRun->GetAdvanceWidth(Range(iter.GetSkippedOffset(),
                                         nextIter.GetSkippedOffset()),
                                   &properties);
       iSize = NSToCoordCeilClamped(advance);
     }
@@ -7494,19 +7492,21 @@ nsTextFrame::GetCharacterRectsInRange(in
       rect.width = iSize;
       rect.height = mRect.height;
 
       if (StyleContext()->IsTextCombined()) {
         rect.width *= GetTextCombineScaleFactor(this);
       }
     }
     aRects.AppendElement(rect);
-
-    iter.AdvanceOriginal(1);
     aInOffset++;
+    // Don't advance iter if we've reached the end
+    if (aInOffset < kEndOffset) {
+      iter.AdvanceOriginal(1);
+    }
   }
 
   return NS_OK;
 }
 
 nsresult
 nsTextFrame::GetChildFrameContainingOffset(int32_t   aContentOffset,
                                            bool      aHint,